Bonus - Setting up Reverse SSH Tunnels Permanently

From Unofficial Tesla Tech
Jump to navigation Jump to search

Bonus - Setting up Reverse SSH Tunnels Permanently

Completely Optional™, but if you'd like to extend other services (Squid, Postfix, WireGuard,, DaviCal, Cups, Hass, etc) to anywhere remote from the server:

Presumably your system is running systemd, since we are in the 21st Century. So we'll set up to establish reverse SSH tunnels for whatever service you'd like to present remotely.

Create the sleeper User

... a completely non-privileged unlogin-able account to set up and maintain the tunnel;

On BOTH client and server machines:
# useradd -s /usr/sbin/nologin sleeper

On the CLIENT machine:
# ssh-keygen -h -t ed25519 -o -a 100 -v
(We are using the noncompromised and open-source ed25519 encryption algorithm, since we are modern people...)

Enable sleeper's Access to Remote Server

# scp /home/sleeper/.ssh/id_ed25519.pub {serverMachine}:/home/sleeper/.ssh/authorized_keys

On the SERVER machine:
# chown -R sleeper:sleeper /home/sleeper
# chmod 600 /home/sleeper/authorized_keys

On the CLIENT machine:
# usermod -s /usr/bin/sh sleeper
# ssh {serverMachine}

The authenticity of host '{serverMachine} (10.??.??.??}' can't be established.
ED25519 key fingerprint is SHA256:{blah, blah}.
Are you sure you want to continue connecting (yes/no/[fingerprint])? yes
Warning: Permanently added '{serverMachine} (10.??.??.??}' (ED25519) to the list of known hosts.
sleeper@{serverMachine}: Permission denied (publickey,gssapi-keyex,gssapi-with-mic).

Ok login permission was denied on the remote machine because user sleeper there is set to 'nologin'. Let's do the same favor for the local Client machine:

# usermod -s /usr/sbin/nologin sleeper

So now, sleeper on the Client can set up a reverse SSH tunnel from the Server to it.

Set Up systemd File

Create the systemd file so the tunnel is automatically set up on boot. We don't put it in some random place in the filesystem, nor some system directory where it may be stomped on by an update;  as gentlemen we comply with Posix standards and put it in /usr/local/lib/systemd/system/ .

On the CLIENT machine:
# mkdir -p /usr/local/lib/systemd/system
# nano /usr/local/lib/systemd/system/tunnel.target

[Unit]
Description=Tunnel orchestration
After=network.target network-online.target wpa_supplicant.service

Conflicts=rescue.target

[Install]
WantedBy=multi-user.target


Save and close.

# nano /usr/local/lib/systemd/system/tun-{service, for example squid}.service

[Unit]
Description=tunnel for {service}
BindsTo=tunnel.target

[Service]
User=sleeper
ExecStart=/bin/sh -c '/bin/ssh -v -l sleeper -i /home/sleeper/.ssh/id_ed25519 -2 -4 -N -L 3128:127.0.0.1:3128 {Server} sleep 365d'
Restart=always
RestartSec=30
TimeoutSec=15

[Install]
WantedBy=multi-user.target


(of course setting 3128 to your service's port and 'Server' to the server providing it)

Save and close.

# systemctl enable tun-squid.service
# systemctl start tun-squid.service

And Test

# systemctl status tun-squid.service
● tun-squid.service - tunnel for (service)
Loaded: loaded (/usr/local/lib/systemd/system/tun-squid.service; enabled; vendor preset: disabled)
Active: active (running) since Sun 2020-03-29 06:37:43 PDT; 2h 41min ago
Main PID: 2121 (ssh)
Tasks: 1 (limit: 26213)
Memory: 1.5M
CGroup: /system.slice/tun-squid.service
└─2121 /bin/ssh -v -l sleeper -i /home/sleeper/.ssh/id_ed25519 -2 -4 -N -L 3128:127.0.0.1:3128 {Server} sleep 365d

Mar 29 09:01:37 {Client} sh[2121]: debug1: channel 5: new [direct-tcpip]
Mar 29 09:01:37 {Client} sh[2121]: debug1: channel 2: free: direct-tcpip: listening port 3128 for 127.0.0.1 port 3128, connect from 127.0.0.1 port 49802 to 127.0.0.1 port 3128, nchannels 6

Now also on the client make sure you are seeing that service locally like you should:
# lsof -i -n -P
,,, and you should see amongst the services, the saemon ssh listening on your desired port:
ssh 2121 sleeper 5u IPv4 21772095 0t0 TCP 127.0.0.1:3128 (LISTEN)

Hazzah, from now on just point your client processes to 127.0.0.1:{port}

Finally, for convenience I suggest you memorialize a 'listen' command in /etc/profile.d/myprofile

alias listen='lsof -i -n -P |more'