I have a simple Linux router with multiple NICs and IPv4 forwarding enabled.

The router has two static WAN IP addresses, assigned to one interface (eth0, eth0:0). (In the following text, I will obfuscate the actual public IP addresses (257 as an octet).)

The router can be pinged on both external WAN IP addresses from the outside Internet.


  • eth0: Internet connection,, gateway
  • eth0:0: Second IP address on that interface:
  • eth1: LAN 1,
  • eth2: LAN 2,
  • eth3: LAN 3,

My setup works and all LAN clients (LAN 1-3) can access the Internet and are externally seen as Moreover, I have two incoming port forwardings.

My iptables NAT table looks like this:

# Port forwarding:
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination
-A PREROUTING -i eth0:0 -p tcp -m tcp --dport 25 -j DNAT --to-destination

How can I have the LAN3 clients (eth3) appear as on the Internet (eth0:0) for outgoing connections instead of (eth0)?

  • 2
    Use SNAT and specify the address?
    – ilkkachu
    Oct 30, 2023 at 6:01

1 Answer 1


Use SNAT instead of MASQUERADE

... in order to choose something else than the default.

Instead of using MASQUERADE for the generic case (all other LANs), add a SNAT exception for LAN3 clients. This must match before the other nat/POSTROUTING rule in order to override it so -I is used below instead of -A to apply at the correct place on the existing ruleset (mind the bogus 257):

iptables -t nat -I POSTROUTING -s -o eth0 -j SNAT --to-source

iptables (contrary to nftables) cannot match the input interface of a routed packet in a POSTROUTING hook, so -i eth3 can't be used above, and the match is done by checking the original IP address source instead.

Addressing a problem with eth0:0

While at it, fix the incorrect use of so-called alias interface name, which is a concept that exists only for compatibility with Linux' ifconfig command which use has been obsolete for more than 20 years on Linux but is still around. Indeed on Linux ifconfig cannot handle more than one IPv4 address on an interface and this workaround has been here to overcome it. eth0:0 is actually seen by anything else than ifconfig, including the kernel, as the address set on eth0 with a label associated eth0:0. This secondary address could have been added like this (after the main address was already put in place) with the modern ip addr equivalent:

ip addr add brd + label eth0:0 dev eth0 

This matters because iptables won't match correctly with a rule using eth0:0. So it has to be replaced withing iptables with a check on the interface: eth0 plus a check on the IP address in the same rule.

So if the port 80 is intended to reach only for the first public IP address and not both, replace:

-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination


-A PREROUTING -i eth0 -d -p tcp -m tcp --dport 80 -j DNAT --to-destination

If it's for both addresses, then the initial rule is ok.

But for sure the rule for port 25 should be rewritten like this:

-A PREROUTING -i eth0 -d -p tcp -m tcp --dport 25 -j DNAT --to-destination

The match has to be done on the actual interface (eth0) and the address, because that's what eth0:0 is: the address and not an interface.

The final ruleset becomes then (mind the bogus 257 of course):

-A PREROUTING -d -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination
-A PREROUTING -d -i eth0 -p tcp -m tcp --dport 25 -j DNAT --to-destination
-A POSTROUTING -s -o eth0 -j SNAT --to-source

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .