DEV Community

Cover image for Server hardening and attack surface reduction
binadit
binadit

Posted on • Originally published at binadit.com

Server hardening and attack surface reduction

Your production servers are probably over-exposing themselves

That fresh server deployment you just spun up? It's likely running dozens of services you didn't ask for, listening on ports you don't need, and giving applications way more privileges than necessary. Welcome to the wonderful world of default configurations, where convenience beats security every single time.

As engineers, we know this intellectually, but the pressure to ship fast means hardening often gets pushed to "later." The problem is that attackers aren't waiting for later.

The real cost of "we'll secure it tomorrow"

I've seen teams lose entire weekends rebuilding compromised systems because someone exploited a default SSH configuration. Others have faced regulatory fines when attackers moved laterally through their network via unnecessary services running as root.

The pattern is always the same: default installation, rushed deployment, eventual compromise through something that should never have been running in production.

Why defaults work against you

Vendors optimize for successful installations, not secure ones. That Ubuntu server comes with Bluetooth drivers you'll never use. Your web application server might be running print services. Your headless database server probably installed desktop packages.

Here's what I typically find on "standard" deployments:

# Services you didn't know were running
sudo systemctl list-units --state=running | grep -v essential

# Ports you didn't mean to open  
sudo netstat -tlnp | wc -l  # Often 15+ ports

# Users with more access than needed
grep -E '^[^:]*:[^:]*:[0-9]{4}:' /etc/passwd
Enter fullscreen mode Exit fullscreen mode

Common hardening mistakes that bite back

Breaking dependencies by disabling services blindly
I've watched engineers disable what looked like unnecessary services, only to discover their monitoring system depended on them. Always map dependencies first.

Inconsistent hardening across environments
Hardening your web servers while leaving your internal APIs with default configs is like locking your front door but leaving windows open.

Security theater that doesn't survive updates
Those careful firewall rules you crafted? They might get reset during the next OS update if you didn't configure them properly.

A systematic approach that actually works

Start with service inventory

# Document everything running
sudo systemctl list-units --type=service --state=running > services_audit.txt

# For each service, ask: what breaks if I disable this?
sudo systemctl disable unnecessary-service
sudo systemctl mask unnecessary-service  # Prevent accidental re-enabling
Enter fullscreen mode Exit fullscreen mode

Network surface reduction

# Default deny, explicit allow
sudo ufw --force reset
sudo ufw default deny incoming
sudo ufw default allow outgoing

# Only open what you actually need
sudo ufw allow from 10.0.0.0/8 to any port 22  # SSH from internal only
sudo ufw allow 443  # HTTPS only, not HTTP
sudo ufw enable
Enter fullscreen mode Exit fullscreen mode

Privilege boundaries

# Create service-specific users
sudo useradd -r -s /bin/false -d /var/lib/myapp myapp

# Run applications with minimal privileges
# In your systemd service file:
[Service]
User=myapp
Group=myapp
NoNewPrivileges=true
PrivateDevices=true
ProtectSystem=strict
Enter fullscreen mode Exit fullscreen mode

File system restrictions

# Mount with security options
# In /etc/fstab:
/dev/sdb1 /var/www ext4 defaults,noexec,nosuid,nodev 0 2
tmpfs /tmp tmpfs defaults,noexec,nosuid,nodev,size=1G 0 0
Enter fullscreen mode Exit fullscreen mode

Real impact: before and after

Recently worked with a team running a Django application on "standard" Ubuntu servers. Before hardening: 23 open ports, 47 security findings from vulnerability scans, services running as root.

After systematic hardening: 3 open ports (HTTPS, restricted SSH, database), 3 low-severity findings, all services running under dedicated accounts.

The kicker? System performance improved because we weren't running unnecessary background processes.

Implementation strategy

Week 1: Discovery

  • Audit all running services and open ports
  • Document what each service actually does
  • Identify quick wins (services you can safely disable)

Week 2: Network hardening

  • Implement restrictive firewall rules
  • Segment internal network traffic
  • Test everything still works

Week 3: Privilege reduction

  • Create service-specific user accounts
  • Remove unnecessary sudo access
  • Implement file system restrictions

Week 4: Monitoring and validation

  • Set up logging for security events
  • Run vulnerability scans
  • Document your hardened baseline

The bottom line

Server hardening isn't about implementing every security control you can find. It's about understanding exactly what your system needs to function, then ruthlessly removing everything else.

Start small, document everything, and test thoroughly. Your future self (and your incident response team) will thank you.

Originally published on binadit.com

Top comments (0)