ungleich-staticcms/content/u/blog/nftables-magic-redirect-all.../contents.lr

115 lines
3.2 KiB
Markdown

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 <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)!
## "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).