1

I have a raspberry pi with two interfaces:

  • wlan0
  • eth0

wlan0 is connected to my internal network 192.168.2.0/24. eth0 is connected to a network switch with a LAN network 10.0.0.0/8.

Currently I have all traffic in the LAN 10.0.0.0/8 able to use Internet via my wlan0 interface, and I am able to connect to any machines in the 10.0.0.0/8 network from the raspberry pi. E.g. ssh into 10.0.0.2.

  • The raspberry pi wlan0 interface has IP address 192.168.2.30.
  • The raspberry pi eth0 interface has IP address 10.0.0.1.

I have configured this by enabling IP forwarding with net.ipv4.ip_forward=1.

I then added the following iptables rules:

sudo iptables -t nat -A POSTROUTING -o wlan0 -j MASQUERADE
sudo iptables -A FORWARD -i wlan0 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
sudo iptables -A FORWARD -i eth0 -o wlan0 -j ACCEPT

However, I now need to be able to intercept traffic hitting the wlan0 interface on port 80 or port 443 (from the other side, (192.168.0.2/24) and route it directly to another IP address on the LAN that this raspberry pi is connected to (10.23.220.88).

This is my current iptables filter table:

pi@something:~ $ sudo iptables -L -n -v --line-numbers
Chain INPUT (policy ACCEPT 48847 packets, 20M bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 157 packets, 9952 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     319K  467M ACCEPT     all  --  wlan0  eth0    0.0.0.0/0            0.0.0.0/0            state RELATED,ESTABLISHED
2     161K   12M ACCEPT     all  --  eth0   wlan0   0.0.0.0/0            0.0.0.0/0

Chain OUTPUT (policy ACCEPT 26150 packets, 18M bytes)
num   pkts bytes target     prot opt in     out     source               destination

and this is my iptables current NAT table:

pi@something:~ $ sudo iptables -t nat -L --line-numbers
Chain PREROUTING (policy ACCEPT)
num  target     prot opt source               destination

Chain INPUT (policy ACCEPT)
num  target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
num  target     prot opt source               destination
1    MASQUERADE  all  --  anywhere             anywhere

Chain OUTPUT (policy ACCEPT)
num  target     prot opt source               destination

How can I achieve this without disturbing the fact that I am routing internet through this raspberry pi to my 10.0.0.0/8 network, and the fact that I can connect into the 10.0.0.0/8 network?

1

That one is easy. Just add:

iptables -t nat -A PREROUTING -p tcp -d 192.168.2.X --dport 80 -jDNAT --to-destination 10.23.220.88:80
iptables -t nat -A PREROUTING -p tcp -d 192.168.2.X --dport 443 -jDNAT --to-destination 10.23.220.88:443

Where X is last byte from your wlan0 IP.

If you want to have a specific source (somebody specific from your wlan0 network) you just add --source 192.168.2.Y where Y is the last byte from the IP of that machine in the network.

| improve this answer | |
  • Thanks for this @Zatarra, it got me half way there, but I also needed a POSTROUTING rule to modify the packet's original source address to repoint it to my pi router performing the NAT. I've added the extra detail and rule I required as another answer below, but upvoted your answer for getting me half way there. Much appreciated. – Shogan Nov 11 '19 at 23:40
0

Zatarra's answer got me part of the way there, but after trying it out and having no luck, I went and did some refresh reading on how NAT works and realised that I still needed a POSTROUTING (SNAT) rule to make sure the source address of the packet is changed from the original HTTP client's address to the address of the raspberry pi router (which is performing the NAT).

This way the raspberry pi router receives the packet back from the 10.23.220.88 host on it's eth0 interface (10.0.0.1) and then knows that it should actually go back again from there via wlan0 to the original HTTP client on the 192.168.2.0/24 network.

So I needed the PREROUTING rule that Zatarra mentioned (and importantly, needed to modify it to make the source interface my wlan0 interface where external traffic was coming in - this is so that internal traffic talking back out to the internet via the router via eth0 didn't also get caught in this rule and sent back in again to my 10.23.220.88 address), but also needed the SNAT / POSTROUTING rule.

So the solution for me ended up being a combination of:

sudo iptables -t nat -A PREROUTING -i wlan0 -p tcp --dport 80 -j DNAT --to-destination 10.23.220.88:80
sudo iptables -t nat -A POSTROUTING -p tcp -d 10.23.220.88 --dport 80 -j SNAT --to-source 10.0.0.1

Repeat of course for port 443 too.

This is in addition to already having had the MASQUERADE rule in place for POSTROUTING (as per my original post where I explained I already had MASQUERADE enabled).

So my final NAT iptables rules look like this:

pi@somehost:~ $ sudo iptables -t nat -L --line-numbers -v
Chain PREROUTING (policy ACCEPT 18635 packets, 3477K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1       11   628 DNAT       tcp  --  wlan0  any     anywhere             anywhere             tcp dpt:http to:10.23.220.88:80

Chain INPUT (policy ACCEPT 17050 packets, 3354K bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain POSTROUTING (policy ACCEPT 118 packets, 10432 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1       28  1843 MASQUERADE  all  --  any    wlan0   anywhere             anywhere
2       11   628 SNAT       tcp  --  any    any     anywhere             10.23.220.88         tcp dpt:http to:10.0.0.1

and here are my iptables filter rules:

pi@somehost:~ $ sudo iptables -t filter -L --line-numbers -v
Chain INPUT (policy ACCEPT 775K packets, 142M bytes)
num   pkts bytes target     prot opt in     out     source               destination

Chain FORWARD (policy ACCEPT 2013 packets, 145K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     153K  213M ACCEPT     all  --  wlan0  eth0    anywhere             anywhere             state RELATED,ESTABLISHED
2    71327 5506K ACCEPT     all  --  eth0   wlan0   anywhere             anywhere

Chain OUTPUT (policy ACCEPT 38847 packets, 4782K bytes)
num   pkts bytes target     prot opt in     out     source               destination

I found these two articles great to explain the whole iptables process and refresh my memory on how NAT works:

| improve this answer | |
  • You could have easily fix that by using MASQUERADE: iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE – Zatarra Nov 13 '19 at 9:29
  • I already had a MASQUERADE nat rule setup as per my original question's info. – Shogan Nov 22 '19 at 23:38
  • Well, you are just doing NAT, not actually routing. NAT is not a substitute for real routing, and you avoid NAT if at all possible. You do not need NAT since you are not dealing with overlapping addressing or private to public routing. Simple routing would seem to work. – Ron Maupin Nov 23 '19 at 0:35
  • Not sure if it makes a difference here, but I am actually forwarding web traffic via this route: public internet -> router1 (192.168.1.0/24 network) -> router2 (192.168.2.0/24 network) -> router3 (the above mentioned 192.168.2.30 Pi device) -> filter rule forward to eth0 device on the Pi device), which then gets picked up and forwarded into the 10.23.220.88 IP web service mentioned above. – Shogan Nov 23 '19 at 0:56
  • As far as I see you had only for wlan0 : 1 28 1843 MASQUERADE all -- any wlan0 anywhere anywhere – Zatarra Nov 23 '19 at 20:44

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.