Port forwarding
Before adding anything, check what the internet (our server at 192.0.2.10) can reach right now:
- The public LAN is wide open. The web server answers, and so does a database listener on port 5432 that should never be reachable from outside. Nothing is filtering: R1 is just routing.
- The NAT-LAN can't be reached at all. There's no route to 10.0.0.0/24 on the internet, and R1 has no reason to send anything there.
- Port 8080 on R1's WAN address is refused: nothing is listening, and nothing is forwarded yet.
To publish one service from the NAT-LAN, use destination NAT, also called port forwarding. Traffic arriving on eth0 for TCP port 8080 has its destination rewritten to 10.0.0.10 port 80, the web server on the NAT-LAN host.
Note what the web server sees: the real client address (192.0.2.10). Destination NAT only changes the destination, so the server's logs and access controls still work.
Using the forward from inside
Try the same URL from the public LAN, and it fails. The rule only matches traffic arriving on eth0, and this request came in on eth2. Getting it to work from inside is called hairpin NAT (or NAT reflection), and it needs extra rules, including source NAT so that replies come back through R1. Most networks avoid the problem with split DNS instead: inside, the name resolves to the private address directly.
root@server:~# curl -sS -m 5 http://198.51.100.2/
hello from pubhost
root@server:~# nc -zv -w 3 198.51.100.2 5432
Connection to 198.51.100.2 5432 port [tcp/postgresql] succeeded!
root@server:~# curl -sS -m 5 http://10.0.0.10/
curl: (7) Failed to connect to 10.0.0.10 port 80 after 0 ms: Couldn't connect to server
root@server:~# curl -sS -m 5 http://203.0.113.2:8080/
curl: (7) Failed to connect to 203.0.113.2 port 8080 after 0 ms: Couldn't connect to server- Lines 1–2: The public LAN's web server: expected.
- Lines 3–4: Its database, too: not expected, and nothing stops it.
- Lines 5–6: The NAT-LAN: no route from the internet.
- Lines 7–8: Nothing forwarded yet, so R1 refuses it.
set nat destination rule 100 description 'WAN port 8080 to the web server on lanhost'
set nat destination rule 100 inbound-interface name 'eth0'
set nat destination rule 100 protocol 'tcp'
set nat destination rule 100 destination port '8080'
set nat destination rule 100 translation address '10.0.0.10'
set nat destination rule 100 translation port '80'- Line 2: Only traffic arriving from the internet.
- Lines 3–4: TCP port 8080 on the WAN address…
- Lines 5–6: …becomes 10.0.0.10 port 80.
root@server:~# curl -sS -m 5 http://203.0.113.2:8080/
hello from lanhost
root@lanhost:~# cat /tmp/http.log
192.0.2.10 - - [17/Oct/2026 00:54:16] "GET / HTTP/1.1" 200 -- Lines 1–2: From the internet, R1's WAN address on port 8080 reaches the private web server.
- Line 4: The web server sees the real client, 192.0.2.10.
vyos@R1:~$ show nat destination rules
Rule Source Destination Proto In-Int Translation
------ --------- ------------- ------- -------- -------------
100 0.0.0.0/0 0.0.0.0/0 TCP eth0 10.0.0.10
sport any dport 8080 port 80
vyos@R1:~$ show nat destination translations
Pre-NAT Post-NAT Proto Timeout Mark Zone
---------------- ------------ ------- --------- ------ ------
203.0.113.2:8080 10.0.0.10:80 tcp 117 0- Line 9: 203.0.113.2:8080 rewritten to 10.0.0.10:80.
root@pubhost:~# curl -sS -m 5 http://203.0.113.2:8080/
curl: (7) Failed to connect to 203.0.113.2 port 8080 after 2 ms: Couldn't connect to server- Lines 1–2: Arrives on eth2, not eth0, so the rule doesn't match: no hairpin NAT.
Check your understanding
A port forward works from home but not from a laptop in the office. What's the most likely reason?
- The forward is configured on the wrong port
- The rule only matches traffic arriving on the WAN interface; office traffic arrives on a LAN interface
- The office laptop needs NAT turned off
- Destination NAT doesn't support TCP