1

On CentOS 7 Linux (acting as LAMP - and not "firewall/gateway") I have created a custom systemd service for running embedded Jetty at port 8080 as user nobody:

[Unit]
Description=WebSocket Handler Service
After=network-online.target

[Service]
Type=simple
User=nobody
Group=nobody
ExecStart=/usr/bin/java -classpath '/usr/share/java/jetty/*' de.afarber.MyHandler 123.123.123.123:8080
ExecStop=/bin/kill ${MAINPID}
SuccessExitStatus=143

[Install]
WantedBy=multi-user.target

However I actually need the server to listen at the port 80 - so that WebSocket connections to it work even through corporate firewalls.

The Jetty document on Setting Port 80 Access for a Non-Root User suggests to run the following command:

# iptables -t nat -I PREROUTING -p tcp --dport 80 -j REDIRECT --to-port 8080

Luckily I already use iptables-services package at my dedicated server and the current /etc/sysconfig/iptables file contains:

*filter
:INPUT DROP
:FORWARD DROP
:OUTPUT ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp -m multiport --dports 25,80,443,8080 -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m tcp --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m limit --limit 2/min --limit-burst 1 -j ACCEPT
COMMIT

My problem is that I don't know the proper PREROUTING-syntax for the above file.

I have tried running the command above and then iptables -S in the hope that iptables will list the needed line for me - but that didn't happen.

UPDATE:

Unfortunately the following /etc/sysconfig/iptables file does not work:

*nat
:INPUT ACCEPT
:OUTPUT ACCEPT
:PREROUTING ACCEPT
:POSTROUTING ACCEPT
-A PREROUTING -p tcp -m tcp --dst 123.123.123.123 --dport 80 -j REDIRECT --to-ports 8080
COMMIT

*filter
:INPUT ACCEPT
:OUTPUT ACCEPT
:FORWARD ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -m icmp --icmp-type any -j ACCEPT
-A INPUT -p tcp -m tcp -m state --state NEW -m multiport --dports 25,80,443,8080 -j ACCEPT
-A INPUT -p tcp -m tcp -m state --state NEW --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m limit --limit 2/min --limit-burst 1 -j ACCEPT
-A FORWARD -p tcp -m tcp --dst 123.123.123.123 --dport 8080 -j ACCEPT
COMMIT

I need incoming HTTP-connections to 123.123.123.123:80 to be redirected to 123.123.123.123:8080 (where Jetty is listening as user "nobody"), but for some reason this does not happen.

When I browse to http://123.123.123.123:8080 then I see Jetty response.

But when I browse to http://123.123.123.123 connection is refused.

Can anybody please spot the error for me?

Here is my current nat table:

# iptables -t nat -L
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination
REDIRECT   tcp  --  anywhere             afarber.de           tcp dpt:http redir ports 8080

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination

Here is my current filter table:

# iptables -t filter -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination
ACCEPT     all  --  anywhere             anywhere             state RELATED,ESTABLISHED
ACCEPT     all  --  anywhere             anywhere
ACCEPT     icmp --  anywhere             anywhere             icmp any
ACCEPT     tcp  --  anywhere             anywhere             tcp state NEW multiport dports smtp,http,https,webcache
ACCEPT     tcp  --  anywhere             anywhere             tcp dpt:ssh flags:FIN,SYN,RST,ACK/SYN state NEW limit: avg 2/min burst 1

Chain FORWARD (policy ACCEPT)
target     prot opt source               destination
ACCEPT     tcp  --  anywhere             afarber.de           tcp dpt:webcache

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Here my /etc/sysctl.conf file:

net.ipv4.ip_forward=1
net.ipv6.conf.all.disable_ipv6=1
net.ipv6.conf.default.disable_ipv6=1

Problem: requests to -d 123.123.123.123 --dport 80 are not redirected to 8080

UPDATE 2:

The line does not help either:

-A PREROUTING -p tcp -m tcp -i eth0:1 --dst 123.123.123.123 --dport 80 -j DNAT --to-destination :8080

the connection to 123.123.123.123:80 is still dropped

1
  • 1
    Please, DO NOT edit "/etc/sysconfig/iptables" manually. Just load all required rules using the "iptables", ensure that your app is working correctly and do "service iptables save". It will dump the currently running rules to the saved config. Jun 21, 2016 at 9:44

2 Answers 2

4

It would be like this:

*nat
:PREROUTING ACCEPT [0:0]
:INPUT ACCEPT [0:0]
:OUTPUT ACCEPT [3:353]
:POSTROUTING ACCEPT [3:353]
-A PREROUTING -p tcp -m tcp --dport 80 -j REDIRECT --to-ports 8080
COMMIT
# Completed on Mon Jun 20 23:41:41 2016

Do you know how to do it the easy way? I assume you have disabled the firewalld and installed iptables-services because you wanted your centos7 to work as centos6.

"/etc/sysconfig/iptables" is the file where iptables-services save the rules. You can edit it manualy, but there is no need to. You can just enter any rules using the "iptables" command and then "service iptables save" to save the currently active rules to the file.

You can also make is so that the rules will be saved every time the iptables service is restrted by setting here "/etc/sysconfig/iptables-config" IPTABLES_SAVE_ON_STOP and IPTABLES_SAVE_ON_RESTART

6
  • Thank you! Should I just append your text to my current /etc/sysconfig/iptables? I am confused that you have *nat and I have *filter - and wonder how to have both. Also I am worried if my computer starts forwarding and accepting other packets since you have changed INPUT/OUTPUT drop to accept Jun 20, 2016 at 19:56
  • 1
    Don't edit this file manually, it's hard and not needed. Just add your rules using "iptables", ensure that everything is working and then save the rules with "service iptables save". It will write this file automatically. Jun 20, 2016 at 20:49
  • 1
    There are different tables in the iptables filter, nat and mangle and they are used for different purposes and have their own chains. Well, it's too much information for a single post to tell about them all. You can use "iptables-save" to view the current rules. Actually "service iptbles save" just writes the output of "iptbles-save" to the file. Jun 20, 2016 at 20:54
  • 1
    Most likely you want DROP for the INPUT and ACCEPT for all other chains. These are called policies and can be set "iptables -t (table) -P (chain) (target)" Jun 20, 2016 at 21:01
  • 1
    @AlexanderFarber with respect to that last comment, when I'm working on firewall rules remotely I like to start with echo service iptables stop | at now + 15min as root, knowing that if I lock myself out, I need only wait a few minutes and I can get back in. If my change doesn't lock me out, I can use atrm to remove the job before it runs.
    – MadHatter
    Jun 21, 2016 at 9:48
0

I think I have finally figured it out - the NAT HOWTO says, that -j REDIRECT is just a shortcut for -j DNAT with destination address being the one of the interface:

There is a specialized case of Destination NAT called redirection: it is a simple convenience which is exactly equivalent to doing DNAT to the address of the incoming interface.

But in my case that just can not work, because my CentOS 7 server has 4 IP addresses.

(I am sorry, that I haven't mentioned it, because I didn't think it would matter).

At eth0 port 80 runs Apache (which can drop root rights).

And at eth0:1 port 8080 runs Jetty (which can not drop root rights). But I need Jetty at port 80 (so that websockets work for corporate users behind proxies) and I want it to run as user "nobody".

And now I have figured out, how to redirect the incoming requests with net.ipv4.ip_forward=1 in /etc/sysctl.conf and with the following /etc/sysconfig/iptables:

*filter
:INPUT DROP
:OUTPUT ACCEPT
:FORWARD ACCEPT
-A INPUT -m state --state RELATED,ESTABLISHED -j ACCEPT
-A INPUT -i lo -j ACCEPT
-A INPUT -p icmp -j ACCEPT
-A INPUT -p tcp -m state --state NEW -m multiport --dports 25,80,443,8080 -j ACCEPT
-A INPUT -p tcp -m state --state NEW --dport 22 --tcp-flags FIN,SYN,RST,ACK SYN -m limit --limit 2/min --limit-burst 1 -j ACCEPT
COMMIT

*nat
:INPUT ACCEPT
:OUTPUT ACCEPT
:PREROUTING ACCEPT
:POSTROUTING ACCEPT
-A PREROUTING -p tcp --dst 123.123.123.123 --dport 80 -j DNAT --to-destination 123.123.123.123:8080
COMMIT

You must log in to answer this question.

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