my %configinputfw=();
my %configoutgoingfw=();
my %confignatfw=();
-my %aliases=();
my @p2ps=();
my $configfwdfw = "${General::swroot}/firewall/config";
&General::readhasharray($configinput, \%configinputfw);
&General::readhasharray($configoutgoing, \%configoutgoingfw);
&General::readhasharray($configgrp, \%customgrp);
-&General::get_aliases(\%aliases);
my @log_limit_options = &make_log_limit_options();
# Collect all destinations.
my @destinations = &fwlib::get_addresses($hash, $key, "tgt");
+ # True if the destination is the firewall itself.
+ my $destination_is_firewall = ($$hash{$key}[5] eq "ipfire");
+
# Check if logging should be enabled.
my $LOG = ($$hash{$key}[17] eq 'ON');
# Check if this protocol knows ports.
my $protocol_has_ports = ($protocol ~~ @PROTOCOLS_WITH_PORTS);
- foreach my $source (@sources) {
- foreach my $destination (@destinations) {
- # Skip invalid rules.
- next if (!$source || !$destination || ($destination eq "none"));
+ foreach my $src (@sources) {
+ # Skip invalid source.
+ next unless ($src);
- # Sanitize source.
- if ($source ~~ @ANY_ADDRESSES) {
- $source = "";
- }
+ # Sanitize source.
+ my $source = $src;
+ if ($source ~~ @ANY_ADDRESSES) {
+ $source = "";
+ }
+
+ foreach my $dst (@destinations) {
+ # Skip invalid rules.
+ next if (!$dst || ($dst eq "none"));
# Sanitize destination.
+ my $destination = $dst;
if ($destination ~~ @ANY_ADDRESSES) {
$destination = "";
}
}
push(@nat_options, @source_options);
push(@nat_options, ("-d", $nat_address));
+ push(@nat_options, @time_options);
- my ($dnat_address, $dnat_mask) = split("/", $destination);
- @destination_options = ("-d", $dnat_address);
-
+ my $dnat_port;
if ($protocol_has_ports) {
- my $dnat_port = &get_dnat_target_port($hash, $key);
+ $dnat_port = &get_dnat_target_port($hash, $key);
+ }
+
+ my @nat_action_options = ();
+
+ # Use iptables REDIRECT
+ my $use_redirect = ($destination_is_firewall && !$destination && $protocol_has_ports && $dnat_port);
+ if ($use_redirect) {
+ push(@nat_action_options, ("-j", "REDIRECT", "--to-ports", $dnat_port));
+
+ # Use iptables DNAT
+ } else {
+ if ($destination_is_firewall && !$destination) {
+ $destination = &fwlib::get_external_address();
+ }
+ next unless ($destination);
- if ($dnat_port) {
- $dnat_address .= ":$dnat_port";
+ my ($dnat_address, $dnat_mask) = split("/", $destination);
+ @destination_options = ("-d", $dnat_address);
+
+ if ($protocol_has_ports) {
+ my $dnat_port = &get_dnat_target_port($hash, $key);
+
+ if ($dnat_port) {
+ $dnat_address .= ":$dnat_port";
+ }
}
+
+ push(@nat_action_options, ("-j", "DNAT", "--to-destination", $dnat_address));
}
if ($LOG) {
run("$IPTABLES -t nat -A $CHAIN_NAT_DESTINATION @nat_options @log_limit_options -j LOG --log-prefix 'DNAT '");
}
- run("$IPTABLES -t nat -A $CHAIN_NAT_DESTINATION @nat_options -j DNAT --to-destination $dnat_address");
+ run("$IPTABLES -t nat -A $CHAIN_NAT_DESTINATION @nat_options @nat_action_options");
# Source NAT
} elsif ($NAT_MODE eq "SNAT") {
push(@options, ("-p", $protocol));
}
- # Process source ports.
- my $use_src_ports = ($$hash{$key}[7] eq "ON");
- my $src_ports = $$hash{$key}[10];
+ if ($protocol ~~ @PROTOCOLS_WITH_PORTS) {
+ # Process source ports.
+ my $use_src_ports = ($$hash{$key}[7] eq "ON");
+ my $src_ports = $$hash{$key}[10];
- if ($use_src_ports && $src_ports) {
- push(@options, &format_ports($src_ports, "src"));
- }
-
- # Process destination ports.
- my $use_dst_ports = ($$hash{$key}[11] eq "ON");
- my $use_dnat = (($$hash{$key}[28] eq "ON") && ($$hash{$key}[31] eq "dnat"));
+ if ($use_src_ports && $src_ports) {
+ push(@options, &format_ports($src_ports, "src"));
+ }
- if ($use_dst_ports) {
- my $dst_ports_mode = $$hash{$key}[14];
- my $dst_ports = $$hash{$key}[15];
+ # Process destination ports.
+ my $use_dst_ports = ($$hash{$key}[11] eq "ON");
+ my $use_dnat = (($$hash{$key}[28] eq "ON") && ($$hash{$key}[31] eq "dnat"));
- if (($dst_ports_mode eq "TGT_PORT") && $dst_ports) {
- if ($nat_options_wanted && $use_dnat && $$hash{$key}[30]) {
- $dst_ports = $$hash{$key}[30];
- }
- push(@options, &format_ports($dst_ports, "dst"));
+ if ($use_dst_ports) {
+ my $dst_ports_mode = $$hash{$key}[14];
+ my $dst_ports = $$hash{$key}[15];
- } elsif ($dst_ports_mode eq "cust_srv") {
- if ($protocol eq "ICMP") {
- push(@options, ("--icmp-type", &fwlib::get_srv_port($dst_ports, 3, "ICMP")));
- } else {
- $dst_ports = &fwlib::get_srv_port($dst_ports, 1, uc($protocol));
+ if (($dst_ports_mode eq "TGT_PORT") && $dst_ports) {
+ if ($nat_options_wanted && $use_dnat && $$hash{$key}[30]) {
+ $dst_ports = $$hash{$key}[30];
+ }
push(@options, &format_ports($dst_ports, "dst"));
- }
- } elsif ($dst_ports_mode eq "cust_srvgrp") {
- push(@options, &fwlib::get_srvgrp_port($dst_ports, uc($protocol)));
+ } elsif ($dst_ports_mode eq "cust_srv") {
+ if ($protocol eq "ICMP") {
+ push(@options, ("--icmp-type", &fwlib::get_srv_port($dst_ports, 3, "ICMP")));
+ } else {
+ $dst_ports = &fwlib::get_srv_port($dst_ports, 1, uc($protocol));
+ push(@options, &format_ports($dst_ports, "dst"));
+ }
+
+ } elsif ($dst_ports_mode eq "cust_srvgrp") {
+ push(@options, &fwlib::get_srvgrp_port($dst_ports, uc($protocol)));
+ }
}
}
# Check if a single ICMP type is selected.
- if (!$use_src_ports && !$use_dst_ports && $protocol eq "icmp") {
+ if ($protocol eq "icmp") {
my $icmp_type = $$hash{$key}[9];
if (($icmp_type ne "All ICMP-Types") && $icmp_type) {