L11. Reducing Attack Surface: Services, Ports and Daemons
Video generating
Check back soon for the video lesson on Reducing Attack Surface: Services, Ports and Daemons
Every running service is a potential entry point for an attacker. Learn how to audit running services with systemctl, identify open ports with ss, and disable or remove anything your server does not need.
What Is Attack Surface?
Attack surface is the total number of points where an attacker could try to enter or extract data from your system. Every running service, open port, and installed package adds to this surface. A hardened server runs only what it needs and nothing more.
Think of it this way: if your server's only job is to serve a web application, it should not be running a mail server, a print service, or a database it does not use. Each unnecessary service is a liability.
Understanding systemd Services
Most modern Linux distributions use systemd as their init system. systemd manages services (also called units) through the systemctl command.
Service States
| State | Meaning |
|---|---|
| active (running) | The service is currently running |
| active (exited) | The service ran a one-time task and finished |
| inactive (dead) | The service is not running |
| enabled | The service starts automatically at boot |
| disabled | The service does not start at boot |
Listing Running Services
# Show all running services
systemctl list-units --type=service --state=running# Show all enabled services (start at boot)
systemctl list-unit-files --type=service --state=enabled
Managing Services
# Stop a running service immediately
sudo systemctl stop cups.service# Prevent it from starting at boot
sudo systemctl disable cups.service
# Do both in one command
sudo systemctl disable --now cups.service
# Check the status of a specific service
systemctl status sshd.service
Common Services You Can Safely Disable
On a fresh server install, several services may be running that you do not need:
| Service | Purpose | Disable If... |
|---|---|---|
| cups / cups-browsed | Printing | Server has no printers |
| avahi-daemon | mDNS/DNS-SD discovery | Not needed on servers |
| bluetooth | Bluetooth support | No Bluetooth hardware |
| ModemManager | Cellular modem support | No modems |
| accounts-daemon | User account info for desktop | Headless server |
# Example: disable printing and discovery services
sudo systemctl disable --now cups cups-browsed avahi-daemon
Finding Open Ports
A running service often listens on a network port. Even if you do not know which services are running, you can discover them by checking which ports are open.
Using ss (Socket Statistics)
# Show all listening TCP ports with the process name
sudo ss -tlnp# Show all listening UDP ports
sudo ss -ulnp
# Example output:
# LISTEN 0 128 0.0.0.0:22 0.0.0.0:* users:(("sshd",pid=1234,fd=3))
# LISTEN 0 511 0.0.0.0:80 0.0.0.0:* users:(("nginx",pid=5678,fd=6))
The -t flag filters TCP, -l shows only listening sockets, -n shows numeric ports instead of service names, and -p shows the process that owns each socket.
Using netstat (Legacy)
# Equivalent command with netstat
sudo netstat -tlnp
ss is the modern replacement for netstat and is available on all current distributions. Use ss unless you are on a very old system.
Investigating Unknown Services
If you find a port open and do not recognize the service:
# Find which process is using port 8080
sudo ss -tlnp | grep 8080# Get details about the process
ps aux | grep <PID>
# Check which package owns the binary
dpkg -S /usr/bin/some-binary # Debian/Ubuntu
rpm -qf /usr/bin/some-binary # RHEL/CentOS
Removing Unneeded Packages
Disabling a service stops it from running, but the software remains installed. Removing the package entirely is more thorough:
# Debian/Ubuntu
sudo apt remove --purge telnet rsh-client
sudo apt autoremove# RHEL/CentOS
sudo dnf remove telnet rsh
Removing packages also removes their configuration files (with --purge), which eliminates the risk of a misconfiguration reactivating them later.
A Practical Audit Workflow
- List all running services:
systemctl list-units --type=service --state=running - List all open ports:
sudo ss -tlnp - For each unknown entry, identify the process and decide: does this server need it?
- Disable and stop services that are not needed
- Remove packages you will never use
- Document what you disabled and why
This audit should be part of your initial server setup and repeated periodically. New packages installed by team members can introduce services you did not plan for.
- ✓Every running service and open port increases the attack surface: run only what the server needs
- ✓systemctl disable --now stops a service immediately and prevents it from starting at boot
- ✓ss -tlnp shows all listening TCP ports along with the process name that owns each socket
- ✓Removing unneeded packages with --purge is more thorough than just disabling the service
1. What does the command "systemctl disable --now cups.service" do?
2. Which command shows all listening TCP ports along with the owning process on a modern Linux system?
3. Why is removing an unneeded package more secure than just disabling its service?