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