Our Blog

WireSocks for Easy Proxied Routing

Reading time ~9 min

I built some infrastructure that you could deploy and use to easily tunnel from arbitrary sources over a proxy such as SOCKS, using anything that can run WireGuard. This is convenient in cases where it would be nicer to have a full network route to a target network (with working DNS) vs just having application specific proxy rules. In this post I’ll elaborate a bit on that idea. If you are just looking for the code you can find it here: https://github.com/sensepost/wiresocks.

Introduction

We often get into a position where some sort of internal device has been compromised and you want to take it further. This involves getting network traffic through your compromised device via a SOCKS proxy. SOCKS proxies are everywhere and there are many examples of Cobalt Strike or Metasploit being used to proxy traffic through an agent or tools like ReGeorg, Pivotnacci or Chisel being used to proxy traffic via a compromised web server or similar.

Existing solutions

Once you have a SOCKS proxy setup, that is usually when good old reliable proxychains-ng comes into the picture where you’d use it to tunnel the majority of your tooling through the proxy. However, recently a lot of really nice tools have been released which have been made to run on Windows. This comes with the issue of how are we going to trick these Windows applications into using our proxy.

The SpectorOps team wrote an excellent post detailing how to use software such as Proxifier and Proxycap on Windows to force your tools to use your proxy. If you haven’t, go read it! Unfortunately, in some edge cases those tools fail or become annoying by not catching all the traffic as you’d like.

Having this happen a few times, I was struck with some inspiration. Why not do the redirection at a network level and avoid all the weird Windows nuances?

Network Level Proxying

Luckily for me there already was a project that handled this called tun2socks (originally I used RedSocks, but @RoganDawes showed me tun2socks which removes some of the iptables complexity in RedSocks) which is really just some Golang magic together with some routes that lets you redirect traffic into a tun device and have it push traffic through your SOCKS proxy. This seemed like a great idea, except every time you would want to use it for your Windows machine you would have to setup a Linux router with this installed and route your Windows machine through it. This would be more effort than Proxyfier, I felt. Turns out, we have this easy network tooling that runs on Windows (amongst others) that takes your traffic from one point to another called VPNs. More specifically in this instance I used WireGuard which is an awesome simple VPN that has clients for all manner of operating systems.

WireSocks

Glueing those two services together, ie. tun2socks and Wireguard, we can connect arbitrary clients via Wireguard and route traffic into a SOCKS proxy and into client networks.

High level architecture diagram for WireSocks

Using this setup, we can now interact with a remote network, using a traditional network route, complete with DNS resolution (more on that in a moment!).

Listing of a Domain Controller’s shared folders via a SOCKS proxy exposed using Cobalt Strike, leveraging WireGuard and tun2socks to reach it.

To make getting up and running even simpler I did some searching for docker containers to handle some of the work for me. I found that tun2socks also had a container, xjasonlyu/tun2socks and linuxserver/wireguard which I had previously used for my own WireGuard server. I did some editing of the tun2socks docker container with a simpler entry point to our use case.

Using docker compose to glue the services together and to set this up quickly on a jump box, I gave it a test and was able to get SeatBelt.exe into the network from my own Windows VM just by connecting to the WireGuard VPN. \o/

Running SeatBelt on a remote host, inside the compromised network over our WireGuard tunnel, via a SOCKS proxy.

DNS via WireSocks

There is one problem though, UDP traffic is not working great (even though SOCKS5 supports it), which causes issues as DNS is over UDP. After fighting with tunnelling UDP traffic and eventually working out that the specific SOCKS proxy I was using did not support UDP I opted to setup a DNS server which would take UDP requests and forward them on as TCP. This was very easy as the linuxserver/wireguard docker had CoreDNS as its own DNS server for WireGuard clients. After looking at CoreDNS’ plugins I discovered the forward plugin supported an option to force TCP. This means that if the client uses the WireGuard CoreDNS server the request would be converted to TCP and would then be captured by tun2socks solving the issue. Once again I went for an allow list approach so that we can specify which DNS requests get forwarded through the SOCKS proxy so that we don’t spam the victims internal DNS with random requests. An example Corefile follows:

# Domain that you would like to convert to TCP so that
# it gets pushed through tun2socks
example.zzz {
    loop
    log
    # Change IP to that of the internal DNS server you want to use.
    forward . 123.123.123.123:53 {
        force_tcp
    }
}

Bringing it all together

To get this all setup easily, I created a basic Dockerfile based off the one in the tun2socks repo so that it would take my own entrypoint.sh. My entrypoint removed a lot of the iptables marks in the original and instead just parses some environment variables such as $TUN_INCLUDED_ROUTES to add routes in the docker container running tun2socks.

config_route() {
  for addr in $(echo "$TUN_INCLUDED_ROUTES" | tr ',' '\n'); do
    ip route add $addr dev $TUN
  done
}

This docker now would setup the TUN interface and the configured routes would be redirected into the TUN and therefore into the SOCKS proxy. Now I just needed to run the second WireGuard docker and get it to use the same routes as well as have access to the network namespace of the tun2socks docker so it could use the TUN interface. Or I could just add a WireGuard server to the tun2socks docker.

Turns out the first option is easier. It is possible to tell a docker to use the network namespace of another container when it gets setup. This is done by specifying container:container_name as a --net option like below:

docker run -it --rm --net container:wiresocks alpine /bin/sh

The above command would run an alpine container but its network stack would be the same as the wiresocks container which includes all the routes as well as the TUN interface. This allows you to generically add any dockerised tools into that namespace which would obey the routes and essentially be SOCKS’d via the proxy. This means you can bring any docker container into the same namespace and have it access the same network!

Using the same namespace trick to attach a docker container with impacket tools installed to use the same socks proxy hack.

Going back to WireGuard I created a docker-compose that handles most of the setup for you so that you can have any client machine get routed via SOCKS transparently: https://github.com/sensepost/wiresocks/blob/main/docker-compose.yml

Getting started with Wiresocks

Using WireSocks should be pretty simple. You need a host (say a jump box), a proxy (such as SOCKS) into your target network (your jump box should be able to reach it), and docker compose installed. Then, clone the WireSocks repository, copy the example .env.example file to .env, edit it appropriately and run docker compose up -d. With the stack up and running, you should see a new config/ directory which will contain the WireGuard client configuration files you’d need to configure on your clients (like Windows, Linux, macOS etc.).

Conclusion

So all of this provides a generic way to get a computer’s TCP traffic into a SOCKS proxy without too much funny business. UDP support is something that the SOCKS proxy would need support for and it also needs to play nicely with tun2socks, so if someone can figure that out before me, please let me know!

The tool/docker can be found here: https://github.com/sensepost/wiresocks

Hopefully this helps some people who have been frustrated by their tools not using their SOCKS.