Tired of always having to type that ssh -D ...
command and change your
browser proxy settings to let your connection exit from somewhere else in
the world?
Or, even better, do you want several devices on your LAN to be able to just
send their stuff over the tunnel and beat some stupid geo-fencing even if they
can’t ssh
themselves?
If you have a spare Raspberry Pi (or whatever other linux box), here is a simple way to setup a tiny proxy server for your LAN :)
the aim
As boring as it may sound, I want to be able to watch RaiPlay, the free streaming service of the italian state TV (RAI). They cover a lot of interesting sport events but sadly they make them unavailable to connections coming from outside of Italy.
This is where having ssh
access to a machine in Italy is really handy.
the plan
The plan is easy:
- Set up a permanent ssh tunnel using
autossh
, so that it reconnects upon failure. - Set up a
lighttpd
web server to publish aproxy.pac
file with some proxy rules to use with mobile devices (e.g. route all traffic to*.it
domains through the tunnel).
dependencies
First let’s install what we need:
sudo apt update
sudo apt install autossh lighttpd
Then I assume you have an ~/.ssh/config
entry for your server myserver
,
something that looks like
Host myserver
HostName stocazzo.it
User myuser
I also assume that you have already setup an ssh key for passwordless acces with
ssh-copy-id -i ~/.ssh/id_ed25519.pub myserver
Now let’s go!
autossh
Let’s setup a systemd service for our permanent tunnel, in this way autossh will be automatically started at boot.
First we create the service file
sudo vim.tiny /etc/systemd/system/autossh-myserver-tunnel.service
and fill it with
[Unit]
Description=AutoSSH tunnel service to myserver
After=network.target
[Service]
User=XYZ
Group=XYZ
Environment="AUTOSSH_GATETIME=0"
ExecStart=/usr/bin/autossh -M 0 -o "ServerAliveInterval 30" -o "ServerAliveCountMax 3" -g -D 6666 -T -N myserver
[Install]
WantedBy=multi-user.target
making sure to replace XYZ
with your user name on your RPI and myserver
with
whatever your server is named in your ~/.ssh/config
.
Of course you can always man ssh
to know what all those options do, but a
little explanation doesn’t hurt:
-D 6666
This is where the magic happens: any incoming connection on port6666
is forwarded to the other side of the tunnel.-T -N
These two prevent the opening of a terminal and the execution of any remote command, since we just want to usessh
for port forwarding.-g
This allows remote connections coming from, e.g., other hosts in your LAN to use the tunnel.
Now you can start the service and check its state with the following
sudo systemctl start autossh-myserver-tunnel
sudo systemctl status autossh-myserver-tunnel
If there is any issue you can just stop
it and try again.
If everything is fine, you can enable the service to be run at startup with enable
:
sudo systemctl enable autossh-myserver-tunnel
Now you can test your new proxy from your browser: just go in the proxy settings
(or use something like FoxyProxy on Firefox) and set your home server ip, port
6666
and SOCKS5
as proxy type. Cheers :)
proxy.pac
The proxy.pac
file can be used by devices that support Proxy Auto-Configuration. It contains a javascript function that is inquired with
every browser request and it determines if and what proxy should be used for it
based on the url. More info here.
This file should be made available to devices on the LAN using an http server, such as lighttpd
.
The lighttpd
server should be already enabled and running as a systemd
service.
Let’s just check it with
sudo systemctl status lighttpd
Now let’s assume your home server where this setup is taking place is reachable
on your lan under the address raspberry.local
(or whatever ip address).
Then let’s create and open the proxy.pac
file
sudo vim.tiny /var/www/html/proxy.pac
and let’s fill it with something like the following self-explanatory javascript code
function FindProxyForURL(url, host)
{
if (dnsDomainIs(host, ".it")) return "SOCKS raspberry.local:6666; DIRECT";
else return "DIRECT";
}
This will forward all requests with *.it
address through our tunnel at
raspberry.local:6666
, unless it is somehow unavailable, in which case it will
default to a DIRECT
connection.
All other addresses will also use a DIRECT
connection.
More info on all the available functions and their syntax here.