A secure, iptables rule-set for Ubuntu home router

2

I am using a Ubuntu 14.04 server machine as my primary home router and firewall. It has DNS, DHCP and uses iptables to secure everything up. Iptables also acts as a nat.

On eth0 I have my incoming internet connection, and on eth1 I have my LAN for serving DNS and DHCP. All clients (connected to eth1) should be able to do anything outbound as normal. And on the lan I have a few machines which I want to connect to from the outside using PREROUTING.

However, lately I discovered that my ruleset was defined with ACCEPT on the *filter of INPUT without any DROP defined on the end. Therefore i have now defined DROP on incoming. After discovering this I have gotten a bit concerned and want to double check the whole ruleset if I have missed something more.

Is this set of iptables sufficient for securing everything up? As I have understood from reading up a bit is that PREROUTING and FORWARD can be set to ACCEPT since it will hit INPUT if nothing matches there, and i turn get DROPped by the default rule. Is this correct?

*filter
:INPUT DROP
-A INPUT -i eth1 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 22 -j ACCEPT
-A INPUT -i eth0 -p tcp -m tcp --dport 80 -m state --state NEW -j ACCEPT
-A INPUT -i eth0 -p udp -m udp --dport 53 --sport 53 -m state --state NEW -j    ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT

:FORWARD ACCEPT
-A FORWARD -i eth0 -j ACCEPT

:OUTPUT ACCEPT
COMMIT

*nat
:PREROUTING ACCEPT
-A PREROUTING -i eth0 -p tcp -m tcp -s x.x.x.x --dport 8466 -j DNAT --to-destination 192.168.0.149:8465
-A PREROUTING -i eth0 -p tcp -m tcp -s x.x.x.x --dport 5667 -j DNAT --to-destination 192.168.0.111:5666
-A PREROUTING -i eth0 -p tcp -m tcp -s x.x.x.x --dport 5666 -j DNAT --to-destination 192.168.0.201:5666
-A PREROUTING -i eth0 -p tcp -m tcp -s x.x.x.x --dport 2548 -j DNAT --to-destination 192.168.0.201:548
-A PREROUTING -i eth0 -p tcp -m multiport --dports 32400,32469 -j DNAT --to-destination 192.168.0.201

:INPUT ACCEPT

:OUTPUT ACCEPT

:POSTROUTING ACCEPT
-A POSTROUTING -o eth0 -j MASQUERADE

COMMIT

hrdy

Posted 2015-06-11T14:33:53.433

Reputation: 65

Answers

0

Yes, this is correct.

One strange thing: you have your DNS server open to the outside??? This opens your LAN to DNS DDoS attacks. Don't you mean to leave your DNS server open on the inside? (-i eth1). If you leave it open to the outside world, there are ways to mitigate the impact of DNS DDos attacks, are you aware of them?

Just to make sure you mean what you say:

  1. You are running an ssh-server and an http server (only on port 80? Why not port 443?) on your gateway.

  2. You want a single IP address to have access to ports 8466, 5667, 5666 and 2548.

  3. Instead, you allow every IP to connect to ports 32400 and 32469.

(just in case you wonder: no gamer, here).

Why did you drop icmp packets? They perform useful functions.

Contrary to public opinion, you do not need to add rules to drop malformed packets, and to drop packets for private, non-routable IP addresses. In other words, this is a sufficient rule set: you may wish to read here what professionals say of iptables rule sets, especially the first answer.

MariusMatutiae

Posted 2015-06-11T14:33:53.433

Reputation: 41 321

Yes, you are correct. I will remove the outside entry for my DNS.

  1. Yes, I am running a nxing server with http proxy towards my other machines on the inside.
  2. Yes, only single IP adresses should be able to connect to my icinga / nagios plugins on ports 8466, 5667, 5666 and 2548.
  3. Yes, I want to be able to connect to my Plex (videos and such) from anywhere.
  4. I have disabled ICMP since I dont need it. I feel more "stealth" without it. And I monitor my services / servers / machines with nagios and icinga.
  5. < – hrdy – 2015-06-11T20:18:02.867

So, what you are saying is that other than my public DNS-entry this is all fine and should be secure even though FORWARD and PREROUTING is set to ACCEPT on everything? – hrdy – 2015-06-11T20:23:24.057

And why does the PREROUTING stop working if I set is to DROP instead of ACCEPT? The NAT functions works fine when set to accept. – hrdy – 2015-06-11T20:34:57.043

@hrdy Yes, I am saying this is secure: the gateway only accepts ssh and http ports, it only forwards the ports you selected to those machines, everything else is dropped. – MariusMatutiae – 2015-06-12T05:28:59.547

@hrdy As for the change of behavior when you set the default PREROUTING policy, this has to do with Reverse Packet filtering. You may ask another question, or read this: http://www.slashroot.in/linux-kernel-rpfilter-settings-reverse-path-filtering

– MariusMatutiae – 2015-06-12T06:55:20.293

0

I have to contradict the previous answer. This setup is not secure. Basically by doing

:FORWARD ACCEPT -A FORWARD -i eth0 -j ACCEPT

You are allowing all traffic from outside to be forwarded to the inside. So you do not need the PREROUTING entries.

So if I'm an attacker on the same subnet as your public IP (someone using the same ISP in the same region). If I connect a machine directly on the ISP, so I get one of its public IP, I can create a route like

ip route add 192.168.0.0/24 via <your_public_ip>

(I can get your public IP by just scanning the internet for other people on my subnet)

Then I can do curl http://192.168.0.201:548 and your firewall will happily forward that request to your machine on your local network. Actually I would be able to scan your network by doing:

nmap -sn -T4 192.168.0.0/24

And I would get a list of all IPs up and running on your network.

Then for each I could do:

nmap -sS -T4 192.168.0.201

And I would get the list of opened port. I have verified this by creating 2 VMs and simulating a router and client machine on which I was running a Nginx server. I was able to access from the "WAN" side the Nginx server on the "LAN" side although there was no PREROUTING rule allowing this. I was also able to sweep the "LAN" side and so that only 1 VM was up and running :-)

What you need to do is:

:FORWARD DROP -A FORWARD -i eth1 -o eth1 -j ACCEPT -A FORWARD -i eth1 -o eth0 -j ACCEPT -A FORWARD -i eth0 -m conntrack --ctstate RELATED,ESTABLISHED,DNAT -j ACCEPT

The above rules will drop all forwarding by default. Note if you need forwarding between other interfaces you will need to add the entries. Then the other rules do:

  1. accept forwarding from LAN side to LAN side (that one is optional, but you could have some setup which requires it. For instance my LAN interface is a network bridge made of several interface, just like a switch, so I need that rule)
  2. accept forwarding from LAN to WAN
  3. accept forwarding from WAN to LAN only if the packets were accepted in PREROUTING and send to DNAT target, or if they are from an established connection or related to it (think ICMP packets related to the connection)

However the other answer is correct that you are exposing DNS to the internet and that is unusual. In addition, exposing port 22 and port 80 is perhaps not the best idea. Look online, there are many ways to improve your setup here, like rate limiting and using an IPS (even as simple as fail2ban) and especially harden SSH and switch to HTTPS.

Dropping packets from private IP space is probably not necessary, but dropping invalid packets is still a good thing. Anyway as soon as you use conntrack, it is "tagging" invlid packets, so why not using this feature and avoiding routing packets which will be drop later on by your application. Just kill them.

Final remark: when you do not know how to test your own firewall, you should consider to use a firewall distribution (e.g. ipfire, OPNsense, etc.) or at least a software on your Linux box that can do that out-of-the-box (e.g. shorewall). You have the advantages that it would be easier to get a secure setup, however of course it has the draw back that you won't learn iptables. If it is to learn iptables, then use first a real firewall setup for router on your "production router". Play with iptables on machine or on a VM setup, ask other questions here for example on how to test and verify your firewall. Once you have proved it, then put it in "prod". :-) That's how I have proceeded, so I only state this as a constructive advise.

Huygens

Posted 2015-06-11T14:33:53.433

Reputation: 1 340