Select Page

Tunnels are simple tools that can help you evade walls and filters. Consider a wall that selects traffic based on logical rules. If you can encapsulate your traffic in a way that agrees with the filtering rules, your traffic will pass inspection and flow through. Use a proxy to direct traffic through your tunnel and your manipulation of the route can be transparent to both sides of the connection.

If it helps to picture a physical analog, think of a tremendous, magnificent border wall that can be circumvented entirely by tunneling underneath. This, the fact that a wall can always be evaded, is the technical reason why the idea of a monolithic border wall is just malignant idiocy. In this example, the tunnel and proxy are the same. As the engineer of a physical tunnel, you choose two endpoints to connect and you specify what to send through the tunnel.




In this post we'll go through the steps to set up tunnels with the objective of creating interactive sessions without violating protocol mismatches that would cause advanced firewall configurations to block your traffic. The idea is to get a stable, working configuration on your testing environment that you can use repeatedly in the field. Have you come across a scenario where you have wanted to access tools on your command and control infrastructure, or perhaps you want to exfiltrate data to a virtual private server (VPS), but are filtered by egress rules? Today we try to address that problem.

Easy encrypted tunnels

Tunneling works out of the box on modern Linux, but YMMV on anything else. Standard tools are SSH and stunnel. In this scenario we are creating a tunnel between a local client and a VPS (I use Debian GNU/Linux instances on Google Compute Engine) connected to the Internet. Binding to low ports on Linux requires root privileges; using ports >1024 does not. In our set up, the VPS allows SSL connections on 443 and SSH connections on 22. The client will establish connections on those ports and use high port numbers to bind a proxy service.

The first tunneling method requires just a remote SSH server and regular user access on the local client. The client initiates a tunnel which runs entirely in userspace on the client system. This is a tunnel over SSH, which is useful when you need to establish a tunnel.

The following configuration steps will establish the tunnel and forward proxy every time you SSH to the remote server from the local client. This configuration defines a dynamic proxy, which acts as a SOCKS proxy server on the client system. A SOCKS proxy is more contained than standard port forwarding because the application using the proxy can make requests, like DNS lookups, that remain within the proxy routes (as long as the application can accommodate the SOCKS proxy configuration).

  1. Add a record to ~/.ssh/config . You can have many records in this file.
  2. Generate a public/private key pair for andylake (e.g. ssh-keygen -t rsa -b 4096 -f ~/.ssh/andylake ) and add the key to the authorization file on the remote server (e.g. ssh-copy-id bloodhound@andylake ).
  3. Configure your applications to use the localhost proxy (link to proxy section).

A more robust, generalizable tunneling method creates an SSL/TLS channel through stunnel. You can encapsulate pretty much anything TCP over stunnel. stunnel is designed to underpin the application layer of a connection so that applications can establish remote connections without having to configure encryption in the application specifically.

Set up requires a privilege-dropping service account. Connections are established under the privileges of this account; other users can start applications that use the tunnel. In this scenario we may want to have stunnel listen one the server side and accept connections on HTTP/SSL port 443 and forward its decrypted payloads to port 22 on the same host (in this case the 'decrypted payload' is SSH traffic and is not plaintext).

Combine stunnel and autossh for a resilient reverse shell!

Local proxies

Point your application to localhost at the high port bound by the SSH client SOCKS proxy to forward traffic through your encrypted tunnel. You can do this on the application level through individual settings and plugins, like FoxyProxy for Chrome and Firefox (this is essentially how the Tor packaged browser works).

Alternatively you can do this at operating system level on Linux through iptables. This method is a static proxy and will only forward traffic on specific ports defined in the rules. This differs from a SOCKS proxy in that, for example, DNS queries will not be sent through the proxy. However, this method is entirely transparent to the application running on the client; the application does not need to be configured to connect to localhost as the proxy redirection is done by iptables at the kernel level.

A network address translation (NAT) rule like the following will set up a forward proxy on the client host that is transparent to the ssh application.

In this case, we need to modify the stunnel configuration to rewrite the destination address as it forwards packets, via this configuration:

Outbound SSH connections are transparently rerouted through an SSL/TLS session. Do you know why we would want to do this?

Application layer filtering

Next-generation firewalls inspect traffic at a more contextual level than the firewalls that came before. A firewall that performs application filtering allows a connection to establish while capturing the first few packets. The connection is categorized to determine the "application" generating traffic by pattern matching strings in the captured packets. This type of inspection ensures that a connection is legitimate in the sense that protocols match as expected, and also that the sender and receiver are approved in the rules list.

However, resource and latency constraints limit the depth of inspection to only the first few packets. So what happens if you generate a connection that overruns this limit? If the packet filter cannot make a determination from the initial connection, it considers the traffic 'uncategorized', which is commonly blocked by default. If the pattern up to the end of the buffer matches an allowed category, then the connection may persist. If not, the device resets both ends.

You can tunnel through a layer seven filter by first establishing an SSL connection to your remote server and then further tunneling SSH through that connection. The analogy is a peeling an onion to get at the juicy layers on the inside. How many layers will an inspection device unwrap before clearing the connection?

As far as I know, there isn't a standard answer to that question, but anecdotally we have bypassed business-class gateways with just one TLS wrapping of SSH traffic. Enterprise application firewalls balance throughput, latency, and connection verification, and can't get the balance correct in every case.


The truth is nobody really knows how antennas work.

Latest posts by antennatheory (see all)