sysop@hub:~/tools/firewall-rule-reviewer$
firewall-rule-reviewer
Firewall rule lists grow for years and nobody reads them from top to bottom. Drop yours here and see what is really open: remote administration and databases reachable from the internet, port ranges wider than anyone meant, rules that can never apply because an earlier one overrules them, and every rule rewritten as one plain sentence. The rules are read by your browser and never uploaded.
getting the rules
| Source | How | Notes |
|---|---|---|
| Azure network security groups | az network nsg list -o json > nsgs.json | All NSGs of the subscription in one file. A single NSG, a rule list or an exported ARM template work too. |
| Linux, iptables | sudo iptables-save > rules.txt | Also reads the output of iptables -S. With nftables, iptables-save still works when the iptables-nft layer is installed. |
| Windows Firewall | The script below writes firewall.csv. | Enabled inbound allow rules with their ports and addresses. |
| Any other firewall | Export the rules as CSV, or build the table in a spreadsheet. | The first line holds the column names. Needed: Action and Port or Source. Understood as well: Name, Direction, Destination, Protocol, Enabled, Priority, Group, Description. The row order counts as the rule order. |
The Windows Firewall export. Run it in an elevated PowerShell on the machine, then drop firewall.csv above. It only reads.
Get-NetFirewallRule -Enabled True -Direction Inbound -Action Allow | ForEach-Object {
$p = $_ | Get-NetFirewallPortFilter
$a = $_ | Get-NetFirewallAddressFilter
[pscustomobject]@{
Name = $_.DisplayName
Direction = $_.Direction
Action = $_.Action
Enabled = $_.Enabled
Profile = $_.Profile
Protocol = $p.Protocol
LocalPort = $p.LocalPort -join ','
RemoteAddress = $a.RemoteAddress -join ','
LocalAddress = $a.LocalAddress -join ','
}
} | Export-Csv firewall.csv -NoTypeInformation -Encoding UTF8
what it checks
| Check | Triggers when | Severity |
|---|---|---|
| Everything open | An inbound rule allows every port from any source. | critical |
| Remote administration | SSH, RDP, WinRM, Telnet, VNC, the Docker API or the Kubelet are allowed from any source. | critical |
| Databases | SQL Server, MySQL, PostgreSQL, Oracle, MongoDB, Redis, Elasticsearch, Memcached and similar are allowed from any source. | critical |
| File sharing and RPC | SMB, NetBIOS, Windows RPC or NFS are allowed from any source. | critical |
| Directory services | LDAP, LDAPS, Kerberos or the Global Catalog are allowed from any source. | high |
| Cleartext protocols | FTP, TFTP, POP3, IMAP or SNMP are allowed from any source. | high |
| Wide port ranges | A range of 1,000 ports or more is allowed from any source. | high |
| Accept by default | iptables only: the INPUT or FORWARD policy is ACCEPT and no final rule drops the rest. | high |
| Rules that never apply | An earlier rule with the opposite decision covers the rule completely. | medium |
| Flat internal network | A whole private network (/16 or larger, or the VirtualNetwork tag) is allowed on every port. | medium |
| Very large source ranges | A public source range larger than a /16. | medium |
| Outbound not restricted | Everything may go out, by rule or by default. | medium or info |
| Redundant and disabled rules | Covered by an earlier rule with the same decision, or switched off. | info |
The page reads rules, it does not test the network. It cannot know what is attached behind a rule, whether a second firewall sits in front, or whether a port is really in use. Address groups, service objects and negated matches are compared by name only or left out, and IPv6 ranges are compared as text. Treat the result as a reading aid for a review, then confirm from outside, for example with the domain check or a port scan you are allowed to run. Related: Azure networking cheat sheet, networking cheat sheet, server hardening checklist.