rules.pl: Fix SNAT over VPN.

Message ID 20200220162423.3571-1-stefan.schantl@ipfire.org
State Accepted
Commit c4b7692ad942d883dbea8f078b2a5c0c1de125f2
Headers
Series rules.pl: Fix SNAT over VPN. |

Commit Message

Stefan Schantl Feb. 20, 2020, 4:24 p.m. UTC
  This commit adds flags which will are applied if SNAT should be used on
the red address or any configured alias.

They prevent doing the SNAT when tranismitting packet through a VPN over the red interface.

Fixes #12162.

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

Comments

Michael Tremer Feb. 23, 2020, 2:28 p.m. UTC | #1
Hello,

I just tested this patch on our main firewall in Hanover and the problem is resolved.

It is not the most beautiful piece of code, but it does the job.

-Michael

Tested-by: Michael Tremer <michael.tremer@ipfire.org>

> On 20 Feb 2020, at 16:24, Stefan Schantl <stefan.schantl@ipfire.org> wrote:
> 
> This commit adds flags which will are applied if SNAT should be used on
> the red address or any configured alias.
> 
> They prevent doing the SNAT when tranismitting packet through a VPN over the red interface.
> 
> Fixes #12162.
> 
> Signed-off-by: Stefan Schantl <stefan.schantl@ipfire.org>
> ---
> config/firewall/rules.pl | 19 +++++++++++++++++--
> 1 file changed, 17 insertions(+), 2 deletions(-)
> 
> diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl
> index 86db47367..6129af861 100644
> --- a/config/firewall/rules.pl
> +++ b/config/firewall/rules.pl
> @@ -479,16 +479,31 @@ sub buildrules {
> 
> 						# Source NAT
> 						} elsif ($NAT_MODE eq "SNAT") {
> +							my @snat_options = ( "-m", "policy", "--dir", "out", "--pol", "none" );
> 							my @nat_options = @options;
> 
> +							# Get addresses for the configured firewall interfaces.
> +							my @local_addresses = &fwlib::get_internal_firewall_ip_addresses(1);
> +
> +							# Check if the nat_address is one of the local addresses.
> +							foreach my $local_address (@local_addresses) {
> +								if ($nat_address eq $local_address) {
> +									# Clear SNAT options.
> +									@snat_options = ();
> +
> +									# Finish loop.
> +									last;
> +								}
> +							}
> +
> 							push(@nat_options, @destination_intf_options);
> 							push(@nat_options, @source_options);
> 							push(@nat_options, @destination_options);
> 
> 							if ($LOG) {
> -								run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options @log_limit_options -j LOG --log-prefix 'SNAT '");
> +								run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options @snat_options @log_limit_options -j LOG --log-prefix 'SNAT '");
> 							}
> -							run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options -j SNAT --to-source $nat_address");
> +							run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options @snat_options -j SNAT --to-source $nat_address");
> 						}
> 					}
> 
> -- 
> 2.25.0
>
  

Patch

diff --git a/config/firewall/rules.pl b/config/firewall/rules.pl
index 86db47367..6129af861 100644
--- a/config/firewall/rules.pl
+++ b/config/firewall/rules.pl
@@ -479,16 +479,31 @@  sub buildrules {
 
 						# Source NAT
 						} elsif ($NAT_MODE eq "SNAT") {
+							my @snat_options = ( "-m", "policy", "--dir", "out", "--pol", "none" );
 							my @nat_options = @options;
 
+							# Get addresses for the configured firewall interfaces.
+							my @local_addresses = &fwlib::get_internal_firewall_ip_addresses(1);
+
+							# Check if the nat_address is one of the local addresses.
+							foreach my $local_address (@local_addresses) {
+								if ($nat_address eq $local_address) {
+									# Clear SNAT options.
+									@snat_options = ();
+
+									# Finish loop.
+									last;
+								}
+							}
+
 							push(@nat_options, @destination_intf_options);
 							push(@nat_options, @source_options);
 							push(@nat_options, @destination_options);
 
 							if ($LOG) {
-								run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options @log_limit_options -j LOG --log-prefix 'SNAT '");
+								run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options @snat_options @log_limit_options -j LOG --log-prefix 'SNAT '");
 							}
-							run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options -j SNAT --to-source $nat_address");
+							run("$IPTABLES -t nat -A $CHAIN_NAT_SOURCE @nat_options @snat_options -j SNAT --to-source $nat_address");
 						}
 					}