3

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.

Interfaces:

  • eth0: Internet connection, 134.257.10.10/24, gateway 134.257.10.1
  • eth0:0: Second IP address on that interface: 134.257.10.20/24
  • eth1: LAN 1, 192.168.1.1/24
  • eth2: LAN 2, 192.168.2.1/24
  • eth3: LAN 3, 192.168.3.1/24

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

My iptables NAT table looks like this:

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
# Port forwarding:
-A PREROUTING -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.1.10:80
-A PREROUTING -i eth0:0 -p tcp -m tcp --dport 25 -j DNAT --to-destination 192.168.3.33:25
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT

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

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

1 Answer 1

3

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 192.168.3.0/24 -o eth0 -j SNAT --to-source 134.257.10.20

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 134.257.10.20/24 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 134.257.10.20/24 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 192.168.1.10:80 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 192.168.1.10:80

with:

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

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 134.257.10.20 -p tcp -m tcp --dport 25 -j DNAT --to-destination 192.168.3.33:25

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):

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]
-A PREROUTING -d 134.257.10.10/32 -i eth0 -p tcp -m tcp --dport 80 -j DNAT --to-destination 192.168.1.10:80
-A PREROUTING -d 134.257.10.20/32 -i eth0 -p tcp -m tcp --dport 25 -j DNAT --to-destination 192.168.3.33:25
-A POSTROUTING -s 192.168.3.0/24 -o eth0 -j SNAT --to-source 134.257.10.20
-A POSTROUTING -o eth0 -j MASQUERADE
COMMIT

You must log in to answer this question.

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