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