3

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

8
  • looks like case 2; after PREROUTING local packets go to the local filter where they get dropped in your case. The solution is to a) run 8080 and 3000 locally (so they are not exposed) and open those ports in iptables like 80 etc or b) add rule to allow those ports for traffic coming locally only Mar 26, 2014 at 19:13
  • @LinuxDevOps Makes sense. How do a) and b) different in your answer? I'm not sure how to accomplish either case exactly, but it does make sense that I'd have to open up 8080 and 3000 to local traffic if I want this to work. Do you have a link or example of how to do that? And is there any security concerns there? Thanks! Mar 26, 2014 at 19:27
  • Sorry for the confusion, I think you just need to open those ports -A INPUT -p tcp -m tcp --dport 8080 -j ACCEPT (same for 3000) , if you are redirecting from 80/443 to 8080/3000 is like the latter ports are open and exposed to the Internet anyways, I'm supposing you want http(s) requests to go directly to Node and there's no proxy (apache etc) at the front before it. Mar 26, 2014 at 19:44
  • @LinuxDevOps Interesting! Yes, http(s) requests are going directly to Node. I had assumed opening 8080 and 3000 to the public would be an issue, but it sounds from your answer that there is literally no difference since I'm forwarding 80 and 443 there anyway. Thanks for the help! Mar 26, 2014 at 19:49
  • correct, there's no difference from the outside, if everything works now let me put it together in a cleaner answer Mar 26, 2014 at 19:54

1 Answer 1

6

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.

2
  • 2
    For the sake of information, what if I want to explicitly block direct requests for port 3000 ? I.E. mysite.com is OK but mysite.com:3000 is NOT OK. Sep 25, 2014 at 23:09
  • @ArthurCorenzan if you are redirecting 80 traffic to 8080 - why not just run node on 80?
    – Xeoncross
    Jan 18, 2015 at 2:11

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .