6a700c05f9a33bdd4a28e6d6d9363da7aba879f1
[rahunas] / tools / rahunas-firewall.in
1 #!/bin/sh
2 # The firewall script to provides the ability to capture the web request from 
3 # the clients and redirect them to the login page to get the authorization to 
4 # access the network.
5
6 PATH=/sbin:/bin:/usr/sbin:/usr/bin:@prefix@/sbin:@prefix@/bin
7 prefix=@prefix@
8 exec_prefix=@exec_prefix@
9
10 IPTABLES=/sbin/iptables
11 IPSET=/usr/sbin/ipset
12 IFCONFIG=/sbin/ifconfig
13 FARPD=/usr/sbin/farpd
14
15 NAME="rahunas"
16 INIT=@sysconfdir@/default/rahunas
17 RUN=@localstatedir@/run/rahunas-firewall
18 RUNDIR=@localstatedir@/run/rahunas-set
19 VSERVER_LIST=@localstatedir@/run/rahunas-vserver
20 MAIN_EXT_IFACE_LIST=@localstatedir@/run/rahunas_ext_iface_list
21
22 RUN_DAEMON=no
23
24 test -f $INIT || exit 0 
25 . $INIT
26
27 test -f $RAHUNAS_CONFIG || exit 1
28 test -f $VSERVER_LIST || touch $VSERVER_LIST
29 test -d $RUNDIR || mkdir -p $RUNDIR
30
31 get_section_name () {
32   file=$1
33   
34   grep "^.*\= {$" $file | sed "s/= {//" |  sed "s/^ *\(.*[^ ]\) *$/\1/"
35 }
36
37 get_config_value () {
38   section=$1
39   key=$2
40   file=$3
41
42   cat $file | sed -e "0,/$section = {/ ! { /}/,/$section = {/ ! s/^/>>/ }" | grep "^>>" | sed -e "s/^>>//g" | grep -w "$key" | cut -d= -f2 | sed "s/^ *\(.*[^ ]\) *$/\1/" | sed 's/"//g'
43 }
44
45 ##
46 #  Global Declaration
47 ##
48
49 # Main
50 MAIN_CONF_DIR=`get_config_value main conf_dir $RAHUNAS_CONFIG`
51 MAIN_BANDWIDTH_SHAPE=`get_config_value main bandwidth_shape $RAHUNAS_CONFIG`
52 MAIN_BITTORRENT_DOWNLOAD_MAX=`get_config_value main bittorrent_download_max $RAHUNAS_CONFIG`
53 MAIN_BITTORRENT_UPLOAD_MAX=`get_config_value main bittorrent_upload_max $RAHUNAS_CONFIG`
54 MAIN_DHCP=`get_config_value main dhcp $RAHUNAS_CONFIG`
55
56 MAIN_EXT_IFACE_FIREWALL=`get_config_value main external_iface_firewall $RAHUNAS_CONFIG`
57 MAIN_EXT_IFACE_PORTS_ALLOW=`get_config_value main external_iface_ports_allow $RAHUNAS_CONFIG`
58 MAIN_EXT_IFACE_PING_ACCEPT=`get_config_value main external_iface_ping_accept $RAHUNAS_CONFIG`
59
60 if [ "$ENV_OVERRIDE" != "yes" ]; then
61   # Virtual Server : config
62   VSERVER_ID=
63   DEV_EXTERNAL=
64   DEV_INTERNAL=
65   BRIDGE=
66   MASQUERADE=
67   IGNORE_MAC=
68   VSERVER_IP=
69   CLIENTS=
70   EXCLUDED=
71   DNS=
72   SSH=
73   PROXY=
74   PROXY_HOST=
75   PROXY_PORT=
76   BITTORRENT=
77   BITTORRENT_ALLOW=
78   VSERVER_PORTS_ALLOW=
79   VSERVER_PORTS_INTERCEPT=
80   SETNAME=
81   VIPMAP=
82   VIPMAP_FAKE_ARP=
83 fi
84
85 DEV_EXTERNAL_LIST=
86
87 BANDWIDTH_SHAPE=
88 BITTORRENT_DOWNLOAD_MAX=
89 BITTORRENT_UPLOAD_MAX=
90
91
92 # Virtual Server : set and chains
93 CHAIN_INPUT=
94 CHAIN_INPUT_AUTH=
95 CHAIN_FORWARD=
96 CHAIN_FORWARD_AUTH=
97 CHAIN_MANGLE_PREROUTING=
98 CHAIN_MANGLE_FORWARD=
99 CHAIN_MANGLE_POSTROUTING=
100 CHAIN_NAT_PREROUTING=
101 CHAIN_NAT_POSTROUTING=
102 CHAIN_NAT_AUTHEN=
103 CHAIN_NAT_VIP_PREROUTING=
104 CHAIN_NAT_VIP_POSTROUTING=
105 CHAIN_P2P_DETECT=
106 CHAIN_P2P_RECHECK=
107 CHAIN_P2P_CHECK=
108 P2P_SET=
109 P2P_ALLOW_SET=
110 DEV_IN_PARAM=
111 DEV_OUT_PARAM=
112
113 get_config () {
114   file=$1
115   opt=$2
116
117   if [ "$ENV_OVERRIDE" != "yes" ]; then
118     test -f $file || return 1
119   
120     SETNAME=`get_section_name $file`
121   
122     # Get configuration
123     VSERVER_ID=`get_config_value $SETNAME vserver_id $file`
124     test -n "$VSERVER_ID" || return 2
125   
126     if [ "$opt" = "start" ]; then
127       hash="$VSERVER_ID:$SETNAME"
128       test1=`grep -w "$hash" $VSERVER_LIST` || true
129       test2=`grep -w "$SETNAME" $VSERVER_LIST` || true
130     
131       test -n "$test1" -o -n "$test2" && return 3 
132   
133       echo "$hash:$file" >> $VSERVER_LIST
134     fi
135   
136     DEV_EXTERNAL=`get_config_value $SETNAME dev_external $file`
137     DEV_INTERNAL=`get_config_value $SETNAME dev_internal $file`
138     BRIDGE=`get_config_value $SETNAME bridge $file`
139     MASQUERADE=`get_config_value $SETNAME masquerade $file`
140     IGNORE_MAC=`get_config_value $SETNAME ignore_mac $file`
141     VSERVER_IP=`get_config_value $SETNAME vserver_ip $file`
142     CLIENTS=`get_config_value $SETNAME clients $file`
143     EXCLUDED=`get_config_value $SETNAME excluded $file`
144     DNS=`get_config_value $SETNAME dns $file`
145     SSH=`get_config_value $SETNAME ssh $file`
146     PROXY=`get_config_value $SETNAME proxy $file`
147     PROXY_HOST=`get_config_value $SETNAME proxy_host $file`
148     PROXY_PORT=`get_config_value $SETNAME proxy_port $file`
149     BITTORRENT=`get_config_value $SETNAME bittorrent $file`
150     BITTORRENT_ALLOW=`get_config_value $SETNAME bittorrent_allow $file`
151     VSERVER_PORTS_ALLOW=`get_config_value $SETNAME vserver_ports_allow $file`
152     VSERVER_PORTS_INTERCEPT=`get_config_value $SETNAME vserver_ports_intercept $file`
153     VIPMAP=`get_config_value $SETNAME vipmap $file`
154     VIPMAP_NETWORK=`get_config_value $SETNAME vipmap_network $file`
155     VIPMAP_FAKE_ARP=`get_config_value $SETNAME vipmap_fake_arp $file`
156   fi
157  
158   BANDWIDTH_SHAPE=$MAIN_BANDWIDTH_SHAPE
159   BITTORRENT_DOWNLOAD_MAX=$MAIN_BITTORRENT_DOWNLOAD_MAX
160   BITTORRENT_UPLOAD_MAX=$MAIN_BITTORRENT_UPLOAD_MAX
161
162   # Bridge config
163   if [ "$BRIDGE" = "yes" ]; then
164     DEV_IN_PARAM="-m physdev --physdev-in"
165     DEV_OUT_PARAM="-m physdev --physdev-out"
166   else
167     DEV_IN_PARAM="-i"
168     DEV_OUT_PARAM="-o"
169   fi
170   
171   # Chains declaration
172   CHAIN_INPUT="${SETNAME}_in"
173   CHAIN_INPUT_AUTH="${SETNAME}_in_auth"
174   CHAIN_FORWARD="${SETNAME}_fwd"
175   CHAIN_FORWARD_AUTH="${SETNAME}_fwd_auth"
176   CHAIN_MANGLE_PREROUTING="${SETNAME}_mg_pre"
177   CHAIN_MANGLE_FORWARD="${SETNAME}_mg_fwd"
178   CHAIN_MANGLE_POSTROUTING="${SETNAME}_mg_post"
179   CHAIN_NAT_PREROUTING="${SETNAME}_nat_pre"
180   CHAIN_NAT_POSTROUTING="${SETNAME}_nat_post"
181   CHAIN_NAT_AUTHEN="${SETNAME}_nat_authen"
182   CHAIN_NAT_VIP_PREROUTING="${SETNAME}_nat_vip_pre"
183   CHAIN_NAT_VIP_POSTROUTING="${SETNAME}_nat_vip_post"
184   
185   # P2P checking chains declaration
186   CHAIN_P2P_DETECT="${SETNAME}_p2p_detect"
187   CHAIN_P2P_RECHECK="${SETNAME}_p2p_rechk"
188   CHAIN_P2P_CHECK="${SETNAME}_p2p_chk"
189   P2P_SET="${SETNAME}_p2p"
190   P2P_ALLOW_SET="${SETNAME}_p2p_allow"
191 }
192
193 ##
194 # Extracting the external device list
195 ##
196 dev_external_list () {
197   LIST=`echo $DEV_EXTERNAL | sed 's/,/ /g'`
198   for dev in $LIST; do
199     echo -n "$dev "  
200   done
201   echo ""
202 }
203
204 ##
205 # Detecting the parsing IP is the local
206 ##
207 is_ip_local () {
208   IP=$1
209   $IFCONFIG | grep "inet addr" | grep -w "$IP" > /dev/null
210   if [ $? = 0 ]; then
211     return 1
212   else
213     return 0
214   fi
215 }
216
217 ##
218 # Add set
219 ##
220 add_set () {
221   ipset_opt=""
222   ipset_ignoremac=""
223   
224   ipset_opt="--network $CLIENTS"
225   
226   if [ "$IGNORE_MAC" = "yes" ]; then
227     ipset_ignoremac="--ignoremac"
228   fi
229   
230   $IPSET -N $SETNAME rahunas $ipset_opt $ipset_ignoremac 
231
232   if [ "$VIPMAP" = "yes" ]; then
233     $IPSET -N ${SETNAME}-vip rahunas $ipset_opt $ipset_ignoremac
234   fi
235
236   if [ "$BITTORRENT" = "throttle" ]; then
237     $IPSET -N $P2P_SET iphash
238   fi
239
240   if [ -n "$BITTORRENT_ALLOW" ]; then
241     $IPSET -N $P2P_ALLOW_SET iphash 
242     for ip in $BITTORRENT_ALLOW
243     do
244       $IPSET -A $P2P_ALLOW_SET $ip
245     done
246   fi
247 }
248
249 ##
250 # Cleanup set
251 ##
252 cleanup_set () {
253   $IPSET -F $SETNAME
254   $IPSET -X $SETNAME
255
256   if [ "$VIPMAP" = "yes" ]; then
257     $IPSET -F ${SETNAME}-vip
258     $IPSET -X ${SETNAME}-vip
259   fi
260
261   if [ "$BITTORRENT" = "throttle" ]; then
262     $IPSET -F $P2P_SET
263     $IPSET -X $P2P_SET 
264   fi
265
266   if [ -n "$BITTORRENT_ALLOW" ]; then
267     $IPSET -F $P2P_ALLOW_SET
268     $IPSET -X $P2P_ALLOW_SET 
269   fi
270 }
271
272 ##
273 # Navigation rules
274 ##
275 navigation_rules () {
276   opt=$1
277   if [ "$opt" = "start" ]; then
278     action="-I"
279   elif [ "$opt" = "stop" ]; then
280     action="-D"
281   fi
282
283   # INPUT from external
284   if [ "$opt" = "start" ]; then
285     for dev in $DEV_EXTERNAL_LIST; do
286       # Filter duplicated external interfaces
287       if ! cat $MAIN_EXT_IFACE_LIST | grep $dev > /dev/null; then
288         echo "$dev" >> $MAIN_EXT_IFACE_LIST
289
290         $IPTABLES $action INPUT $DEV_IN_PARAM $dev -j ${NAME}_ext_fw
291       fi
292     done
293   else #stop
294     for dev in `cat $MAIN_EXT_IFACE_LIST`; do
295       $IPTABLES $action INPUT $DEV_IN_PARAM $dev -j ${NAME}_ext_fw
296       sed -i "/$dev/d" $MAIN_EXT_IFACE_LIST
297     done
298   fi
299
300   # INPUT
301   $IPTABLES $action INPUT \
302     $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
303     -j $CHAIN_INPUT
304   $IPTABLES $action INPUT -m connmark --mark 2/2 \
305     $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
306     -j $CHAIN_INPUT_AUTH
307
308   # FORWARD
309   $IPTABLES $action FORWARD \
310     $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
311     -j $CHAIN_FORWARD
312   $IPTABLES $action FORWARD \
313     $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
314     -j $CHAIN_FORWARD
315
316   # In some situation the connections could not established before
317   # the FORWARD rules allow the clients, thus the connections never mark.
318   # Just allow them passthrough the rules if the connections do not mark but
319   # the clients are in the set (allow them).
320   $IPTABLES $action FORWARD -m set --set $SETNAME dst -j $CHAIN_FORWARD_AUTH
321   $IPTABLES $action FORWARD -m set --set $SETNAME src -j $CHAIN_FORWARD_AUTH
322
323   $IPTABLES $action FORWARD -m connmark --mark 2/2 \
324     $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
325     -j $CHAIN_FORWARD_AUTH
326   $IPTABLES $action FORWARD -m connmark --mark 2/2 \
327     $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
328     -j $CHAIN_FORWARD_AUTH
329
330   # MANGLE
331   $IPTABLES -t mangle $action PREROUTING \
332     $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
333     -j $CHAIN_MANGLE_PREROUTING
334   
335   for dev in $DEV_EXTERNAL_LIST; do
336     $IPTABLES -t mangle $action PREROUTING \
337       $DEV_IN_PARAM $dev -d $CLIENTS \
338       -j $CHAIN_MANGLE_PREROUTING
339   done
340
341   $IPTABLES -t mangle $action FORWARD \
342     $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
343     -j $CHAIN_MANGLE_FORWARD
344   $IPTABLES -t mangle $action FORWARD \
345     $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
346     -j $CHAIN_MANGLE_FORWARD
347
348   $IPTABLES -t mangle $action POSTROUTING \
349     $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
350     -j $CHAIN_MANGLE_POSTROUTING
351
352   for dev in $DEV_EXTERNAL_LIST; do
353     $IPTABLES -t mangle $action POSTROUTING \
354       $DEV_OUT_PARAM $dev -s $CLIENTS \
355       -j $CHAIN_MANGLE_POSTROUTING
356   done
357
358   # NAT
359   $IPTABLES -t nat $action PREROUTING \
360     $DEV_IN_PARAM $DEV_INTERNAL -s $CLIENTS \
361     -j $CHAIN_NAT_PREROUTING
362   for dev in $DEV_EXTERNAL_LIST; do
363     $IPTABLES -t nat $action PREROUTING \
364       $DEV_IN_PARAM $dev -d $CLIENTS \
365       -j $CHAIN_NAT_PREROUTING
366   done
367
368   $IPTABLES -t nat $action POSTROUTING \
369     $DEV_OUT_PARAM $DEV_INTERNAL -d $CLIENTS \
370     -j $CHAIN_NAT_POSTROUTING
371   for dev in $DEV_EXTERNAL_LIST; do
372     $IPTABLES -t nat $action POSTROUTING \
373       $DEV_OUT_PARAM $dev -s $CLIENTS \
374       -j $CHAIN_NAT_POSTROUTING
375   done
376 }
377
378 ##
379 # Cleanup old rules
380 ##
381 cleanup () {
382
383   navigation_rules stop  
384
385   $IPTABLES -F $CHAIN_INPUT_AUTH
386   $IPTABLES -X $CHAIN_INPUT_AUTH
387
388   $IPTABLES -F $CHAIN_INPUT
389   $IPTABLES -X $CHAIN_INPUT
390   
391   $IPTABLES -F $CHAIN_FORWARD_AUTH
392   $IPTABLES -X $CHAIN_FORWARD_AUTH
393
394   $IPTABLES -F $CHAIN_FORWARD
395   $IPTABLES -X $CHAIN_FORWARD
396   
397   $IPTABLES -t mangle -F $CHAIN_MANGLE_PREROUTING
398   $IPTABLES -t mangle -X $CHAIN_MANGLE_PREROUTING
399
400   $IPTABLES -t mangle -F $CHAIN_MANGLE_POSTROUTING
401   $IPTABLES -t mangle -X $CHAIN_MANGLE_POSTROUTING
402   
403   $IPTABLES -t nat -F $CHAIN_NAT_PREROUTING
404   $IPTABLES -t nat -X $CHAIN_NAT_PREROUTING
405   
406   $IPTABLES -t mangle -F $CHAIN_MANGLE_FORWARD
407   $IPTABLES -t mangle -X $CHAIN_MANGLE_FORWARD
408
409   $IPTABLES -t nat -F $CHAIN_NAT_POSTROUTING
410   $IPTABLES -t nat -X $CHAIN_NAT_POSTROUTING
411   
412   $IPTABLES -t nat -F $CHAIN_NAT_AUTHEN
413   $IPTABLES -t nat -X $CHAIN_NAT_AUTHEN
414
415   if [ "$VIPMAP" = "yes" ]; then
416     $IPTABLES -t nat -F $CHAIN_NAT_VIP_PREROUTING
417     $IPTABLES -t nat -X $CHAIN_NAT_VIP_PREROUTING
418
419     $IPTABLES -t nat -F $CHAIN_NAT_VIP_POSTROUTING
420     $IPTABLES -t nat -X $CHAIN_NAT_VIP_POSTROUTING
421   fi
422
423   if [ "$BITTORRENT" = "throttle" ]; then
424     $IPTABLES -t mangle -F $CHAIN_P2P_CHECK
425     $IPTABLES -t mangle -X $CHAIN_P2P_CHECK
426
427     $IPTABLES -t mangle -F $CHAIN_P2P_RECHECK
428     $IPTABLES -t mangle -X $CHAIN_P2P_RECHECK
429
430     $IPTABLES -t mangle -F $CHAIN_P2P_DETECT
431     $IPTABLES -t mangle -X $CHAIN_P2P_DETECT
432   fi
433 }
434
435 ##
436 # Define new chains
437 ##
438 new_chains () {
439   $IPTABLES -N $CHAIN_INPUT_AUTH
440   $IPTABLES -N $CHAIN_INPUT
441   $IPTABLES -N $CHAIN_FORWARD_AUTH
442   $IPTABLES -N $CHAIN_FORWARD
443   $IPTABLES -t mangle -N $CHAIN_MANGLE_PREROUTING
444   $IPTABLES -t mangle -N $CHAIN_MANGLE_FORWARD
445   $IPTABLES -t mangle -N $CHAIN_MANGLE_POSTROUTING
446   $IPTABLES -t nat -N $CHAIN_NAT_PREROUTING
447   $IPTABLES -t nat -N $CHAIN_NAT_POSTROUTING
448   $IPTABLES -t nat -N $CHAIN_NAT_AUTHEN
449
450   if [ "$VIPMAP" = "yes" ]; then
451     $IPTABLES -t nat -N $CHAIN_NAT_VIP_PREROUTING
452     $IPTABLES -t nat -N $CHAIN_NAT_VIP_POSTROUTING
453   fi
454
455   if [ "$BITTORRENT" = "throttle" ]; then
456     $IPTABLES -t mangle -N $CHAIN_P2P_CHECK
457     $IPTABLES -t mangle -N $CHAIN_P2P_RECHECK
458     $IPTABLES -t mangle -N $CHAIN_P2P_DETECT
459   fi
460 }
461
462 ##
463 # Policy
464 ##
465 policy () {
466   $IPTABLES -P INPUT DROP
467   $IPTABLES -P OUTPUT ACCEPT
468   $IPTABLES -P FORWARD DROP 
469
470   $IPTABLES -A INPUT -i lo -j ACCEPT
471
472   # DHCP Settings
473
474   if [ "$MAIN_DHCP" = "yes" ]; then
475     $IPTABLES -A INPUT -p udp --dport 67:68 -j ACCEPT 
476     $IPTABLES -A FORWARD -p udp --dport 67:68 -j DROP
477   elif [ "$MAIN_DHCP" = "no" ]; then
478     $IPTABLES -A INPUT -p udp --dport 67:68 -j DROP 
479     $IPTABLES -A FORWARD -p udp --dport 67:68 -j DROP
480   elif [ "$MAIN_DHCP" = "forward" ]; then
481     $IPTABLES -A INPUT -p udp --dport 67:68 -j DROP 
482     $IPTABLES -A FORWARD -p udp --dport 67:68 -j ACCEPT
483   fi
484
485   $IPTABLES -N ${NAME}_ext_fw
486
487   if [ "x$MAIN_EXT_IFACE_FIREWALL" = "xyes" ]; then
488     # Accept all connections that made by server itself
489     $IPTABLES -A ${NAME}_ext_fw -m state --state ESTABLISHED,RELATED -j ACCEPT
490
491     # Accept DNS reply
492     $IPTABLES -A ${NAME}_ext_fw -p udp --sport 53 \
493       -m state --state ESTABLISHED,RELATED -j ACCEPT
494
495     if [ -n "$MAIN_EXT_IFACE_PORTS_ALLOW" ]; then
496       $IPTABLES -A ${NAME}_ext_fw -p tcp \
497         -m multiport --dports ${MAIN_EXT_IFACE_PORTS_ALLOW} -j ACCEPT
498     fi
499
500     if [ "x$MAIN_EXT_IFACE_PING_ACCEPT" = "xyes" ]; then
501       # Accept echo-request from outside
502       $IPTABLES -A ${NAME}_ext_fw -p icmp --icmp-type 8 \
503         -m state --state NEW,ESTABLISHED,RELATED -j ACCEPT
504     fi
505
506     # Accept echo-reply from outside
507     $IPTABLES -A ${NAME}_ext_fw -p icmp --icmp-type 0 \
508       -m state --state ESTABLISHED,RELATED -j ACCEPT
509   else
510     if [ "x$MAIN_EXT_IFACE_FIREWALL" = "xaccept" -o "x$MAIN_EXT_IFACE_FIREWALL" = "x" ]; then
511       $IPTABLES -A ${NAME}_ext_fw -j ACCEPT
512     fi
513   fi
514
515   $IPTABLES -A ${NAME}_ext_fw -j RETURN
516 }
517
518 cleanup_policy () {
519   # Assume before the script running the default policy are all ACCEPT
520   $IPTABLES -P INPUT ACCEPT
521   $IPTABLES -P OUTPUT ACCEPT
522   $IPTABLES -P FORWARD ACCEPT 
523
524   $IPTABLES -D INPUT -i lo -j ACCEPT
525
526   # DHCP Settings
527
528   if [ "$MAIN_DHCP" = "yes" ]; then
529     $IPTABLES -D INPUT -p udp --dport 67:68 -j ACCEPT 
530     $IPTABLES -D FORWARD -p udp --dport 67:68 -j DROP
531   elif [ "$MAIN_DHCP" = "no" ]; then
532     $IPTABLES -D INPUT -p udp --dport 67:68 -j DROP 
533     $IPTABLES -D FORWARD -p udp --dport 67:68 -j DROP
534   elif [ "$MAIN_DHCP" = "forward" ]; then
535     $IPTABLES -D INPUT -p udp --dport 67:68 -j DROP 
536     $IPTABLES -D FORWARD -p udp --dport 67:68 -j ACCEPT
537   fi
538
539   $IPTABLES -F ${NAME}_ext_fw
540   $IPTABLES -X ${NAME}_ext_fw
541 }
542
543 rules () {
544
545   navigation_rules start
546   
547   ##
548   # Allow all traffic for established and related connections
549   ##
550   
551   $IPTABLES -A $CHAIN_INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT
552   $IPTABLES -A $CHAIN_FORWARD -m state --state ESTABLISHED,RELATED -j ACCEPT
553   
554   $IPTABLES -A $CHAIN_INPUT -i lo -j ACCEPT
555   
556   ##
557   # Allow incoming to our DNS server
558   ##
559   if [ "$DNS" = "yes" ]; then
560     $IPTABLES -A $CHAIN_INPUT -p udp --dport domain -j ACCEPT
561     $IPTABLES -A $CHAIN_FORWARD -p udp --dport domain -j DROP
562   elif [ "$DNS" = "no" ]; then
563     $IPTABLES -A $CHAIN_INPUT -p udp --dport domain -j DROP
564     $IPTABLES -A $CHAIN_FORWARD -p udp --dport domain -j ACCEPT
565   elif [ "$DNS" = "forward" ]; then
566     $IPTABLES -A $CHAIN_INPUT -p udp --dport domain -j ACCEPT
567     $IPTABLES -A $CHAIN_FORWARD -p udp --dport domain -j ACCEPT
568   fi 
569
570   ##
571   # Allow incoming to allowed ports with rate limit setting
572   ##
573
574   # Ignore rate limit checking for the requester that initiate from localhost
575   $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport -s 127.0.0.1 \
576     -d $VSERVER_IP --dports $VSERVER_PORTS_ALLOW -j ACCEPT 
577
578   $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport -d $VSERVER_IP \
579     --dports $VSERVER_PORTS_ALLOW \
580     -m recent --rcheck --seconds 6 --name incoming_throttle -j DROP
581
582   $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport -d $VSERVER_IP \
583     --dports $VSERVER_PORTS_ALLOW \
584     -m hashlimit --hashlimit 20/sec \
585     --hashlimit-mode srcip --hashlimit-burst 30 \
586     --hashlimit-htable-expire 4000 --hashlimit-name incoming \
587     -j ACCEPT
588
589   $IPTABLES -A $CHAIN_INPUT -p tcp -m multiport -d $VSERVER_IP \
590     --dports $VSERVER_PORTS_ALLOW \
591     -m recent --set --name incoming_throttle -j DROP
592   
593   ##
594   # Allow incoming to our SSH server for remote maintenance access
595   ##
596   if [ "$SSH" = "yes" ]; then
597     $IPTABLES -A $CHAIN_INPUT -p tcp -d $VSERVER_IP --dport ssh -j ACCEPT
598   fi
599
600   ##
601   # Allow rate limited ICMP 
602   ##
603   $IPTABLES -A $CHAIN_INPUT -p icmp -m limit --limit 5/second \
604     -d $VSERVER_IP -j ACCEPT
605
606
607
608   ##
609   # Bittorrent Blocking (layer7 module in kernel is needed)
610   # Note: 
611   #   bittorrent-announce is customized pattern, warning if not exists.
612   ##
613   if [ "$BITTORRENT" = "yes" ] || [ -n "$BITTORRENT_ALLOW" ]; then
614     if [ -n "$BITTORRENT_ALLOW" ]; then
615       BITTORRENT_ALLOW_OPTIONS="-m set ! --set $P2P_ALLOW_SET"
616
617       # Source host
618       $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m layer7 --l7proto bittorrent-announce $BITTORRENT_ALLOW_OPTIONS src -j DROP
619       $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m layer7 --l7proto bittorrent $BITTORRENT_ALLOW_OPTIONS src -j DROP
620     fi
621   elif [ "$BITTORRENT" = "block" ]; then
622       $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m layer7 --l7proto bittorrent-announce -j DROP
623       $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m layer7 --l7proto bittorrent -j DROP
624   fi
625   
626   ##
627   # Mark the connections that have been authorized
628   ##
629   $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set $SETNAME dst -j CONNMARK --set-mark 2 
630   $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -m set --set $SETNAME src -j CONNMARK --set-mark 2 
631
632   ##
633   # P2P Throttle
634   ##
635   if [ "$BITTORRENT" = "throttle" ]; then
636     $IPTABLES -t mangle -A $CHAIN_MANGLE_FORWARD -m connmark --mark 2/2 -j $CHAIN_P2P_CHECK
637     $IPTABLES -t mangle -A $CHAIN_MANGLE_FORWARD -m set --set $P2P_SET src -j MARK --set-mark 3
638     $IPTABLES -t mangle -A $CHAIN_MANGLE_FORWARD -m set --set $P2P_SET dst -j MARK --set-mark 3
639
640
641     $IPTABLES -t mangle -A $CHAIN_P2P_CHECK -m layer7 --l7proto bittorrent -j $CHAIN_P2P_DETECT
642     $IPTABLES -t mangle -A $CHAIN_P2P_CHECK -m layer7 --l7proto bittorrent-announce -j $CHAIN_P2P_DETECT
643     $IPTABLES -t mangle -A $CHAIN_P2P_CHECK -m set --set $P2P_SET src -j $CHAIN_P2P_RECHECK
644     $IPTABLES -t mangle -A $CHAIN_P2P_CHECK -j RETURN
645
646
647     $IPTABLES -t mangle -A $CHAIN_P2P_DETECT -m recent --name $P2P_SET --update --seconds 600 -j RETURN
648     $IPTABLES -t mangle -A $CHAIN_P2P_DETECT -j SET --add-set $P2P_SET src
649     $IPTABLES -t mangle -A $CHAIN_P2P_DETECT -m recent --name $P2P_SET --set -j RETURN
650
651     $IPTABLES -t mangle -A $CHAIN_P2P_RECHECK -m recent --name $P2P_SET --rcheck --seconds 600 -j RETURN
652     $IPTABLES -t mangle -A $CHAIN_P2P_RECHECK -j SET --del-set $P2P_SET src
653     $IPTABLES -t mangle -A $CHAIN_P2P_RECHECK -m recent --name $P2P_SET --remove -j RETURN 
654   fi
655    
656   ##
657   # Accept Forwarding for the authorized clients
658   ##
659   $IPTABLES -A $CHAIN_FORWARD_AUTH -j ACCEPT
660
661   ##
662   # SQUID Cache-Proxy
663   ##
664   if [ "$PROXY" = "yes" ] || [ "$PROXY" = "transparent" ]; then
665     if [ "$PROXY_HOST" = "localhost" ] || [ "$PROXY_HOST" = "127.0.0.1" ]; then
666       $IPTABLES -A $CHAIN_INPUT_AUTH -p tcp --dport $PROXY_PORT -j ACCEPT
667     else
668       # PROXY_HOST specify, check if it local
669       is_ip_local $PROXY_HOST
670       PROXY_LOCAL=$?
671       if [ $PROXY_LOCAL = 1 ]; then
672         $IPTABLES -A $CHAIN_INPUT_AUTH -p tcp -d $PROXY_HOST \
673           --dport $PROXY_PORT -j ACCEPT
674       fi
675     fi
676
677     if [ "$VIPMAP" = "yes" ]; then
678       $IPTABLES -t nat -A $CHAIN_NAT_PREROUTING \
679         -m set --set ${SETNAME}-vip src -j $CHAIN_NAT_VIP_PREROUTING
680
681       $IPTABLES -t nat -A $CHAIN_NAT_VIP_PREROUTING -j ACCEPT
682     fi
683
684     if [ "$PROXY" = "transparent" ]; then
685       if [ "$PROXY_HOST" = "localhost" ] || [ "$PROXY_HOST" = "127.0.0.1" ]
686       then
687         $IPTABLES -t nat -A $CHAIN_NAT_PREROUTING -p tcp --dport http \
688           -d ! $VSERVER_IP \
689           -m connmark --mark 2/2 -j REDIRECT --to-ports $PROXY_PORT
690       else
691         $IPTABLES -t nat -A $CHAIN_NAT_PREROUTING -p tcp --dport http \
692           -d ! $VSERVER_IP \
693           -m connmark --mark 2/2 \
694           -j DNAT --to-destination $PROXY_HOST:$PROXY_PORT
695       fi
696     fi
697   fi
698   
699   ##
700   # Redirect unauthorized clients to login page (with rate limited throttling)
701   ##
702   
703   $IPTABLES -t nat -A $CHAIN_NAT_PREROUTING -p tcp -m multiport \
704     --dports $VSERVER_PORTS_INTERCEPT -d ! $VSERVER_IP \
705     -m connmark ! --mark 2/2 \
706     -j $CHAIN_NAT_AUTHEN
707   
708   $IPTABLES -t nat -A $CHAIN_NAT_AUTHEN -p tcp \
709     -j DNAT --to-destination $VSERVER_IP:80
710
711   ##
712   # MASQUERADE
713   ##
714   if [ "$VIPMAP" = "yes" ]; then
715     $IPTABLES -t nat -A $CHAIN_NAT_POSTROUTING \
716       -m set --set ${SETNAME}-vip src -j $CHAIN_NAT_VIP_POSTROUTING
717   fi
718
719   if [ "$MASQUERADE" = "yes" ]; then
720     $IPTABLES -t nat -A $CHAIN_NAT_POSTROUTING -j MASQUERADE
721   fi
722
723   ##
724   # Excluded IP
725   ##
726   for excluded in $EXCLUDED;
727   do
728     $IPTABLES -t mangle -I $CHAIN_MANGLE_PREROUTING -s $excluded \
729       -j CONNMARK --set-mark 2
730     $IPTABLES -t mangle -I $CHAIN_MANGLE_PREROUTING -d $excluded \
731       -j CONNMARK --set-mark 2
732   done 
733
734   ##
735   # Return to main chains
736   ##
737   $IPTABLES -A $CHAIN_INPUT_AUTH -j RETURN
738   $IPTABLES -A $CHAIN_INPUT -j RETURN
739   $IPTABLES -A $CHAIN_FORWARD_AUTH -j RETURN
740   $IPTABLES -A $CHAIN_FORWARD -j RETURN
741   $IPTABLES -t mangle -A $CHAIN_MANGLE_PREROUTING -j RETURN
742   $IPTABLES -t mangle -A $CHAIN_MANGLE_FORWARD -j RETURN
743   $IPTABLES -t mangle -A $CHAIN_MANGLE_POSTROUTING -j RETURN
744   $IPTABLES -t nat -A $CHAIN_NAT_PREROUTING -j RETURN
745   $IPTABLES -t nat -A $CHAIN_NAT_POSTROUTING -j RETURN
746
747   if [ "$VIPMAP" = "yes" ]; then
748     $IPTABLES -t nat -A $CHAIN_NAT_VIP_PREROUTING -j RETURN
749     $IPTABLES -t nat -A $CHAIN_NAT_VIP_POSTROUTING -j RETURN
750
751     if [ "$VIPMAP_FAKE_ARP" = "yes" ]; then
752       for dev in $DEV_EXTERNAL_LIST; do
753         $FARPD -i $dev $VIPMAP_NETWORK
754       done
755     fi
756   fi
757 }
758
759 do_get_config () {
760   file=$1
761   opt=$2
762   get_config $file $opt || true
763
764   # Extract the external device into list
765   DEV_EXTERNAL_LIST=`dev_external_list`
766
767   if [ $? -eq 1 ]; then
768     echo "Error: Could not parsing $file, file does not exists"
769     return 1
770   elif [ $? -eq 2 ]; then
771     echo "Error: Could not parsing $file, config file is malformed"
772     return 2
773   elif [ $? -eq 3 ]; then
774     if [ "$opt" != "stop" ]; then
775       echo "Error: Could not parsing $file, network's name is duplicated!"
776       return 3
777     fi
778   fi
779 }
780
781 start () {
782   test "$RUN_DAEMON" = "yes" || return 0
783   test ! -f $RUN || return 0
784
785   if [ ! -d $MAIN_CONF_DIR ]; then
786     echo "Error: The config directory $MAIN_CONF_DIR does not exists"
787     exit 1
788   fi
789
790   policy 
791
792   touch $RUN
793 }
794
795 stop () {
796   test -f $RUN || return 0
797    
798   cleanup_policy
799
800   killall farpd >/dev/null 2>&1
801
802   rm -f $RUN
803   echo "" > $VSERVER_LIST
804 }
805
806 restart() {
807   stop
808   start
809 }
810
811 start_config() {
812   test ! -f $RUNDIR/$SETNAME || return 0
813   test "$KEEP_SET" = "yes" || add_set
814   new_chains
815   rules
816   touch $RUNDIR/$SETNAME
817   return 0
818 }
819
820 start_config_env() {
821   do_get_config "" start
822   start_config
823   return $?
824 }
825
826 start_config_file() {
827   file=$1
828   do_get_config $file start
829   if [ $? -gt 0 ]; then
830     return 1
831   fi 
832   
833   start_config
834   return $?
835 }
836
837 stop_config() {
838   test -f $RUNDIR/$SETNAME || return 0
839   cleanup
840   test "$KEEP_SET" = "yes" || cleanup_set
841   rm -f $RUNDIR/$SETNAME
842   return 0
843 }
844
845 stop_config_env() {
846   do_get_config "" stop
847   stop_config
848   return $?
849 }
850
851 stop_config_file() {
852   file=$1
853   do_get_config $file stop
854   if [ $? -gt 0 ]; then
855     return 1
856   fi 
857
858   stop_config
859   return $?
860 }
861
862 case "$1" in
863   start)
864     start
865     ;;
866   stop)
867     stop
868     ;;
869   restart)
870     restart
871     ;;
872   start-config)
873     if [ "$ENV_OVERRIDE" = "yes" ]; then
874       start_config_env
875     elif [ -f "$2" ]; then
876       start_config_file $2
877     fi
878     ;;
879   stop-config)
880     if [ "$ENV_OVERRIDE" = "yes" ]; then
881       stop_config_env
882     elif [ -f "$2" ]; then
883       stop_config_file $2
884     fi
885     ;;
886   *)
887     N=@sbindir@/rahunas-firewall
888     echo "Usage: $N {start|stop|restart}"
889     exit 3
890     ;;
891 esac 
892
893 exit 0