Level 1 First matching rule for one address
Build Firewall(rules). rules is an ordered list of (action, block) pairs:
actionis"ALLOW"or"DENY".blockis an IPv4 block in CIDR form such as"172.16.4.0/22", or a bare address such as"8.8.4.4", which means/32. The prefix length can be anything from/0to/32. If the base address has bits set past the prefix ("10.9.9.9/8"), ignore them: that block is the same as"10.0.0.0/8".
check(ip) -> str takes a dotted-quad address and returns the action of the earliest rule in the list whose block contains it. If no rule matches, return "DENY".
Up to 10,000 rules and 100,000 check calls may be made on one firewall, so do the parsing once in the constructor and avoid scanning every rule for every call.
fw = Firewall([
("DENY", "172.16.4.8/29"), # 172.16.4.8 .. 172.16.4.15
("ALLOW", "172.16.0.0/16"),
("DENY", "0.0.0.0/0"),
])
fw.check("172.16.4.12") # "DENY" the first rule wins
fw.check("172.16.4.16") # "ALLOW"
fw.check("9.9.9.9") # "DENY" caught by /0
Firewall([]).check("1.2.3.4") # "DENY" nothing matched
Show hint
an address is a 32-bit integer, and a /p block is every address that shares its top p bits.