When one address hammers your login page or scans your server all day, the quickest answer is to block it at the firewall. UFW makes this a one-line job, with one catch: rule order. This guide shows how to block a single IP or a whole range so that the block really applies, how to find the addresses worth blocking and how to lift a block later.
Before you start
- A Linux VPS running Ubuntu 22.04, Ubuntu 24.04 or Debian 12 with UFW active and SSH allowed. See Set up the UFW firewall on Ubuntu and Debian if needed.
- A
sudouser connected over SSH. - Your own public IP address. On your computer, search "what is my IP" or run
curl -4 ifconfig.me.
Warning: Check that the address or range you block does not include your own IP. Blocking a /16 or larger range can easily catch your home or office connection and cut off SSH. If that happens, log in through the browser console in your VPS provider's control panel and delete the rule.
Why rule order matters
UFW checks rules from the top and uses the first one that matches. New rules go to the bottom of the list. So if your list starts with ALLOW 80/tcp Anywhere, a later DENY from 198.51.100.20 never applies to web traffic: the allow rule matches first.
The fix is to insert deny rules at the top with insert 1 (or prepend on newer UFW versions).
Block a single IP
sudo ufw insert 1 deny from 198.51.100.20 comment 'SSH brute force'This drops all traffic from that address to every port. To block it from one port only:
sudo ufw insert 1 deny from 198.51.100.20 to any port 22 proto tcpdeny or reject
- deny silently drops packets. The sender waits and times out. This is the normal choice for attackers.
- reject sends back an error so the sender knows straight away. Use it for internal hosts you want to fail fast.
sudo ufw insert 1 reject from 198.51.100.20Block a subnet
Use CIDR notation to block a range in one rule:
sudo ufw insert 1 deny from 198.51.100.0/24 comment 'Scanner range'/24 covers 256 addresses (198.51.100.0 to 198.51.100.255). A /16 covers 65,536. Read CIDR notation and subnets explained before blocking anything larger than a /24.
IPv6 addresses
IPv6 deny rules belong in the IPv6 part of the list. insert 1 works for an IPv6 rule only if position 1 is an IPv6 rule, which it usually is not. Use prepend if your UFW version has it:
sudo ufw prepend deny from 2001:db8:1234::/48Otherwise run sudo ufw status numbered, find the first (v6) rule and insert at that number. Attackers with IPv6 often hold a whole /64 or larger, so blocking a single IPv6 address rarely helps.
Find attacking IPs in your logs
Failed SSH logins. Count the addresses behind failed password attempts:
sudo journalctl -u ssh --since today | grep 'Failed password' | grep -oE 'from [0-9a-f.:]+' | sort | uniq -c | sort -rn | headOn Ubuntu 22.04 and Debian 12 the unit may be named ssh or sshd; if one returns nothing, try the other.
Firewall blocks. If UFW logging is on, see who is hitting closed ports most:
sudo journalctl -k --since today | grep 'UFW BLOCK' | grep -o 'SRC=[^ ]*' | sort | uniq -c | sort -rn | headWeb attacks. Check your Nginx access log for repeated hits on login pages:
sudo awk '{print $1}' /var/log/nginx/access.log | sort | uniq -c | sort -rn | headManual blocks suit a handful of persistent offenders. For the constant flow of bots, let Fail2ban ban and unban automatically; see Install and configure Fail2ban. For thousands of addresses, an ipset or nftables set is far faster than one UFW rule per IP.
Check it works
List the rules and confirm the deny sits above any allow rule for the same traffic:
sudo ufw status numbered[ 1] Anywhere DENY IN 198.51.100.20 # SSH brute force
[ 2] 22/tcp ALLOW IN Anywhere
[ 3] 443/tcp ALLOW IN AnywhereWith logging on, blocked attempts from that address now appear as [UFW BLOCK] lines with SRC=198.51.100.20.
Unblock an IP later
Delete by number, after listing again:
sudo ufw status numbered
sudo ufw delete 1Or delete by repeating the exact rule text:
sudo ufw delete deny from 198.51.100.20Comments help here. A rule tagged with a reason and date is easy to review and remove months later.
Troubleshooting
- The blocked IP still gets through: the deny rule is below an allow rule. Delete it and add it again with
insert 1. - "ERROR: Invalid position": you tried to insert an IPv4 rule among IPv6 rules, or the reverse. Choose a number inside the right block, or use
prepend. - You blocked yourself: use your VPS provider's browser console, run
sudo ufw status numberedand delete the rule. See Locked out by your firewall? How to get back in. - The attacker keeps coming back from new IPs: block the range, or rely on Fail2ban and key-only SSH logins.
Next steps
- Manage the rules you have built up: Delete, insert and reorder UFW rules safely.
- See who you are blocking: Read and tune UFW firewall logs.
