Bypass Network Lockdowns
I manage the network infrastructure for a robotics club on campus. Unfortunately, the campus network has been heavily locked down for security. It takes years to get Information Services and Technology (IST) to agree to forward a port, and it’s even harder for student clubs.
Our club members need access to the robot through the open internet. This is especially important for new members who aren’t able to access the club’s room after hours.
Due to this, I’ve put considerable effort into bypassing the restrictions placed by the university. As it turns out, once you know what you’re doing, it’s pretty easy! All you need is outward access to the internet, from there you can easily get inward access to any port.
ZeroTier One
The easiest method, and probably recommended for most users, is using Software Driven WAN (SDWAN). This is similar to a VPN, but unlike Wireguard, ZeroTier One doesn’t1 require a centralized server.
Advantages:
- Very simple setup
- Very low latency through UDP hole-punching
- Free (for up to 25 clients)
Drawbacks:
- Requires installing separate software on all clients
- Sometimes fails to connect for up to an hour… very hard to debug when it happens
- Can only be used by clients on the VPN. For example, a public webserver won’t be able to use this
- Limit of 25 clients (on the free version)
To use ZeroTier:
- Sign up for an account at zerotier.com
- Under “Networks” create a network and give it a name. Ensure Access Control is private.
- Install ZeroTier One on all clients you’d like to connect. You can add more later.
- On Linux, start and enable the ZeroTier one daemon with
systemctl enable --now zerotier-one.service
. - Find your network ID in the online console, then join with
sudo zerotier-cli join <network-id>
. - Back in the web console, click the checkmark next to the new client that joined, and give it a name.
- Now
sudo zerotier-cli listnetworks
should sayOK PRIVATE
for your network. - Repeat steps 3-7 for every new client you add.
Now you should be able to use the IP listed in the web console for your device.
This will be in the right column under “Managed IPs”. For example, if your
server has a zerotier IP of 172.27.100.10
another client would be able to
ping 172.27.100.10
or with an ssh daemon running ssh <user>@172.27.100.10
.
[[1]]: ZeroTier One still requires a centralized server, but they have “root servers” which are available to the public for free, so no setup required on our part.
Reverse Proxy
Reverse proxies are a slightly more involved but generally better approach. They use a second computer to forward information to the internal network.
Advantages:
- Can be accessed by the public
- No additional software limits
- No client limits
Drawbacks:
- No UDP hole punching: might have a bit more latency
- Requires a centralized server with a public IP (not necessarily static tho)
To setup a reverse proxy, you’ll need a computer with a public IP, that’s accessible behind the router. You could use your home computer, but it’ll need to always stay on. A more popular approach is grabbing a cheap cloud computer. I personally use the most basic droplets on Digital Ocean for $4/month. Be sure to choose the closest datacenter possible and ideally in the same country, to minimize latency.
I’ll be referring to the computer powering the reverse proxy as the “droplet”, but the steps can easily be applied on your own Linux machine.
Setting up a reverse proxy
- Build the rathole binary that’s compatible with your system. The droplet may require a different llvm target.
- Create a client-side rathole configuration on the server. The token can be
any random string. Assuming the IP of the droplet is
172.27.10.10
and we’re using port9001
, the configuration might look like this:
- Create a systemd service on the server called
rathole_client.service
. Edit the path of yourrathole
executable, and the argument to the config file above:
- On the droplet, create a
server.toml
. It might look something like this, matching theclient.toml
provided in step 2.
- On the droplet, you can simply start rathole manually in a tmux session with
./rathole server.toml
. - On the client run
systemctl enable --now rathole_client.service
Check the output of both commands (systemctl status rathole_client.service
) to
make sure there aren’t any errors. Assuming it’s all good, you should be able to
contract the server through the droplet. For example, if we wanted to ssh into
the emiliko
user on the server, the above config should allow that through:
This will be forwarded to port 22 on the server!
Reverse Proxy without a Static IP
If you’re planning to use a home computer, you’ll quickly find that most internet service providers do not offer static IPs for consumer plans. Luckily, there’s a very simple way around this: Domain Name Servers (DNS).
You will need a domain to achieve this. Domains should not cost more than
$20/year. Here I’ll use the domain example.com
as an example.
The idea is that a domain will point to a specific IP, but this IP is determined through a lookup to the DNS. This means that if we change the IP the DNS has every time our computer’s IP changes, we’ll appear to have a static IP!
First, put your nameservers on a good DNS provider. I use Cloudflare, it’s free and fast. You’ll need to find the DNS page. The URL will look something like:
https://dash.cloudflare.com/<long-project-id>/example.com/dns/records
There, you’ll want to add an “A Record”. The name will be the subdomain. So if
my computer is called mycomputer
and that’s in the name field, it’ll be
accessible at mycomputer.example.com
.
Now you need to identify your IP address. This is your PUBLIC IP address, not
your LOCAL IP address. One easy way to do this is curl -q https://ifconfig.me/ip
.
Make sure “Proxy Status” is OFF. Proxying the connection appears to make this whole idea break down very quickly, so don’t.
With that “A Record” set, try host mycomputer.example.com
to see when the DNS
updates. This can take up to 4 hour, but usually takes under a minute in
practice. With this, you should be able to access your computer using the
domain! Of course, make sure your router’s ports are forwarding to your
computer.
We now need to make your computer update Cloudflare’s DNS, whenever the IP
changes. I use the script below to do this. Fill in the HOST4
, HOST6
,
TOKEN
, ZONE_ID
. The TOKEN
is your Cloudflare application token:
Now we need a systemd-timer to run this script. I run it once every 15 minutes. Please refer to the systemd-timers blog for more information, but breifly I use:
Timer:
Then start it with systemctl enable update_a_record.service
. The name of the
service will be different based on what you called the files.
Now to use this for reverse-proxy purposes, go back to your client.toml
config
and update the remote_addr
:
Multiple Services
Unless you have a lot of funds, you’ll likely only have one server running. However, you may want several “services” running on this one server. This is especially an issue when it comes to websites, as browsers request to port 80 or 443 (https) on the given IP.
Luckily, when a website is requested, he header of that request includes the
domain name that request is going to. For example, I might have example1.com
and example2.com
pointing to the exact same IP address. However, the server
will be able to see if the request is coming for example1.com
or
example2.com
and choose to serve different content.
Nginx is the typical way to do this, but Caddy is much easier to get running. It almost provides extremely simple Let’s Encrypt integration for free https.
Here’s a very basic Caddyfile we use at arvp: