2 ###############################################################################
4 # IPFire.org - A linux based firewall #
5 # Copyright (C) 2013 Alexander Marx <amarx@ipfire.org> #
7 # This program is free software: you can redistribute it and/or modify #
8 # it under the terms of the GNU General Public License as published by #
9 # the Free Software Foundation, either version 3 of the License, or #
10 # (at your option) any later version. #
12 # This program is distributed in the hope that it will be useful, #
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of #
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the #
15 # GNU General Public License for more details. #
17 # You should have received a copy of the GNU General Public License #
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. #
20 ###############################################################################
23 no warnings
'uninitialized';
31 my %customservicegrp=();
38 my %defaultNetworks=();
41 require '/var/ipfire/general-functions.pl';
43 my $confignet = "${General::swroot}/fwhosts/customnetworks";
44 my $confighost = "${General::swroot}/fwhosts/customhosts";
45 my $configgrp = "${General::swroot}/fwhosts/customgroups";
46 my $configsrv = "${General::swroot}/fwhosts/customservices";
47 my $configsrvgrp = "${General::swroot}/fwhosts/customservicegrp";
48 my $configccdnet = "${General::swroot}/ovpn/ccd.conf";
49 my $configccdhost = "${General::swroot}/ovpn/ovpnconfig";
50 my $configipsec = "${General::swroot}/vpn/config";
51 my $configovpn = "${General::swroot}/ovpn/settings";
54 my $netsettings = "${General::swroot}/ethernet/settings";
56 &General
::readhash
("/var/ipfire/ethernet/settings", \
%netsettings);
57 &General
::readhash
("${General::swroot}/ovpn/settings", \
%ovpnsettings);
58 &General
::readhash
("${General::swroot}/vpn/settings", \
%ipsecsettings);
59 &General
::readhash
("$netsettings", \
%defaultNetworks);
61 &General
::readhasharray
("$confignet", \
%customnetwork);
62 &General
::readhasharray
("$confighost", \
%customhost);
63 &General
::readhasharray
("$configgrp", \
%customgrp);
64 &General
::readhasharray
("$configccdnet", \
%ccdnet);
65 &General
::readhasharray
("$configccdhost", \
%ccdhost);
66 &General
::readhasharray
("$configipsec", \
%ipsecconf);
67 &General
::readhasharray
("$configsrv", \
%customservice);
68 &General
::readhasharray
("$configsrvgrp", \
%customservicegrp);
73 foreach my $key (sort {$a <=> $b} keys %customservice){
74 if($customservice{$key}[0] eq $val){
75 if ($customservice{$key}[0] eq $val){
76 return $customservice{$key}[2];
88 foreach my $key (sort {$a <=> $b} keys %customservicegrp){
89 if($customservicegrp{$key}[0] eq $val){
90 if (&get_srv_prot
($customservicegrp{$key}[2]) eq 'TCP'){
92 }elsif(&get_srv_prot
($customservicegrp{$key}[2]) eq 'UDP'){
94 }elsif(&get_srv_prot
($customservicegrp{$key}[2]) eq 'ICMP'){
97 #Protocols used in servicegroups
98 push (@ips,$customservicegrp{$key}[2]);
102 if ($tcp eq '1'){push (@ips,'TCP');}
103 if ($udp eq '1'){push (@ips,'UDP');}
104 if ($icmp eq '1'){push (@ips,'ICMP');}
105 my $back=join(",",@ips);
114 foreach my $key (sort {$a <=> $b} keys %customservice){
115 if($customservice{$key}[0] eq $val && $customservice{$key}[2] eq $prot){
116 return $customservice{$key}[$field];
127 foreach my $key (sort {$a <=> $b} keys %customservicegrp){
128 if($customservicegrp{$key}[0] eq $val){
129 if ($prot ne 'ICMP'){
130 $value=&get_srv_port
($customservicegrp{$key}[2],1,$prot);
131 }elsif ($prot eq 'ICMP'){
132 $value=&get_srv_port
($customservicegrp{$key}[2],3,$prot);
134 push (@ips,$value) if ($value ne '') ;
138 if ($#ips gt 0){$back="-m multiport --dports ";}else{$back="--dport ";}
139 }elsif ($prot eq 'ICMP'){
140 $back="--icmp-type ";
143 $back.=join(",",@ips);
150 foreach my $key (sort {$a <=> $b} keys %ipsecconf){
151 if($ipsecconf{$key}[1] eq $val){
152 return $ipsecconf{$key}[$field];
156 sub get_ipsec_host_ip
160 foreach my $key (sort {$a <=> $b} keys %ipsecconf){
161 if($ipsecconf{$key}[1] eq $val){
162 return $ipsecconf{$key}[$field];
170 foreach my $key (sort {$a <=> $b} keys %ccdhost){
171 if($ccdhost{$key}[1] eq $val){
172 return $ccdhost{$key}[$field];
180 foreach my $key (sort {$a <=> $b} keys %ccdhost){
181 if($ccdhost{$key}[1] eq $val){
182 return $ccdhost{$key}[$field];
191 foreach my $key (sort {$a <=> $b} keys %ccdnet){
192 if($ccdnet{$key}[0] eq $val){
193 return $ccdnet{$key}[$field];
201 foreach my $key (sort {$a <=> $b} keys %customgrp){
202 if ($customgrp{$key}[0] eq $val){
203 &get_address
($customgrp{$key}[3],$src);
213 return "0.0.0.0/0.0.0.0";
214 }elsif($val eq 'GREEN'){
215 return "$netsettings{'GREEN_NETADDRESS'}/$netsettings{'GREEN_NETMASK'}";
216 }elsif($val eq 'ORANGE'){
217 return "$netsettings{'ORANGE_NETADDRESS'}/$netsettings{'ORANGE_NETMASK'}";
218 }elsif($val eq 'BLUE'){
219 return "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}";
220 }elsif($val eq 'RED'){
221 return "0.0.0.0/0 -o $con";
222 }elsif($val =~ /OpenVPN/i){
223 return "$ovpnsettings{'DOVPN_SUBNET'}";
224 }elsif($val =~ /IPsec/i){
225 return "$ipsecsettings{'RW_NET'}";
226 }elsif($val eq 'IPFire'){
233 foreach my $key (sort {$a <=> $b} keys %customnetwork){
234 if($customnetwork{$key}[0] eq $val){
235 return "$customnetwork{$key}[1]/$customnetwork{$key}[2]";
243 foreach my $key (sort {$a <=> $b} keys %customhost){
244 if($customhost{$key}[0] eq $val){
245 if ($customhost{$key}[1] eq 'mac' && $src eq 'src'){
246 return "-m mac --mac-source $customhost{$key}[2]";
247 }elsif($customhost{$key}[1] eq 'ip' && $src eq 'src'){
248 return "$customhost{$key}[2]";
249 }elsif($customhost{$key}[1] eq 'ip' && $src eq 'tgt'){
250 return "$customhost{$key}[2]";
251 }elsif($customhost{$key}[1] eq 'mac' && $src eq 'tgt'){
268 if ($type eq "src") {
269 $addr_type = $$hash{$key}[3];
270 $value = $$hash{$key}[4];
272 } elsif ($type eq "tgt") {
273 $addr_type = $$hash{$key}[5];
274 $value = $$hash{$key}[6];
277 if ($addr_type ~~ ["cust_grp_src", "cust_grp_tgt"]) {
278 foreach my $grp (sort {$a <=> $b} keys %customgrp) {
279 if ($customgrp{$grp}[0] eq $value) {
280 my @address = &get_address
($customgrp{$grp}[3], $customgrp{$grp}[2], $type);
283 push(@addresses, @address);
288 my @address = &get_address
($addr_type, $value, $type);
291 push(@addresses, @address);
305 # If the user manually typed an address, we just check if it is a MAC
306 # address. Otherwise, we assume that it is an IP address.
307 if ($key ~~ ["src_addr", "tgt_addr"]) {
308 if (&General
::validmac
($value)) {
309 push(@ret, "-m mac --mac-source $value");
314 # If a default network interface (GREEN, BLUE, etc.) is selected, we
315 # try to get the corresponding address of the network.
316 } elsif ($key ~~ ["std_net_src", "std_net_tgt", "Standard Network"]) {
317 my $external_interface = &get_external_interface
();
319 my $network_address = &get_std_net_ip
($value, $external_interface);
320 if ($network_address) {
321 push(@ret, $network_address);
325 } elsif ($key ~~ ["cust_net_src", "cust_net_tgt", "Custom Network"]) {
326 my $network_address = &get_net_ip
($value);
327 if ($network_address) {
328 push(@ret, $network_address);
332 } elsif ($key ~~ ["cust_host_src", "cust_host_tgt", "Custom Host"]) {
333 my $host_address = &get_host_ip
($value, $type);
335 push(@ret, $host_address);
339 } elsif ($key ~~ ["ovpn_net_src", "ovpn_net_tgt", "OpenVPN static network"]) {
340 my $network_address = &get_ovpn_net_ip
($value, 1);
341 if ($network_address) {
342 push(@ret, $network_address);
346 } elsif ($key ~~ ["ovpn_host_src", "ovpn_host_tgt", "OpenVPN static host"]) {
347 my $host_address = &get_ovpn_host_ip
($value, 33);
349 push(@ret, $host_address);
353 } elsif ($key ~~ ["ovpn_n2n_src", "ovpn_n2n_tgt", "OpenVPN N-2-N"]) {
354 my $network_address = &get_ovpn_n2n_ip
($value, 11);
355 if ($network_address) {
356 push(@ret, $network_address);
360 } elsif ($key ~~ ["ipsec_net_src", "ipsec_net_tgt", "IpSec Network"]) {
361 my $network_address = &get_ipsec_net_ip
($value, 11);
362 if ($network_address) {
363 push(@ret, $network_address);
366 # The firewall's own IP addresses.
367 } elsif ($key ~~ ["ipfire", "ipfire_src"]) {
369 if ($value eq "ALL") {
373 } elsif ($value eq "GREEN") {
374 push(@ret, $defaultNetworks{"GREEN_ADDRESS"});
377 } elsif ($value eq "BLUE") {
378 push(@ret, $defaultNetworks{"BLUE_ADDRESS"});
381 } elsif ($value eq "ORANGE") {
382 push(@ret, $defaultNetworks{"ORANGE_ADDRESS"});
385 } elsif ($value ~~ ["RED", "RED1"]) {
386 my $address = &get_external_address
();
388 push(@ret, $address);
393 my %alias = &get_alias
($value);
395 push(@ret, $alias{"IPT"});
399 # If nothing was selected, we assume "any".
406 sub get_external_interface
()
408 open(IFACE
, "/var/ipfire/red/iface") or return "";
414 sub get_external_address
()
416 open(ADDR
, "/var/ipfire/red/local-ipaddress") or return "";
417 my $address = <ADDR
>;
426 foreach my $alias (sort keys %aliases) {
428 return $aliases{$alias};
437 # Any static address of any zone.
438 if ($zone eq "AUTO") {
439 if ($source && ($source !~ m/mac/i )) {
440 my $firewall_ip = &get_internal_firewall_ip_address
($source, 1);
445 $firewall_ip = &get_matching_firewall_address
($source, 1);
451 return &get_external_address
();
453 } elsif ($zone eq "RED" || $zone eq "GREEN" || $zone eq "ORANGE" || $zone eq "BLUE") {
454 return $defaultNetworks{$zone . "_ADDRESS"};
456 } elsif ($zone eq "Default IP") {
457 return &get_external_address
();
460 return &get_alias
($zone);
463 print_error
("Could not find NAT address");
465 sub get_internal_firewall_ip_addresses
467 my $use_orange = shift;
469 my @zones = ("GREEN", "BLUE");
471 push(@zones, "ORANGE");
475 for my $zone (@zones) {
476 next unless (exists $defaultNetworks{$zone . "_ADDRESS"});
478 my $zone_address = $defaultNetworks{$zone . "_ADDRESS"};
479 push(@addresses, $zone_address);
484 sub get_matching_firewall_address
487 my $use_orange = shift;
489 my ($address, $netmask) = split("/", $addr);
491 my @zones = ("GREEN", "BLUE");
493 push(@zones, "ORANGE");
496 foreach my $zone (@zones) {
497 next unless (exists $defaultNetworks{$zone . "_ADDRESS"});
499 my $zone_subnet = $defaultNetworks{$zone . "_NETADDRESS"};
500 my $zone_mask = $defaultNetworks{$zone . "_NETMASK"};
502 if (&General
::IpInSubnet
($address, $zone_subnet, $zone_mask)) {
503 return $defaultNetworks{$zone . "_ADDRESS"};
509 sub get_internal_firewall_ip_address
512 my $use_orange = shift;
514 my ($net_address, $net_mask) = split("/", $subnet);
515 if ((!$net_mask) || ($net_mask ~~ ["32", "255.255.255.255"])) {
519 my @addresses = &get_internal_firewall_ip_addresses
($use_orange);
520 foreach my $zone_address (@addresses) {
521 if (&General
::IpInSubnet
($zone_address, $net_address, $net_mask)) {
522 return $zone_address;