On the machine A:
ssh -L 3307:C:3306 user@B
This allocated a socket listen to port 3307 on A. And whenever a connection is made to this port, it is forwarded over ssh tunnel to C:3306.
You can then connect to MySQL server on C with:
mysql -u <user> -p -h 127.0.0.1 -P 3307
(127.0.0.1 to connect via TCP/IP instead of a socket)
No, I cannot connect to MySQL on C from B. Only SSH listening on 21343
is open to B.
If the firewall on C only allow to connect from localhost, something like this:
iptables -A INPUT -p tcp -s 127.0.0.1 --dport 3306 -j ACCEPT
iptables -A INPUT -p tcp --dport 3306 -j DROP
so, AFAIK, there is no way to do this. If you try to connect over ssh tunnel, you will get the below errors:
ERROR 2013 (HY000): Lost connection to MySQL server at 'reading initial communication packet', system error: 0
You need a NAT rule (to direct the traffic) and a regular firewall rule (to permit it).
The former will look something like
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 4444 -j DNAT --to-destination 192.168.122.50:22
The latter will look something like
iptables -A FORWARD -i eth0 -p tcp --dport 4444 -j ACCEPT
It's up to you to make sure those come at the right point in your existing PREROUTING
and FORWARD
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 general ACCEPT
for ESTABLISHED
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
and iptables -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 (*
) to virbr0
. You need to make arrangments for the line you've added to come before line 4, perhaps by adding the rule with
iptables -I FORWARD 4 -i eth0 -p tcp --dport 4444 -j ACCEPT
which 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?
Best Answer
The "only" way we can make a port forward using KVM (libvirt) with the "default network" (virbr0) is using the hack/workaround informed by @Antony Nguyen . Or more simply you can use libvirt-hook-qemu.
This thread has a complete explanation of how to solve this problem for CentOS 7 (and certainly for other distros) using libvirt-hook-qemu: https://superuser.com/a/1475915/195840 .