root/5100R/branches/dev/ui/base-firewall.mod/glue/handlers/Firewall_update

Revision 201, 7.4 kB (checked in by will, 7 years ago)

dev "menlo" branch patch, it's huge

  • Property svn:eol-style set to native
  • Property svn:keywords set to Author Date Id Revision
Line 
1 #!/usr/bin/perl
2
3 # some constants:
4 my $iptables = 0;
5 $iptables = 1 if (-x "/usr/bin/iptables");
6 my $fw_conf = "/etc/ipchains.conf";
7 $fw_conf = "/etc/iptables.conf" if ($iptables);
8 my $fwbin = "/sbin/ipchains";
9 $fwbin = "/usr/bin/iptables" if ($iptables);
10
11 use lib qw( /usr/sausalito/perl );
12 use Sauce::Util;
13 use CCE;
14
15 my $cce = new CCE;
16 $cce->connectfd (\*STDIN, \*STDOUT);
17
18 # Okay, let's regenerate /etc/ipchains
19 my %chains = (); # ipchains rule array data goes here.
20 my %chain_meta = (); # ipchain object data goes here.
21 my @warnings = ();
22
23 # get all chains
24 my (@chain_oids) = $cce->find("FirewallChain");
25
26 foreach $chain_oid (@chain_oids) {
27   load_chain($chain_oid);
28 }
29
30 validate_chains();
31
32 rewrite_fw_conf();
33
34 restart_firewall();
35
36 {
37   my (@sysoids) = $cce->find("System");
38   $cce->set($sysoids[0], "Firewall", { 'dirty' => 0 });
39 }
40
41 $cce->bye("SUCCESS");
42 exit(0);
43
44 ###############################################################3
45
46 # load_chain - load chain of rule objects into memory.
47 sub load_chain
48 {
49   my $chain_oid = shift;
50   my $rules = [];
51  
52   my ($ok, $obj) = $cce->get($chain_oid);
53  
54   if (!$ok) {
55     push (@warnings, "[[base-firewall.Missing-chain]]");
56     die("Could not get object id $chain_oid");
57   }
58  
59   my $chain_name = $obj->{name};
60   $chain_meta{$chain_name} = $obj;
61   my (@rule_oids) = CCE->scalar_to_array($obj->{rules});
62   my $rule_oid;
63   foreach $rule_oid (@rule_oids) {
64     my $rule;
65     ($ok, $rule) = $cce->get($rule_oid);
66     if (!$ok) {
67       push (@warnings,
68         CCE->msg_create("base-firewall.Missing-rule-in-chain",
69           { 'chain' => ${chain_name} }));
70     }
71     push (@$rules, $rule);
72   }
73  
74   $chains{$chain_name} = $rules;
75 }
76
77 # validate_chains: perform some integrity checking on rule chains.
78 sub validate_chains
79 {
80   my ($chain, $rule, $i);
81   foreach $chain (values %chains) {
82     for ($i = 0; $i <= $#{$chain}; $i++) {
83       $rule = $chain->[$i];
84       if ($rule->{policy} eq 'JUMP') {
85         # verify that the jump_target chain exists:
86         if (!defined($chains{$rule->{jump_target}})) {
87           push (@warnings,
88             $cce->msg_create( "base-firewall.Missing-subchain",
89               { 'chain' => ${chain_name},
90                 'subchain' => $rule->{jump_target}
91               }));
92           splice (@$chain, $i, 1); # delete rule
93         } # if bad target
94       } #if JUMP
95     } # for each rule
96   } # for each chain
97 } # done.
98
99 use Data::Dumper;
100
101 # rewrite_fw_conf
102 sub rewrite_fw_conf
103 {
104   my @data = ( "\n$fwbin -F\n" );
105
106   my $sysobj;
107   {
108         my @oids = $cce->find("System");
109         my $ok;
110         ($ok, $sysobj) = $cce->get($oids[0], "Firewall");
111   }
112
113   if (!$sysobj->{enabled}) {
114         $fwbin = "# " . $fwbin;
115         push (@data, "# Firewall currently not enabled.\n");
116   }
117
118   my ($name, $chain, $rule);
119   while (($name, $chain) = each %chains) {
120     # warn "dump $name: ",Dumper($chain_meta{$name}),"\n";
121     my $default_policy = $chain_meta{$name}->{default};
122     if ($iptables && ($default_policy eq 'DENY')) {
123         $default_policy = 'DROP';
124     }
125
126     push (@data, "# $name chain:\n");
127     if ( ($name =~ m/^((input)|(forward)|(output))$/)
128       && $default_policy )
129     {
130       if ($iptables)
131       {
132         $name =~ tr/[a-z]/[A-Z]/;
133       }
134       # set the default policy:
135       push (@data, "$fwbin -P $name $default_policy\n");
136     }
137     foreach $rule (@$chain) {
138       push (@data, rule_to_ipchains_command($name, $rule));
139     }
140     push (@data, "\n");
141   }
142  
143   my $data = join("",@data);
144   Sauce::Util::replaceblock(
145     $fw_conf,
146     "# start of auto-generated ipchains commands, do not edit below this line",
147     $data,
148     "# end of auto-generated ipchains commands, do not edit above this line",
149   );
150 }
151
152 sub restart_firewall
153 {
154   if($iptables)
155   {
156     system("/etc/rc.d/init.d/iptables restart >& /tmp/iptables.out");
157   }
158   else
159   {
160     system("/etc/rc.d/init.d/ipchains restart >& /tmp/ipchains.out");
161   }
162 }
163
164 sub rule_to_ipchains_command
165 {
166   # /usr/bin/iptables -P INPUT ACCEPT
167   # /usr/bin/iptables -A INPUT -p tcp -s 10.9.0.0/16  -d 10.9.28.128/32 --source-port 80 -j ACCEPT
168   # /usr/bin/iptables -A INPUT -p tcp -s 10.9.0.0/16  -d 127.0.0.1/32 --source-port 80 -j ACCEPT
169   # /usr/bin/iptables -t nat -A PREROUTING -s 10.9.0.0/16 -p tcp --destination-port 80 -j DNAT --to-destination 127.0.0.1:3128
170
171   my ($chain,$rule) = (shift,shift);
172   $chain =~ tr/[a-z]/[A-Z]/ if ($iptables);
173
174   my @data = ();
175
176   my @source_nets = ips_to_nets (
177     $rule->{source_ip_start},
178     $rule->{source_ip_stop});
179   my @dest_nets = ips_to_nets (
180     $rule->{dest_ip_start},
181     $rule->{dest_ip_stop});
182
183   if ($rule->{source_ports} || $rule->{dest_ports}) {
184         if ($rule->{protocol} eq 'all') {
185                 foreach my $proto ('tcp', 'udp', 'icmp') {
186                         $rule->{protocol} = $proto;
187                         push(@data, rule_to_ipchains_command($chain, $rule));
188                 }
189                 return @data;
190         }
191   }
192  
193   my ($srcnet, $destnet);
194   foreach $srcnet (@source_nets) {
195     foreach $destnet (@dest_nets) {
196       if ($iptables) {
197         push (@data,
198         "${fwbin} -A $chain",
199         " -p ", $rule->{protocol},
200         " -s ", $srcnet,
201         " -d ", $destnet);
202         if($rule->{source_ports}) {
203           # $rule->{source_ports} =~ s/\:/\-/g;
204           push(@data, " --source-port ".$rule->{source_ports});
205         }
206         if($rule->{dest_ports}) {
207           # $rule->{dest_ports} =~ s/\:/\-/g;
208           push(@data, " --destination-port ".$rule->{dest_ports});
209         }
210         if ($rule->{interface}) {
211           push (@data, " -i ", $rule->{interface});
212         }
213         if ($rule->{policy} eq "JUMP") {
214           push (@data, " -j ", $rule->{jump_target});
215         } else {
216           push (@data, " -j ", $rule->{policy});
217         }
218         if ($rule->{policy} eq "REDIRECT") {
219           push (@data, ' --destination-port ', $rule->{redir_target});
220         }
221         push (@data,"\n");
222       } else {
223         push (@data,
224         "${fwbin} -A $chain",
225         " -p ", $rule->{protocol},
226         " -s ", $srcnet, " ", $rule->{source_ports},
227         " -d ", $destnet, " ", $rule->{dest_ports});
228         if ($rule->{interface}) {
229           push (@data, " -i ", $rule->{interface});
230         }
231         if ($rule->{policy} eq "JUMP") {
232           push (@data, " -j ", $rule->{jump_target});
233         } else {
234           push (@data, " -j ", $rule->{policy});
235         }
236         if ($rule->{policy} eq "REDIRECT") {
237           push (@data, " ", $rule->{redir_target});
238         }
239         push (@data,"\n");
240       }
241     }
242   }
243   return @data;
244 }
245
246 # ips_to_nets:
247 # this is a very happy function that converts ranges of ips into
248 # batches of netmasks.  I'm proud of my little algorithm here.
249 #
250 # params: a start ip and stop ip
251 #
252 # returns: a list of strings, each containing "ip/netmask".
253 sub ips_to_nets
254 {
255   my ($start, $stop) = (shift, shift);
256  
257   # convert to 32-bit integers:
258   my $start_bin = ip2bin($start);
259   my $stop_bin = ip2bin($stop);
260
261   # generate set of subnets that describes the ipspace 
262   my @nets = ();
263   while ($start_bin <= $stop_bin) {
264     my $mask = 0xFFFFFFFF;
265     my $last_mask = $mask;
266     while ( (($start_bin & (~$mask)) == 0)
267       &&    (($start_bin | (~$mask)) <= $stop_bin)
268       &&    ($last_mask)
269     )
270     {
271       $last_mask = $mask;
272       $mask <<= 1;
273     }
274     my $ip = bin2ip($start_bin);
275     my $nm = sum(split(//,unpack("B32", pack("N",$last_mask))));
276     # my $nm = bin2ip($last_mask);
277     push (@nets, "$ip/$nm");
278    
279     $start_bin = ($start_bin | (~$last_mask)) + 1;
280   }
281  
282   return @nets;
283 }
284
285 sub sum
286 {
287   my $a = 0; my $b;
288   while (defined($b = shift)) { $a+=$b; }
289   return $a;
290 }
291
292 sub bin2ip
293 {
294   return join(".",unpack("C4",pack("N",shift)));
295 }
296
297 sub ip2bin
298 {
299   return unpack("N",pack("C4",split(/\./, shift)));
300 }
301
Note: See TracBrowser for help on using the browser.