resocks
resocks
is a reverse/back-connect SOCKS5 proxy tunnel that can be used to
route traffic through a system that can't be directly accessed (e.g. due to
NAT). The channel is secured by mutually trusted TLS with auto-generated
certificates based on a connection key. Read our
blog post
for more information.
Usage
Start the listener on the system that acts as the entry point of the SOCKS5 tunnel:
# on proxy entry point system with IP 1.2.3.4
$ resocks listen
Copy the connection key and pass it to resocks
on the relay
system:
# on remote relay system with IP 10.0.0.1
$ resocks 1.2.3.4 --key $CONNECTION_KEY
Now configure tools on the proxy entry point system to use the local SOCKS5 server, for example:
$ curl --proxy 'socks5://127.0.0.1:1080' 'http://10.0.0.2'
You can also generate a connection key with resocks generate
and pass it to
the listen
command to avoid generating a new connection key every time. It
can also be specified via an environment variable:
$ export RESOCKS_KEY="$(resocks generate)"
$ resocks listen
Security
The threat model of resocks
primarily takes into account attackers that can
inspect, intercept and modify traffic between the listener and the relay.
Specifically, resocks
aims to defend against the following scenarios:
- A: Malicious Observer: Attackers with network access between the listener and the proxy should not be able to see the SOCKS5 traffic that is routed through the tunnel.
- B: Malicious Listener: When connecting the proxy to a listener, attackers should not be able to redirect the traffic to a malicious listener, as this would grant them access to the proxy server's network.
- C: Malicious Relay: Attackers should not be able to connect to an existing listener in order to be able to receive the traffic that was meant to be routed through the legitimate proxy.
This threat model suggests using a mutually authenticated encrypted connection between the listener and the relay as described here.
Please note that resocks
is not designed to defend against the following
scenarios:
- D: Malicious User on Listener System: Malicious users on the system hosting the listener is generally able to connect to the SOCKS5 proxy or extract the connection key.
- E: Malicious User on the Relay System: A malicious user on the system hosting the relay can generally extract the connection key.
However, as described here, there a some defense-in-depth
measures that can employed to harden resocks
against such attacks.
Key-Based TLS
The tunnel between the listener and the relay is secured by a shared connection
key which is used to establish a mutually trusted TLS 1.3 connection. This works
by using the key on both sides to derive the same CA certificate which is then
used to sign the server and client certificates that are generated on the spot.
The library that implements this technique (kbtls
) is available
here.
Defense-in-Depth
When running either the resocks
listener or relay on an untrusted system
(scenarios D/E), attackers can potentially read the connection key which
undermines the defenses against scenarios A, B and C.
By default, the connection key is passed as a command line flag and can be read
out by attackers with the permission to see process listing with arguments.
Alternatively, the connection key can be specified via environment variable
($RESOCKS_KEY
) or it could be statically built into the binary as described
below. In this case, the read permissions will need to be revoked
for other users. In certain scenarios, these techniques may prevent certain
low-privileged attackers from gaining access to the connection keys.
Building
resocks
can be built with the following command:
go build
In order to compile a static connection key as the default connection key directly into the binary, use the following command:
go run . generate # generate a connection key
go build -ldflags="-X main.defaultConnectionKey=YOUR_CONNECTION_KEY"
Similarly, the default connect back address can also be statically compiled into the binary:
go build -ldflags="-X main.defaultConnectBackAddress=192.0.2.1"