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