From 7e737f0d74fc1b30472e8830210f693d2879c91a Mon Sep 17 00:00:00 2001 From: Felix Fietkau Date: Sun, 19 Feb 2006 03:05:32 +0000 Subject: [PATCH] add webif-configurable scripts for firewalling and port forwarding SVN-Revision: 3255 --- .../base-files/default/etc/config/firewall | 46 +++ .../base-files/default/etc/init.d/S45firewall | 6 + .../base-files/default/usr/lib/common.awk | 46 +++ .../base-files/default/usr/lib/firewall.awk | 64 ++++ .../base-files/ipkg/base-files.conffiles | 1 + .../files/usr/lib/webif/apply-firewall.sh | 3 + .../webif/files/www/cgi-bin/webif/firewall.sh | 333 ++++++++++++++++++ 7 files changed, 499 insertions(+) create mode 100644 openwrt/package/base-files/default/etc/config/firewall create mode 100644 openwrt/package/base-files/default/usr/lib/common.awk create mode 100644 openwrt/package/base-files/default/usr/lib/firewall.awk create mode 100644 openwrt/package/webif/files/usr/lib/webif/apply-firewall.sh create mode 100755 openwrt/package/webif/files/www/cgi-bin/webif/firewall.sh diff --git a/openwrt/package/base-files/default/etc/config/firewall b/openwrt/package/base-files/default/etc/config/firewall new file mode 100644 index 0000000000..7edd4ba4e4 --- /dev/null +++ b/openwrt/package/base-files/default/etc/config/firewall @@ -0,0 +1,46 @@ +# RULE SYNTAX: +# +# forward::[:] +# - forwards all packets matched by to , +# optionally changing the port to +# +# accept: +# - accepts all traffic matched by +# +# drop: +# - drops all traffic matched by +# +# +# MATCHING OPTIONS: +# +# src= +# - match the source ip +# +# dest= +# - match the destination ip +# +# proto= +# - match the protocol by name or number +# +# sport= +# - match the source port(s), see below for syntax +# +# dport= +# - match the destination port(s), see below for syntax +# +# +# +# PORT SYNTAX: +# +# You can enter an arbitrary list of ports and port ranges in the following format: +# - 22,53,993,1000-1024 +# +# If you don't set the protocol to tcp or udp, it will apply to both +# +# +# +# EXAMPLES: +# +# drop:dport=22 src=1.3.3.7 +# accept:proto=tcp dport=22 +# forward:dport=60168:192.168.1.2:60169 diff --git a/openwrt/package/base-files/default/etc/init.d/S45firewall b/openwrt/package/base-files/default/etc/init.d/S45firewall index 96ac521334..8a573835e0 100755 --- a/openwrt/package/base-files/default/etc/init.d/S45firewall +++ b/openwrt/package/base-files/default/etc/init.d/S45firewall @@ -90,3 +90,9 @@ iptables -t nat -N postrouting_rule ## USER RULES [ -f /etc/firewall.user ] && . /etc/firewall.user +[ -e /etc/config/firewall ] && { + rm -f /tmp/.firewall.sh + awk -f /usr/lib/common.awk -f /usr/lib/firewall.awk /etc/config/firewall > /tmp/.firewall.sh + . /tmp/.firewall.sh + rm -f /tmp/.firewall.sh +} diff --git a/openwrt/package/base-files/default/usr/lib/common.awk b/openwrt/package/base-files/default/usr/lib/common.awk new file mode 100644 index 0000000000..860c6492e2 --- /dev/null +++ b/openwrt/package/base-files/default/usr/lib/common.awk @@ -0,0 +1,46 @@ +function portstr(type, str) { + if (str ~ /^[0-9]+-[0-9]+$/) { + gsub(/-/, ":", str) + if (type == "src") return " --sport " str + else return " --dport " str + } else { + if (insmod_mport != 1) { + print "insmod ipt_multiport >&- 2>&-" + insmod_mport = 1 + } + if (type == "src") return " -m multiport --sports " str + else return " -m multiport --dports " str + } +} + +function str2ipt(str) { + str2data(str) + _cmd = "" + if (_l["src"] != "") _cmd = _cmd " -s " _l["src"] + if (_l["dest"] != "") _cmd = _cmd " -d " _l["dest"] + if (_l["proto"] != "") { + _cmd = _cmd " -p " _l["proto"] + } + # scripts need to check for proto="" and emit two rules in that case + if ((_l["proto"] == "") || (_l["proto"] == "tcp") || (_l["proto"] == "udp")) { + if (_l["sport"] != "") _cmd = _cmd portstr("src", _l["sport"]) + if (_l["dport"] != "") _cmd = _cmd portstr("dest", _l["dport"]) + } + if (_l["layer7"] != "") { + if (insmod_l7 != 1) { + print "insmod ipt_layer7 >&- 2>&-" + insmod_l7 = 1 + } + _cmd = _cmd " -m layer7 --l7proto " _l["layer7"] + } + return _cmd +} + +function str2data(str) { + delete _l + _n = split(str, _o, "[\t ]") + for (_i = 1; _i <= _n; _i++) { + _n2 = split(_o[_i], _c, "=") + if (_n2 == 2) _l[_c[1]] = _c[2] + } +} diff --git a/openwrt/package/base-files/default/usr/lib/firewall.awk b/openwrt/package/base-files/default/usr/lib/firewall.awk new file mode 100644 index 0000000000..d5fba0550c --- /dev/null +++ b/openwrt/package/base-files/default/usr/lib/firewall.awk @@ -0,0 +1,64 @@ +BEGIN { + print "proto=\"$(nvram get wan_proto)\"" + print "[ -z \"$proto\" -o \"$proto\" = \"none\" ] && exit" + print "ifname=\"$(nvram get wan_ifname)\"" + print "[ -z \"$ifname\" ] && exit" + print "" + print "iptables -X input_$ifname 2>&- >&-" + print "iptables -N input_$ifname" + print "iptables -X forward_$ifname 2>&- >&-" + print "iptables -N forward_$ifname" + print "iptables -t nat -X prerouting_$ifname 2>&- >&-" + print "iptables -t nat -N prerouting_$ifname" + print "" + print "iptables -A input_rule -i \"$ifname\" -j input_$ifname" + print "iptables -A forwarding_rule -i \"$ifname\" -j forward_$ifname" + print "iptables -t nat -A prerouting_rule -i \"$ifname\" -j prerouting_$ifname" + print "" + FS=":" +} + +($1 == "accept") || ($1 == "drop") || ($1 == "forward") { + delete _opt + str2data($2) + if ((_l["proto"] == "") && (_l["sport"] _l["dport"] != "")) { + _opt[0] = " -p tcp" + _opt[1] = " -p udp" + } else { + _opt[0] = "" + } +} + +($1 == "accept") { + target = " -j ACCEPT" + for (o in _opt) { + print "iptables -t nat -A prerouting_$ifname" _opt[o] str2ipt($2) target + print "iptables -A input_$ifname " _opt[o] str2ipt($2) target + print "" + } +} + +($1 == "drop") { + for (o in _opt) { + print "iptables -t nat -A prerouting_$ifname" _opt[o] str2ipt($2) " -j DROP" + print "" + } +} + +($1 == "forward") { + target = " -j DNAT --to " $3 + fwopts = "" + if ($4 != "") { + if ((_l["proto"] == "tcp") || (_l["proto"] == "udp") || (_l["proto"] == "")) { + if (_l["proto"] != "") fwopts = " -p " _l["proto"] + fwopts = fwopts " --dport " $4 + target = target ":" $4 + } + else fwopts = "" + } + for (o in _opt) { + print "iptables -t nat -A prerouting_$ifname" _opt[o] str2ipt($2) target + print "iptables -A forward_$ifname " _opt[o] " -d " $3 fwopts " -j ACCEPT" + print "" + } +} diff --git a/openwrt/package/base-files/ipkg/base-files.conffiles b/openwrt/package/base-files/ipkg/base-files.conffiles index be064d856b..4c317bd68e 100644 --- a/openwrt/package/base-files/ipkg/base-files.conffiles +++ b/openwrt/package/base-files/ipkg/base-files.conffiles @@ -1,3 +1,4 @@ +/etc/config/firewall /etc/firewall.user /etc/group /etc/hosts diff --git a/openwrt/package/webif/files/usr/lib/webif/apply-firewall.sh b/openwrt/package/webif/files/usr/lib/webif/apply-firewall.sh new file mode 100644 index 0000000000..8d33ec8831 --- /dev/null +++ b/openwrt/package/webif/files/usr/lib/webif/apply-firewall.sh @@ -0,0 +1,3 @@ +HANDLERS_file="${HANDLERS_file} + firewall) mv /tmp/.webif/file-firewall /etc/config/firewall && /etc/init.d/S45firewall;; +" diff --git a/openwrt/package/webif/files/www/cgi-bin/webif/firewall.sh b/openwrt/package/webif/files/www/cgi-bin/webif/firewall.sh new file mode 100755 index 0000000000..0fd84f884b --- /dev/null +++ b/openwrt/package/webif/files/www/cgi-bin/webif/firewall.sh @@ -0,0 +1,333 @@ +#!/usr/bin/webif-page +&- 2>&- +FW_FILE_NEW="/tmp/.webif/file-firewall-new" + +empty "$FORM_cancel" || { + FORM_save="" + FORM_edit="" +} + +empty "$FORM_save" || { + SAVED=1 + case "$FORM_proto" in + tcp|udp|"") proto_valid=1;; + *) proto_valid=invalid;; + esac + validate <>||$proto_valid +string|FORM_target|@TR<>|required|$FORM_target +string|FORM_proto|@TR<>||$FORM_proto +ip|FORM_src|@TR<>||$FORM_src +ip|FORM_dest|@TR<>||$FORM_dest +ports|FORM_sport|@TR<>||$FORM_sport +ports|FORM_dport|@TR<>||$FORM_dport +ip|FORM_target_ip|@TR<>||$FORM_target_ip +port|FORM_target_port|@TR<>||$FORM_target_port +EOF + equal "$?" 0 || { + unset FORM_save + } + equal "$FORM_target" "forward" && empty "$FORM_target_ip$FORM_target_port" && { + ERROR="${ERROR}@TR<>
" + FORM_save="" + } +} + +empty "$FORM_up$FORM_down$FORM_save$FORM_delete$FORM_new" || { + empty "$FORM_up" || equal "$FORM_up" 1 || { + FORM_down="$(($FORM_up - 1))" + } + awk \ + -v down="$FORM_down" \ + -v save="$FORM_save" \ + -v del="$FORM_delete" \ + -v edit="$FORM_edit" \ + -v proto="$FORM_proto" \ + -v src="$FORM_src" \ + -v sport="$FORM_sport" \ + -v dest="$FORM_dest" \ + -v dport="$FORM_dport" \ + -v layer7="$FORM_layer7" \ + -v target="$FORM_target" \ + -v target_ip="$FORM_target_ip" \ + -v target_port="$FORM_target_port" \ + -v new="$FORM_new" \ + -v new_target="$FORM_new_target" \ + -f - "$FW_FILE" > "$FW_FILE_NEW" < down) { + print line_down + line_down = "" +} + +END { + if (line_down != "") print line_down + if (new_target == "forward") new_target = new_target "::192.168.1.1" + if ((new != "") && (new_target != "")) print new_target +} +EOF + FW_FILE=/tmp/.webif/file-firewall + mv "$FW_FILE_NEW" "$FW_FILE" + empty "$FORM_new" && FORM_edit="" +} + +header "Network" "Firewall" "@TR<>" '' + +?> + +>: " _l["proto"] "
" + if (_l["src"] != "") ret = ret "@TR<>: " _l["src"] "
" + if (_l["sport"] != "") ret = ret "@TR<>: " _l["sport"] "
" + if (_l["dest"] != "") ret = ret "@TR<>: " _l["dest"] "
" + if (_l["dport"] != "") ret = ret "@TR<>: " _l["dport"] "
" +# if (_l["layer7"] != "") ret = ret "@TR<>: " _l["layer7"] "
" + if (ret == "") ret = ret "@TR<>" + return ret +} +function delbutton(name) { + return button("del_" name, "Delete") +} +function input_line(caption, name, value) { + return "@TR<<" caption ">>: " textinput(name, value) delbutton(name) "" +} +function iptstr2edit(str, edit) { + edit = "" + str2data(str); + if (int(data_submit) == 1) set_data() + if (new_match == "proto") _l["proto"] = "tcp" + if ((new_match == "src") || (new_match == "dest")) _l[new_match] = "0.0.0.0" + if ((new_match == "sport") || (new_match == "dport")) _l[new_match] = "0" + if ((new_match != "") && (_l[new_match] == "")) _l[new_match] = " " + + if (_l["proto"] != "") { + edit = edit "@TR<>: " + edit = edit "" delbutton("proto") + edit = edit "" + } + if (_l["src"] != "") edit = edit input_line("Source IP", "src", _l["src"]) + if (_l["sport"] != "") edit = edit input_line("Source Ports", "sport", _l["sport"]) + if (_l["dest"] != "") edit = edit input_line("Destination IP", "dest", _l["dest"]) + if (_l["dport"] != "") edit = edit input_line("Destination Ports", "dport", _l["dport"]) + if (_l["layer7"] != "") edit = edit input_line("Application Protocol", "layer7", _l["layer7"]) + + edit = edit " " + edit = edit button("add_match", "Add") "" + + return edit +} + +BEGIN { + print start_form("@TR<>"); + print "" + print "" + FS=":" + n = 0 +} + +(\$1 == "drop") || (\$1 == "accept") || (\$1 == "forward" ) { + n++ + print "" + if (n == edit) { + print "" + print hidden("data_submit", "1") hidden("edit", edit) + print "" + print "" + } else { + printf "" + } +} + +END { + print "" + print "" + print "
@TR<>@TR<>@TR<> 

" + print "" + print iptstr2edit(\$2) + print "" + } else { + printf "" + } +} + +(\$1 == "drop") || (\$1 == "accept") { + if (n == edit) { + if (int(data_submit) == 1) \$1 = target + printf "" + printf "" + printf "" + } else { + printf "" + } +} + +\$1 == "forward" { + if (n == edit) { + if (target_ip == "") target_ip = \$3 + if (target_port == "") target_port = \$4 + print "" + print "" + } else { + if (\$3 \$4 == "") \$3 = "forward" + printf "" + } +} + +(\$1 == "drop") || (\$1 == "accept") || (\$1 == "forward" ) { + if (n == edit) { + printf "" + + print "

 
" iptstr2web(\$2) "
@TR<>:" + printf "
" \$1 "
@TR<>:" textinput("target_ip", target_ip) hidden("target", "forward") "
@TR<>:" textinput("target_port", target_port) "
" \$3 "" \$4 "
 " button("save", "Save") button("cancel", "Cancel") "
" + print "
" + printf "@TR<>
" + printf "@TR<>" + printf "
" + printf "@TR<>
" + printf "@TR<>" + print "

@TR<>: " + print "
" + print hidden("edit", n + 1); + print "" button("new", "Add") "
" + print end_form("..."); +} +EOF + +footer ?> + -- 2.30.2