I have a host that acts as a gateway for routing a home network to Internet. IP Masquerading has been enabled for months now and the system has worked fine.

How do I configure it to function also as a firewall? Any conditions I put on traffic in the FORWARD chain just dont work.

For example

-A FORWARD -i eth1 -p tcp -j ACCEPT

Just drops all TCP traffic from routing, instead of just restricting it to traffic originating from eth1. Also...

 -A FORWARD -s -p tcp -j ACCEPT

...doesn't just allow TCP traffic from the subnet, the moment I apply the rule all TCP traffic stops routing.

I have been unable to find any clear documentation on packet mangling with masquerade, or on how to ditch masquerade and instead use SNAT.

  • eth0 is external interface, on same subnet as DSL router
  • eth1 is internal interface, with all my hosts working fine on DHCP

How do I configure iptables to do both IP masquerading and firewalling?

# Generated by iptables-save v1.4.21 on Thu Oct 29 12:48:19 2015
:PREROUTING ACCEPT [10859:2328892]
:INPUT ACCEPT [1002:126271]
:OUTPUT ACCEPT [1256:91484]
# Completed on Thu Oct 29 12:48:19 2015
# Generated by iptables-save v1.4.21 on Thu Oct 29 12:48:19 2015
:FORWARD ACCEPT [127:18532]
-A INPUT -i eth1 -p tcp -m tcp --dport 80 -j ACCEPT -m comment --comment "HTTP Serve eth1"
-A INPUT -i eth1 -p tcp -m tcp --dport 443 -j ACCEPT -m comment --comment "SSH Serve eth1"
-A INPUT -i eth1 -p tcp -m tcp --dport 22 -m state --state NEW,ESTABLISHED -j ACCEPT -m comment --comment "ssh on eth1"
-A INPUT -i eth0 -p tcp -m tcp --dport 53 -j DROP -m comment --comment "drop dns from eth0"
-A INPUT -p icmp -j ACCEPT
-A INPUT -i eth0 -j DROP
-A INPUT -i eth1 -j REJECT
-A FORWARD -p tcp -j ACCEPT -m comment --comment "all tcp from internal"
-A FORWARD -p udp -j ACCEPT -m comment --comment "all udp from internal"
-A FORWARD -p icmp -j ACCEPT
-A OUTPUT -o eth1 -p tcp -m tcp --sport 22 -m state --state ESTABLISHED -j ACCEPT
-A OUTPUT -p udp -m udp --dport 53 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 53 -j ACCEPT
-A OUTPUT -p tcp -m tcp --dport 80 -m state --state NEW,ESTABLISHED -j ACCEPT
# Completed on Thu Oct 29 12:48:19 2015
  • NB, I disabled masquerading (seems an inferior solution) and enabled SNAT as follows, however, I lost all Internet and SSH connectivity to the router within five minutes of this. I guess if I can just crack this then we have an answer workable for my (and many others situations?) -A POSTROUTING -o eth0 -j SNAT --to – TemperedGlass Oct 31 '15 at 15:23
  • If SNAT is not working, you’re probably using the wrong source address. – Daniel B Oct 31 '15 at 15:28
  • Also, what are you even trying to accomplish? Please provide the output of iptables-save with your desired rules as well as a verbal description of them. – Daniel B Oct 31 '15 at 15:29
  • I am SNATING it now with - Internet is working, but I cant filter the traffic (nat tables tell me not to do it there, and if I apply subnets / interfaces etc in the FORWARD table then the traffic for the protocol fails. I want to block certain hosts from accessing the Internet. So an example failed rule (the save file above is the only working config) would be -A FORWARD -p tcp -s -j DROP -m comment --comment "block tcp from" effect of above = all tcp forwarding fails after iptables-restore from config with that rule. – TemperedGlass Oct 31 '15 at 15:40
  • Thanks for responses so far btw. Hopefully its clearer now? – TemperedGlass Oct 31 '15 at 15:42

iptables, and networking in general, is more complicated than you're giving it credit for.

So let's say you only do this, hoping to enable all outgoing traffic from internal eth1, as in your first line:

-A FORWARD -i eth1 -p tcp -j ACCEPT

Where this breaks is that all connections and traffic is 2-way. FORWARD is processing all traffic that's not targeting the router (INPUT) or sourced from the router (OUTPUT). So FORWARD gets both your outbound tcp traffic initiating connection (which your rule allows) and all the replies attempting to acknowledge that connection and pass traffic back (which since you're dropping everything else that doesn't match, would require a new rule to permit).

This is where iptables gets very complicated, very quickly, because to set up a rule for every potential packet in both directions is crazy. It starts to get simpler if the first rule is always to allow traffic over established connections using -m state --state ESTABLISHED, as you started to use over in your other question sorting out your NAT problem. That will let you just write rules for connections you want to allow to start. It may also be helpful to sort incoming and outgoing connections into their own rules (unless you're only worried about outgoing), as in below:

-N outbound
-N inbound
-A FORWARD -i eth0 -o eth1 -j inbound
-A FORWARD -i eth1 -o eth0 -j outbound
#allow outgoing web access
-A outbound -p tcp -m tcp --dport 80,443 -j ACCEPT
#and nothing else
-A outbound DROP

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.