Network segmentation limits the blast radius of a security breach by isolating services into separate network zones. Even on a single VPS, you can use iptables, Docker networks, and Linux network namespaces to implement effective segmentation.
Why Network Segmentation on a Single Server?
- Prevents lateral movement if one service is compromised
- Restricts database access to only the application server
- Isolates untrusted workloads from sensitive services
- Meets compliance requirements (PCI-DSS, SOC 2)
Method 1: iptables Internal Filtering
# Block external access to database ports
sudo iptables -A INPUT -p tcp --dport 3306 -s 127.0.0.1 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 3306 -j DROP
# Block external access to Redis
sudo iptables -A INPUT -p tcp --dport 6379 -s 127.0.0.1 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 6379 -j DROP
# Save rules
sudo iptables-save | sudo tee /etc/iptables/rules.v4
Method 2: Docker Network Isolation
# Create separate networks for different tiers
docker network create --driver bridge frontend
docker network create --driver bridge backend
docker network create --internal --driver bridge database
# The --internal flag prevents external access entirely
# Architecture:
# frontend network: nginx (public-facing)
# backend network: app (connects frontend and database)
# database network: mysql, redis (isolated)
Method 3: systemd Service Isolation
# Use systemd to restrict network access per service
# In the service override:
# IPAddressAllow=127.0.0.1/8 ::1/128
# IPAddressDeny=any
# PrivateNetwork=false
# RestrictAddressFamilies=AF_INET AF_INET6 AF_UNIX
Method 4: Service Binding
# Bind services to localhost only
# MySQL: bind-address = 127.0.0.1
# Redis: bind 127.0.0.1 ::1
# PostgreSQL: listen_addresses = localhost
# MongoDB: bindIp: 127.0.0.1
Verification
# Verify services are only listening on localhost
ss -tlnp | grep -E "3306|6379|5432|9200"
# Should show 127.0.0.1:PORT, NOT 0.0.0.0:PORT
# Test from external (should fail)
nmap -p 3306,6379,5432 YOUR_SERVER_IP