title: How to redirect all ports to one port with nftables
---
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).

To be able to do so from anywhere in the world, we needed to
ensure that we have some way of connecting to them, even if the
network filters traffic to the ssh port (tcp/22).

While our main motivation was to enable ssh, the example below can be
adjusted to any service, including http, https, smtp, ...

## 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 <port>` 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)!

## A note on 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).
