I have a server (serv05) at work with a public ip, hosting two KVM guests - vtest1 & vtest2 - in two different private network - 192.168.122.0 & 192.168.100.0 - respectively, this way:
[root@serv05 ~]# ip -o addr show | grep -w inet
1: lo inet 127.0.0.1/8 scope host lo
2: eth0 inet xxx.xxx.xx.197/24 brd xxx.xxx.xx.255 scope global eth0
4: virbr1 inet 192.168.100.1/24 brd 192.168.100.255 scope global virbr1
6: virbr0 inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
#
[root@serv05 ~]# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr1
xxx.xxx.xx.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
192.168.122.0 0.0.0.0 255.255.255.0 U 0 0 0 virbr0
169.254.0.0 0.0.0.0 255.255.0.0 U 1002 0 0 eth0
0.0.0.0 xxx.xxx.xx.62 0.0.0.0 UG 0 0 0 eth0
I've also setup IP FORWARDing and Masquerading this way:
iptables --table nat --append POSTROUTING --out-interface eth0 -j MASQUERADE
iptables --append FORWARD --in-interface virbr0 -j ACCEPT
All works up to this point. If I want to remote access vtest1 (or vtest2) first I ssh to serv05 and then from there ssh to vtest1. Is there a way to setup a port forwarding so that vtest1 can be accessed directly from the outside world? This is what I probably need to setup:
external_ip (tcp port 4444) -> DNAT -> 192.168.122.50 (tcp port 22)
I know it's easily doable using a SOHO router but can't figure out how can I do that on a Linux box.
Update: 1
Now I've made ssh to listen to both of the ports:
[root@serv05 ssh]# netstat -tulpn | grep ssh
tcp 0 0 xxx.xxx.xx.197:22 0.0.0.0:* LISTEN 5092/sshd
tcp 0 0 xxx.xxx.xx.197:4444 0.0.0.0:* LISTEN 5092/sshd
and port 4444 is allowed in the iptables rules:
[root@serv05 sysconfig]# grep 4444 iptables
-A PREROUTING -i eth0 -p tcp -m tcp --dport 4444 -j DNAT --to-destination 192.168.122.50:22
-A INPUT -p tcp -m state --state NEW -m tcp --dport 4444 -j ACCEPT
-A FORWARD -i eth0 -p tcp -m tcp --dport 4444 -j ACCEPT
But I'm getting connection refused:
maci:~ santa$ telnet serv05 4444
Trying xxx.xxx.xx.197...
telnet: connect to address xxx.xxx.xx.197: Connection refused
telnet: Unable to connect to remote host
Any idea what's I'm still missing?
Update: 2
I've removed the third interface, virbr1, from the iptables just make the output shorter.
[root@serv05 sysconfig]# iptables -vL -n
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
108 8112 ACCEPT all -- * * 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED
0 0 ACCEPT icmp -- * * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT all -- lo * 0.0.0.0/0 0.0.0.0/0
189 42273 ACCEPT all -- eth0 * 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- * * xxx.xxx.xx.0/24 0.0.0.0/0 state NEW tcp dpt:21
0 0 ACCEPT tcp -- * * 192.168.122.0/24 0.0.0.0/0 state NEW tcp dpt:21
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22
0 0 ACCEPT tcp -- * * 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:4444
0 0 ACCEPT tcp -- * * xxx.xxx.xx.0/24 0.0.0.0/0 state NEW tcp dpt:80
0 0 ACCEPT tcp -- * * 192.168.122.0/24 0.0.0.0/0 state NEW tcp dpt:80
2 64 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * virbr0 0.0.0.0/0 192.168.122.0/24 state RELATED,ESTABLISHED
0 0 ACCEPT all -- virbr0 * 192.168.122.0/24 0.0.0.0/0
0 0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0
0 0 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- virbr0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
0 0 ACCEPT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:4444
Chain OUTPUT (policy ACCEPT 57 packets, 11124 bytes)
pkts bytes target prot opt in out source destination
The very same thing is here too, virbr1 is intentionally removed from the output.
[root@serv05 sysconfig]# iptables -t nat -vL -n
Chain PREROUTING (policy ACCEPT 611 packets, 105K bytes)
pkts bytes target prot opt in out source destination
0 0 DNAT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:4444 to:192.168.122.50:22
Chain POSTROUTING (policy ACCEPT 4 packets, 344 bytes)
pkts bytes target prot opt in out source destination
0 0 MASQUERADE tcp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
0 0 MASQUERADE udp -- * * 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
0 0 MASQUERADE all -- * * 192.168.122.0/24 !192.168.122.0/24
0 0 MASQUERADE tcp -- * * 192.168.100.0/24 !192.168.100.0/24 masq ports: 1024-65535
0 0 MASQUERADE udp -- * * 192.168.100.0/24 !192.168.100.0/24 masq ports: 1024-65535
0 0 MASQUERADE all -- * * 192.168.100.0/24 !192.168.100.0/24
Chain OUTPUT (policy ACCEPT 4 packets, 344 bytes)
pkts bytes target prot opt in out source destination
Update: 3
SSH is not listening to port 4444 anymore:
[root@serv05 sysconfig]# netstat -tulpn | grep ssh
tcp 0 0 xxx.xxx.xx.197:22 0.0.0.0:* LISTEN 15231/sshd
The FORWARD order is fixed:
[root@serv05 sysconfig]# iptables -vL -n
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
[ .... ]
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- * virbr0 0.0.0.0/0 192.168.122.0/24 state RELATED,ESTABLISHED
0 0 ACCEPT all -- virbr0 * 192.168.122.0/24 0.0.0.0/0
0 0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0
0 0 ACCEPT tcp -- eth0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:4444
1 64 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- virbr0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- * * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited
Chain OUTPUT (policy ACCEPT 5 packets, 612 bytes)
pkts bytes target prot opt in out source destination
but still getting connection refused:
maci:~ santa$ telnet serv05 4444
Trying xxx.xxx.xx.197...
telnet: connect to address xxx.xxx.xx.197: Connection refused
telnet: Unable to connect to remote host
Is there any other gray-area to cover?
You need a NAT rule (to direct the traffic) and a regular firewall rule (to permit it).
The former will look something like
The latter will look something like
It's up to you to make sure those come at the right point in your existing
PREROUTING
andFORWARD
chains, and in addition you may need a second firewall rule to permit the back-half of those connections out, if you don't already have a generalACCEPT
forESTABLISHED
packets.Edit: the order of your rules is extremely important. The right rule in the wrong place will do no good. Could you replace the grep output above with the result of
iptables -L -n -v
andiptables -t nat -L -n -v
? And if you want port 4444 to be forwarded, don't run a local sshd also bound to that port.Edit 2: and there's your problem. The ACCEPT you've added in the FORWARD chain is line 7, but line 4 has already explicitly denied all not-previously-permitted traffic from everywhere (
*
) tovirbr0
. You need to make arrangments for the line you've added to come before line 4, perhaps by adding the rule withwhich will insert it at line 4, displacing the current line 4 to be line 5 (and so on).
Regarding the current sshd, I mean what I said: that you shouldn't have a daemon bound to port 4444 if you're trying to forward that port. I don't care what other ports it's bound to, only that 4444 is a bad idea.
Edit 3: the machine you're testing this from, this is completely outside the serv05 system, yes? And (after a very trying day putting Fedora 16 on several boxes) I fear you may be right, could you put a comparable
ACCEPT
rule for 4444 in the INPUT chain as well, being careful to get it before any REJECTs?