Setting up a simple SOCKS proxy tunnel over SSH
Tags: linux, tutorial, devops, beginners
Published: 2022-09-10 14:58:27

If you have any kind of Linux/Unix server accessible over SSH, it's very easy to use it as a simple proxy server. This can be useful to bypass content filters and other restrictions on your local Internet connection. Even the cheapest Linux/BSD VPS options will be more than enough for this.

This feature is built into OpenSSH, and you don't need to install any additional software, or do any additional configuration.

All you need to do is open an ssh connection from the client side with a dynamic port forwarding option:

```
ssh -D 1080 myserver
```

`-D` option tells ssh to use the local 1080 port for dynamic, application-level port forwarding. In a practical sense, this means that your ssh client will act as a SOCKS 4/5 server on that port.

Depending on your configuration, you may also need to specify an SSH port and user (i.e. `ssh -p 2222 myuser@myserver`, but in that case, you may want to consider setting up a host profile in your ~/.ssh/config file instead).

After that, all you need to do is tell your browser to use a SOCKS proxy on localhost:1080.

## Browser setup

In Firefox, you can set SOCKS proxy in Settings / Network Settings / Configure Proxy Access to the Internet - Manual proxy configuration:

- SOCKS Host: localhost
- Port: 1080
- SOCKS v5

With Google Chrome/Chromium, you need to start the browser with `--proxy-server` argument:
```
chromium --proxy-server="socks5://localhost:1080"
```

## Non-interactive / scripting use

If you don't want the SSH client to open an interactive session, you can prevent it from executing the shell with `-N` flag, and `-f` flag to put it into the background, i.e.:
```
ssh -N -f -D 1080 myserver
```

If you want to automatically restart the connection when necessary, you can use `autossh` tool (the syntax is the same):
```
autossh -N -f -D 1080 myserver
```

## Putty

If you're using Putty instead of CLI ssh client, you need to add 1080 as a source port and select Dynamic as a forwarding option under Connection / SSH / Tunnels.

## Relevant ssh options

```text
     -D [bind_address:]port
             Specifies a local “dynamic” application-level port forwarding.
             This works by allocating a socket to listen to port on the local
             side, optionally bound to the specified bind_address.  Whenever a
             connection is made to this port, the connection is forwarded over
             the secure channel, and the application protocol is then used to
             determine where to connect to from the remote machine.  Currently
             the SOCKS4 and SOCKS5 protocols are supported, and ssh will act
             as a SOCKS server.  Only root can forward privileged ports.  Dy‐
             namic port forwardings can also be specified in the configuration
             file.

             IPv6 addresses can be specified by enclosing the address in
             square brackets.  Only the superuser can forward privileged
             ports.  By default, the local port is bound in accordance with
             the GatewayPorts setting.  However, an explicit bind_address may
             be used to bind the connection to a specific address.  The
             bind_address of “localhost” indicates that the listening port be
             bound for local use only, while an empty address or ‘*’ indicates
             that the port should be available from all interfaces.

     -N      Do not execute a remote command.  This is useful for just for‐
             warding ports.

     -f      Requests ssh to go to background just before command execution.
             This is useful if ssh is going to ask for passwords or
             passphrases, but the user wants it in the background.  This im‐
             plies -n.  The recommended way to start X11 programs at a remote
             site is with something like ssh -f host xterm.

             If the ExitOnForwardFailure configuration option is set to “yes”,
             then a client started with -f will wait for all remote port for‐
             wards to be successfully established before placing itself in the
             background.
```

<hr><small>
Note: This is a snapshot of the wiki page from the <a href="https://betterways.dev">BetterWays.dev wiki</a>, you can find the latest (better formatted) version here: <a href="https://betterways.dev/setting-up-a-simple-socks-proxy-tunnel-over-ssh">betterways.dev/setting-up-a-simple-socks-proxy-tunnel-over-ssh</a>.
</small>