Skip to content

Instantly share code, notes, and snippets.

@ViRb3
Last active September 28, 2019 23:13
Show Gist options
  • Save ViRb3/910ec66669dfd5301427dccf624d52de to your computer and use it in GitHub Desktop.
Save ViRb3/910ec66669dfd5301427dccf624d52de to your computer and use it in GitHub Desktop.
Set up a Linux box as reverse tunnel

I got my Raspberry Pi 3. I hooked it up to my university's Wi-Fi... and then realized - I have no way to SSH into it. Or connect to it at all. The university does not maintain a client-to-client network, and of course, you cannot port-forward. I tried some third-party solutions (ngrik, remot3.it), and while they worked, I wanted something free, unlimited, with my own static domain, which was also very fast. Given I already have a VPS, I turned it into a reverse tunnel to my RPi3.

General diagram

[‾‾‾‾‾‾‾‾]     SSH request    [‾‾‾‾‾‾‾‾]     SSH request    [‾‾‾‾‾‾‾‾]
|        |  --------------->  |        |  --------------->  |        |
| Anyone |      port 6000     |   VPS  |       port 22      |  RPi3  |
|        |                    |        |                    |        |
|        |     SSH response   |        |     SSH response   |        |
[________]  <---------------  [________]  <---------------  [________]
                port 6000                      port 22

Tutorial

1. Create a connection between the VPS and the RPi3

Due to the above limitations, I created a virtual network using OpenVPN. This way, the VPS can pass all traffic through this internal network. I used the following fantastic script to set up the server. You may want to modify it so it doesn't touch your iptables, since internet forwarding won't be required. I then connected the two computers and made sure they see each other by pinging each other's internal IPs. It is also very important to set a static IP for the RPi3 in this virtual network. In my case, that is: 10.8.0.100

2. Enable IP Forwarding in the VPS

This tells the computer that it should pass along any traffic that is meant for a different computer on its network.

We modify /etc/sysctl.conf:

net.ipv4.ip_forward = 1

and force a configuration reload:

sysctl -p

or simply:

echo 1 > /proc/sys/net/ipv4/ip_forward

3. Set up routing rules in the VPS

I opted for ufw, but you can do the same with bare iptables, since the commands are the same.

We add the rules under /etc/ufw/before.rules:

# PART 1/2
*nat
-A PREROUTING -p tcp --dport 6000 -j DNAT --to-destination 10.8.0.100:22
-A POSTROUTING -d 10.8.0.0/24 -j MASQUERADE
COMMIT

The first rule takes any traffic on port 6000 and re-writes it so its destination becomes 10.8.0.100 (the RPi3) on port 22.

The second rule MASQUERADEs all traffic in the subnet of the virtual network (10.8.0.XXX). This does 2 things:

  • Re-write outbound traffic to originate from the VPS
  • Re-write inbound traffic to reach the original client

We also have to allow the now redirected traffic to be forwarded, since, by default, UFW blocks all forwarding. You can insert the following rule to the already existing filter section, or make one yourself (remember to COMMIT!):

*filter
    .
    .
# PART 2/2
-A FORWARD -p tcp --dport 22 -j ACCEPT
    .
    .
COMMIT

And you're done!

Trigger a ufw reload and use port 6000 on the VPS to access SSH on the RPi3. You can use this same method for any other port and service as well.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment