A walkthrough to use SSH Socks as an adequate replacement of a VPN service.
Note: This page has previously been posted as the following page on SSH Tunnels. The publication date is replicated here.
Problem
Our browser is google-chrome, and we want it to connect to our cloud server via a proxy.
Therefore we can configure google-chrome to connect to the internet via the configured proxy.
The configuration should make google-chrome dependent on the proxy to be present, otherwise it should not be able to connect to the internet.
Solution
There are multitude of layers in our solution.
First we need to run a command to initiate the SOCKS5 proxy connection.
Then we need to configure google-chrome to make use of the SOCKS5 proxy port as its web proxy.
For convenience reasons, we have to automate the setup since the first time our shell starts.
Start the connection
It can be done in as simple as:
$ ssh -TND <PORT> user@host
The choice of port is arbitrary.
I selected one that is unlikely to be used by any existing services.
Argument -T disables pseudo-tty allocation, while -N disables interactive prompt.
Argument -D PORT is the one that actually do the creation of an encrypted SOCKS5 tunnel.
It might also be useful to have -v passed for verbosity, so we can check that we are actually connected.
We also want it to be kept alive, and ideally to simplify the invocation.
To keep our connection alive after running it, we can actually add ServerAliveInterval 120 to our ~/.ssh/config.
It simply tells our ssh client that in case it receives no data from the server after a specified interval (here our interval is 120 seconds), it would send a message to server to get a response.
The full command we needs to reach our server to initiate our proxy is then:
$ ssh -TNvD <PORT> [email protected]
However to simplify that we just need to specify our user name and host name in our ~/.ssh/config file.
The equivalent of -D <PORT> in the config file is the line DynamicForward <PORT>.
Therefore we can compose the following config file:
# file ~/.ssh/config
Host proxy
User username
HostName domain.tld
ServerAliveInterval 120
DynamicForward <PORT>
Then all we need to connect to our server is simplified to:
$ ssh -TNv proxy
Configure Google Chrome to use proxy
Apparently, it is rather trivial to force Google Chrome to honor proxy setting. Arch Linux Wiki suggests to make the following function:
function secure_chromium {
port=<PORT>
export SOCKS_SERVER=localhost:$port
export SOCKS_VERSION=5
chromium &
exit
}
or:
function secure_chromium {
port=<PORT>
chromium --proxy-server="socks://localhost:$port" &
exit
}
then source them from our ~/.bashrc.
In that manner, whenever we want to have a secure connection, we can just run secure_chromium, and enjoy our secure internet connection.
However our requirement is that we must make chrome dependent on it, that it would not be able to connect to the internet without it.
The most obvious solution is to pass --proxy-server=socks://localhost:<PORT> for each run of google chrome.
But it was too much work, and setting up a custom script for it is just superfluous.
The solution is actually rather simple, we just have to create the following line with that argument passed within:
# file ~/.config/chrome-flags.conf
--proxy-server=socks://localhost:<PORT>
# Note that for chromium it is ~/.config/chromium-flags
Therefore our google chrome is constrained to use the proxy server.
Automatic configuration
Currently we are using our tmux configuration with convenience scripts provided by xadfsh/xadf.
We use set_tmux at the start of our session to launch a single or a series of named tmux session, and when there’s a corresponding config file for that named session, it would also be autoloaded.
Inside a named tmux session’s custom config file ssh.conf, we included the following lines:
# file ~/.tmux.conf.d/sessions/ssh.conf
new-window -t ssh:1 -n 'socks'
send-keys -t ssh:1 'clear;ssh -TNv proxy' C-m
Then we included in our autostart file:
# Launch named session ssh among other named sessions
set_tmux ... ssh ...
Note: The script
set_tmuxis a convenience script provided here. To use it, I recommend you to read the script carefully and understand what it is doing. See the repositoryxadfsh/xadf, study it, and adapt it to your case if necessary.
Therefore our connection will automatically be initiated upon entering our terminal.
However the limitation is that if the connection is severed, we would be left without a proxy.
Therefore one more solution to that is to have a systemd user service:
# file ~/.config/systemd/user/proxy.service
[Unit]
Description=SSH tunnel to proxy
[Service]
Type=simple
Restart=always
RestartSec=10
ExecStart=/usr/bin/ssh -F %h/.ssh/config -N proxy
Then we can enable and start it with:
systemctl --user enable proxy
systemctl --user start proxy
If this is configured, then we no longer need our tmux based solution.