xeno add
[firewall-squeep] / common.sh
index 4bb66ff664b0a8be18b419a9eda030f0abc78680..5c2ed1a56e052dc5b53a08e20dfeb4e4099e49d0 100644 (file)
--- a/common.sh
+++ b/common.sh
@@ -5,9 +5,21 @@ set -e
 IPTABLES=$(which iptables)
 IP6TABLES=$(which ip6tables)
 IPSET=$(which ipset)
+TC=$(which tc)
+
+err(){
+       echo "$@" 1>&2
+}
+
+die(){
+       local status=$1
+       shift
+       err "$@"
+       exit ${status}
+}
 
 function decommentcat(){
-       sed 's/\s*#.*$//;/^\s*$/d' "$@"
+       cat "$@" | sed 's/\s*#.*$//;/^\s*$/d'
 }
 
 function create_set(){
@@ -20,3 +32,146 @@ function create_set(){
        fi
 }
 
+function create_drop_chain(){
+       local chain="$1"
+
+       if ! $IPTABLES -L "${chain}" >/dev/null 2>&1
+       then
+               echo "initializing chain '${chain}'"
+               $IPTABLES -N "${chain}" || $IPTABLES -F "${chain}"
+               $IPTABLES -A "${chain}" -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
+               $IPTABLES -A "${chain}" -j REJECT --reject-with icmp-port-unreachable
+               $IPTABLES -v -L "${chain}"
+       fi
+
+       if ! $IP6TABLES -L "${chain}" >/dev/null 2>&1
+       then
+               echo "initializing chain '${chain}' ipv6"
+               $IP6TABLES -N "${chain}" || $IP6TABLES -F "${chain}"
+               $IP6TABLES -A "${chain}" -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
+               $IP6TABLES -A "${chain}" -j REJECT --reject-with icmp6-port-unreachable
+               $IP6TABLES -v -L "${chain}"
+       fi
+}
+
+function insert_setmatch_rules(){
+       local single=0
+       if [ "x$1" = "x-single-set" ]
+       then
+               single=1
+               shift
+       fi
+       local ipt set_name="$1"
+       shift
+       for v in '' '6'
+       do
+               eval ipt="\$IP${v}TABLES"
+               if [ $single -eq 1 ]
+               then
+                       v=''
+               fi
+               if ! $ipt -C INPUT -m set --match-set "${set_name}${v}" src "$@" >/dev/null 2>&1
+               then
+                       echo "initializing rule '${set_name}${v}'"
+                       $ipt -I INPUT -m set --match-set "${set_name}${v}" src "$@"
+               fi
+       done
+}
+
+# try to recreate sets faster than one-at-a-time by generating restore rules
+function ipset_restore_from_cidr(){
+       local vmatch
+       local set_name="$1"
+
+       for v in '' '6'
+       do
+               case "$v" in
+               6) vmatch=':';;
+               *) vmatch='\.';;
+               esac
+               # extract existing set configuration to create temporary set
+               (set -o pipefail; $IPSET save "${set_name}${v}" 2>/dev/null | grep -m 1 '^create ' | sed "s/\(create ${set_name}${v}\)/\1-tmp/") || continue
+               # populate with new data
+               decommentcat "${set_name}.cidr" "${set_name}.cidr.$(hostname -s)" 2>/dev/null | sed -n 's/\(.*'"${vmatch}"'.*\)/add '"${set_name}${v}-tmp"' \1/p' | sort -n | uniq
+       done
+}
+
+function reload_cidr_sets(){
+       local v n
+       local set_name="$1"
+
+       ipset_restore_from_cidr "${set_name}" | ipset restore
+        for v in '' 6
+        do
+                n="${set_name}${v}"
+                $IPSET swap "${n}-tmp" "${n}"
+                $IPSET destroy "${n}-tmp"
+                $IPSET list -t "${n}"
+        done
+}
+
+function _old_reload_cidr_sets(){
+       local sfx n s v
+       local set_name="$1"
+       shift
+
+       # init new temporary sets
+       echo "updating set '${set_name}'"
+
+       create_set "${set_name}-tmp" hash:net "$@"
+       create_set "${set_name}6-tmp" hash:net "$@" family inet6
+
+       # populate them
+       for sfx in '' .$(hostname -s)
+       do
+               cidrfile="${set_name}.cidr${sfx}"
+               if [ -e "${cidrfile}" ]
+               then
+                       for s in $(decommentcat "${cidrfile}")
+                       do
+                               case "${s}" in
+                                       *.*) table="${set_name}-tmp" ;;
+                                       *:*) table="${set_name}6-tmp" ;;
+                                       *)
+                                               echo "unknown entry '${s}' in '${cidrfile}'" 1>&2
+                                               continue
+                                       ;;
+                               esac
+                               $IPSET add "${table}" "${s}"
+                       done
+               fi
+       done
+
+       # take new sets live
+       for v in '' 6
+       do
+               n="${set_name}${v}"
+               $IPSET swap "${n}-tmp" "${n}"
+               $IPSET destroy "${n}-tmp"
+               $IPSET list -t "${n}"
+       done
+}
+
+function add_service_entry(){
+       local port proto
+       port=$(echo "$1" | cut -d/ -f1)
+       proto=$(echo "$1" | cut -d/ -f2)
+       $IPSET -exist add allowed_${proto} ${port}
+}
+
+function allow_services(){
+       local s
+       for s in "$@"
+       do
+               case "${s}" in
+               */*)    add_service_entry "${s}"
+                       ;;
+               *)      for svc in $(egrep "^${s}\s+" /etc/services | decommentcat | awk '{print $2}')
+                       do
+                               add_service_entry "${svc}"
+                       done
+                       ;;
+               esac
+       done
+}
+