Block outgoing traffic to private networks with UFW

3 min
VPS/VDS Hosting

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:
Bash
sudo apt update && sudo apt install -y ufw
  • A second SSH session kept open while you change the firewall.

🧭 Which ranges to block

RangeUse
10.0.0.0/8RFC1918 private
172.16.0.0/12RFC1918 private
192.168.0.0/16RFC1918 private
100.64.0.0/10Carrier-grade NAT (RFC6598)
169.254.0.0/16IPv4 link-local
192.0.0.0/24IETF protocol assignments
198.18.0.0/15Benchmarking
fc00::/7IPv6 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:

Bash
ip 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.

Bash
sudo 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:

Bash
sudo 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):

Bash
sudo 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:

Bash
sudo 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:

Bash
sudo 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:

TEXT
1# 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:

Bash
sudo 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:

Bash
sudo 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:

Bash
sudo 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.

Stay up to date with the latest offers, discounts and special promotions.

View promotions

We use cookies

We use analytics cookies to improve your experience on our site. No data is sold to third parties. Learn more in our privacy policy.