Work from Home Through P2P Network

by 0xc0000156

After years of being a Windows programmer using VS and some other IDEs, I started to appreciate Vim.

For me, it's still hard to use, but it hasn't changed in decades which now seems to be a good thing.  I became more and more lazy after turning 35.  Plus, combine Vim with Latex - I feel special.

One good thing about Vim is that it's lightweight.  It allows me to work remotely through an SSH terminal.  I can just set up a server at work.  The server doesn't even need a GUI and it keeps on for months.

I have a laptop at work.  For some reason, some laptops don't have Ethernet sockets anymore.  So my laptop can only connect to a Wi-Fi network.  But the IP address is dynamically assigned.  Each time it connects to the Wi-Fi, it may got a new one.  If I want to connect to it from home, there might be a problem.  I thought I could write a script and let it send an email with the new IP address.  Turns out that was too difficult for me.  I also don't want to use remote control software such as TeamViewer because the rendering of GUI is slow.  All I need is an SSH terminal and Vim.

I also have a desktop at work which has a static IP address.  So my goal is to let the laptop connect to my desktop whenever it boots up or whenever it gets a new IP address.  I could simply create a reverse tunnel.

Let's say my laptop's IP address is L.L.L.L and my desktop's IP address is D.D.D.D.  On my laptop, I execute the following command:

laptop$ ssh user@D.D.D.D -R 8888:localhost:22

Where user is my username.  This command says: SSH to D.D.D.D (desktop) as user user.  Once connected, open a TCP port (8888 at the desktop).  All the connections to port 8888 will be forwarded to the laptop's port 22 (which is the SSH port).

Notice that the localhost in this command is quite confusing - it means the laptop.  I can use the laptop's IP address instead, but it kind of defeats the purpose.  (You also can specify any IP address here - connections will be forwarded to it.)

Following this command, I need to type in the password and a shell will be spawned.  Meanwhile, port 8888 is opened, so on my desktop, if I type:

desktop$ ssh localhost -p 8888

It will connect to my laptop.

Now I need this to be done in an automatic way.  First, no typing password.

Step 1

Create authentication SSH-keygen keys on my laptop:

laptop$ ssh-keygen -t rsa

Leave empty for passphrase.  It creates files:

~/.ssh/id_rsa 
~/.ssh/id_rsa.pub

Step 2

Create .ssh directory on desktop D.D.D.D:

laptop$ ssh user@D.D.D.D mkdir -p .ssh

Step 3

Upload generated public-keys to desktop D.D.D.D:

laptop$ cat .ssh/id_rsa.pub | ssh user@D.D.D.D 'cat >> .ssh/authorized_keys'

Step 4

Set permissions:

laptop$ ssh user@D.D.D.D 'chmod 700 .ssh; chmod 640 .ssh/authorized_keys'

O.K., try to login without a password!:

laptop$ ssh user@D.D.D.D

Now, I need this reverse tunnel to be established after the system boots up or to be reestablished whenever the network recovers from a breakdown.  It seems that system daemon is a good choice (I use Ubuntu).

I create the following script on my laptop:

laptop$ sudo vi /etc/systemd/system/sshreversetunnel.service

And add:

[Unit]
Description=SSH Reverse Tunnel
After=network.target

[Service]
Restart=always
RestartSec=20
User=user
ExecStart=/usr/bin/ssh -NT -o ServerAliveInterval=60 -o "ExitOnForwardFailure yes" -R 8888:localhost:22 user@D.D.D.D

[Install]
WantedBy=multi-user.target

To enable and start it:

$ sudo systemctl enable sshreversetunnel
$ sudo systemctl start sshreversetunnel

To update once the config file is changed:

$ sudo systemctl daemon-reload

At this point, you probably already know that I copy and paste from Stack Overflow.  And you probably would ask: why don't you just do your work at your desktop?

What if I don't have a static IP desktop?  Or what if my home and my work don't even share the same network?  There may be several layers of NAT.

To solve this, I need some relay on the Internet that can deliver my connections.  The first thing that comes to my mind is instant messaging or IRC.  Years ago, I tried Google's Gtalk, which used an extended XMPP protocol.  It provided open-sourced library libjingle, gnat.  But, as we all know, Google shut down the Gtalk service.

I needed to find another project or I would have to write an ugly one myself.  After trying several open-source projects that claimed they could do it, I finally found one that worked for me.  It's called Tuntox.  You can learn more about it at their GitHub page: github.com/gjedeer/tuntox.

You can compile it yourself - I didn't.  I downloaded the binary from the Releases tab.  On my laptop:

laptop$ wget https://github.com/gjedeer/tuntox/releases/download/0.0.9/tuntox-x64
laptop$ chmod +x tuntox-x64
laptop$ TUNTOX_SHARED_SECRET=password ./tuntox-x64 -C ./

2018-11-23 03:32:58: [INFO] Tuntox built from git commit 896775c6089baa24edee06e04f5b83c3bb3bef5d
2018-11-23 03:32:58: [INFO] Using 56214 for TCP relay port and 23893-23903 for UDP
2018-11-23 03:32:58: [INFO] Using Tox ID: xxxxxxxxxxxxxxxxxxxxxxxxxx
2018-11-23 03:33:06: [INFO] Connection status changed: An UDP connection has been established

Note:  Replace password with your real password and remember your Tox ID.  Parameter -C ./ indicates that Tuntox will create a file called tox_save under the current directory.  With this file, it will have a fixed Tox ID all the time.

Now from any computer, with this Tox ID, run the following command:

$ TUNTOX_SHARED_SECRET=password ./tuntox-x64 -i xxxxxxxxxxxxxxxxxxxxxxxxxx -L 2222:127.0.0.1:22

2018-11-22 22:46:08: [DEBUG] Server whitelist mode enabled
2018-11-22 22:46:08: [INFO] Tuntox built from git commit 896775c6089baa24edee06e04f5b83c3bb3bef5d
2018-11-22 22:46:08: [INFO] Using 26501 for TCP relay port and 14364-14374 for UDP
2018-11-22 22:46:08: [INFO] Connecting to Tox...
2018-11-22 22:46:16: [INFO] Connection status changed: An UDP connection has been established
2018-11-22 22:46:16: [INFO] Connected. Sending friend request.
2018-11-22 22:46:16: [INFO] Waiting for friend to accept us...
2018-11-22 22:46:30: [INFO] Friend request accepted (A TCP connection has been established (via TCP relay))!

Quite like the previous SSH command, it opens local port 2222.  Open another terminal:

$ ssh localhost -p 2222

Try it out - it works!

Combine it with the system daemon script that we introduced earlier:

[Unit]
Description=SSH P2P Tunnel
After=network.target

[Service]
Restart=always
RestartSec=20
User=user
Environment=TUNTOX_SHARED_SECRET=123123
ExecStart=/home/u/tuntox/tuntox-x64 -D -C /home/u/tuntox/

[Install]
WantedBy=multi-user.target

Now I can connect to my laptop from anywhere, so I can work from home.  Or I get a pretty good backdoor!

Return to $2600 Index