I have a server with two network adaptors: eth0 and eth1.
This server is running two distinct https webservers:
One is listening on eth0 (172.29.49.112:8443)
The other is listening on eth1 (172.29.49.113:4443)
I have NAT rules for iptables that successfully redirect the standard https port (443) for both of these applications, but the iptables rules will only work for ONE of the rules at a time (which one it activates seems to be random across reboots).
Here are the rules loaded at boot time from rc.local (yes, I know that running my firewall rules from rc.local is not recommended):
#!/bin/sh -e
# setup port forwarding for gerrit and jenkins instances
su root -c "/sbin/iptables -t nat -A PREROUTING -i eth1 -d 172.29.49.113 -p tcp --dport 443 -j REDIRECT --to-port 4443"
su root -c "/sbin/iptables -t nat -A PREROUTING -i eth0 -d 172.29.49.112 -p tcp --dport 443 -j REDIRECT --to-port 8443"
# start gerrit (jenkins should auto-start as a service)
su gerrit2 -c "/home/gerrit2/gerrit/bin/gerrit.sh start"
exit 0
And here is the output of "iptables -t nat -L -n -v":
Chain PREROUTING (policy ACCEPT 14458 packets, 1446K bytes)
pkts bytes target prot opt in out source destination
6 360 REDIRECT tcp -- eth0 * 0.0.0.0/0 172.29.49.112 tcp dpt:443 redir ports 8443
0 0 REDIRECT tcp -- eth1 * 0.0.0.0/0 172.29.49.113 tcp dpt:443 redir ports 4443
Chain INPUT (policy ACCEPT 7436 packets, 874K bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 94 packets, 7050 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 94 packets, 7050 bytes)
pkts bytes target prot opt in out source destination
As you can see there are no other rules being loaded.
When I only run one of the two rules everything works correctly (for that rule), but then even if I clear the rules with "iptables -t nat -F" I can't enable the other rule (unless I reboot – that seems to clear things properly).
Why am I trying to do this?
I want my users to be able to access jenkins.servername.localnet and gerrit.servername.localnet rather than jenkins.servername.localnet:4443 etc.
(Obviously jenkins.servername.localnet resolves to 172.29.49.113 and .112 for gerrit).
At one point I thought that it may be the jenkins/gerrit webservers listening on all IPs causing the problem. But both of them are set to listen only on a single IP (jenkins – 172.29.49.113, gerrit – 172.29.49.112).
It's probably not required, but just incase it helps – here is the output of ifconfig:
eth0 Link encap:Ethernet HWaddr 00:0c:29:99:52:e8
inet addr:172.29.49.112 Bcast:172.29.63.255 Mask:255.255.240.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:78588 errors:0 dropped:0 overruns:0 frame:0
TX packets:27399 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:16180230 (15.4 MiB) TX bytes:6329245 (6.0 MiB)
eth1 Link encap:Ethernet HWaddr 00:0c:29:99:52:f2
inet addr:172.29.49.113 Bcast:172.29.63.255 Mask:255.255.240.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:45058 errors:0 dropped:0 overruns:0 frame:0
TX packets:9 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:3496805 (3.3 MiB) TX bytes:378 (378.0 B)
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:1090 errors:0 dropped:0 overruns:0 frame:0
TX packets:1090 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:268078 (261.7 KiB) TX bytes:268078 (261.7 KiB)
This has been incredibly frustrating since it ALMOST works.
I'm running Debian Wheezy, Gerrit 2.10 and Jenkins 1.604.
Things I've already looked at:
CAP_NET_BIND_SERVICE is not an easy solution because gerrit is initialized through a script.
authbind is a tool that will probably do what I want, but I'd prefer avoiding yet another layer.
Best Answer
Tero Kilkanen pointed me in the right direction on this, although it took a while for me to work out the syntax. It looks like iptables was confused regarding which IP the newly redirected data should go to.
DNAT specifies the target port AND the target IP, so it works correctly now. The final commands I used were as follows:
Note for wurtel and user1036745: Setting the input nic with a wildcard did not make a difference. (especially since by default iptables sets a wildcard entry for the input nic anyway, so no need to specify "eth+") But thanks for taking the time to reply anyway.