Destination NAT changes where matching packets are sent after they arrive at a Linux gateway. With iptables, a DNAT rule can accept traffic on a gateway address and port, then rewrite the destination to an internal service before the packet is routed.

DNAT belongs in the nat table's PREROUTING chain for traffic arriving from another host. The translated packet must still be allowed through the FORWARD chain, and the backend must route replies back through the gateway unless another source NAT rule is intentionally used.

Examples below use wan0 as the outside interface, lan0 as the backend-side interface, gateway port 8080, and backend 10.10.0.20:80. Replace those values before running commands, keep a rollback path open, and save rules only after an outside client request and the NAT counters prove the translation matched.

Steps to configure DNAT with iptables:

  1. Identify the gateway interfaces and backend route.
    $ ip -br addr
    lo               UNKNOWN        127.0.0.1/8 ::1/128
    wan0             UP             203.0.113.10/24
    lan0             UP             10.10.0.1/24

    wan0 receives client traffic. lan0 reaches the backend network.

  2. Confirm the backend service responds from the gateway.
    $ curl -sS http://10.10.0.20/
    backend service through gateway

    Fix listener, routing, or application errors before adding DNAT. A destination rewrite cannot make a closed backend service answer.

  3. Save the current runtime rules as a rollback file.
    $ sudo iptables-save > ~/iptables.before-dnat.rules

    Keep a console session or known-good remote session open. Restore with sudo iptables-restore < ~/iptables.before-dnat.rules if the change breaks required traffic.

  4. Enable IPv4 packet forwarding for the current runtime.
    $ sudo sysctl -w net.ipv4.ip_forward=1
    net.ipv4.ip_forward = 1

    This lets the host route IPv4 packets between interfaces when routes and firewall rules allow it. Do not enable forwarding on a host that should remain a single-interface endpoint.

  5. Add the DNAT rule for the gateway port.
    $ sudo iptables -t nat -A PREROUTING -i wan0 -p tcp --dport 8080 -j DNAT --to-destination 10.10.0.20:80

    The rule changes the packet destination before route lookup. It does not by itself permit forwarding through the filter table.

  6. Allow new and established forwarded traffic to the backend.
    $ sudo iptables -A FORWARD -i wan0 -o lan0 -p tcp -d 10.10.0.20 --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
  7. Allow established return traffic from the backend.
    $ sudo iptables -A FORWARD -i lan0 -o wan0 -p tcp -s 10.10.0.20 --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT

    The backend must send replies through this gateway for the client to see a complete connection. Use a scoped SNAT or masquerade rule only when backend routing cannot be fixed or client addresses do not need to be preserved.

  8. Confirm the DNAT rule is present.
    $ sudo iptables -t nat -S PREROUTING
    -P PREROUTING ACCEPT
    -A PREROUTING -i wan0 -p tcp -m tcp --dport 8080 -j DNAT --to-destination 10.10.0.20:80
  9. Confirm the FORWARD rules are present.
    $ sudo iptables -S FORWARD
    -P FORWARD DROP
    -A FORWARD -d 10.10.0.20/32 -i wan0 -o lan0 -p tcp -m tcp --dport 80 -m conntrack --ctstate NEW,ESTABLISHED -j ACCEPT
    -A FORWARD -s 10.10.0.20/32 -i lan0 -o wan0 -p tcp -m tcp --sport 80 -m conntrack --ctstate ESTABLISHED -j ACCEPT
  10. Test the gateway port from an outside client path.
    $ curl -sS http://203.0.113.10:8080/
    backend service through gateway

    A test from the gateway itself can miss interface, upstream firewall, and routing problems. Use a client that reaches the gateway the same way real users do.

  11. Check the DNAT counter after the client test.
    $ sudo iptables -t nat --list PREROUTING --line-numbers --numeric --verbose --exact
    Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
    num      pkts      bytes target     prot opt in     out     source               destination
    1           1         60 DNAT       tcp  --  wan0   *       0.0.0.0/0            0.0.0.0/0            tcp dpt:8080 to:10.10.0.20:80

    The pkts and bytes counters increase when traffic reaches the gateway port and matches the translation rule.

  12. Save the verified runtime rules through the host's persistence method.
    $ sudo netfilter-persistent save
    run-parts: executing /usr/share/netfilter-persistent/plugins.d/15-ip4tables save

    Save only after the outside client test, DNAT counter, and forward counters all succeed.
    Related: How to save iptables rules permanently