I'm trying to do an ssh tunnel into a server behind NAT:

ssh from laptop --> Host with port forwarding in firewall --> Get directly into guest (, behind host NAT).

Using iptables on Host - it will work:

# iptables -I OUTPUT  -d -j ACCEPT
# iptables -I FORWARD  -d -j ACCEPT
# iptables -I INPUT  -d -j ACCEPT
# iptables -t nat -I PREROUTING -d -p tcp --dport 222 -j DNAT --to-destination

However, iptables are not saved on Host reboot, since firewalld service is running (firewalld is the default in RHEL 7).

So I'm trying to do the same port forwarding with firewall-cmd.

Using firewall-cmd on Host - it will NOT work:

# firewall-cmd --permanent --zone=public --add-forward-port=port=222:proto=tcp:toport=22:toaddr='
# firewall-cmd --permanent --zone=public --add-masquerade
# firewall-cmd --permanent --direct --add-rule ipv4 filter FORWARD 0 -d -j ACCEPT
# firewall-cmd --permanent --direct --add-rule ipv4 filter OUTPUT 0 -d -j ACCEPT
# firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -d -j ACCEPT

# firewall-cmd --permanent --direct --add-rule ipv4 nat PREROUTING 0 -d -p tcp --dport 222 -j DNAT --to-destination

# firewall-cmd --permanent --add-rich-rule='rule family="ipv4" source address="" forward-port port="222" protocol="tcp" to-port="22" to-addr='""

# firewall-cmd --reload

# firewall-cmd --list-all

public (active)
  target: default
  icmp-block-inversion: no
  interfaces: enp4s0f0
  services: ssh dhcpv6-client
  ports: 8139/tcp
  masquerade: yes
  forward-ports: port=222:proto=tcp:toport=22:toaddr=
  rich rules: 
     rule family="ipv4" destination address="" forward-port port="222" protocol="tcp" to-port="22" to-addr="" 

# firewall-cmd --direct --get-all-rules

ipv4 filter INPUT 0 -d -j ACCEPT
ipv4 filter OUTPUT 0 -d -j ACCEPT
ipv4 filter FORWARD 0 -d -j ACCEPT
ipv4 nat PREROUTING 0 -d -p tcp --dport 222 -j DNAT --to-destination

Now, when trying to connect to the guest - from my laptop, via host port 222 - the ssh connection is refused:

ssh -l stack my-host -p 222
ssh: connect to host my-host port 222: Connection refused

Any idea what am I missing ?

  • Your first three rules effectively disable all firewalling. Why have you put these rules in place? – Michael Hampton Sep 7 '18 at 12:05
  • @MichaelHampton - I tried everything that could make this ssh tunnel work via firewalld, and as you see, even those first three rules did not open the tunnel. – Noam Manos Sep 20 '18 at 8:59
  • I've open bugzilla 1590924 for this issue. – Noam Manos Sep 20 '18 at 9:17
  • Did you ever come to a resolution? I see the bug doesn't have one noted either. – flickerfly Jul 3 at 21:13
  • 1
    @flickerfly - not yet, I'm still using iptables directly, and try to avoid reboots (that requires reset of iptables) – Noam Manos Jul 18 at 22:36

You could try firewall-cmd --add-forward-port:

firewall-cmd --permanent --add-forward-port=port=222:proto=tcp:toaddr=172.x.x.x:toport=22
firewall-cmd --reload

General syntax (https://firewalld.org/documentation/man-pages/firewall-cmd.html):

firewall-cmd [--permanent] [--zone=zone] \
 --add-forward-port=port=portid[-portid]:proto=protocol[:toport=portid[-portid]][:toaddr=address[/mask]] \
  • 1
    I did try that, it's already included in my steps above - It doesn't work (Connection refused when trying to ssh to port 222). – Noam Manos Sep 20 '18 at 9:13

Have faced a similar issue personally and this solution has come to my rescue. Please give it a try and let me know if it helped.

There are few ways to access a server behind NAT: Port forwarding, you can configure the router/firewall to forward the incoming traffic to an internal server. Usually, you need to specify the Protocol (UDP/TCP), External Service Port, and Internal Service Port.

For the ssh port forwarding with firewall-cmd, please try this command:

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 222 -j DNAT \--to 172.x.x.x.:22 

From the given code, I kind of understand that this is what you are trying to achieve. So, please make sure to check the port. In my case, I have tried the same with port 80.

This rule specifies the NAT table to use the built-in PREROUTING chain to forward incoming HTTP requests exclusively to the listed destination IP address

  • 2
    Thanks @james, that's an "iptables" command, not "firewall-cmd". I can achieve ssh tunnel with iptables, but not with firewalld. – Noam Manos Jun 14 '18 at 19:11

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.