Reverse SSH proxy with SystemD

You have a really shitty ISP (Internet Service Provider) and have no way to port forward, or are behind 10,000 billion firewalls and NAT things. Do you cry, or do womething with it? If you want to have your Home / ServerRoom / AnyOtherCrapLocation accessible and do not have to administer a shitload of users, then

First, unfortunately, you need a server well outside, out there, in the internet.

Try out ($5 / month) or (1€ / month) and set up a server, that you can connect to, from within your alcatraz environment. Or (mis)use a friend, that has one. 

We’ll call this host “freetown”


Second, you need a constantly running machine inside your impenetrable environment

Buy a raspberry, honestly. You can use a laptop, or a table PC, but it just consumes a lot of energy. RasPi is quite OK for this kind of applications. Consumption is well below 500mA at 5V. Which translates to 2.5W at peak usage (60Wh a day -> 21.915kWh / year). The cost? Something around $4 a year.

This will more likely be a 15kWh / year, based on usage – $3?. Cool, for comparison, a very decent, new fridge consumes 280 kWh / year. 

Use a Raspbian image to boot it, as this section covers systemd services.

We shall call this host “alcatraz”

Third, you need to set it up, so there is absolute trust and security.

This is kinda tricky, best left to somebody that keeps up with all the security stuff daily (mind you, I am an IT guy myself, but cannot keep track of that all the time)

alcatraz needs to see freetown. (even a cell window is fine)

pi@alcatraz:~ $ ping freetown
PING freetown ( 56(84) bytes of data.
64 bytes from ( icmp_seq=1 ttl=45 time=134 ms
64 bytes from ( icmp_seq=2 ttl=45 time=129 ms
64 bytes from ( icmp_seq=3 ttl=45 time=133 ms
64 bytes from ( icmp_seq=4 ttl=45 time=129 ms
64 bytes from ( icmp_seq=5 ttl=45 time=135 ms
--- freetown ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4005ms
rtt min/avg/max/mdev = 129.408/132.570/135.527/2.613 ms

The prisoner at alcatraz which was put there by the guards (root)…

pi@alcatraz:~/$ sudo -i
root@alcatraz:~/$ useradd prisoner -m -s /bin/bash
root@alcatraz:~/$ id prisoner
  uid=1002(prisoner) gid=1002(prisoner) groups=1002(prisoner),100(users)

needs a new identity in freetown… he must know some people, though, the sshusers

user@freetown:~/$ sudo -i
root@freetown:~/$ useradd freeman -m -s /bin/bash -G sshusers
root@freetown:~/$ id freeman
uid=1003(freeman) gid=1004(freeman) groups=1004(freeman),1001(sshusers)

And of course the prisoner needs keys to freetown, and they need to know him in freetown.

a, generate keys

prisoner@alcatraz:~ $ ssh-keygen 
Generating public/private rsa key pair.
Enter file in which to save the key (/home/prisoner/.ssh/id_rsa): 
Created directory '/home/prisoner/.ssh'.
Enter passphrase (empty for no passphrase): 
Enter same passphrase again: 
Your identification has been saved in /home/prisoner/.ssh/id_rsa.
Your public key has been saved in /home/prisoner/.ssh/
The key fingerprint is:
SHA256:TWUqY15gsY/Xc6o1Be3gBR1YnfWPxEBYZjs9qRE5G2o prisoner@plutonium-dev
The key's randomart image is:
+---[RSA 2048]----+
|        +. +@=oo+|
|   .   o.*  =O.oo|
| =        +.*+O .|
|      o OEo.X o. |
|    S.+   = = .  |
|     . =         |
|     +           |
|   o      .      |
|  .              |

b, distribute keys

First, list the pulic key generated in alcatraz

prisoner@alcatraz:~ $ cd .ssh
prisoner@alcatraz:~/.ssh $ cat 
ssh-rsa AAAAB3mcoisdjcnXw[spldm0923jdlksmKLJmHRU//xH1VCt+/Ep5G1gXZqYFLaoWyh2tM6xnu9CJCIJp9aEkojsdfoijOIJjkosndfoijqwMI7Oc/fbZ9Mps3lctuq2ciAiejuoKfW7HKL33jHxOl77uehSLUrxJu9uY5bW0GFqz5CyCHuW5SNrKU2Avf1et644uKqde4ihlkms9qmwdlkmLKNLIJFwknmsfeBQD prisoner@alcatraz

and let it be known in freetown

freeman@freetown:~$ echo 'ssh-rsaAAAAB3mcoisdjcnXw[spldm0923jdlksmKLJmHRU//xH1VCt+/Ep5G1gXZqYFLaoWyh2tM6xnu9CJCIJp9aEkojsdfoijOIJjkosndfoijqwMI7Oc/fbZ9Mps3lctuq2ciAiejuoKfW7HKL33jHxOl77uehSLUrxJu9uY5bW0GFqz5CyCHuW5SNrKU2Avf1et644uKqde4ihlkms9qmwdlkmLKNLIJFwknmsfeBQD prisoner@alcatraz' >> /home/callhome/.ssh/authorized_keys

is it there?

freeman@freetown:~$ cat /home/callhome/.ssh/authorized_keys
ssh-rsaAAAAB3mcoisdjcnXw[spldm0923jdlksmKLJmHRU//xH1VCt+/Ep5G1gXZqYFLaoWyh2tM6xnu9CJCIJp9aEkojsdfoijOIJjkosndfoijqwMI7Oc/fbZ9Mps3lctuq2ciAiejuoKfW7HKL33jHxOl77uehSLUrxJu9uY5bW0GFqz5CyCHuW5SNrKU2Avf1et644uKqde4ihlkms9qmwdlkmLKNLIJFwknmsfeBQD prisoner@alcatraz

Yep, good to go, the prisroner now has free access to freetown

c, test it out

The connection:

prisoner@alcatraz:~ $ ssh freeman@freetown

The tunnel:

prisoner@alcatraz:~ $ ssh -R 5013:localhost:22 freeman@freetown
freeman@freetown:~ $ ssh prisoner@localhost -p 5013

The authenticity of host '[localhost]:5013 ([]:5013)' can't be established.
ECDSA key fingerprint is aa:77:22:4e:11:3e:16:f0:4c:xy:bc:ad:24:9a:94:bb.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added '[localhost]:5013' (ECDSA) to the list of known hosts.
prisoner@localhost's password:
Linux plutonium-dev 4.9.41-v7+ #1023 SMP Tue Aug 8 16:00:15 BST 2017 armv7l

The programs included with the Debian GNU/Linux system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Debian GNU/Linux comes with ABSOLUTELY NO WARRANTY, to the extent
permitted by applicable law.
Last login: Mon Jan 8 13:12:46 2018 from

Tadaaa, now let’s get the SystemD service running…


Fourth, you’ll need to set up a systemd service on the insider / alcatraz (Raspberry PI), FINALLY

For this, just switch to root

pi@alcatraz:~/$ sudo -i

and create a file in /etc/systemd/system/freedom.service. You can name it any name you want (anything.service), just make a note what it is.

root@alcatraz:~/$ echo '
Description=Forward local SSH port to remote host

# SSH connection uses the private key stored in this
# users home dir (~/.ssh/)

# SSH connection with port forwarding
# Forwards local port 22 to port 1234
ExecStart=/usr/bin/ssh -o StrictHostKeyChecking=no -o UserKnownHostsFile=/dev/null -o ServerAliveInterval=20 -o ServerAliveCountMax=1 -o ExitOnForwardFailure=yes -N -T -R1234:localhost:22 freeman@freetown

# wait 60 seconds before trying to restart the connection
# if it disconnects 

# keep retrying no matter what

' > /etc/systemd/system/freedom.service

Service would love to be started right after boot

root@freetown:~# systemctl enable freedom 
Created symlink from /etc/systemd/system/ to /etc/systemd/system/freedom.service.

Before you reboot, just for… just because…

root@alcatraz:~/ systemctl start freedom 

check how it went

root@alcatraz:~/ sudo journalctl -u freedom 
  Jun 25 18:03:00 alcatraz systemd[1]: Starting SSH reverse tunnelling... 
  Jun 25 18:03:00 alcatraz systemd[1]: Started SSH reverse tunnelling. 
  Jun 25 18:03:01 alcatraz ssh[23582]: Warning: Permanently added 'freetown' (ECDSA) to the list of known hosts.

Fifth, go for it

As it goes, most of the people want business. And smuggling stuff into prisons is a very profitable business – and this whole exercise was nothing else. 

So, we want to be able to access alcatraz from our freetown on the internet, via the tunnel that the prisoner user dug out for us. Well, let’s do it. 

It starts in freetown (localhost) on the port 1234 and exits in alcatraz on port 22 (default ssh port)

The freetown user can be any kind of user that is able to execute ssh. In alcatraz, you are able to reach any user (prisoner or ward) that is defined on the prison system.

user@freetown:~$ ssh prisoner567@localhost -p 1234

A final note on port forwarding and ssh tunneling

As non-priviledged ports cannot be opened by other users than root, it is quite a struggle to have reasonable “standard” port forwarded anywhere. If you wish to establish a tunnel between 2 servers, using standard users AND have ports with a number lower than 1000 tunneled, you better prepare a two step approach. 

Create a tunnel on a non-priviledged port:

The is the ip address and port the tunnel listens to on freetown, the later portion is the host:port in local network, confused?

prisoner@alcatraz$: ssh -R freeman@freetown 

On the “outside” or “freetown” system, enable port forwarding as root (here you need to be root, albeit just once, not ssh root enabled):

This takes whatever comes in on port 443 (https) on freetown host and will redirect it to port 4433 (which is sucked in through a tunnel and ends up in alcatraz)

iptables -t nat -I PREROUTING -p tcp --dport 443 -j REDIRECT --to-ports 4433
# list out entries...
iptables -t nad -L

Leave a Reply

Your email address will not be published. Required fields are marked *