#!/bin/sh export PATH=/sbin:/bin:/usr/sbin:/usr/bin:/mod/sbin:/mod/bin:/mod/usr/sbin:/mod/usr/bin export LD_LIBRARY_PATH=/mod/lib case "$1" in ""|load|start|restart) if [ ! -r "/mod/etc/conf/firewall.cfg" ]; then echo "Error[firewall]: not configured" 1>&2 exit 1 fi . /mod/etc/conf/firewall.cfg ;; esac mac_chain() { if [ -z "$2" -o "$2" = "*" ]; then echo "$1" else # dirty hack let num="$(cat /tmp/.mac_chain)+1" echo "$num" > /tmp/.mac_chain chain="MAC_$num" target="$1" iptables -N "$chain" OIFS=$IFS; IFS=',' set -- $2 IFS=$OIFS while [ $# -gt 0 ]; do mac="$1" [ -n "$mac" ] && iptables -A "$chain" -m mac --mac-source "$mac" -j "$target" shift done echo "$chain" fi } _port_chain() { chain="$1" target="$2" OIFS=$IFS; IFS=',' set -- $3 IFS=$OIFS while [ $# -gt 0 ]; do port="$(echo "$1" | tr '\-' ':')" case "$port" in U*|u*) proto='udp'; port=${port#[Uu]} ;; T*|t*) proto='tcp'; port=${port#[Tt]} ;; *) proto='both' ;; esac if [ -n "$port" ]; then [ "$proto" = "udp" -o "$proto" = "both" ] && iptables -A "$chain" -p udp --dport "$port" -j "$target" [ "$proto" = "tcp" -o "$proto" = "both" ] && iptables -A "$chain" -p tcp --dport "$port" -j "$target" fi shift done } port_chain() { if [ -z "$2" -o "$2" = "*" ]; then echo "$1" else # dirty hack let num="$(cat /tmp/.port_chain)+1" echo "$num" > /tmp/.port_chain chain="PORT_$num" iptables -N "$chain" [ "$FIREWALL_ICMP" = "yes" ] && iptables -A "$chain" -p icmp -j "$1" _port_chain "$chain" "$1" "$2" echo "$chain" fi } log_chain() { if [ -z "$2" -o "$2" = "*" -o \ "$FIREWALL_LOG" != "yes" ]; then echo "$1" else # dirty hack let num="$(cat /tmp/.log_chain)+1" echo "$num" > /tmp/.log_chain chain="LOG_$num" iptables -N "$chain" iptables -A "$chain" -j LOG --log-prefix="$2: " iptables -A "$chain" -j "$1" echo "$chain" fi } load_modules() { modprobe ip_tables modprobe ip_conntrack hashsize=255 modprobe ipt_LOG modprobe iptable_filter modprobe ipt_state modprobe ip_conntrack_ftp modprobe ipt_mac modprobe ipt_multiport modprobe ipt_iprange } remove_modules() { rmmod ipt_iprange rmmod ip_conntrack_ftp rmmod ipt_mac rmmod ipt_multiport rmmod ipt_state rmmod iptable_filter rmmod ipt_LOG rmmod ip_conntrack rmmod ip_tables } start() { echo -n 'Starting firewall...' load_modules echo 0 > /tmp/.mac_chain echo 0 > /tmp/.port_chain echo 0 > /tmp/.log_chain iptables -F iptables -X iptables -Z iptables -A INPUT -i lo -j ACCEPT iptables -A OUTPUT -o lo -j ACCEPT iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT iptables -A INPUT -p tcp ! --syn -m state --state NEW -j DROP iptables -N FIREWALL_FWD iptables -A FIREWALL_FWD -p tcp ! --syn -j DROP iptables -A FIREWALL_FWD -i dsl -j ACCEPT iptables -N FIREWALL_INP iptables -A FIREWALL_INP -p tcp ! --syn -j DROP iptables -A FIREWALL_INP -i dsl -j ACCEPT iptables -A FORWARD -m state --state NEW -j FIREWALL_FWD if [ "$FIREWALL_WEBCFG" = "yes" ]; then . /mod/etc/conf/mod.cfg iptables -N WEBCFG iptables -A WEBCFG -i "$FIREWALL_WEBCFG_IF" -j ACCEPT [ "$FIREWALL_LOG" = "yes" ] && iptables -A WEBCFG -j LOG --log-prefix="$FIREWALL_WEBCFG_LOG_PREFIX: " iptables -A WEBCFG -j DROP iptables -A FIREWALL_INP -p tcp --dport 80 -j WEBCFG iptables -A FIREWALL_INP -p tcp --dport "$MOD_HTTPD_PORT" -j WEBCFG fi if [ "$FIREWALL_IFILT" = "yes" ]; then iptables -N IFILT iptables -A IFILT -i "$FIREWALL_IFILT_IF" -j ACCEPT [ "$FIREWALL_LOG" = "yes" ] && iptables -A IFILT -j LOG --log-prefix="$FIREWALL_IFILT_LOG_PREFIX: " iptables -A IFILT -j DROP _port_chain "FIREWALL_INP" "IFILT" "$FIREWALL_IFILT_PORTS" fi if [ -r "/tmp/flash/whitelist" ]; then cat /tmp/flash/whitelist | grep -v "^#" | while read -r ips macs ports prefix; do if [ -n "$ips" ]; then target="$(mac_chain "$(port_chain "$(log_chain "ACCEPT" "$prefix")" "$ports")" "$macs")" if [ "$ips" = "*" ]; then iptables -A FIREWALL_FWD -j "$target" else OIFS=$IFS; IFS=',' set -- $ips IFS=$OIFS while [ $# -gt 0 ]; do ip="$1" if [ -n "$ip" ]; then case "$ip" in *-*) iptables -A FIREWALL_FWD -m iprange --src-range "$ip" -j "$target" ;; *) iptables -A FIREWALL_FWD -s "$ip" -j "$target" ;; esac fi shift done fi fi done fi if [ "$FIREWALL_HOSTS" = "yes" -a -r "/tmp/flash/exhosts" ]; then target="$(port_chain "$(log_chain "ACCEPT" "$FIREWALL_HOSTS_LOG_PREFIX")" "$FIREWALL_HOSTS_PORTS")" cat /tmp/flash/exhosts | grep -v "^#" | while read -r ip mac interface host desc; do if [ -n "$ip" ]; then ip_match=''; mac_match='' [ -n "$ip" -a "$ip" != "*" ] && ip_match="-s $ip" [ -n "$mac" -a "$mac" != "*" ] && mac_match="-m mac --mac-source $mac" iptables -A FIREWALL_FWD $ip_match $mac_match -j "$target" fi done fi [ "$FIREWALL_LOG" = "yes" ] && iptables -A FIREWALL_FWD -j LOG --log-prefix="Dropped connection: " iptables -A FIREWALL_FWD -j DROP iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD DROP echo 'done.' rm -f /tmp/.mac_chain rm -f /tmp/.port_chain rm -f /tmp/.log_chain touch /var/run/firewall } start_inp() { iptables -A INPUT -m state --state NEW -j FIREWALL_INP } stop() { rm -f /var/run/firewall echo -n 'Stopping firewall...' iptables -P INPUT ACCEPT iptables -P OUTPUT ACCEPT iptables -P FORWARD ACCEPT iptables -F iptables -X iptables -Z remove_modules echo 'done.' } case "$1" in ""|load) modreg cgi 'firewall' 'Firewall' deffile='/mod/etc/default.firewall/whitelist.def' [ -r "/tmp/flash/whitelist.def" ] && deffile='/tmp/flash/whitelist.def' modreg file 'whitelist' 'Whitelist' 1 "$deffile" if [ "$FIREWALL_ENABLED" != "yes" ]; then echo "firewall is disabled" 1>&2 exit 1 fi if [ -e "/var/run/firewall" ]; then echo "firewall already started." else stop > /dev/null 2>&1 start $0 waitinp < /dev/null 2>&1 > /dev/null & fi ;; unload) stop modunreg file 'whitelist' modunreg cgi 'firewall' ;; start) start start_inp ;; stop) stop ;; restart) stop start start_inp ;; waitinp) sleep 300 start_inp ;; status) if [ -e "/var/run/firewall" ]; then echo 'running' else echo 'stopped' fi ;; *) echo "Usage: $0 [load|unload|start|stop|restart|waitinp|status]" 1>&2 exit 1 ;; esac exit 0