Detecting and Responding to Port Scans

Intermediate Security

Your firewall or IDS logs are showing systematic probes across a wide range of ports from one or more external IP addresses. A port scan is typically the reconnaissance phase of a broader attack — the attacker is mapping your exposed services before selecting an exploitation vector.

Symptoms

  • Firewall logs showing connection attempts to dozens or hundreds of ports from a single source IP
  • IDS/IPS (Snort, Suricata) raising 'port sweep' or 'port scan' alerts
  • High rate of TCP RST or ICMP port-unreachable responses visible in packet capture
  • Unusual inbound traffic spikes on odd or uncommon port numbers
  • Repeated connections to ports hosting known-vulnerable services (21, 23, 3389, 5900)

Possible Root Causes

  • Automated internet-wide scanning bots (Shodan, Censys, ZMap) cataloguing the internet
  • Targeted reconnaissance by a threat actor prior to an exploitation attempt
  • Compromised host on your own network performing internal lateral movement scanning
  • Misconfigured security scanner or vulnerability assessment tool running on a schedule
  • Worm or malware on a third-party network attempting to propagate to new hosts

Diagnosis Steps

1. Identify port scan patterns in firewall logs

# iptables: log rejected packets to detect scans (add this rule first if not present)
sudo iptables -A INPUT -m recent --name portscan --set -j LOG --log-prefix "PORTSCAN: "
sudo iptables -A INPUT -m recent --name portscan --rcheck --seconds 60 --hitcount 10 -j DROP

# Review existing logged port scan activity
sudo grep "PORTSCAN\|PORT_SCAN\|UFW BLOCK" /var/log/syslog | awk '{print $13}' | grep SRC | sort | uniq -c | sort -rn | head -20

# With ufw (Ubuntu default firewall)
sudo ufw status verbose
sudo grep "UFW BLOCK" /var/log/ufw.log | awk '{print $12}' | sort | uniq -c | sort -rn | head -20

2. Capture the scan in real time with tcpdump

# Capture packets from the suspected scanner (replace 203.0.113.50)
sudo tcpdump -i eth0 -nn host 203.0.113.50 -c 500

# Look for SYN-only packets (half-open / stealth scan signature)
sudo tcpdump -i eth0 -nn 'tcp[tcpflags] & tcp-syn != 0 and tcp[tcpflags] & tcp-ack == 0' -c 200

# Identify UDP scan probes
sudo tcpdump -i eth0 -nn udp and host 203.0.113.50 -c 200

3. Check what services the scanner found open

# See which of YOUR ports are actually open and listening
sudo ss -tlnp    # TCP listening sockets
sudo ss -ulnp    # UDP listening sockets

# Cross-reference with nmap self-scan (from another machine or loopback)
nmap -sV -p 1-65535 YOUR_IP --max-rtt-timeout 200ms

4. Geolocate and assess the scanner

# Whois lookup on scanner IP
whois 203.0.113.50

# Check scanner against threat-intel databases
curl -s "https://ipinfo.io/203.0.113.50/json"

Solution

Block the scanner at the firewall

# Immediate block with iptables
sudo iptables -A INPUT -s 203.0.113.50 -j DROP
sudo iptables -A INPUT -s 203.0.113.50 -j LOG --log-prefix "BLOCKED_SCANNER: "

# Save iptables rules so they persist after reboot
sudo iptables-save | sudo tee /etc/iptables/rules.v4

# With ufw
sudo ufw deny from 203.0.113.50 to any

Auto-block port scanners with iptables recent module

# Detect and block IPs that hit more than 10 ports in 60 seconds
sudo iptables -A INPUT -m recent --name portscan --update --seconds 60 --hitcount 10 -j DROP
sudo iptables -A INPUT -m recent --name portscan --set

Minimise your attack surface

# Drop default-deny all inbound, then whitelist only needed services
sudo iptables -P INPUT DROP
sudo iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 443 -j ACCEPT
sudo iptables -A INPUT -p tcp --dport 22 -s TRUSTED_IP_RANGE -j ACCEPT

# Disable or uninstall unnecessary services
sudo systemctl disable --now telnet vsftpd  # Example unused services

Prevention

  • Default-deny firewall policy: Only open ports you actively use; drop everything else without logging to avoid log flooding.
  • Close unused services: Run ss -tlnp monthly and uninstall or disable services not in use — scanners cannot find services that do not exist.
  • Deploy a honeypot port: Configure a non-functional listener on a common target port (e.g., TCP 23 / telnet) and alert on any connection — instant scan detection.
  • Use fail2ban's port scan jail: The portscan filter in fail2ban auto-bans IPs that generate firewall log entries above a threshold.
  • Subscribe to threat-intel feeds: Use blocklists (Spamhaus DROP, Emerging Threats) in your firewall to pre-emptively block known scanner infrastructure.

Related Protocols

Related Terms

More in Security