#!/bin/gawk -f BEGIN { # paths iptables = "/sbin/iptables" # global vars nstatements = 0; current["table"] = ""; current["chain"] = ""; chainnum = 0; builtinchains = "(INPUT|OUTPUT|FORWARD|PREROUTING|POSTROUTING)"; builtin["filter"] = "INPUT OUTPUT FORWARD"; builtin["nat"] = "PREROUTING OUTPUT POSTROUTING"; builtin["mangle"] = "PREROUTING OUTPUT"; builtintables = "filter nat mangle"; noflush = 0; printrules = 0; installrules = 0; hiterr = 0; if (ARGC < 2) { usage(); exit(1); } for (i=1; i \n","iptables-config.awk"); print "options:"; print "\t<--help|-h|--usage|-u>\t- print this usage"; print "\t<--print|-p>\t- print rules"; print "\t<--noflush|-n>\t- dont flush existing rules"; print "\t<--install|-i>\t- install rules"; print; print "If neither of --install or --print is specified then the script"; print "will silently process the config file and report any errors"; hiterr = 1; exit(1); } function bugout(str) { hiterr = 1; print "invalid line: " str; exit(1); } function addstatement(str) { statements[nstatements++] = str; } function dopolicy(str ,a,i,f,t,c,s) { f = match(str,/(policy) ([[:alnum:]]+) ([[:alnum:]]+)/,a); if (!f || a[1] != "policy" ) { for (t in a) { print "f: " f " err: " a[t]; } bugout(str); } if (a[2] == "all") { t = builtin[current["table"]]; split(t,c); for (t in c) { s = "-t " current["table"] " -P " c[t] " " a[3]; addstatement(s); } } else { s = "-t " current["table"] " -P " a[3]; addstatement(s); } } function dochain(str ,a,f,s) { f = split(str,a); if (!f || f > 2 || a[1] != "chain") { print "calling bugout with: " $0 " str: "; bugout(str); } if (!(a[2] in chains) && (a[2] !~ builtinchains) ) { chains[a[2]] = 1; s = "-t " current["table"] " -N " a[2]; addstatement(s); s = "-t " current["table"] " -F " a[2]; addstatement(s); } current["chain"] = a[2]; delete a; } function dotable(str ,a) { f = split(str,a); if (!f || f > 2 || a[1] != "table") { bugout(str); } current["table"] = a[2]; } function ruleparse(a, start, end, params ,i,s) { i = start; while ( i <= end ) { if (a[i] == "not" || a[i] == "!") { s = s " ! "; delete a[i]; } else if(a[i] ~ /^prot/) { params["prot"] = a[i+1]; s = s " -p " params["prot"]; i++; } else if ( a[i] ~ /^state/) { params["state"] = a[i+1]; s = s " -m state --state " params["state"]; i++; } else if ( a[i] ~ /^frag/ ) { params["frag"] = 1; s = s " --fragment "; } else if ( a[i] ~ /^s(ou)?rc/ ) { if (a[i+1] ~ /^port/ ) { if (params["prot"] !~ /tcp|udp/) { print "source port: not tcp/udp"; return -1; } params["sport"] = a[i+2]; s = s " --sport " params["sport"]; i+=2; } else if (a[i+1] == "ip") { params["src"] = a[i+2]; s = s " -s " params["src"]; i++; } else { params["src"] = a[i+1]; s = s " -s " params["src"]; i++; } } else if ( a[i] ~ /^d(e)?st/ ) { if (a[i+1] ~ /^port/) { if (params["prot"] !~ /tcp|udp/) { print "dst: not tcp/udp"; return -1; } params["dport"] = a[i+2]; s = s " --dport " params["dport"]; i+=2; } else if ( a[i+1] == "ip") { params["dst"] = a[i+2]; s = s " -d " params["dst"]; i+=2; } else { params["dst"] = a[i+1]; s = s " -d " params["dst"]; i++; } } else if ( a[i] ~ /^dev/ ) { if ( a[i+1] == "in" ) { params["devin"] = a[i+2]; s = s " -i " params["devin"]; } else if (a[i+1] == "out" ) { params["devout"] = a[i+2] s = s " -o " params["devout"]; } else { print "dev"; return -1; } i+=2; } else if (a[i] ~ /^flag/ ) { if ( params["prot"] != "tcp") { print "tcp flag"; return -1; } params["flagm"] = a[i+1]; params["flagc"] = a[i+2]; s = s " --tcp-flags " params["flagm"] s= s " " params["flagc"]; i+=2; } else if (a[i] ~ /^opt/ ) { if ( params["prot"] != "tcp") { print "tcpopt"; return -1;; } params["topt"] = a[i+1]; s = s " --tcp-option " params["topt"]; i++; } else if (a[i] == "type") { if (params["prot"] != "icmp") { print "icmp type"; return -1; } params["icmptype"] = a[i+1]; s = s " --icmp-type " params["icmptype"]; i++; } else if (a[i] == "limit") { params["limit"] = 1; s = s " -m limit "; } else if (a[i] == "burst") { if (!params["limit"]) { print "limit burst"; return -1; } params["burst"] = a[i+1]; s = s " --limit-burst " params["burst"]; i++; } else if (a[i] == "rate") { if (!params["limit"]) { print "limit rate"; return -1; } params["rate"] = a[i+1]; s = s " --limit " params["rate"]; i++; } else if (a[i] == "level") { if (params["target"] != "LOG") { print "log level: " params["target"]; return -1; } params["loglvl"] = a[i+1]; s = s " --log-level " params["loglvl"]; i++; } else if (a[i] == "prefix") { if (params["target"] != "LOG") { print "log prefix"; return -1; } params["logprefix"] = a[i+1]; i++; if ( params["logprefix"] ~ /^'/ ) { i++; while (i <= end && params["logprefix"] !~ /'$/) { params["logprefix"] = params["logprefix"] " " a[i]; i++; } } s = s " --log-prefix " params["logprefix"]; } else if (a[i] == "tos") { if (params["target"] != "TOS") { print "tos"; return -1; } params["tos"] = a[i+1]; i++; s = s " --set-tos " params["tos"]; } else if (a[i] == "nat") { if (params["target"] == "SNAT") { params["nat"] = a[i+1]; s = s " --to-source " params["nat"]; } else if (params["target"] == "DNAT") { params["nat"] = a[i+1]; s = s " --to-destination " params["nat"]; } else { print "[SD]NAT" return -1; } i++; } else if (a[i] ~ /^rej/) { if (params["target"] != "REJECT") { #print "reject"; return -1; } if (a[i+1] != "with" ) { params["rejectwith"] = a[i+1]; i++; } else { params["rejectwith"] = a[i+2]; i += 2; } s = s " --reject-with " params["rejectwith"]; } else if (a[i] == "owner" && ((i+1) in a) ) { if (a[i+1] == "uid") { params["owner"] = "--uid"; } else if (a[i+1] == "gid") { params["owner"] = "--gid"; } else if (a[i+1] == "pid") { params["owner"] = "--pid"; } else if (a[i+1] == "sid") { params["owner"] = "--sid"; } if ("owner" in params) { s = s " -m owner " params["owner"]; s = s "-owner " a[i+2]; i += 2; } else { return -1; } } else { print "unrecognised parameter: " a[i]; return -1; } i++; } return s; } function doattach(str ,a,s,r,params) { f = split(str,a); if (!f || a[1] != "attach" || a[3] != "to") { bugout(str); } params["target"] = a[2]; params["chain"] = a[4]; s = "-t " current["table"] s = s " -A " params["chain"] " -j " params["target"]; if (f > 5) { if( (t = ruleparse(a, 5, f, params)) == -1) bugout(str); } s = s t; addstatement(s); } function dorule(str ,a,s,f,params) { f = split(str,a); if (!f || a[1] != "rule") { bugout(str); } params["target"] = a[2]; s = "-t " current["table"] " -A " current["chain"] " "; if ( (t = ruleparse(a, 3, f,params)) == -1) { bugout(str); } if ( s ~ /[{}]/) { bugout(str); } s = s " -j " params["target"] t; addstatement(s); } function dobuild(str ,a,f,l,list,lname,r,s) { f = split(str,a); if (!f || a[1] != "build") { bugout(str); } if (a[4] in lists) { lname = a[4]; } else { bugout(str) } split(lists[lname],list); for (l in list) { s = ""; for (i=5; i <= f; i++) { r = "{" lname "}"; if (s == "") { s = gensub(r,list[l],"g",a[i]); } else { s = s " " gensub(r,list[l],"g",a[i]); } } if (s ~ /^((create|use) )?chain/) { dochain(s); } else if (s ~ /^rule/ ) { dorule(s); } else if (s ~ /^(use )?table/) { dotable(s); } else if (s ~ /^attach/ ) { doattach(s); } else if (s ~ /^build/ ) { dobuild(s); } } return; } ### start of line processing { while ($NF == "\\") { s = $0; getline; $0 = s " " $0; } gsub(/\\/,""); } #$1 == "include" { # while (getline stuff < $2) { # print stuff; # } #} $1 == "rule" { dorule($0); } $1 == "chain" { dochain($0); } $1 == "table" { dotable($0) } $1 == "list" { str = $3; for (i=4; i < NF+1; i++) { str = str " " $i; } lists[$2] = str; } $1 == "build" { dobuild($0); } $1 == "attach" { doattach($0); } $1 == "policy" { dopolicy($0); } END { if (hiterr) { exit(2); } # flush built in chains if (!noflush) { for (t in builtin) { split(builtin[t],chain) for (c in chain) { s = iptables " -t " t " -F " chain[c]; if (printrules) print s; if (installrules) system(s); } } } for (i=0; i