firewall: rules.pl: Allow REDIRECT rules.
authorMichael Tremer <michael.tremer@ipfire.org>
Fri, 21 Mar 2014 12:28:00 +0000 (13:28 +0100)
committerMichael Tremer <michael.tremer@ipfire.org>
Fri, 21 Mar 2014 12:28:00 +0000 (13:28 +0100)
config/firewall/rules.pl

index 12c0c2b..d9c9b5c 100755 (executable)
@@ -175,6 +175,9 @@ sub buildrules {
                # 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');
 
@@ -320,21 +323,38 @@ sub buildrules {
                                                        push(@nat_options, @source_options);
                                                        push(@nat_options, ("-d", $nat_address));
 
-                                                       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 = ();
 
-                                                               if ($dnat_port) {
-                                                                       $dnat_address .= ":$dnat_port";
+                                                       # 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 {
+                                                               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") {