In this article, I discussed a setup to use pubnix to reliably surface LAN hosts SSH access, via port forwarding and the use of AutoSSH.
Directly allowing ssh access to a home network machine can be risky. I used to do that. At first, I noticed frequent password guessing attachs in the logs. Later I made two mitigations. One is changing the ssh port off of 22. The other is using sshguard to ban attachers after some failures. While that worked out fine, the biggest security risk remains - that my machine is directly accessible through the internet.
I don’t think there is ever a perfect solution to it. But I found
using ssh reverse port forwarding (-R
) can effectively
reduce the risk surface. On top of that, I’ve found the use of
autossh
has been a success - it is surprisingly reliable.
Therefore, I’m sharing this setup with you all.
Here’s an explain of the reverse port forwarding:
On host HOME, we start ssh to PUBNIX:
ssh -R 4444:localhost:2222 PUBNIX
^ ^ ^
| | |
| | `- host port
| `- host (forwarded to) (name resolved on local)
`- remote port (listened to (on remote side))
-R [bind_address:]port:host:hostport
Specifies that the given port on the remote (server) host is to be forwarded to the given host and port on the local side. This works by allocating a socket to listen to port on the remote side, and whenever a connection is made to this port, the connection is forwarded over the secure channel, and a connection is made to host port hostport from the local machine.
Note that the host
is resolved locally, thus
localshot
refers to HOME.
.-----------. .--------.
| HOME | | PUBNIX |
| (1) ssh ----------------------- > |
| | | |
| (2) 2222 <<<<<<<<<<<<<<<<<<<<<<| 4444 <---------- SSH Client
| (sshd)| .---------.
.------------
AutoSSH starts and monitors an ssh connection, and tries to reconnect if it terminates. Some unix distro may provide a service for it, but I found it works well enough to as a crontab.
@reboot AUTOSSH_DEBUG=1 autossh -M0 -fN -o ServerAliveInterval=15 -o ServerAliveCountMax=3 -o ExitOnForwardFailure=yes -R 4444:localhost:2222 user@pubnix.org
Once we have LAN_HOST_A
surfaced, we can make use of ssh
config’s proxyjump
feature to surface multiple LAN
hosts.
.-----------. .--------.
LAN_HOST_B.... | LAN_HOST_A| | PUBNIX |
. | (1) ssh ----------------------- > |
............| | | |
LAN_HOST_C...............| (2) 2222 <<<<<<<<<<<<<<<<<<<<<<| 4444 <---------- SSH Client
proxyjump | (sshd)| .---------.
.------------
In a client’s ~/.ssh/config
, where we want to access a
deeply buried LAN host (e.g., LAN_HOST_B
):
host PUBNIX
hostname example.pubnix.com
user xxx
host LAN_HOST_A
hostname localhost
port 4444
proxyjump PUBNIX
host LAN_HOST_B
hostname 192.169.0.xxx
proxyjump LAN_HOST_A
host LAN_HOST_C
hostname 192.169.0.yyy
proxyjump LAN_HOST_A
Note that the awesome fact that proxyjump can be chained, e.g.,
LAN_HOST_B <-- LAN_HOST_A <-- PUBNIX
I have this setup working for months and it is very reliable.