When a compromised script or a misconfigured application starts probing 10.x or 192.168.x addresses, the traffic leaves your server and often triggers abuse reports from the network. Blocking outbound connections to private ranges is a simple safeguard on any VPS Linux Infrawire. This guide shows how to do it with UFW without breaking DNS or your own connectivity.
📋 Prerequisites
- A VPS with root SSH access, on Ubuntu 24.04 or Debian 12 (UFW is available on both).
- Basic knowledge of UFW. If it is not installed yet:
Bashsudo apt update && sudo apt install -y ufw
- A second SSH session kept open while you change the firewall.
🧭 Which ranges to block
| Range | Use |
|---|---|
10.0.0.0/8 | RFC1918 private |
172.16.0.0/12 | RFC1918 private |
192.168.0.0/16 | RFC1918 private |
100.64.0.0/10 | Carrier-grade NAT (RFC6598) |
169.254.0.0/16 | IPv4 link-local |
192.0.0.0/24 | IETF protocol assignments |
198.18.0.0/15 | Benchmarking |
fc00::/7 | IPv6 unique local addresses |
Do not block fe80::/10: IPv6 uses link-local addresses for neighbor discovery and often for the default gateway, so blocking it cuts IPv6 entirely.
🔍 Check what your VPS really needs first
If your gateway or DNS resolver sits in a private range, a blanket block will cut your network. Look at your configuration before adding any rule:
Baship route ip -6 route cat /etc/resolv.conf resolvectl status | grep -E 'DNS Servers|Link'
If a resolver or a service you depend on has a private address (PRIVATE_DNS_IP), allow it explicitly and place that rule first, as shown below. If everything you use is public, you can skip that step.
🧱 Method 1: ufw deny out
Make sure SSH stays reachable, then set the default policies. Inbound replies to your SSH sessions are not affected by outbound rules on private ranges.
Bashsudo ufw allow 22/tcp sudo ufw default deny incoming sudo ufw default allow outgoing
If you need an exception, insert it at position 1 so it is evaluated before the denials:
Bashsudo ufw insert 1 allow out to PRIVATE_DNS_IP port 53
Now add the denials, one per range (UFW rules are evaluated in order, first match wins):
Bashsudo ufw deny out to 10.0.0.0/8 sudo ufw deny out to 172.16.0.0/12 sudo ufw deny out to 192.168.0.0/16 sudo ufw deny out to 100.64.0.0/10 sudo ufw deny out to 169.254.0.0/16 sudo ufw deny out to 192.0.0.0/24 sudo ufw deny out to 198.18.0.0/15 sudo ufw deny out to fc00::/7 sudo ufw enable
ufw enable may warn that it can disrupt SSH connections; since port 22 is allowed, answer y. Review the order with:
Bashsudo ufw status numbered
📄 Method 2: before.rules
If you prefer a single block of rules that is applied before the user rules, edit /etc/ufw/before.rules. Back it up first:
Bashsudo cp /etc/ufw/before.rules /etc/ufw/before.rules.bak sudo nano /etc/ufw/before.rules
In the *filter section, after the lines that accept loopback and established connections, add:
TEXT1# Block outbound traffic to private networks 2-A ufw-before-output -d 10.0.0.0/8 -j REJECT 3-A ufw-before-output -d 172.16.0.0/12 -j REJECT 4-A ufw-before-output -d 192.168.0.0/16 -j REJECT 5-A ufw-before-output -d 100.64.0.0/10 -j REJECT 6-A ufw-before-output -d 169.254.0.0/16 -j REJECT
IPv6 has its own file, /etc/ufw/before6.rules, with the chain ufw-before-output:
TEXT-A ufw-before-output -d fc00::/7 -j REJECT
Put an exception for PRIVATE_DNS_IP just above these lines with -A ufw-before-output -d PRIVATE_DNS_IP -j ACCEPT. Reload:
Bashsudo ufw reload
REJECT answers immediately with an error, so applications fail fast instead of waiting for a timeout. Use -j DROP if you prefer silence.
✅ Verify
The rules must be loaded and blocked destinations must fail, while public ones keep working:
Bashsudo ufw status verbose ping -c 1 10.0.0.1 # must fail ping -c 1 192.168.1.1 # must fail curl -m 5 http://10.0.0.1 # must fail ping -c 2 1.1.1.1 # must succeed dig +short example.com # must resolve curl -I https://www.debian.org
With ufw deny out the failed ping typically reports Operation not permitted. Packet counters confirm the hits:
Bashsudo iptables -L ufw-user-output -n -v sudo iptables -L ufw-before-output -n -v
🛠️ Troubleshooting
DNS stopped working. Your resolver is in a private range. Remove or fix the order with sudo ufw status numbered, then add sudo ufw insert 1 allow out to PRIVATE_DNS_IP port 53. You can also switch to a public resolver in your network configuration.
IPv6 is broken after the change. You probably blocked fe80::/10 or a gateway in fc00::/7. Remove the rule with sudo ufw delete deny out to fc00::/7 and re-add only what is needed.
You are locked out of a service in a private network (VPN, internal API). Add an allow rule for that exact address with ufw insert 1 allow out to PRIVATE_IP. If you are locked out of SSH itself, use any console access to the server and run sudo ufw disable.
🔒 Your VPS can no longer scan private networks by accident: abuse reports of this kind should stop.