Last active
April 7, 2020 10:52
-
-
Save craigphicks/b596ae415ac8325f6b331826cd2b2d64 to your computer and use it in GitHub Desktop.
Convert `iptables -S` output to a depth-first tree listing
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/usr/bin/env python3 | |
''' | |
Convert `iptables -S` output to a depth-first tree listing | |
Reads from standard input | |
Craig P Hicks 2019 | |
MIT License | |
''' | |
import sys | |
tbls=[(None,''),('ACCEPT',''),('DROP',''),('REJECT',''),('RETURN',''),('LOG',''),('QUEUE','')] | |
rules=[] | |
tbl_rule_pairs=[] | |
tbl_rule_pairs_be=[] | |
def tbl_index(name): | |
global tbls | |
for i in range(0,len(tbls)): | |
if tbls[i][0]==name: | |
return i | |
def parse_input(): | |
global tbls | |
global rules | |
global tbl_rule_pairs | |
global tbl_rule_pairs_be | |
lines=sys.stdin.readlines() | |
for line in lines: | |
line=line.strip() | |
toks=line.split() | |
if len(toks)>=2: | |
if toks[0]=='-N': | |
tbls.append((toks[1],line,0,0)) | |
elif toks[0]=='-P': | |
tbl_parent_idx=0 | |
tbl_child_idx=len(tbls) | |
tbl_rule_pairs.append((tbl_parent_idx,len(rules))) | |
rules.append((0,tbl_child_idx,line)) | |
tbls.append((toks[1],line,0,0)) | |
elif toks[0]=='-A': | |
tbl_parent_idx=tbl_index(toks[1]) | |
assert '-j' in toks | |
jidx=toks.index('-j') | |
tbl_child_idx=tbl_index(toks[jidx+1]) | |
tbl_rule_pairs.append((tbl_parent_idx,len(rules))) | |
rules.append((tbl_parent_idx,tbl_child_idx,line)) | |
tbl_rule_pairs_be=[None]*len(tbls) | |
tbl_rule_pairs.sort() | |
tblidx=-1 | |
pair_b=-1 | |
for trpidx in range(0,len(tbl_rule_pairs)): | |
if tbl_rule_pairs[trpidx][0]!=tblidx: | |
if tblidx!=-1: | |
tbl_rule_pairs_be[tblidx]=(pair_b,trpidx) | |
tblidx=tbl_rule_pairs[trpidx][0] | |
pair_b=trpidx | |
if tblidx!=-1: | |
tbl_rule_pairs_be[tblidx]=(pair_b,len(tbl_rule_pairs)) | |
def trav_df(indent_level,tblidx): | |
global tbls | |
global rules | |
global tbl_rule_pairs | |
global tbl_rule_pairs_be | |
#print(tbls[tblidx][1]) | |
trp_be=tbl_rule_pairs_be[tblidx] | |
if not trp_be: | |
return | |
for trp in tbl_rule_pairs[trp_be[0]:trp_be[1]]: | |
assert trp[0]==tblidx | |
print((' '*indent_level*2)+rules[trp[1]][2]) | |
trav_df(indent_level+1, rules[trp[1]][1]) | |
if __name__ == '__main__': | |
parse_input() | |
trav_df(0,0) |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-P INPUT DROP | |
-P FORWARD DROP | |
-P OUTPUT ACCEPT | |
-N forwarding_lan_rule | |
-N forwarding_rule | |
-N forwarding_wan_rule | |
-N input_lan_rule | |
-N input_rule | |
-N input_wan_rule | |
-N output_lan_rule | |
-N output_rule | |
-N output_wan_rule | |
-N reject | |
-N syn_flood | |
-N zone_lan_dest_ACCEPT | |
-N zone_lan_forward | |
-N zone_lan_input | |
-N zone_lan_output | |
-N zone_lan_src_ACCEPT | |
-N zone_wan_dest_ACCEPT | |
-N zone_wan_dest_REJECT | |
-N zone_wan_forward | |
-N zone_wan_input | |
-N zone_wan_output | |
-N zone_wan_src_REJECT | |
-A INPUT -i lo -m comment --comment "!fw3" -j ACCEPT | |
-A INPUT -m comment --comment "!fw3: Custom input rule chain" -j input_rule | |
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT | |
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "!fw3" -j syn_flood | |
-A INPUT -i br-lan -m comment --comment "!fw3" -j zone_lan_input | |
-A FORWARD -m comment --comment "!fw3: Custom forwarding rule chain" -j forwarding_rule | |
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT | |
-A FORWARD -i br-lan -m comment --comment "!fw3" -j zone_lan_forward | |
-A FORWARD -m comment --comment "!fw3" -j reject | |
-A OUTPUT -o lo -m comment --comment "!fw3" -j ACCEPT | |
-A OUTPUT -m comment --comment "!fw3: Custom output rule chain" -j output_rule | |
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT | |
-A OUTPUT -o br-lan -m comment --comment "!fw3" -j zone_lan_output | |
-A reject -p tcp -m comment --comment "!fw3" -j REJECT --reject-with tcp-reset | |
-A reject -m comment --comment "!fw3" -j REJECT --reject-with icmp-port-unreachable | |
-A syn_flood -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m limit --limit 25/sec --limit-burst 50 -m comment --comment "!fw3" -j RETURN | |
-A syn_flood -m comment --comment "!fw3" -j DROP | |
-A zone_lan_dest_ACCEPT -o br-lan -m comment --comment "!fw3" -j ACCEPT | |
-A zone_lan_forward -m comment --comment "!fw3: Custom lan forwarding rule chain" -j forwarding_lan_rule | |
-A zone_lan_forward -m comment --comment "!fw3: Zone lan to wan forwarding policy" -j zone_wan_dest_ACCEPT | |
-A zone_lan_forward -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port forwards" -j ACCEPT | |
-A zone_lan_forward -m comment --comment "!fw3" -j zone_lan_dest_ACCEPT | |
-A zone_lan_input -m comment --comment "!fw3: Custom lan input rule chain" -j input_lan_rule | |
-A zone_lan_input -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT | |
-A zone_lan_input -m comment --comment "!fw3" -j zone_lan_src_ACCEPT | |
-A zone_lan_output -m comment --comment "!fw3: Custom lan output rule chain" -j output_lan_rule | |
-A zone_lan_output -m comment --comment "!fw3" -j zone_lan_dest_ACCEPT | |
-A zone_lan_src_ACCEPT -i br-lan -m conntrack --ctstate NEW,UNTRACKED -m comment --comment "!fw3" -j ACCEPT | |
-A zone_wan_forward -m comment --comment "!fw3: Custom wan forwarding rule chain" -j forwarding_wan_rule | |
-A zone_wan_forward -p esp -m comment --comment "!fw3: Allow-IPSec-ESP" -j zone_lan_dest_ACCEPT | |
-A zone_wan_forward -p udp -m udp --dport 500 -m comment --comment "!fw3: Allow-ISAKMP" -j zone_lan_dest_ACCEPT | |
-A zone_wan_forward -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port forwards" -j ACCEPT | |
-A zone_wan_forward -m comment --comment "!fw3" -j zone_wan_dest_REJECT | |
-A zone_wan_input -m comment --comment "!fw3: Custom wan input rule chain" -j input_wan_rule | |
-A zone_wan_input -p udp -m udp --dport 68 -m comment --comment "!fw3: Allow-DHCP-Renew" -j ACCEPT | |
-A zone_wan_input -p icmp -m icmp --icmp-type 8 -m comment --comment "!fw3: Allow-Ping" -j ACCEPT | |
-A zone_wan_input -p igmp -m comment --comment "!fw3: Allow-IGMP" -j ACCEPT | |
-A zone_wan_input -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT | |
-A zone_wan_input -m comment --comment "!fw3" -j zone_wan_src_REJECT | |
-A zone_wan_output -m comment --comment "!fw3: Custom wan output rule chain" -j output_wan_rule | |
-A zone_wan_output -m comment --comment "!fw3" -j zone_wan_dest_ACCEPT |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
-P INPUT DROP | |
-A INPUT -i lo -m comment --comment "!fw3" -j ACCEPT | |
-A INPUT -m comment --comment "!fw3: Custom input rule chain" -j input_rule | |
-A INPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT | |
-A INPUT -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m comment --comment "!fw3" -j syn_flood | |
-A syn_flood -p tcp -m tcp --tcp-flags FIN,SYN,RST,ACK SYN -m limit --limit 25/sec --limit-burst 50 -m comment --comment "!fw3" -j RETURN | |
-A syn_flood -m comment --comment "!fw3" -j DROP | |
-A INPUT -i br-lan -m comment --comment "!fw3" -j zone_lan_input | |
-A zone_lan_input -m comment --comment "!fw3: Custom lan input rule chain" -j input_lan_rule | |
-A zone_lan_input -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port redirections" -j ACCEPT | |
-A zone_lan_input -m comment --comment "!fw3" -j zone_lan_src_ACCEPT | |
-A zone_lan_src_ACCEPT -i br-lan -m conntrack --ctstate NEW,UNTRACKED -m comment --comment "!fw3" -j ACCEPT | |
-P FORWARD DROP | |
-A FORWARD -m comment --comment "!fw3: Custom forwarding rule chain" -j forwarding_rule | |
-A FORWARD -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT | |
-A FORWARD -i br-lan -m comment --comment "!fw3" -j zone_lan_forward | |
-A zone_lan_forward -m comment --comment "!fw3: Custom lan forwarding rule chain" -j forwarding_lan_rule | |
-A zone_lan_forward -m comment --comment "!fw3: Zone lan to wan forwarding policy" -j zone_wan_dest_ACCEPT | |
-A zone_lan_forward -m conntrack --ctstate DNAT -m comment --comment "!fw3: Accept port forwards" -j ACCEPT | |
-A zone_lan_forward -m comment --comment "!fw3" -j zone_lan_dest_ACCEPT | |
-A zone_lan_dest_ACCEPT -o br-lan -m comment --comment "!fw3" -j ACCEPT | |
-A FORWARD -m comment --comment "!fw3" -j reject | |
-A reject -p tcp -m comment --comment "!fw3" -j REJECT --reject-with tcp-reset | |
-A reject -m comment --comment "!fw3" -j REJECT --reject-with icmp-port-unreachable | |
-P OUTPUT ACCEPT | |
-A OUTPUT -o lo -m comment --comment "!fw3" -j ACCEPT | |
-A OUTPUT -m comment --comment "!fw3: Custom output rule chain" -j output_rule | |
-A OUTPUT -m conntrack --ctstate RELATED,ESTABLISHED -m comment --comment "!fw3" -j ACCEPT | |
-A OUTPUT -o br-lan -m comment --comment "!fw3" -j zone_lan_output | |
-A zone_lan_output -m comment --comment "!fw3: Custom lan output rule chain" -j output_lan_rule | |
-A zone_lan_output -m comment --comment "!fw3" -j zone_lan_dest_ACCEPT | |
-A zone_lan_dest_ACCEPT -o br-lan -m comment --comment "!fw3" -j ACCEPT |
This is such a life-saver ! Thank you!
I think iptables -S
should have a --human-readable
flag and show it like this. Thank you so much !
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
This program "iptree.py" is designed to read output from "iptables -S". It first parses that into a call-tree, and then traverses the tree in depth first order. Not-connected rules and empty tables are omitted. IMHO, it is easier to understand in tree form.
The sample-input.txt file is from the default(*) iptables rules for a OpenWRT 18.02.6. The result after processing with iptree.py is shown in sample-output.txt. Note that the device (a raspberry pi) I am testing has no "WAN" port hence the WAN rules are all disconnected.
(* except that policy for INPUT was changed from ACCEPT to DROP)