Firewall: Proper allow to create REDIRECT rules.

Message ID 20210630184031.7726-1-stefan.schantl@ipfire.org
State Accepted
Commit 21b37391f9769718df7bd726453140f4ec8ff1c0
Headers
Series Firewall: Proper allow to create REDIRECT rules. |

Commit Message

Stefan Schantl June 30, 2021, 6:40 p.m. UTC
  This patch now proper allows to create rules for redirecting requests of a
given host, group or network(s) to a specified port or service to the
local IPFire system.

So it implements a very generic and easy to use feature to redirect
(for example all DNS, NTP, or whatever) requests to the a local running
instance and so to force usage of that local hosted service.

* The feature supports specifiying a single port and redirect the requests to another given one.
  ( For example requests to UDP 123 can be redirected to local UDP 1234
  if you run an NTP server on that port.)

* It also supports direct usage of services or even service groups.
  ( So you can create a service group for DNS and redirect them to the
  local recursor, or create a "redirected services" group which easily
  can be managed...)

Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
---
 config/firewall/rules.pl | 28 ++++++++++++++++++++++------
 1 file changed, 22 insertions(+), 6 deletions(-)
  

Patch

diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl
index bc6187052..0dd1c9024 100644
--- a/config/firewall/rules.pl
+++ b/config/firewall/rules.pl
@@ -449,16 +449,28 @@  sub buildrules {
 								my @nat_protocol_options = &get_protocol_options($hash, $key, $protocol, 1);
 								push(@nat_options, @nat_protocol_options);
 							}
+
+							# Add time options.
 							push(@nat_options, @time_options);
 
+							# Determine if a REDIRECT rule should be created.
+							my $use_redirect = ($destination_is_firewall && !$destination && $protocol_has_ports);
+
 							# Make port-forwardings useable from the internal networks.
-							my @internal_addresses = &fwlib::get_internal_firewall_ip_addresses(1);
-							unless ($nat_address ~~ @internal_addresses) {
-								&add_dnat_mangle_rules($nat_address, $source_intf, @nat_options);
+							if (!$use_redirect) {
+								my @internal_addresses = &fwlib::get_internal_firewall_ip_addresses(1);
+								unless ($nat_address ~~ @internal_addresses) {
+									&add_dnat_mangle_rules($nat_address, $source_intf, @nat_options);
+								}
 							}
 
+							# Add source options.
 							push(@nat_options, @source_options);
-							push(@nat_options, ("-d", $nat_address));
+
+							# Add NAT address.
+							if (!$use_redirect) {
+								push(@nat_options, ("-d", $nat_address));
+							}
 
 							my $dnat_port;
 							if ($protocol_has_ports) {
@@ -468,9 +480,13 @@  sub buildrules {
 							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));
+								push(@nat_action_options, ("-j", "REDIRECT"));
+
+								# Redirect to specified port if one has given.
+								if ($dnat_port) {
+									push(@nat_action_options, ("--to-ports", $dnat_port));
+								}
 
 							# Use iptables DNAT
 							} else {