Ubuntu – iptables port forwarding (prerouting port 80) and firewall not working together

iptableslinodenode.jsport-forwardingUbuntu

I have read many articles and answers on this topic and I have been in discussion with Linode support, but no one seems to be able to answer my exact problem.

Seems easy – I'd like to use a iptables firewall to restrict access to all ports except 22, 80 and 443. Linode has a great write up here: https://library.linode.com/securing-your-server#sph_creating-a-firewall and I used their firewall rules as is. The firewall works well.

I also want to preroute some ports, because this is a nodejs app. So I used:

sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -A PREROUTING -t nat -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3000

These rules work if I do not have the firewall rules. In fact, I'm using them right now, but I've had to leave the firewall down.

If I add the firewall rules, the PREROUTING stops working. If I save the active iptables rules into a file to view, both the firewall (filter rules) and the PREROUTING (nat rules) are present, but only the firewall rules work. See here:

# Generated by iptables-save v1.4.18 on Wed Mar 26 02:40:04 2014
*security
:INPUT ACCEPT [1606:135329]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1206:144815]
COMMIT
# Completed on Wed Mar 26 02:40:04 2014
# Generated by iptables-save v1.4.18 on Wed Mar 26 02:40:04 2014
*raw
:PREROUTING ACCEPT [1620:139613]
:OUTPUT ACCEPT [1206:144815]
COMMIT
# Completed on Wed Mar 26 02:40:04 2014
# Generated by iptables-save v1.4.18 on Wed Mar 26 02:40:04 2014
*nat
:PREROUTING ACCEPT [4:248]
:INPUT ACCEPT [6:376]
:OUTPUT ACCEPT [12:728]
:POSTROUTING ACCEPT [12:728]
-A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
-A PREROUTING -p tcp -m tcp --dport 443 -j REDIRECT --to-ports 3000
COMMIT
# Completed on Wed Mar 26 02:40:04 2014
# Generated by iptables-save v1.4.18 on Wed Mar 26 02:40:04 2014
*mangle
:PREROUTING ACCEPT [1620:139613]
:INPUT ACCEPT [1606:135329]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [1206:144815]
:POSTROUTING ACCEPT [1206:144815]
COMMIT
# Completed on Wed Mar 26 02:40:04 2014
# Generated by iptables-save v1.4.18 on Wed Mar 26 02:40:04 2014
*filter
:INPUT ACCEPT [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT ACCEPT [0:0]
-A INPUT -i lo -j ACCEPT
-A INPUT -d 127.0.0.0/8 -j REJECT --reject-with icmp-port-unreachable
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -p tcp -m tcp --dport 80 -j ACCEPT
-A INPUT -p tcp -m tcp --dport 443 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -m limit --limit 5/min -j LOG --log-prefix "iptables denied: " --log-level 7
-A INPUT -j DROP
-A FORWARD -j DROP
-A OUTPUT -j ACCEPT
COMMIT
# Completed on Wed Mar 26 02:40:04 2014 

If I use iptables -F, it will flush the firewall (filter) rules only and the PREROUTING will start working again. So it's definitely a conflict. The order of the rule blocks doesn't seem to matter as this (above) is the standard output by iptables regardless of the order in which I saved the rules to iptables.

To me, it seems like it's one of two things:

  1. PREROUTING ports that also have the ACCEPT rule could mean the
    prerouting is ignored
  2. that I'm PREROUTING to a port that is technically blocked (but I thought that's where the "PRE" came in)

Anyone know?

Thanks!

Paul

Best Answer

After PREROUTING local packets go to the local filter where they get dropped (your case 2).

So you just need to allow incoming traffic to those ports in iptables:

iptables -A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT

iptables -A INPUT -p tcp -m tcp --dport 3000 -j ACCEPT

Since you are redirecting http(s) traffic from 80/443 to 8080/3000 is like the latter ports are open and exposed to the Internet anyways, so there's no difference from the outside wrorld and there are no further security implications.