Connect to home via ssh
2024-05-11 09:55 WIB - Hendrik Lie
Problem
The problem with a normal home network is that it is hidden behind a NAT. Moreover setting up port forwarding is not exactly trivial for end-user. Therefore, since we have a readily accessible remote server, we can leverage it for our purpose.
Solution
Basically now there are three devices under our control: -
homecomputer - mymobile -
cloudserver
We can then configure cloudserver as a bridge, as we are
in control with it. That way we can, configure a ssh reverse tunnel
homecomputer > cloudserver connection, and also another
ssh reverse tunnel to mymobile > cloudserver . Then we
should also create their corresponding ssh tunnels:
homecomputer < cloudserver and
mymobile < cloudserver.
SSH tunnel from home and phone to cloud
From homecomputer we can issue:
ssh -R 2222:localhost:22 \
-L 2223:localhost:2223 \
user@cloudserver
Here’s how it works:
- The
-Rargument tellshomecomputerto: expose port22onlocalhost, and any connection fromcloudserverport2222should be accepted by our exposed port. - The
-Largument tellshomecomputerto: tunnel any connection made tolocalhost:2223into port2223oncloudserver.
Then we just have to configure the reverse from
mymobile:
ssh -R 2223:localhost:8022 \
-L 8023:localhost:2222 \
user@cloudserver
SSH tunnel between home and phone with cloud as a bridge
This way, from homecomputer to mymobile, I
just have to run:
ssh -p 2223 localhost
And from mymobile to homecomputer, I just
have to run:
ssh -p 8023 user@localhost
Even better, we should consider also adding -TNv
argument to ssh.
Automatic configuration on home
Like the one we write in SSH proxy as
VPN replacement, we can actually configure them as a systemd/user
service:
# file ~/.config/systemd/user/remote-tunnel.service
[Unit]
Description=SSH tunnel to domain.tld
[Service]
Type=simple
Restart=always
RestartSec=10
ExecStart=/usr/bin/ssh -F %h/.ssh/config -N remote-tunnel
[Install]
WantedBy=default.targetThis service will be run after user logs in to a session. It will be killed after the last session of that user is closed. If we want it to start at boot and would remain be open after the last session of a user is closed, we can let our service to linger:
loginctl enable-linger
Then we write a configuration file as follows:
# file ~/.ssh/config
# Equivalent to:
# ssh \
# -R 2222:localhost:22 \
# -L 2223:localhost:2223 \
# -D 8257 \
# user@cloudserver
Host remote-tunnel
User user
HostName domain.tld
LocalForward 2223 localhost:2223
RemoteForward 2222 localhost:22
DynamicForward 8257
ServerAliveInterval 120It would then enable us to establish the tunnel (bonus the proxy port) as soon as we login into our account. Then connection to phone is as simple as:
Automatic configuration on phone
I use termux on my phone. From my phone, we can also set a configuration file:
# ssh -R 2223:localhost:8022 \
# -L 8023:localhost:2222 \
# user@domain.tld
Host remote-tunnel
User user
HostName domain.tld
LocalForward 8023 localhost:2222
RemoteForward 2223 localhost:8022
ServerAliveInterval 120Therefore we can just do this to initiate connection:
It can be done with the same tmux setup described in the
SSH proxy as
VPN replacement article. Then to connect to our computer, we
invoke:
Conclusion
The pattern is then:
ssh -R port:localhost:hostport \
-L localport:localhost:remoteport \
[user@]remotehost
Note that localhost in -L part is actually local to
remotehost, not our localhost. Then for [user@]remotehost
part, it means that the username is optional. If the username is not
given, and only remote host is specified, ssh client will attempt to
connect to the remotehost with the same username as the local computer’s
username.
The map from homecomputer is then:
localhost:22 listens from cloudserver:2222
localhost:2223 forwarded to cloudserver:2223
The map from mymobile is then:
localhost:8022 listens from cloudserver:2223
localhost:8023 forwarded to cloudserver:2222
The map from cloudserver is then:
localhost:2222 to homecomputer:22
localhost:2223 to mymobile:8022
localhost:2223 from homecomputer:2223
localhost:2222 from mymobile:8023
Appendix
In an afterthought, we realized that we don’t really need to connect to and from our phone with this method most of the time. At home, we would prefer to connect to the phone via our home’s local network, simply because it’s much faster. Conversely, at work, we would prefer to connect to the phone via our work’s local network.
We would only need to connect to our home computer from our phone when we’re outside and our phone is not in the same network as our work computer. Even then when it does happen, our work computer would not be normally connected to our home computer.
It means our phone really only need to connect to home computer when
we explicitly told it so. Therefore, our work computer can use a similar
~/.ssh/config as our phone, plus we can set up a
systemd/user service.
At such event where we are outside and our work computer are also on,
we can always connect to our home computer with extra steps from our
phone: go to cloudserver, and then
ssh -p 2222 user@localhost will serve the job well.
SSH tunnel between home and office
We put the following in our office’s ssh
configuration:
# file ~/.ssh/config
Host remote-tun
User user
HostName domain.tld
LocalForward 8022 localhost:2222
RemoteForward 2223 localhost:22
DynamicForward 8257
ServerAliveInterval 120
Host home
User user
HostName localhost
Port 8022
ServerAliveInterval 120Then we set up a systemd user service at work:
# file ~/.config/systemd/user/tunnel.service
[Unit]
Description=SSH tunnel to domain.tld
[Service]
Type=simple
Restart=always
RestartSec=10
ExecStart=/usr/bin/ssh -F %h/.ssh/config -N remote-tunTherefore we can connect to our home computer with:
$ ssh home
Further reading
Read more from the sources below: