title: Firewall magic with nftables: how to redirect all ports to one port --- pub_date: 2019-11-07 --- author: ungleich --- twitter_handle: ungleich --- _hidden: no --- _discoverable: yes --- abstract: How to redirect traffic from all (tcp/udp) ports to another port. And why one would want to do that... --- body: ## Motivation Sometimes networks (like hotels or airports) block or filter outgoing traffic and thus prevent you to connect to where you want to connect to. Here at [ungleich](https://ungleich.ch) we are travelling quite a lot, but we always want to be able to access the servers of [Data Center Light](https://datacenterlight.ch), so that we can maintain them from everywhere in the world, so we needed a way to ensure that we have some way of connecting to them, even if the network disallows traffic to the ssh port (tcp/22). ## A solution based on nftables As you might know we are [big fans of nftables](https://ungleich.ch/de/cms/ungleich-blog/2018/08/19/iptables-vs-nftables/) and this hotel/airport problem motivated us to once again checkout what we can achieve just with nftables. Typically these networks will still allow outgoing traffic on *some ports*, but we don't know *which ports*. So instead of guessing which port we should bind SSH to, we will just use nftables to make ssh available on *all TCP ports*. Simple idea, isn't it? ## How it works To achieve our goal we need to tell nftables to take the traffic that goes to any port that is not our target port, to be redirected to our target part. If you have other services running on the host, you might want to adjust this logic though (see below). The following nftables snippet will already do the job: ``` flush ruleset table ip nat { chain prerouting { type nat hook prerouting priority 0; tcp dport != 22 redirect to 22 } chain postrouting { type nat hook postrouting priority 0; } ``` You can save this as nftables.conf and run ``` nft -f nftables.conf ``` to see it working on your system. After applying this, we can use `ssh -p ` to choose any port and connect to our server: ``` ssh -p 80 serverX.placeY.ungleich.ch ``` ## Using specific ranges or ports only If you have other services running on the system, you might want to restrict the ports to be used for ssh. You can either use **sets** (nftables syntax: *{ a, b, c, ... }*) or **intervals** (nftables syntax: *X - Y*) as follows. ``` tcp dport 2000-4000 redirect to :ssh tcp dport {23, 25, 80, 443 } redirect to :ssh ``` (just replace the *tcp dport != ...* line above)! ## "Good ports" Over time you will see that there are some ports which are more likely to be open, even if the network filters your traffic. Some well known ports for this are: * 80: regular http traffic * 53: DNS, uses UDP by default, but TCP is also part of the standard * 443: usually has encrypted https traffic * 783: smtp submission port for sending out emails Of course, if the filtering uses deep packet inspection, this will fail, but then there are other solutions for that... stay tuned!! ## More of it? If you are interested in more of this, we invite you to join our [open infrastructure chat on chat.ungleich.ch](https://chat.ungleich.ch).