my %customnetwork=();
my %customhost=();
my %customgrp=();
+my %customgeoipgrp=();
my %customservice=();
my %customservicegrp=();
my %ccdnet=();
my %ipsecsettings=();
my %netsettings=();
my %ovpnsettings=();
+my %aliases=();
require '/var/ipfire/general-functions.pl';
my $confignet = "${General::swroot}/fwhosts/customnetworks";
my $confighost = "${General::swroot}/fwhosts/customhosts";
my $configgrp = "${General::swroot}/fwhosts/customgroups";
+my $configgeoipgrp = "${General::swroot}/fwhosts/customgeoipgrp";
my $configsrv = "${General::swroot}/fwhosts/customservices";
my $configsrvgrp = "${General::swroot}/fwhosts/customservicegrp";
my $configccdnet = "${General::swroot}/ovpn/ccd.conf";
my $configovpn = "${General::swroot}/ovpn/settings";
my $val;
my $field;
+my $netsettings = "${General::swroot}/ethernet/settings";
&General::readhash("/var/ipfire/ethernet/settings", \%netsettings);
&General::readhash("${General::swroot}/ovpn/settings", \%ovpnsettings);
&General::readhash("${General::swroot}/vpn/settings", \%ipsecsettings);
-
&General::readhasharray("$confignet", \%customnetwork);
&General::readhasharray("$confighost", \%customhost);
&General::readhasharray("$configgrp", \%customgrp);
+&General::readhasharray("$configgeoipgrp", \%customgeoipgrp);
&General::readhasharray("$configccdnet", \%ccdnet);
&General::readhasharray("$configccdhost", \%ccdhost);
&General::readhasharray("$configipsec", \%ipsecconf);
&General::readhasharray("$configsrv", \%customservice);
&General::readhasharray("$configsrvgrp", \%customservicegrp);
+&General::get_aliases(\%aliases);
sub get_srv_prot
{
$udp=1;
}elsif(&get_srv_prot($customservicegrp{$key}[2]) eq 'ICMP'){
$icmp=1;
- }
+ }else{
+ #Protocols used in servicegroups
+ push (@ips,$customservicegrp{$key}[2]);
+ }
}
}
if ($tcp eq '1'){push (@ips,'TCP');}
return $back;
}
-
-
sub get_srv_port
{
my $val=shift;
my $field=shift;
my $prot=shift;
foreach my $key (sort {$a <=> $b} keys %customservice){
- if($customservice{$key}[0] eq $val){
- if($customservice{$key}[2] eq $prot){
- return $customservice{$key}[$field];
- }
+ if($customservice{$key}[0] eq $val && $customservice{$key}[2] eq $prot){
+ return $customservice{$key}[$field];
}
}
}
}elsif($val eq 'BLUE'){
return "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}";
}elsif($val eq 'RED'){
- return "0.0.0.0/0 -o $con";
+ return "0.0.0.0/0";
}elsif($val =~ /OpenVPN/i){
return "$ovpnsettings{'DOVPN_SUBNET'}";
}elsif($val =~ /IPsec/i){
return ;
}
}
+sub get_interface
+{
+ my $net=shift;
+ if($net eq "$netsettings{'GREEN_NETADDRESS'}/$netsettings{'GREEN_NETMASK'}"){
+ return "$netsettings{'GREEN_DEV'}";
+ }
+ if($net eq "$netsettings{'ORANGE_NETADDRESS'}/$netsettings{'ORANGE_NETMASK'}"){
+ return "$netsettings{'ORANGE_DEV'}";
+ }
+ if($net eq "$netsettings{'BLUE_NETADDRESS'}/$netsettings{'BLUE_NETMASK'}"){
+ return "$netsettings{'BLUE_DEV'}";
+ }
+ if($net eq "0.0.0.0/0") {
+ return &get_external_interface();
+ }
+ return "";
+}
sub get_net_ip
{
my $val=shift;
}
}
}
+sub get_addresses
+{
+ my $hash = shift;
+ my $key = shift;
+ my $type = shift;
+
+ my @addresses = ();
+ my $addr_type;
+ my $value;
+ my $group_name;
+
+ if ($type eq "src") {
+ $addr_type = $$hash{$key}[3];
+ $value = $$hash{$key}[4];
+
+ } elsif ($type eq "tgt") {
+ $addr_type = $$hash{$key}[5];
+ $value = $$hash{$key}[6];
+ }
+
+ if ($addr_type ~~ ["cust_grp_src", "cust_grp_tgt"]) {
+ foreach my $grp (sort {$a <=> $b} keys %customgrp) {
+ if ($customgrp{$grp}[0] eq $value) {
+ my @address = &get_address($customgrp{$grp}[3], $customgrp{$grp}[2], $type);
+
+ if (@address) {
+ push(@addresses, @address);
+ }
+ }
+ }
+ }elsif ($addr_type ~~ ["cust_geoip_src", "cust_geoip_tgt"] && $value =~ "group:") {
+ $value=substr($value,6);
+ foreach my $grp (sort {$a <=> $b} keys %customgeoipgrp) {
+ if ($customgeoipgrp{$grp}[0] eq $value) {
+ my @address = &get_address($addr_type, $customgeoipgrp{$grp}[2], $type);
+
+ if (@address) {
+ push(@addresses, @address);
+ }
+ }
+ }
+ } else {
+ my @address = &get_address($addr_type, $value, $type);
+
+ if (@address) {
+ push(@addresses, @address);
+ }
+ }
+
+ return @addresses;
+}
+sub get_address
+{
+ my $key = shift;
+ my $value = shift;
+ my $type = shift;
+
+ my @ret = ();
+
+ # If the user manually typed an address, we just check if it is a MAC
+ # address. Otherwise, we assume that it is an IP address.
+ if ($key ~~ ["src_addr", "tgt_addr"]) {
+ if (&General::validmac($value)) {
+ push(@ret, ["-m mac --mac-source $value", ""]);
+ } else {
+ push(@ret, [$value, ""]);
+ }
+
+ # If a default network interface (GREEN, BLUE, etc.) is selected, we
+ # try to get the corresponding address of the network.
+ } elsif ($key ~~ ["std_net_src", "std_net_tgt", "Standard Network"]) {
+ my $external_interface = &get_external_interface();
+
+ my $network_address = &get_std_net_ip($value, $external_interface);
+
+ if ($network_address) {
+ my $interface = &get_interface($network_address);
+ push(@ret, [$network_address, $interface]);
+ }
+
+ # Custom networks.
+ } elsif ($key ~~ ["cust_net_src", "cust_net_tgt", "Custom Network"]) {
+ my $network_address = &get_net_ip($value);
+ if ($network_address) {
+ push(@ret, [$network_address, ""]);
+ }
+
+ # Custom hosts.
+ } elsif ($key ~~ ["cust_host_src", "cust_host_tgt", "Custom Host"]) {
+ my $host_address = &get_host_ip($value, $type);
+ if ($host_address) {
+ push(@ret, [$host_address, ""]);
+ }
+
+ # OpenVPN networks.
+ } elsif ($key ~~ ["ovpn_net_src", "ovpn_net_tgt", "OpenVPN static network"]) {
+ my $network_address = &get_ovpn_net_ip($value, 1);
+ if ($network_address) {
+ push(@ret, [$network_address, ""]);
+ }
+
+ # OpenVPN hosts.
+ } elsif ($key ~~ ["ovpn_host_src", "ovpn_host_tgt", "OpenVPN static host"]) {
+ my $host_address = &get_ovpn_host_ip($value, 33);
+ if ($host_address) {
+ push(@ret, [$host_address, ""]);
+ }
+
+ # OpenVPN N2N.
+ } elsif ($key ~~ ["ovpn_n2n_src", "ovpn_n2n_tgt", "OpenVPN N-2-N"]) {
+ my $network_address = &get_ovpn_n2n_ip($value, 11);
+ if ($network_address) {
+ push(@ret, [$network_address, ""]);
+ }
+
+ # IPsec networks.
+ } elsif ($key ~~ ["ipsec_net_src", "ipsec_net_tgt", "IpSec Network"]) {
+ my $network_address = &get_ipsec_net_ip($value, 11);
+ if ($network_address) {
+ push(@ret, [$network_address, ""]);
+ }
+
+ # The firewall's own IP addresses.
+ } elsif ($key ~~ ["ipfire", "ipfire_src"]) {
+ # ALL
+ if ($value eq "ALL") {
+ push(@ret, ["0/0", ""]);
+
+ # GREEN
+ } elsif ($value eq "GREEN") {
+ push(@ret, [$netsettings{"GREEN_ADDRESS"}, ""]);
+
+ # BLUE
+ } elsif ($value eq "BLUE") {
+ push(@ret, [$netsettings{"BLUE_ADDRESS"}, ""]);
+
+ # ORANGE
+ } elsif ($value eq "ORANGE") {
+ push(@ret, [$netsettings{"ORANGE_ADDRESS"}, ""]);
+
+ # RED
+ } elsif ($value ~~ ["RED", "RED1"]) {
+ my $address = &get_external_address();
+ if ($address) {
+ push(@ret, [$address, ""]);
+ }
+
+ # Aliases
+ } else {
+ my $alias = &get_alias($value);
+ if ($alias) {
+ push(@ret, [$alias, ""]);
+ }
+ }
+
+ # Handle rule options with GeoIP as source.
+ } elsif ($key eq "cust_geoip_src") {
+ # Get external interface.
+ my $external_interface = &get_external_interface();
+
+ push(@ret, ["-m geoip --src-cc $value", "$external_interface"]);
+
+ # Handle rule options with GeoIP as target.
+ } elsif ($key eq "cust_geoip_tgt") {
+ # Get external interface.
+ my $external_interface = &get_external_interface();
+
+ push(@ret, ["-m geoip --dst-cc $value", "$external_interface"]);
+
+ # If nothing was selected, we assume "any".
+ } else {
+ push(@ret, ["0/0", ""]);
+ }
+
+ return @ret;
+}
+sub get_external_interface()
+{
+ open(IFACE, "/var/ipfire/red/iface") or return "";
+ my $iface = <IFACE>;
+ close(IFACE);
+
+ return $iface;
+}
+sub get_external_address()
+{
+ open(ADDR, "/var/ipfire/red/local-ipaddress") or return "";
+ my $address = <ADDR>;
+ close(ADDR);
+
+ return $address;
+}
+sub get_alias
+{
+ my $id = shift;
+
+ foreach my $alias (sort keys %aliases) {
+ if ($id eq $alias) {
+ return $aliases{$alias}{"IPT"};
+ }
+ }
+}
+
+sub get_nat_address {
+ my $zone = shift;
+ my $source = shift;
+
+ # Any static address of any zone.
+ if ($zone eq "AUTO") {
+ if ($source && ($source !~ m/mac/i )) {
+ my $firewall_ip = &get_internal_firewall_ip_address($source, 1);
+ if ($firewall_ip) {
+ return $firewall_ip;
+ }
+
+ $firewall_ip = &get_matching_firewall_address($source, 1);
+ if ($firewall_ip) {
+ return $firewall_ip;
+ }
+ }
+
+ return &get_external_address();
+
+ } elsif ($zone eq "RED" || $zone eq "GREEN" || $zone eq "ORANGE" || $zone eq "BLUE") {
+ return $netsettings{$zone . "_ADDRESS"};
+
+ } elsif ($zone ~~ ["Default IP", "ALL"]) {
+ return &get_external_address();
+
+ } else {
+ my $alias = &get_alias($zone);
+ unless ($alias) {
+ $alias = &get_external_address();
+ }
+ return $alias;
+ }
+
+ print_error("Could not find NAT address");
+}
+
+sub get_internal_firewall_ip_addresses
+{
+ my $use_orange = shift;
+
+ my @zones = ("GREEN", "BLUE");
+ if ($use_orange) {
+ push(@zones, "ORANGE");
+ }
+
+ my @addresses = ();
+ for my $zone (@zones) {
+ next unless (exists $netsettings{$zone . "_ADDRESS"});
+
+ my $zone_address = $netsettings{$zone . "_ADDRESS"};
+ push(@addresses, $zone_address);
+ }
+
+ return @addresses;
+}
+sub get_matching_firewall_address
+{
+ my $addr = shift;
+ my $use_orange = shift;
+
+ my ($address, $netmask) = split("/", $addr);
+
+ my @zones = ("GREEN", "BLUE");
+ if ($use_orange) {
+ push(@zones, "ORANGE");
+ }
+
+ foreach my $zone (@zones) {
+ next unless (exists $netsettings{$zone . "_ADDRESS"});
+
+ my $zone_subnet = $netsettings{$zone . "_NETADDRESS"};
+ my $zone_mask = $netsettings{$zone . "_NETMASK"};
+
+ if (&General::IpInSubnet($address, $zone_subnet, $zone_mask)) {
+ return $netsettings{$zone . "_ADDRESS"};
+ }
+ }
+
+ return 0;
+}
+sub get_internal_firewall_ip_address
+{
+ my $subnet = shift;
+ my $use_orange = shift;
+
+ my ($net_address, $net_mask) = split("/", $subnet);
+ if ((!$net_mask) || ($net_mask ~~ ["32", "255.255.255.255"])) {
+ return 0;
+ }
+
+ # Convert net mask into correct format for &General::IpInSubnet().
+ $net_mask = &General::iporsubtodec($net_mask);
+
+ my @addresses = &get_internal_firewall_ip_addresses($use_orange);
+ foreach my $zone_address (@addresses) {
+ if (&General::IpInSubnet($zone_address, $net_address, $net_mask)) {
+ return $zone_address;
+ }
+ }
+
+ return 0;
+}
+
+sub get_geoip_locations() {
+ # Path to the directory which contains the binary geoip
+ # databases.
+ my $directory="/usr/share/xt_geoip/LE";
+
+ # Array to store the final country list.
+ my @country_codes = ();
+
+ # Open location and do a directory listing.
+ opendir(DIR, "$directory");
+ my @locations = readdir(DIR);
+ closedir(DIR);
+
+ # Loop through the directory listing, and cut of the file extensions.
+ foreach my $location (sort @locations) {
+ # skip . and ..
+ next if($location =~ /^\.$/);
+ next if($location =~ /^\.\.$/);
+
+ # Remove whitespaces.
+ chomp($location);
+
+ # Cut-off file extension.
+ my ($country_code, $extension) = split(/\./, $location);
+
+ # Add country code to array.
+ push(@country_codes, $country_code);
+ }
+
+ # Return final array.
+ return @country_codes;
+}
return 1;