add tc egress shaping
[firewall-squeep] / common.sh
1 #!/bin/sh
2
3 set -e
4
5 IPTABLES=$(which iptables)
6 IP6TABLES=$(which ip6tables)
7 IPSET=$(which ipset)
8 TC=$(which tc)
9
10 err(){
11 echo "$@" 1>&2
12 }
13
14 die(){
15 local status=$1
16 shift
17 err "$@"
18 exit ${status}
19 }
20
21 function decommentcat(){
22 sed 's/\s*#.*$//;/^\s*$/d' "$@"
23 }
24
25 function create_set(){
26 local set_name="$1"
27 shift
28 if ! $IPSET list "${set_name}" >/dev/null 2>&1
29 then
30 echo "creating set '${set_name}'"
31 $IPSET create "${set_name}" "$@"
32 fi
33 }
34
35 function create_drop_chain(){
36 local chain="$1"
37
38 if ! $IPTABLES -L "${chain}" >/dev/null 2>&1
39 then
40 echo "initializing chain '${chain}'"
41 $IPTABLES -N "${chain}" || $IPTABLES -F "${chain}"
42 $IPTABLES -A "${chain}" -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
43 $IPTABLES -A "${chain}" -j REJECT --reject-with icmp-port-unreachable
44 $IPTABLES -v -L "${chain}"
45 fi
46
47 if ! $IP6TABLES -L "${chain}" >/dev/null 2>&1
48 then
49 echo "initializing chain '${chain}' ipv6"
50 $IP6TABLES -N "${chain}" || $IP6TABLES -F "${chain}"
51 $IP6TABLES -A "${chain}" -m conntrack --ctstate ESTABLISHED,RELATED -j RETURN
52 $IP6TABLES -A "${chain}" -j REJECT --reject-with icmp6-port-unreachable
53 $IP6TABLES -v -L "${chain}"
54 fi
55 }
56
57 function insert_setmatch_rules(){
58 local single=0
59 if [ "x$1" = "x-single-set" ]
60 then
61 single=1
62 shift
63 fi
64 local ipt set_name="$1"
65 shift
66 for v in '' '6'
67 do
68 eval ipt="\$IP${v}TABLES"
69 if [ $single -eq 1 ]
70 then
71 v=''
72 fi
73 if ! $ipt -C INPUT -m set --match-set "${set_name}${v}" src "$@" >/dev/null 2>&1
74 then
75 echo "initializing rule '${set_name}${v}'"
76 $ipt -I INPUT -m set --match-set "${set_name}${v}" src "$@"
77 fi
78 done
79 }
80
81 function reload_cidr_sets(){
82 local set_name="$1"
83
84 # init new temporary sets
85 echo "updating set '${set_name}'"
86
87 create_set "${set_name}-tmp" hash:net
88 create_set "${set_name}6-tmp" hash:net family inet6
89
90 # populate them
91 for sfx in '' .$(hostname -s)
92 do
93 cidrfile="${set_name}.cidr${sfx}"
94 if [ -e "${cidrfile}" ]
95 then
96 for s in $(decommentcat "${cidrfile}")
97 do
98 case "${s}" in
99 *.*) table="${set_name}-tmp" ;;
100 *:*) table="${set_name}6-tmp" ;;
101 *)
102 echo "unknown entry '${s}' in '${cidrfile}'" 1>&2
103 continue
104 ;;
105 esac
106 $IPSET add "${table}" "${s}"
107 done
108 fi
109 done
110
111 # take new sets live
112 for v in '' 6
113 do
114 n="${set_name}${v}"
115 $IPSET swap "${n}-tmp" "${n}"
116 $IPSET destroy "${n}-tmp"
117 $IPSET list -t "${n}"
118 done
119 }
120
121 function add_service_entry(){
122 local port proto
123 port=$(echo "$1" | cut -d/ -f1)
124 proto=$(echo "$1" | cut -d/ -f2)
125 $IPSET -exist add allowed_${proto} ${port}
126 }
127
128 function allow_services(){
129 local s proto port
130 for s in "$@"
131 do
132 case "${s}" in
133 */*) add_service_entry "${s}"
134 ;;
135 *) for svc in $(getent services "${s}" | awk '{print $2}')
136 do
137 add_service_entry "${svc}"
138 done
139 ;;
140 esac
141 done
142 }
143