Linux Networking, SSH & Tunneling from the Command Line
Linux Networking, SSH & Tunneling from the Command Line
Chapter 9 of the Linux series shifts from the single box to the network it lives on. It builds on the process/service knowledge from the previous chapter — you now know what's running; this chapter teaches what it's talking to, and, critically, how you as an operator move traffic through a Linux box using SSH tunnels and port forwarding. This is one of the highest-leverage chapters in the whole Foundations phase: tunneling is the backbone of pivoting in almost every internal penetration test and red-team engagement you'll ever run.
Why This Chapter Matters
Every pentest, CTF, or SOC investigation eventually asks the same question: what is this machine connected to, and how do I get my traffic where it needs to go? Linux gives you a small set of command-line tools to answer both halves of that question — inspection tools (ip, ss, netstat, dig, curl) and, more powerfully, SSH itself as a general-purpose network Swiss Army knife. A single SSH connection can forward arbitrary TCP traffic in either direction, turn a compromised box into a SOCKS proxy for your entire attack toolkit, and let you reach networks that have no direct route to your machine at all. This is called pivoting, and it's a mandatory skill for internal pentests, Active Directory engagements, and any CTF with a multi-hop network layout.
mindmap
root((Linux Networking Toolkit))
Inspection
ip addr / ip route
ss / netstat
dig / nslookup
curl / wget
Connectivity
ping
traceroute
nc / ncat
SSH
Local forward -L
Remote forward -R
Dynamic forward -D / SOCKS
ProxyJump -J
Persistence of tunnels
autossh
systemd + ssh
Foundations: Inspecting the Network Stack
ip — the modern replacement for ifconfig/route
ip addr show # all interfaces and their IPs (ifconfig's replacement)
ip a # short form
ip route show # routing table — what goes where, and via what gateway
ip r # short form
ip link show # interface state (up/down), MAC addresses
ip neigh show # ARP table equivalent
sudo ip addr add 10.10.14.5/24 dev eth0 # manually assign an IP
sudo ip route add 10.10.10.0/24 via 10.10.14.1 # add a static routeWhy it works:
ifconfigandroutecome from the old, now-deprecatednet-toolspackage;ip(fromiproute2) is the maintained standard on every modern distro. Knowingipis not optional anymore — many minimal/hardened boxes (containers especially) don't even shipifconfig.
ss — the modern replacement for netstat
ss -tulwn # TCP/UDP listening sockets, numeric ports, no name resolution
ss -tup # TCP/UDP with the owning PROCESS name (needs privilege for others' sockets)
ss -s # summary statistics
ss state established # only established connections
netstat -tulpn # older equivalent, still common in tutorials and older systemsReading ss -tulwn output: LISTEN state + a local address like 0.0.0.0:22 means the service is reachable from any interface; 127.0.0.1:3306 means it's bound to localhost only — a critical distinction when you're assessing what's actually exposed versus what merely runs on the box.
DNS lookups: dig, nslookup, host
dig example.com # full DNS query + answer
dig example.com +short # just the IP
dig example.com MX # mail exchange records
dig example.com ANY # (deprecated by many resolvers, but still tried)
dig @8.8.8.8 example.com # query a SPECIFIC DNS server directly
dig -x 8.8.8.8 # reverse lookup
dig axfr example.com @ns1.example.com # attempt a zone transfer (misconfig hunting)
host example.com
nslookup example.comBug bounty relevance: DNS zone transfer misconfigurations (
dig axfr) and subdomain enumeration built ondig/hostoutput are a direct, standing recon technique used to discover in-scope assets before any web testing begins.
Basic connectivity: ping, traceroute, curl, nc
ping -c 4 10.10.10.5 # 4 ICMP echo requests
traceroute 10.10.10.5 # hop-by-hop path
mtr 10.10.10.5 # combines ping+traceroute, live
curl -v https://example.com # verbose HTTP request — see full request/response
curl -I https://example.com # headers only (HEAD-style)
wget https://example.com/file # download a file
nc -nv 10.10.10.5 445 # raw TCP connect test — "is this port actually open and responsive?"
nc -lvnp 4444 # listen on a port (classic reverse-shell catcher)sequenceDiagram
participant You as Your machine
participant Target as Target host
You->>Target: nc -nv target 445 (TCP SYN)
Target-->>You: SYN-ACK if port open / RST if closed / timeout if filtered
Note over You,Target: This is the same three-way handshake nmap uses under the hood
SSH: Far More Than Remote Login
SSH (Secure Shell) is the encrypted remote-access protocol every Linux admin and pentester lives inside daily. Its architecture is worth understanding properly because every tunneling trick in this chapter is built directly on it.
Basic usage and key-based auth
ssh user@10.10.10.5 # password or key auth, default port 22
ssh -p 2222 user@10.10.10.5 # non-default port
ssh -i ~/.ssh/id_ed25519 user@host # specify a private key explicitly
ssh-keygen -t ed25519 -C "my-key" # generate a modern keypair
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host # install your public key on a remote hostKey-based auth works because of asymmetric cryptography: the server stores your public key in ~/.ssh/authorized_keys; you keep the private key secret. During the handshake, the server challenges you to prove possession of the private key without ever transmitting it — this is why a leaked authorized_keys file is low-risk but a leaked private key is a full compromise.
sequenceDiagram
participant Client
participant Server
Client->>Server: SSH_MSG_KEXINIT (negotiate algorithms)
Server->>Client: SSH_MSG_KEXINIT + host key
Client->>Client: Verify host key against known_hosts
Client->>Server: Offer public key
Server->>Client: Challenge (sign this random data)
Client->>Server: Signature (proves private key possession)
Server->>Client: Auth success, session established, encrypted
The SSH config file — stop retyping flags
~/.ssh/config lets you define per-host shortcuts:
Host box1
HostName 10.10.10.5
User admin
Port 2222
IdentityFile ~/.ssh/id_ed25519_box1
Host jumphost
HostName 203.0.113.10
User pivot
Host internal
HostName 172.16.5.10
User admin
ProxyJump jumphost
After this, ssh box1 and ssh internal (which automatically routes through jumphost) just work — no memorized flag strings.
Tunneling & Port Forwarding: The Core Pivoting Skill
This is the single most valuable practical skill in this chapter. SSH can forward arbitrary TCP traffic through an encrypted connection in three distinct directions.
Local forwarding (-L) — reach something from your side
ssh -L 8080:127.0.0.1:80 user@remotehostTraffic you send to localhost:8080 on your machine gets forwarded, through the SSH connection, to 127.0.0.1:80 as seen from remotehost. This is how you reach an internal web app, database, or admin panel that only listens on localhost on a box you've SSH'd into.
flowchart LR
You[Your browser: localhost:8080] -->|SSH tunnel| Remote[remotehost]
Remote -->|127.0.0.1:80| Service[Internal web app]
Remote forwarding (-R) — expose YOUR side to them
ssh -R 9000:127.0.0.1:22 user@remotehostThis does the opposite: a listener opens on remotehost:9000, and anything connecting to it gets forwarded back to 127.0.0.1:22 on your machine. This is the classic technique for exposing a service on your attack box to a remote network segment you've pivoted into — or, in a legitimate ops context, letting a remote support engineer reach a machine sitting behind NAT.
flowchart LR
Remote[remotehost:9000] -->|SSH tunnel, reversed| You[Your machine: 127.0.0.1:22]
Dynamic forwarding (-D) — turn SSH into a SOCKS proxy
ssh -D 1080 user@remotehostThis is the pivoting workhorse. It opens a SOCKS proxy on 127.0.0.1:1080 on your machine; any application configured to use that SOCKS proxy (browser, proxychains-wrapped tools, Burp Suite) has its traffic tunneled through remotehost, letting you reach the entire network remotehost can see — not just one fixed port.
# proxychains.conf: socks5 127.0.0.1 1080
proxychains nmap -sT -Pn 172.16.5.0/24 # scan an internal network THROUGH the pivot
proxychains curl http://172.16.5.10/ # browse an internal-only web app THROUGH the pivotProxyJump — chaining through multiple hops
ssh -J user1@jumphost1,user2@jumphost2 user3@finaltarget-J (or the ProxyJump config directive) chains SSH connections through one or more intermediate hosts, establishing a direct logical connection to the final target while physically routing through every hop in between — the standard way to reach a deeply internal host during a multi-segment engagement.
flowchart LR
A[Your machine] -->|SSH| B[jumphost1]
B -->|SSH| C[jumphost2]
C -->|SSH| D[final target]
Keeping tunnels alive: autossh and useful flags
ssh -o ServerAliveInterval=30 -o ServerAliveCountAlso=3 -L 8080:127.0.0.1:80 user@host
autossh -M 0 -f -N -L 8080:127.0.0.1:80 user@host # auto-reconnects if the tunnel drops
ssh -N -f -L 8080:127.0.0.1:80 user@host # -N: no remote command, -f: background after authAdvanced Techniques & Edge Cases
- Reverse SOCKS proxy over a single reverse shell — tools like
chiselandligolo-ngbuild on the exact concepts above but work without full SSH access, useful when you only have a raw reverse shell rather than valid SSH credentials on the pivot box. Understanding SSH tunneling first makes these tools trivial to pick up. - SSH agent forwarding (
-A) — forwards your local SSH agent's keys through the chain so you can authenticate onward without copying private keys to intermediate hosts. Use cautiously: a compromised intermediate host with agent forwarding enabled can (while your agent is connected) use your forwarded key to authenticate elsewhere as you. known_hostsverification failures — a changed host key produces a scary "REMOTE HOST IDENTIFICATION HAS CHANGED" warning. In a lab this is usually just a reinstalled VM; on a real engagement or in production, treat it as a potential MITM until proven otherwise — never blindlyssh-keygen -Rand reconnect without checking why the key changed.- NAT and firewalls block
-Rmore often than-L— remote forwarding requires the SSH server to allowGatewayPortsif you want the forwarded port reachable from outside127.0.0.1on that host; check/etc/ssh/sshd_configforGatewayPorts yesif a teammate can't reach your forwarded port.
Real-World Application
- Internal pentests and Active Directory engagements almost universally require pivoting once you land on a single foothold box — dynamic SOCKS forwarding through that box is usually the very next step after initial access, before any AD enumeration tooling (BloodHound, etc.) can even run against the internal network.
- Bug bounty infrastructure testing occasionally involves discovering an SSH service with weak credentials or exposed keys, at which point tunneling techniques let a researcher demonstrate real internal-network impact for a much higher-severity report.
- SOC/DFIR: unusual outbound SSH connections, especially with
-D/-Rstyle dynamic or reverse forwarding, are a well-known technique for both legitimate remote-support tooling and attacker C2/tunneling — analysts specifically watch for long-lived SSH connections to unexpected external hosts.
Detection & Defense: Blue Team Angle
- Monitor SSH connection metadata, not just success/failure: unusually long-lived sessions, connections carrying forwarded ports (visible via
netstat/sson the server showing extra listening sockets tied to thesshdprocess), and connections at unusual hours are all detection-worthy. - Disable what you don't need in
/etc/ssh/sshd_config:AllowTcpForwarding noblocks-L/-R/-Dentirely if a box has no legitimate need for tunneling;GatewayPorts no(the default) prevents forwarded ports from being reachable beyond localhost. - Key-based auth only, disable passwords (
PasswordAuthentication no) removes an entire class of brute-force attack — pair withfail2banto rate-limit and ban repeat offenders regardless. - Centralize and alert on
sshdauth logs (auth.log/journalctl -u ssh) for repeated failures, unusual source geographies, and successful logins from IPs never seen before for that account.
Blue Team CTF / detection challenge angle — Given a pcap or auth log, you're commonly asked to identify pivoting activity: look for an SSH session immediately followed by traffic to internal (RFC1918) addresses that shouldn't be reachable from the apparent source, or for
sshd_configdiffs showingAllowTcpForwardingorGatewayPortsflipped toyesshortly before an incident.
Bug Bounty Angle — Directly finding SSH misconfigurations rarely pays on its own (weak SSH creds are usually out of scope for a web-focused program), but tunneling skill turns a single internal foothold — from an SSRF, exposed Jenkins, or leaked cloud credential — into a demonstrable internal-network compromise, which is exactly the kind of "show maximum realistic impact" narrative that pushes a report from Medium to Critical severity.
CTF Angle — Multi-host CTF networks (HackTheBox Pro Labs, TryHackMe network rooms, OSCP-style labs) are built around exactly this skill: land on host A, discover host B is only reachable from A's internal interface, set up
ssh -Dor achisel/ligolo-ngtunnel, and pivot your scanner/exploit traffic through. Practice pattern:ss -tulwnon the foothold box to find internal-only listeners, thenssh -D 1080+proxychains nmapto map the hidden network.
Common Mistakes & How to Overcome Them
| Mistake | Symptom | Fix |
|---|---|---|
Confusing -L and -R direction |
Tunnel "doesn't work" — wrong side listens | -L = reach FROM you TO them; -R = expose YOUR side TO them |
Forgetting -N when you only want a tunnel |
Unwanted interactive shell opens alongside the tunnel | Add -N to suppress remote command execution |
| Not backgrounding long tunnels | Tunnel dies when you close the terminal | Add -f (background) or run under screen/tmux/autossh |
| Assuming a bound port is reachable externally | Confused why 0.0.0.0 binding "doesn't work" from outside |
Check firewall rules (iptables/nftables) separately from the bind address |
| Ignoring host key change warnings | Walks into an active MITM, or wastes time distrusting a legit VM rebuild | Investigate before blindly removing the old key from known_hosts |
Final Revision / Summary
ipandssare the modern replacements forifconfig/netstat/route— learn them even if tutorials still show the old tools.dig,curl -v, andnccover DNS inspection, raw HTTP visibility, and raw TCP connectivity testing respectively.- SSH is a full network tool, not just remote login:
-L(local forward, reach something from your side),-R(remote forward, expose your side to them),-D(dynamic/SOCKS, tunnel an entire network's worth of traffic), and-J(chain through jump hosts). - Pivoting = using a compromised or accessible host's network position to reach segments you otherwise couldn't — the entire technique is built on SSH tunneling fundamentals.
- Mnemonic: "Local reaches out, Remote reaches in, Dynamic reaches everywhere" — a quick way to remember
-L/-R/-Ddirection.
Cheat Sheet / Quick Reference
# Inspection
ip addr show / ip route show
ss -tulwn
dig example.com +short
curl -v https://host
nc -nv host port
# SSH basics
ssh -i key user@host
ssh-keygen -t ed25519
ssh-copy-id user@host
# Tunneling
ssh -L 8080:127.0.0.1:80 user@host # local forward
ssh -R 9000:127.0.0.1:22 user@host # remote forward
ssh -D 1080 user@host # dynamic SOCKS proxy
ssh -J user1@hop1,user2@hop2 user3@dst # jump chain
autossh -M 0 -f -N -L 8080:127.0.0.1:80 user@host # persistent tunnel
# proxychains usage
proxychains nmap -sT -Pn 172.16.5.0/24
proxychains curl http://172.16.5.10/Practice Labs & Resources
- HackTheBox Pro Labs (Dante, Offshore, RastaLabs) — purpose-built multi-segment networks specifically requiring SSH/chisel/ligolo-ng pivoting to reach later hosts.
- TryHackMe "Pivoting" and "Network Services" rooms — guided, graded exercises on exactly
-L/-R/-Dforwarding. - OSCP-style labs / PWK — pivoting through a compromised host to reach a second internal subnet is a core exam skill, and SSH dynamic forwarding is the most common technique taught for it.
chiselandligolo-ngon GitHub — once SSH tunneling is second nature, these tools generalize the same concept to non-SSH footholds; worth a follow-up lab session.- PortSwigger "SSRF" labs — while not SSH-specific, they're the most common way a web vulnerability turns into the kind of internal-network access this chapter's tunneling skills exploit.