1. Library
  2. Ports
  3. Security

Updated 10 hours ago

Every open port is a service. Every service is code. Every piece of code parsing untrusted network input is a vulnerability waiting to be discovered.

This isn't paranoia—it's math. More code processing network data means more opportunities for bugs. A buffer overflow in a printing service you've never used can compromise your entire system just as effectively as one in your web server. The difference is that you chose to run the web server.

The Question That Matters

Most security guides start with "what should I block?" This is the wrong question. The right question is: what do I actually need?

A web server needs ports 80 and 443. An SSH server needs port 22. A database server needs its database port—but only from application servers, not from the entire Internet. Everything else is risk without reward.

This mental shift—from blocking bad things to allowing only necessary things—is the foundation of real security. It's called default-deny, and it changes everything.

Finding What's Listening

Before you can close ports, you need to see what's open.

On Linux, ss -tulpn shows all listening TCP and UDP ports with their associated processes. The output tells you not just that port 631 is open, but that it's CUPS—the printing system. If you don't print, that's code running for no reason.

On macOS, lsof -i -P -n provides similar information. On Windows, netstat -ano shows listening ports with process IDs you can cross-reference in Task Manager.

For the external view—what the network can actually reach—scan yourself with nmap -sT localhost or, better, scan from another machine to see what's visible through your firewall.

You'll likely find surprises. Default installations run services you never asked for: network discovery protocols, remote procedure calls, printer sharing, file sharing. Each one is code waiting for packets.

Stopping What You Don't Need

Once you know what's running, evaluate each service: Do I use this? Will I ever use this?

On systemd Linux (Ubuntu, Fedora, Debian), disable a service permanently:

sudo systemctl disable --now cups.service    # printing
sudo systemctl disable --now avahi-daemon    # network discovery
sudo systemctl disable --now bluetooth       # bluetooth

The --now flag stops it immediately and prevents it from starting at boot. One command, one fewer attack vector.

On macOS, services live in /Library/LaunchDaemons/ and ~/Library/LaunchAgents/. Unload them with launchctl unload /path/to/service.plist.

On Windows, open Services (services.msc), find the service, stop it, and set its startup type to Disabled. Or use PowerShell: Set-Service -Name "ServiceName" -StartupType Disabled -Status Stopped.

The Firewall as Safety Net

Stopping services is primary. Firewalls are backup.

Even with services disabled, configure your firewall to block by default. If malware tries to open a listener, or if you accidentally enable something, the firewall catches it.

On Linux with UFW:

sudo ufw default deny incoming
sudo ufw allow 22/tcp       # SSH, if you need it
sudo ufw allow 80/tcp       # HTTP, if you're serving web
sudo ufw allow 443/tcp      # HTTPS
sudo ufw enable

Start with nothing allowed. Add only what you need. Document why.

For tighter control, restrict ports to specific sources. If you only SSH from your home network:

sudo ufw allow from 192.168.1.0/24 to any port 22

Now port 22 is open, but only to your network. The rest of the Internet sees nothing.

On Windows, use Windows Defender Firewall or PowerShell:

New-NetFirewallRule -DisplayName "Block SMB" -Direction Inbound -LocalPort 445 -Protocol TCP -Action Block

Segmentation: Limiting Blast Radius

Some ports must be open. The question becomes: open to whom?

A database server needs its port accessible—but only to application servers, never to the Internet. Place it on an internal network segment. The application servers live in a DMZ with strict rules: they can talk to the database, but the database can't initiate connections outward.

If an attacker compromises the web application, they reach the database—but the database can't reach further. The blast radius is contained.

This is defense in depth: layers of restrictions so that compromising one system doesn't compromise everything.

The Ongoing Practice

Port hygiene isn't a one-time task. Systems drift. You install something for testing and forget to remove it. Updates enable new services. Dependencies pull in daemons you didn't expect.

Periodically—monthly is reasonable—run your port discovery commands again. Compare against what you expect. Investigate anything new. Remove anything unused.

The goal is intentionality. Every open port should be there because you chose it, you need it, and you've restricted it as tightly as possible.

Frequently Asked Questions About Closing Unnecessary Ports

Was this page helpful?

😔
🤨
😃