sshuttle

Proxy transparent au-dessus de SSH. Route des sous-réseaux entiers à travers une connexion SSH sans configuration VPN ni root sur l'hôte distant. Transparent proxy over SSH. Routes entire subnets through an SSH connection without VPN configuration or root on the remote host.

↗ https://github.com/sshuttle/sshuttle

Overview

sshuttle creates a VPN-like tunnel over SSH that transparently routes traffic to specified subnets. Unlike SSH port forwarding, it handles entire CIDR ranges without configuration on the remote host. Requires Python on the remote host but no root.

Basic Usage

Route all traffic through SSH host

sshuttle -r user@jumphost 0.0.0.0/0

Route specific subnet only

sshuttle -r user@jumphost 10.10.10.0/24

Route multiple subnets

sshuttle -r user@jumphost 10.10.10.0/24 192.168.1.0/24

Exclude your host from routing (avoid routing SSH connection itself)

sshuttle -r user@jumphost 0.0.0.0/0 --exclude $(host jumphost | awk '{print $NF}')

Specify SSH port

sshuttle -r user@jumphost:2222 10.10.10.0/24

Background mode

sshuttle -r user@jumphost 10.10.10.0/24 --daemon --pidfile /tmp/sshuttle.pid

Authentication Options

SSH key authentication

sshuttle -r user@jumphost 10.10.10.0/24 -e 'ssh -i /path/to/key.pem'

SSH with password (requires sshpass)

sshuttle -r user@jumphost 10.10.10.0/24 -e 'sshpass -p password ssh'

SSH options passthrough

sshuttle -r user@jumphost 10.10.10.0/24 \
  -e 'ssh -o StrictHostKeyChecking=no -i /path/to/key'

Jump host chain (pivot through multiple hops)

sshuttle -r user@outer_host 10.10.10.0/24 \
  -e 'ssh -J user@jump_host'

DNS Routing

Route DNS through the tunnel (resolve internal hostnames)

sshuttle -r user@jumphost 10.10.10.0/24 --dns

Specify DNS server

sshuttle -r user@jumphost 10.10.10.0/24 --dns --to-ns 10.10.10.1

Firewall Methods

Use NAT method (default on Linux)

sshuttle -r user@jumphost 10.10.10.0/24 --method nat

Use iptables TPROXY (better performance)

sudo sshuttle -r user@jumphost 10.10.10.0/24 --method tproxy

macOS / BSD

sshuttle -r user@jumphost 10.10.10.0/24 --method pf

Kill & Management

Kill a daemonized sshuttle

kill $(cat /tmp/sshuttle.pid)

Verbose output for debugging

sshuttle -r user@jumphost 10.10.10.0/24 -v

Verbose showing actual connections

sshuttle -r user@jumphost 10.10.10.0/24 -vv

Common Pivoting Scenario

# Scenario: compromised DMZ host (jumphost) can reach internal network 10.10.10.0/24

Step 1: Set up tunnel

sshuttle -r user@jumphost_IP 10.10.10.0/24 --dns
# Step 2: All traffic to 10.10.10.0/24 now goes through jumphost
nmap -sV 10.10.10.5
curl http://10.10.10.10/internal-api
ssh admin@10.10.10.1

Tips

  • sshuttle doesn’t require sudo on the remote host — just Python
  • Requires sudo on your local machine (needs to modify iptables/pf rules)
  • --dns is essential when targeting internal services that use internal hostnames
  • For multi-hop pivoting, chain with SSH -J jump hosts
Help / Man page
sshuttle [options] [-r [user@]sshserver[:port]] <subnets>

-r HOST         Remote SSH host (and optional port)
-l ADDR         Local listen address (default: auto)
-x SUBNET       Exclude subnet from routing
-e CMD          SSH command to use
--dns           Forward DNS queries through the tunnel
--to-ns DNS     DNS server to forward to
--daemon        Run as background daemon
--pidfile FILE  PID file for daemon mode
--method METHOD Firewall method: nat, tproxy, pf, ipfw
-v              Verbose output
-vv             More verbose
--version       Print version

Subnets:
  0.0.0.0/0     All IPv4 traffic
  ::/0          All IPv6 traffic
  10.0.0.0/8   Private class A
  192.168.0.0/16 Private class C

Vue d’ensemble

sshuttle crée un tunnel de type VPN au-dessus de SSH qui route de manière transparente le trafic vers des sous-réseaux spécifiés. Contrairement au port forwarding SSH, il gère des plages CIDR entières sans configuration sur l’hôte distant. Nécessite Python sur l’hôte distant mais pas de root.

Utilisation de base

# Router tout le trafic à travers l'hôte SSH
sshuttle -r user@jumphost 0.0.0.0/0

# Router uniquement un sous-réseau spécifique
sshuttle -r user@jumphost 10.10.10.0/24

# Router plusieurs sous-réseaux
sshuttle -r user@jumphost 10.10.10.0/24 192.168.1.0/24

# Exclure son propre hôte du routage (éviter de router la connexion SSH elle-même)
sshuttle -r user@jumphost 0.0.0.0/0 --exclude $(host jumphost | awk '{print $NF}')

# Spécifier le port SSH
sshuttle -r user@jumphost:2222 10.10.10.0/24

# Mode arrière-plan
sshuttle -r user@jumphost 10.10.10.0/24 --daemon --pidfile /tmp/sshuttle.pid

Options d’authentification

# Authentification par clé SSH
sshuttle -r user@jumphost 10.10.10.0/24 -e 'ssh -i /path/to/key.pem'

# SSH avec mot de passe (nécessite sshpass)
sshuttle -r user@jumphost 10.10.10.0/24 -e 'sshpass -p password ssh'

# Transmission d'options SSH
sshuttle -r user@jumphost 10.10.10.0/24 \
  -e 'ssh -o StrictHostKeyChecking=no -i /path/to/key'

# Chaîne de jump hosts (pivoter à travers plusieurs sauts)
sshuttle -r user@outer_host 10.10.10.0/24 \
  -e 'ssh -J user@jump_host'

Routage DNS

# Router le DNS à travers le tunnel (résoudre les noms d'hôtes internes)
sshuttle -r user@jumphost 10.10.10.0/24 --dns

# Spécifier un serveur DNS
sshuttle -r user@jumphost 10.10.10.0/24 --dns --to-ns 10.10.10.1

Méthodes de pare-feu

# Utiliser la méthode NAT (par défaut sous Linux)
sshuttle -r user@jumphost 10.10.10.0/24 --method nat

# Utiliser iptables TPROXY (meilleures performances)
sudo sshuttle -r user@jumphost 10.10.10.0/24 --method tproxy

# macOS / BSD
sshuttle -r user@jumphost 10.10.10.0/24 --method pf

Arrêt et gestion

# Arrêter un sshuttle démonisé
kill $(cat /tmp/sshuttle.pid)

# Sortie verbeuse pour débogage
sshuttle -r user@jumphost 10.10.10.0/24 -v

# Verbeux montrant les connexions réelles
sshuttle -r user@jumphost 10.10.10.0/24 -vv

Scénario de pivoting courant

# Scénario : hôte DMZ compromis (jumphost) pouvant atteindre le réseau interne 10.10.10.0/24

Étape 1 : mettre en place le tunnel

sshuttle -r user@jumphost_IP 10.10.10.0/24 --dns
# Étape 2 : tout le trafic vers 10.10.10.0/24 passe maintenant par jumphost
nmap -sV 10.10.10.5
curl http://10.10.10.10/internal-api
ssh admin@10.10.10.1

Conseils

  • sshuttle ne nécessite pas sudo sur l’hôte distant : juste Python
  • Nécessite sudo sur sa propre machine (doit modifier les règles iptables/pf)
  • --dns est essentiel quand on cible des services internes qui utilisent des noms d’hôtes internes
  • Pour du pivoting multi-sauts, chaîner avec les jump hosts SSH -J
Aide / Page de manuel
sshuttle [options] [-r [user@]sshserver[:port]] <subnets>

-r HOST         Remote SSH host (and optional port)
-l ADDR         Local listen address (default: auto)
-x SUBNET       Exclude subnet from routing
-e CMD          SSH command to use
--dns           Forward DNS queries through the tunnel
--to-ns DNS     DNS server to forward to
--daemon        Run as background daemon
--pidfile FILE  PID file for daemon mode
--method METHOD Firewall method: nat, tproxy, pf, ipfw
-v              Verbose output
-vv             More verbose
--version       Print version

Subnets:
  0.0.0.0/0     All IPv4 traffic
  ::/0          All IPv6 traffic
  10.0.0.0/8   Private class A
  192.168.0.0/16 Private class C