Configuring iptables for nat

I’m running a Pihole on a raspberry pi 4 with raspbian buster. I’ve got an additional usb ethernet adapter connected and want to use it to separate my small home network from the shared internet connection I’m using with my neighbors.
I know i could just use a bog standard router with a wan port, but the pihole is running anyways and should have plenty capacity for that.
From my reading up to now this is how I tried configuring it:

  • sysctl net.ipv4.ip_forward is set to 1
  • pihole dhcp is set to give out IPs on eth0 from to and gateway set to
  • eth0 is set to static ip, gateway and dns on
  • eth1 is set to dhcp and is “configured” by the isp router
  • iptables config:
    sudo iptables -A FORWARD -i eth1 -o eth0 -m state --state RELATED,ESTABLISHED -j ACCEPT
    sudo iptables -A FORWARD -i eth0 -o eth1 -j ACCEPT
    sudo iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE

with only eth1 (link to isp router) connected the rasperry pi has no problems connecting to the internet. As soon as eth0 is connected nothing works anymore. No dns requests get resolved on it or any devices on my network. Yet I can see all dns requests in piholes query log. When I try to connect to a website by ip theres also no connection.

What am I doing wrong?

Takeout the gateway for eth0 (presumably in your /e/n/i file if debian hasn’t moved onto netplan yet). That’s definitely not correct for the lan side of your pihole “router”. But your dhcpd (or it’s moral equivalent) does need to be handing out (eth0’s address) to its clients. dns on is probably harmless on eth0 as long as your dhcpd is not handing out as the nameserver.

Also, dns requests from the devices connected to eth0 will be handled by the INPUT chain of the filter table (it doesn’t matter if your pihols resolver is only listening on eth1’s address, the INPUT chain handles all requests destined for the host). So if your default policy is to drop, you need to specifically accept those requests.

If there is something else wrong, it’s not obvious to me from what you have posted so far.

You will also need a route for your 192.168.1/24 subnet on your pihole “router”.
Adding netmask to eth0’s /e/n/i will do the trick. or you can manually add it: ip route add via dev eth0

Thank you! Taking out the gateway for eth0 stopped the dns requests going in circles :smiley:
Adding netmask doesn’t seem to help…

I think I found a solution, but I don’t know why it works.
Following Step 8 here did the trick.
They do something similar:
With net.ipv4.ip_forward = 1

  • flush and delete chains on “filter” and “nat” tables
  • iptables -t nat -A POSTROUTING -o eth1 -j MASQUERADE
  • iptables -A FORWARD -i eth0 -j ACCEPT

And thats it. Why does this work and mine doesn’t?
I’m a little confused as I thought the line with -m state --state RELATED,ESTABLISHED is important to not let any uninitiated outside connection inside my network…

If just that single FORWARD chain rule works, it must be that when you flush and delete the filter table rules, you reset the FORWARD chain default policy to accept so everything is being accepted.

I think a basic, sane set of forward rules in your case would be:

 # allow established return traffic, including from WAN side (eth1)

# allow forward traffic as long as it isn't originating from WAN (eth1) 
-A FORWARD ! -i eth1 -j ACCEPT

# drop everything that hasn't already been accepted

But it’s hard to know why one set of rules works and another doesn’t when you aren’t posting the complete sets.