C.W.K.
Stream
Lesson 05 of 14 · published

Firewall Basics

~15 min · ufw, pf, firewall, default-deny

Level 0Pinger
0 XP0/101 lessons0/12 achievements
0/150 XP to next level150 XP to go0% complete

Default deny, allow what you need

The right firewall posture is simple: deny everything inbound by default, allow only the specific ports you need. Anything else is reasoning your way to swiss cheese. With key-only SSH + fail2ban + firewall scoped to known sources, you've eliminated 99% of practical attack surface.

ufw on Linux, pf on macOS

Linux ufw (Uncomplicated Firewall) is a friendly front-end to iptables/nftables. macOS ships with the BSD-derived pf packet filter; the GUI "Application Firewall" is a separate, weaker layer. For a fleet, the right pattern is to manage host-level firewalls per OS and trust your LAN/Tailnet boundary as the additional perimeter.

Code

ufw — Linux·bash
# Install (often preinstalled)
sudo apt install ufw

# Default policy: deny in, allow out
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Allow SSH (replace with your real port)
sudo ufw allow 2222/tcp

# Or — only allow SSH from a specific subnet
sudo ufw allow from 192.168.1.0/24 to any port 2222 proto tcp

# Allow common things
sudo ufw allow 80/tcp     # HTTP
sudo ufw allow 443/tcp    # HTTPS

# Enable
sudo ufw enable

# Inspect
sudo ufw status verbose
sudo ufw status numbered

# Remove a rule by number
sudo ufw delete 5
pf — macOS·bash
# Edit /etc/pf.conf (start from the existing template)
# Add rules for your scenario, e.g.:
#   block in all
#   pass in proto tcp from 192.168.1.0/24 to any port 22
#   pass in proto tcp from 100.64.0.0/10 to any port 22

# Load and enable
sudo pfctl -f /etc/pf.conf
sudo pfctl -e

# Inspect
sudo pfctl -s rules
sudo pfctl -sa | head -40

# Disable (testing only)
sudo pfctl -d

External links

Exercise

On a Linux server, set up ufw with default deny + ssh allow only from your LAN range and Tailnet. Confirm sudo ufw status verbose shows the policy. From an outside network (phone tethering), confirm SSH on port 22 is unreachable. From your LAN or via Tailscale, confirm SSH still works. That's the actual production posture.

Progress

Progress is local-only — sign in to sync across devices.
Spotted a bug or have feedback on this page?Report an Issue

Comments 0

🔔 Reply notifications (sign in)
Sign inPlease sign in to comment.

No comments yet — be the first.