This post falls squarely into the category of one of those things you spend the best part of a day working out how to set up, but once it’s working won’t touch again for at least 6 months, by which time you’ll have forgotten almost everything about it.

The Problem

Setting up port forwarding for ssh using ufw on ubuntu.


At the office we’ve got an ssh service running on a non-standard port (GitLab). From the WAN side of things this is dealt with simply by using NAT port redirection on the router.

For reasons, on the LAN side of things we require a server to do the same job and forward ssh traffic to GitLab.

The prospect of dealing with iptables directly and getting persisting / loading rules to work was faintly terrifying, so since this is a ubuntu box ufw seemed a good way to go.

The Solution

There were three main components to getting ssh port forwarding working. The time consuming bit of getting this working in the first place was that no single guide had all of these in the same place.

Here’s a quick breakdown of the network setup I’m assuming for the example settings & commands that will follow,

target ip = 192.168.1.50
target port = 4222
source port = 4222
network interface name = eth0

1. Enable port forwarding

Edit /etc/sysctl.conf and enable IPv4 port forwarding. Uncomment or add the line,

net.ipv4.ip_forward=1

and then run sysctl -p to apply the change.

2. Set up the forwarding rule

This bit can’t be done via the ufw cli so we add iptables rules directly to a ufw config file and they’ll get applied when ufw loads.

Edit /etc/ufw/before.rules

*nat
:PREROUTING ACCEPT [0:0]
:POSTROUTING ACCEPT [0:0]

# Forward GitLab ssh traffic from port 4222 on this machine to port 4222 on 192.1.50 
-A PREROUTING -i eth0 -p tcp --dport 4222 -j DNAT --to-destination 192.168.1.50:4222
-A POSTROUTING -s 192.168.1.0/24 -o eth0 -j MASQUERADE
COMMIT

This needs to go before the *filter section.

Restart the ufw service.

3. Create a rule to allow the forwarded traffic

With steps 1 and 2 done ufw will still block the traffic we’re trying to forward to our target machine (If you’re testing at this point you should be able to view the traffic being blocked in /var/log/ufw.log). One more rule is needed to allow this traffic through - this was the final part of the puzzle for me that was absent from the majority of the guides I found.

We can set up this rule with the ufw cli,

ufw route allow in on eth0 to 192.168.1.50 port 4222 proto tcp

Allow all traffic coming in on eth0 that’s going out to 192.168.1.50:4222

It would probably make sense to add a from clause to restrict the inbound traffic to a particular subnet

With that ssh port forwarding was working and it was possible to perform a git clone over ssh from inside the LAN again 👍

References

The various sites I used to put together a solution that worked for me. You’ll probably find them to be much more informative than this post.