Back to lessons

Cybersecurity Triage

Find Public Listeners Not Allowed by UFW

You need to find publicly bound listening ports that are not listed as UFW allow rules.

Command

comm -13 <(ufw status numbered | awk '/ALLOW/ {print}' | grep -Eo '[0-9]+/(tcp|udp)' | cut -d/ -f1 | sort -u) <(ss -ltnp | awk '$4 ~ /^(0[.]0[.]0[.]0|[[]::[]]|[*]):/ {n=split($4,a,":"); print a[n]}' | sort -u)

What changed

Nothing changes. The shell compares public listener ports with allowed firewall ports.

Danger

safe

When to use it

Use when checking for services that may be bound publicly without an explicit host firewall allow rule.

When not to use it

Do not assume the service is internet reachable without checking default policy, provider firewalls, container NAT, and IPv6.

Undo or recovery

No undo needed because this command is read-only.

Expected output

Public listener port numbers that do not appear in UFW allow rules.

demo script

Disposable terminal steps

  1. ss -ltnp | awk 'NR==1 || $4 ~ /^(0[.]0[.]0[.]0|[[]::[]]|[*]):/'
  2. ufw status numbered
  3. comm -13 <(ufw status numbered | awk '/ALLOW/ {print}' | grep -Eo '[0-9]+/(tcp|udp)' | cut -d/ -f1 | sort -u) <(ss -ltnp | awk '$4 ~ /^(0[.]0[.]0[.]0|[[]::[]]|[*]):/ {n=split($4,a,":"); print a[n]}' | sort -u)

simulated output

What it looks like

disposable vessel
::fixture-ready::
$ ss -ltnp | awk 'NR==1 || $4 ~ /^(0[.]0[.]0[.]0|[[]::[]]|[*]):/'
State  Recv-Q Send-Q Local Address:Port Peer Address:Port Process
LISTEN 0      128          0.0.0.0:22        0.0.0.0:*     users:(("sshd",pid=801,fd=3))
LISTEN 0      511          0.0.0.0:80        0.0.0.0:*     users:(("nginx",pid=1907,fd=6))
LISTEN 0      511          0.0.0.0:443       0.0.0.0:*     users:(("nginx",pid=1907,fd=7))
LISTEN 0      64           0.0.0.0:9000      0.0.0.0:*     users:(("node",pid=2219,fd=18))
::exit-code::0
$ ufw status numbered
Status: active

     To                         Action      From
     --                         ------      ----
[ 1] 22/tcp                     ALLOW IN    203.0.113.0/24
[ 2] 80/tcp                     ALLOW IN    Anywhere
[ 3] 443/tcp                    ALLOW IN    Anywhere
[ 4] 25/tcp                     ALLOW IN    Anywhere
[ 5] 5432/tcp                   DENY IN     Anywhere
::exit-code::0
$ comm -13 <(ufw status numbered | awk '/ALLOW/ {print}' | grep -Eo '[0-9]+/(tcp|udp)' | cut -d/ -f1 | sort -u) <(ss -ltnp | awk '$4 ~ /^(0[.]0[.]0[.]0|[[]::[]]|[*]):/ {n=split($4,a,":"); print a[n]}' | sort -u)
9000
::exit-code::0

YouTube Short

Find unlisted public listeners.

Compare public listeners with allowed firewall ports. A wildcard-bound service outside policy deserves review.

LinkedIn hook

The process was public, but the firewall did not mention it.

Question: Do you compare public listeners against firewall allow rules during hardening?

experiments

A/B tests to run

Metric: completion_rate

A: Public but not declared.

B: Find listeners outside policy.