diff options
author | Mohit Mehta <mohit.mehta@vyatta.com> | 2009-08-05 12:24:11 -0700 |
---|---|---|
committer | Mohit Mehta <mohit.mehta@vyatta.com> | 2009-08-05 12:24:11 -0700 |
commit | 4d56db8428fd770c86d80f77511814e2aff37c5e (patch) | |
tree | fba0883a86032086a448e757fada846dd5ce4808 | |
parent | 1dfc6aa94e31a5ee6c420d184ec83dfd463bf615 (diff) | |
download | vyatta-nat-4d56db8428fd770c86d80f77511814e2aff37c5e.tar.gz vyatta-nat-4d56db8428fd770c86d80f77511814e2aff37c5e.zip |
* Fix Bug 1445 - Allow setting protocols tcp and udp in one rule
NAT rules can be defined with 'tcp_udp' as a valid value for protocol
* Fix Bug 4780 - DNAT rule to translate port fails
-rw-r--r-- | lib/Vyatta/NatRule.pm | 91 | ||||
-rwxr-xr-x | scripts/vyatta-show-nat.pl | 18 | ||||
-rw-r--r-- | templates-cfg/service/nat/rule/node.tag/protocol/node.def | 7 |
3 files changed, 97 insertions, 19 deletions
diff --git a/lib/Vyatta/NatRule.pm b/lib/Vyatta/NatRule.pm index c3631ae..79ca644 100644 --- a/lib/Vyatta/NatRule.pm +++ b/lib/Vyatta/NatRule.pm @@ -158,6 +158,10 @@ sub get_num_ipt_rules { if ("$self->{_log}" eq 'enable') { $ipt_rules++; } + if (defined $self->{_proto} && $self->{_proto} eq 'tcp_udp') { + $ipt_rules++; + $ipt_rules++ if $self->{_log} eq 'enable'; + } return $ipt_rules; } @@ -189,10 +193,12 @@ sub rule_str { my $jump_target = ''; my $jump_param = ''; my $use_netmap = 0; + my $tcp_and_udp = 0; if (!defined($self->{_proto}) || - (($self->{_proto} ne "tcp") && ($self->{_proto} ne "6") - && ($self->{_proto} ne "udp") && ($self->{_proto} ne "17"))) { + (($self->{_proto} ne "tcp_udp") + && ($self->{_proto} ne "tcp") && ($self->{_proto} ne "6") + && ($self->{_proto} ne "udp") && ($self->{_proto} ne "17"))) { $can_use_port = 0; } if (($self->{_type} eq "source") || ($self->{_type} eq "masquerade")) { @@ -226,7 +232,12 @@ sub rule_str { if (defined($self->{_proto})) { my $str = $self->{_proto}; $str =~ s/^\!(.*)$/! $1/; - $rule_str .= " -p $str"; + if ($str eq 'tcp_udp') { + $tcp_and_udp = 1; + $rule_str .= " -p tcp"; # we'll add the '-p udp' to 2nd rule later + } else { + $rule_str .= " -p $str"; + } } my $to_src = ''; @@ -259,7 +270,7 @@ sub rule_str { if (defined($self->{_outside_addr}->{_port})) { if (!$can_use_port) { return ("ports can only be specified when protocol is \"tcp\" " - . "or \"udp\" (currently \"$self->{_proto}\")", undef); + . "\"udp\" or \"tcp_udp\" (currently \"$self->{_proto}\")", undef); } if ($use_netmap) { return ("Cannot use ports with an IPv4net type outside-address as it " . @@ -280,9 +291,17 @@ sub rule_str { = Vyatta::Misc::isValidPortNumber($port); return ($err, undef) if (!defined($success)); } else { - ($success, $err) = Vyatta::Misc::isValidPortName($port); + if ($self->{_proto} eq 'tcp_udp') { + ($success, $err) = Vyatta::Misc::isValidPortName($port, 'tcp'); + return ($err, undef) if !defined $success ; + ($success, $err) = Vyatta::Misc::isValidPortName($port, 'udp'); + return ($err, undef) if !defined $success ; + $port = getservbyname($port, 'tcp'); + } else { + ($success, $err) = Vyatta::Misc::isValidPortName($port, $self->{_proto}); return ($err, undef) if !defined $success ; - $port = getservbyname($port, $self->{_proto}); + $port = getservbyname($port, $self->{_proto}); + } } $to_src .= "$port"; } @@ -331,7 +350,14 @@ sub rule_str { } if (defined($self->{_proto})) { - $rule_str .= " -p $self->{_proto}"; + my $str = $self->{_proto}; + $str =~ s/^\!(.*)$/! $1/; + if ($str eq 'tcp_udp') { + $tcp_and_udp = 1; + $rule_str .= " -p tcp"; # we'll add the '-p udp' to 2nd rule later + } else { + $rule_str .= " -p $str"; + } } my $to_dst = ""; @@ -363,7 +389,7 @@ sub rule_str { if (defined($self->{_inside_addr}->{_port})) { if (!$can_use_port) { return ("ports can only be specified when protocol is \"tcp\" " - . "or \"udp\" (currently \"$self->{_proto}\")", undef); + . "\"udp\" or \"tcp_udp\" (currently \"$self->{_proto}\")", undef); } if ($use_netmap) { return ("Cannot use ports with an IPv4net type outside-address as it " @@ -379,10 +405,19 @@ sub rule_str { ($success, $err) = Vyatta::Misc::isValidPortNumber($port); return ($err, undef) if (!defined($success)); } else { - ($success, $err) = Vyatta::Misc::isValidPortName($port); - return ($err, undef) if (!defined($success)); - $port = getservbyname($port, $self->{_proto}); + if ($self->{_proto} eq 'tcp_udp') { + ($success, $err) = Vyatta::Misc::isValidPortName($port, 'tcp'); + return ($err, undef) if !defined $success ; + ($success, $err) = Vyatta::Misc::isValidPortName($port, 'udp'); + return ($err, undef) if !defined $success ; + $port = getservbyname($port, 'tcp'); + } else { + ($success, $err) = Vyatta::Misc::isValidPortName($port, $self->{_proto}); + return ($err, undef) if !defined $success ; + $port = getservbyname($port, $self->{_proto}); + } } + $to_dst = " --to-destination " if $to_dst eq ""; $to_dst .= ":$port"; } @@ -474,17 +509,39 @@ sub rule_str { return (undef, undef) if defined $self->{_disable}; - $rule_str .= " $src_str $dst_str"; + my $comment = "\"NAT-$self->{_rule_number}\" "; + if ($tcp_and_udp == 1) { + $comment = "\"NAT-$self->{_rule_number} tcp_udp\" "; + } + $rule_str .= " $src_str $dst_str" . " -m comment --comment " . $comment; if ("$self->{_log}" eq "enable") { - my $log_rule = $rule_str; my $rule_num = $self->{_rule_number}; my $log_prefix = get_log_prefix($rule_num, $jump_target); - $log_rule .= " -j LOG --log-prefix \"$log_prefix\" "; - $rule_str .= " -j $jump_target $jump_param"; - return (undef, $log_rule, $rule_str); + if ($tcp_and_udp == 1) { + my $tcp_log_rule = $rule_str; + $tcp_log_rule .= " -j LOG --log-prefix \"$log_prefix\" "; + my $udp_log_rule = $tcp_log_rule; + $udp_log_rule =~ s/ \-p tcp / -p udp /; + $rule_str .= " -j $jump_target $jump_param"; + my $udp_rule_str = $rule_str; + $udp_rule_str =~ s/ \-p tcp / -p udp /; + return (undef, $tcp_log_rule, $rule_str, $udp_log_rule, $udp_rule_str); + } else { + my $log_rule = $rule_str; + $log_rule .= " -j LOG --log-prefix \"$log_prefix\" "; + $rule_str .= " -j $jump_target $jump_param"; + return (undef, $log_rule, $rule_str); + } } else { $rule_str .= " -j $jump_target $jump_param"; - return (undef, $rule_str); + if ($tcp_and_udp == 1) { + # protocol is 'tcp_udp'; make another rule for protocol 'udp' + my $udp_rule_str = $rule_str; + $udp_rule_str =~ s/ \-p tcp / -p udp /; + return (undef, $rule_str, $udp_rule_str); + } else { + return (undef, $rule_str); + } } } diff --git a/scripts/vyatta-show-nat.pl b/scripts/vyatta-show-nat.pl index 574c995..0ae25af 100755 --- a/scripts/vyatta-show-nat.pl +++ b/scripts/vyatta-show-nat.pl @@ -21,6 +21,8 @@ my %stats = ( ); open(STATS, "sudo /sbin/iptables -t nat -L -vn |") or exit 1; my $skey = ""; +my ($rule_tcp_pkts, $rule_tcp_bytes, $rule_pkts, $rule_bytes); +my $tcp_done = 0; while (<STATS>) { if (m/^Chain PREROUTING/) { $skey = "destination"; @@ -32,7 +34,21 @@ while (<STATS>) { if ($skey ne "" && (m/SNAT/ || m/DNAT/ || m/MASQUERADE/ || m/RETURN/ || m/NETMAP/)) { m/^\s*(\d+[KMG]?)\s+(\d+[KMG]?)\s/; - push @{$stats{$skey}}, ($1, $2); + $rule_pkts = $1; + $rule_bytes = $2; + if (m/tcp_udp/) { # protocol is tcp_udp, 2 rules in iptables for it + if ($tcp_done == 0) { + $rule_tcp_pkts = $rule_pkts; + $rule_tcp_bytes = $rule_bytes; + $tcp_done = 1; + next; + } else { + $rule_pkts += $rule_tcp_pkts; + $rule_bytes += $rule_tcp_bytes; + $tcp_done = 0; + } + } + push @{$stats{$skey}}, ($rule_pkts, $rule_bytes); } } close STATS; diff --git a/templates-cfg/service/nat/rule/node.tag/protocol/node.def b/templates-cfg/service/nat/rule/node.tag/protocol/node.def index fdd589a..0aff708 100644 --- a/templates-cfg/service/nat/rule/node.tag/protocol/node.def +++ b/templates-cfg/service/nat/rule/node.tag/protocol/node.def @@ -1,8 +1,13 @@ type: txt help: Set protocol to NAT (this can be a protocol name in /etc/protocols, a protocol number, or "all") -syntax:expression: exec "/opt/vyatta/sbin/vyatta-validate-type.pl protocol_negate '$VAR(@)'" ; "invalid protocol \"$VAR(@)\"" comp_help:Possible completions: <text> An IP protocol name from /etc/protocols (e.g. "tcp" or "udp") <0-255> An IP protocol number + tcp_udp Both TCP and UDP all All IP protocols !<protocol> All IP protocols except for the specified name or number (negation) +syntax:expression: exec "if [ -n \"`/opt/vyatta/sbin/vyatta-validate-type.pl protocol_negate '$VAR(@)'`\" ] \ + && [ \"$VAR(@)\" != 'tcp_udp' ]; then \ + echo invalid protocol \"$VAR(@)\" ; \ + exit 1 ; \ + fi ; " |