From: Alexander Marx Date: Thu, 11 Apr 2013 08:50:29 +0000 (+0200) Subject: Forward Firewall: Added multiport support to DNAT/Portforwarding X-Git-Url: http://git.ipfire.org/?p=people%2Fteissler%2Fipfire-2.x.git;a=commitdiff_plain;h=98cee89f94b5a7eedbfeaef1a4f1dcbc2c0c73d5 Forward Firewall: Added multiport support to DNAT/Portforwarding Now it is possible to use multiple ports under DNAT when TARGET has no Port, one Port or one Portrange defined --- diff --git a/config/forwardfw/rules.pl b/config/forwardfw/rules.pl index c7acd122b..917e061eb 100755 --- a/config/forwardfw/rules.pl +++ b/config/forwardfw/rules.pl @@ -177,6 +177,7 @@ sub buildrules my $snatport; my $fireport; my $nat; + my $fwaccessdport; foreach my $key (sort {$a <=> $b} keys %$hash){ next if ($$hash{$key}[6] eq 'RED' && $conexists eq 'off' ); if ($$hash{$key}[28] eq 'ON'){ @@ -184,7 +185,12 @@ sub buildrules $natip=&get_nat_ip($$hash{$key}[29]); if($$hash{$key}[31] eq 'dnat'){ $nat='DNAT'; - $fireport='--dport '.$$hash{$key}[30] if ($$hash{$key}[30]>0); + if ($$hash{$key}[30] =~ /\|/){ + $$hash{$key}[30]=~ tr/|/,/; + $fireport='-m multiport --dport '.$$hash{$key}[30]; + }else{ + $fireport='--dport '.$$hash{$key}[30] if ($$hash{$key}[30]>0); + } }else{ $nat='SNAT'; } @@ -291,7 +297,16 @@ sub buildrules my ($ip,$sub) =split("/",$targethash{$b}[0]); print "$command $$hash{$key}[1] $PROT $STAG $sourcehash{$a}[0] $SPORT $natip $fireport $TIME -j $nat --to $ip$DPORT\n"; $DPORT =~ s/\-/:/g; - my $fwaccessdport="--dport ".substr($DPORT,1,) if ($DPORT); + if ($DPORT){ + $fwaccessdport="--dport ".substr($DPORT,1,); + }elsif(! $DPORT && $$hash{$key}[30] ne ''){ + if ($$hash{$key}[30]=~m/|/i){ + $$hash{$key}[30] =~ s/\|/,/g; + $fwaccessdport="-m multiport --dport $$hash{$key}[30]"; + }else{ + $fwaccessdport="--dport $$hash{$key}[30]"; + } + } print "iptables -A PORTFWACCESS $PROT -i $con $STAG $sourcehash{$a}[0] -d $ip $fwaccessdport $TIME -j $$hash{$key}[0]\n"; }elsif($$hash{$key}[28] eq 'ON' && $$hash{$key}[32] eq 'snat'){ print "$command $$hash{$key}[1] $PROT $STAG $sourcehash{$a}[0] $SPORT -d $targethash{$b}[0] $DPORT $TIME -j $nat --to $natip$fireport\n"; @@ -332,9 +347,17 @@ sub buildrules my ($ip,$sub) =split("/",$targethash{$b}[0]); system "$command $$hash{$key}[1] $PROT $STAG $sourcehash{$a}[0] $SPORT $natip $fireport $TIME -j $nat --to $ip$DPORT\n"; $DPORT =~ s/\-/:/g; - my $fwaccessdport="--dport ".substr($DPORT,1,) if ($DPORT); + if ($DPORT){ + $fwaccessdport="--dport ".substr($DPORT,1,); + }elsif(! $DPORT && $$hash{$key}[30] ne ''){ + if ($$hash{$key}[30]=~m/|/i){ + $$hash{$key}[30] =~ s/\|/,/g; + $fwaccessdport="-m multiport --dport $$hash{$key}[30]"; + }else{ + $fwaccessdport="--dport $$hash{$key}[30]"; + } + } system "iptables -A PORTFWACCESS $PROT -i $con $STAG $sourcehash{$a}[0] -d $ip $fwaccessdport $TIME -j $$hash{$key}[0]\n"; - }elsif($$hash{$key}[28] eq 'ON' && $$hash{$key}[31] eq 'snat'){ if ($$hash{$key}[17] eq 'ON'){ system "$command $$hash{$key}[1] $PROT $STAG $sourcehash{$a}[0] $SPORT -d $targethash{$b}[0] $DPORT $TIME -j LOG --log-prefix 'SNAT '\n"; @@ -499,6 +522,10 @@ sub get_prot return &fwlib::get_srvgrp_prot($$hash{$key}[15]); } } + #DNAT + if ($SRC_TGT eq '' && $$hash{$key}[31] eq 'dnat' && $$hash{$key}[11] eq '' && $$hash{$key}[12] ne ''){ + return "$$hash{$key}[12]"; + } } sub get_port { diff --git a/html/cgi-bin/forwardfw.cgi b/html/cgi-bin/forwardfw.cgi index 584f7f093..72771e8cf 100755 --- a/html/cgi-bin/forwardfw.cgi +++ b/html/cgi-bin/forwardfw.cgi @@ -591,7 +591,7 @@ sub addrule { &error; if (-f "${General::swroot}/forward/reread"){ - print "
    $Lang::tr{'fwhost reread'}


"; + print "
    $Lang::tr{'fwhost reread'}


"; } &Header::openbox('100%', 'left', ""); print "
"; @@ -771,7 +771,7 @@ sub checktarget #check DNAT settings (has to be single Host and single Port or portrange) if ($fwdfwsettings{'USE_NAT'} eq 'ON' && $fwdfwsettings{'nat'} eq 'dnat'){ if($fwdfwsettings{'grp2'} eq 'tgt_addr' || $fwdfwsettings{'grp2'} eq 'cust_host_tgt' || $fwdfwsettings{'grp2'} eq 'ovpn_host_tgt'){ - if ($fwdfwsettings{'USESRV'} eq ''){ + if ($fwdfwsettings{'USESRV'} eq '' && $fwdfwsettings{'dnatport'} eq ''){ $errormessage=$Lang::tr{'fwdfw target'}.": ".$Lang::tr{'fwdfw dnat porterr'}."
"; } #check if manual ip is a single Host (if set) @@ -905,7 +905,6 @@ sub checktarget if ($fwdfwsettings{'USESRV'} ne 'ON'){ $fwdfwsettings{'grp3'}=''; $fwdfwsettings{$fwdfwsettings{'grp3'}}=''; - $fwdfwsettings{'TGT_PROT'}=''; $fwdfwsettings{'ICMP_TGT'}=''; } #check timeframe @@ -946,10 +945,9 @@ sub checkrule #if no port is given in nat area, take target host port if($fwdfwsettings{'nat'} eq 'dnat' && $fwdfwsettings{'grp3'} eq 'TGT_PORT' && $fwdfwsettings{'dnatport'} eq ''){$fwdfwsettings{'dnatport'}=$fwdfwsettings{'TGT_PORT'};} #check if port given in nat area is a single valid port or portrange - if($fwdfwsettings{'nat'} eq 'dnat' && !&check_natport($fwdfwsettings{'dnatport'})){ + if($fwdfwsettings{'nat'} eq 'dnat' && $fwdfwsettings{'TGT_PORT'} ne '' && !&check_natport($fwdfwsettings{'dnatport'})){ $errormessage=$Lang::tr{'fwdfw target'}.": ".$Lang::tr{'fwdfw dnat porterr'}."
"; - } - elsif($fwdfwsettings{'USESRV'} eq 'ON' && $fwdfwsettings{'grp3'} eq 'cust_srv'){ + }elsif($fwdfwsettings{'USESRV'} eq 'ON' && $fwdfwsettings{'grp3'} eq 'cust_srv'){ my $custsrvport; #get servcie Protocol and Port foreach my $key (sort keys %customservice){ @@ -962,6 +960,42 @@ sub checkrule } if($fwdfwsettings{'nat'} eq 'dnat' && $fwdfwsettings{'dnatport'} eq ''){$fwdfwsettings{'dnatport'}=$custsrvport;} } + #check if DNAT port is multiple + if($fwdfwsettings{'nat'} eq 'dnat' && $fwdfwsettings{'dnatport'} ne ''){ + my @parts=split(",",$fwdfwsettings{'dnatport'}); + my @values=(); + foreach (@parts){ + chomp($_); + if ($_ =~ /^(\d+)\-(\d+)$/ || $_ =~ /^(\d+)\:(\d+)$/) { + my $check; + #change dashes with : + $_=~ tr/-/:/; + if ($_ eq "*") { + push(@values,"1:65535"); + $check='on'; + } + if ($_ =~ /^(\D)\:(\d+)$/ || $_ =~ /^(\D)\-(\d+)$/) { + push(@values,"1:$2"); + $check='on'; + } + if ($_ =~ /^(\d+)\:(\D)$/ || $_ =~ /^(\d+)\-(\D)$/) { + push(@values,"$1:65535"); + $check='on' + } + $errormessage .= &General::validportrange($_, 'destination'); + if(!$check){ + push (@values,$_); + } + }else{ + if (&General::validport($_)){ + push (@values,$_); + }else{ + + } + } + } + $fwdfwsettings{'dnatport'}=join("|",@values); + } } #check valid remark if ($fwdfwsettings{'ruleremark'} ne '' && !&validremark($fwdfwsettings{'ruleremark'})){ @@ -1764,6 +1798,7 @@ END print ""; } print""; + $fwdfwsettings{'dnatport'}=~ tr/|/,/; print"Port: "; print"
"; #SNAT @@ -2371,6 +2406,7 @@ END if ($$hash{$key}[31] eq 'dnat'){ print "IPFire ($$hash{$key}[29])"; if($$hash{$key}[30] ne ''){ + $$hash{$key}[30]=~ tr/|/,/; print": $$hash{$key}[30]"; } print"
DNAT->"; diff --git a/html/cgi-bin/fwhosts.cgi b/html/cgi-bin/fwhosts.cgi index 91ed3228b..0283f5c91 100755 --- a/html/cgi-bin/fwhosts.cgi +++ b/html/cgi-bin/fwhosts.cgi @@ -1067,7 +1067,7 @@ if($fwhostsettings{'ACTION'} eq '') sub showmenu { if (-f "${General::swroot}/forward/reread"){ - print "
$Lang::tr{'fwhost reread'}


"; + print "
$Lang::tr{'fwhost reread'}


"; } &Header::openbox('100%', 'left',$Lang::tr{'fwhost menu'}); print<