Unix Networking and Security Basics

Most of this stuff I learned by breaking things. SSH config in particular has a way of locking you out of a remote box at the worst possible time. These are the commands and concepts I actually use, with the caveats that took me a while to figure out.

Checking What's Listening

Before anything else — know what's running on your machine:

$ ss -tlnp       # TCP, listening, numeric, show process
$ ss -ulnp       # UDP version
$ netstat -tlnp  # older alternative, same idea
$ lsof -i :22    # what's using a specific port

ss is the modern replacement for netstat. On current Linux systems they're both available but ss is faster and more complete.

Network Interface Management

The modern way to manage interfaces is with the ip command. ifconfig still works on most systems but it's been deprecated for years.

$ ip addr show              # all interfaces and their addresses
$ ip addr show eth0         # specific interface
$ ip link set eth0 up       # bring interface up
$ ip link set eth0 down     # bring it down

# Add/remove an address temporarily (lost on reboot)
$ ip addr add 192.168.1.100/24 dev eth0
$ ip addr del 192.168.1.100/24 dev eth0

Routing

$ ip route show                          # routing table
$ ip route add default via 192.168.1.1   # set default gateway
$ ip route add 10.0.0.0/8 via 10.0.0.1  # add a static route

SSH — The Right Way

The default SSH config leaves a lot on the table. A few things worth setting up properly:

Key-Based Auth

# Generate a key (ed25519 is better than the old rsa default)
$ ssh-keygen -t ed25519 -C "jason@mymachine"

# Copy public key to remote server
$ ssh-copy-id user@remote_host

# Or manually:
$ cat ~/.ssh/id_ed25519.pub | ssh user@host "mkdir -p ~/.ssh && cat >> ~/.ssh/authorized_keys"

Locking Down sshd_config

Edit /etc/ssh/sshd_config — make your changes, test with a second session still open before restarting, and don't close that session until you've confirmed you can still log in:

PermitRootLogin no
PasswordAuthentication no
PubkeyAuthentication yes
AuthorizedKeysFile .ssh/authorized_keys
AllowUsers jason             # whitelist specific users
MaxAuthTries 3
# Test the config before reloading
$ sshd -t

# Reload (not restart — keeps existing sessions alive)
$ systemctl reload sshd

Lock yourself out of a remote server doing this once and you'll always test with a second session after that.

SSH Config File (~/.ssh/config)

This one saves a lot of typing:

Host myserver
    HostName 203.0.113.10
    User jason
    IdentityFile ~/.ssh/id_ed25519
    Port 2222

Host *.internal
    User admin
    ProxyJump bastion.example.com

After this, ssh myserver just works.

Firewalls

ufw (Ubuntu/Debian)

The friendliest firewall interface on Linux:

$ ufw status verbose
$ ufw allow 22/tcp
$ ufw allow 80/tcp
$ ufw allow from 192.168.1.0/24 to any port 5432   # postgres from local net only
$ ufw deny 23/tcp
$ ufw enable
$ ufw reload

iptables

Lower level, more control. Most people use ufw or firewalld instead, but iptables rules are what's actually running underneath:

$ iptables -L -n -v           # list all rules with packet counts
$ iptables -A INPUT -p tcp --dport 22 -j ACCEPT
$ iptables -A INPUT -p tcp --dport 80 -j ACCEPT
$ iptables -A INPUT -j DROP   # default deny (put this last)

iptables rules don't persist across reboots by default. Use iptables-save and iptables-restore, or just use ufw.

Diagnostic Tools

$ ping -c 4 8.8.8.8          # basic reachability check
$ traceroute 8.8.8.8         # where packets are going
$ mtr 8.8.8.8                # traceroute that updates live (better)
$ dig google.com             # DNS lookup
$ dig @8.8.8.8 google.com    # DNS lookup using a specific server
$ curl -I https://example.com    # check HTTP headers
$ tcpdump -i eth0 port 80    # capture HTTP traffic (needs root)
$ tcpdump -i eth0 -w dump.pcap   # save for later analysis in Wireshark

Fail2ban

If your SSH port is exposed to the internet, you will get brute-force attempts constantly. Fail2ban watches your logs and bans IPs that fail too many times:

$ apt install fail2ban
$ cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local

In /etc/fail2ban/jail.local:

[sshd]
enabled = true
port = ssh
maxretry = 5
bantime = 3600
findtime = 600
$ systemctl enable fail2ban
$ systemctl start fail2ban
$ fail2ban-client status sshd    # see current bans
$ fail2ban-client set sshd unbanip 1.2.3.4   # unban an IP