diff options
author | kouak <kouak@kouak.org> | 2015-02-15 22:37:14 +0100 |
---|---|---|
committer | kouak <kouak@kouak.org> | 2015-02-15 22:37:14 +0100 |
commit | 9571f0e592088c49c6c16724c5124631326066fd (patch) | |
tree | 89fe54ea2a5232496e32524c4dd99f5f8ae0ee10 | |
parent | 9ee62f2e55cd83110c5964c020233c0c983154a0 (diff) | |
download | vyatta-nat-9571f0e592088c49c6c16724c5124631326066fd.tar.gz vyatta-nat-9571f0e592088c49c6c16724c5124631326066fd.zip |
Add initial support for NPTv6 (#387)
-rw-r--r-- | Makefile.am | 4 | ||||
-rw-r--r-- | lib/VyOS/Nptv6Rule.pm | 161 | ||||
-rwxr-xr-x | scripts/vyos-update-nptv6.pl | 119 | ||||
-rw-r--r-- | templates-cfg/nat/nptv6/node.def | 3 | ||||
-rw-r--r-- | templates-cfg/nat/nptv6/rule/node.def | 11 | ||||
-rw-r--r-- | templates-cfg/nat/nptv6/rule/node.tag/description/node.def | 3 | ||||
-rw-r--r-- | templates-cfg/nat/nptv6/rule/node.tag/disable/node.def | 1 | ||||
-rw-r--r-- | templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def | 7 | ||||
-rw-r--r-- | templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def | 30 | ||||
-rw-r--r-- | templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def | 7 |
10 files changed, 346 insertions, 0 deletions
diff --git a/Makefile.am b/Makefile.am index 2877aab..d56ca9d 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,7 @@ cfgdir = $(datadir)/vyatta-cfg/templates opdir = $(datadir)/vyatta-op/templates share_perl5dir = $(datadir)/perl5/Vyatta +share_vyos_perl5dir = $(datadir)/perl5/VyOS bin_sudo_usersdir = $(bindir)/sudo-users curverdir = $(sysconfdir)/config-migrate/current @@ -9,12 +10,15 @@ sbin_SCRIPTS += scripts/vyatta-update-src-nat.pl sbin_SCRIPTS += scripts/vyatta-show-nat-statistics.pl sbin_SCRIPTS += scripts/vyatta-show-nat-rules.pl sbin_SCRIPTS += scripts/vyatta-clear-nat-counters.pl +sbin_SCRIPTS += scripts/vyos-update-nptv6.pl bin_sudo_users_SCRIPTS = scripts/vyatta-nat-translations.pl share_perl5_DATA = lib/Vyatta/NatRuleCommon.pm share_perl5_DATA += lib/Vyatta/DstNatRule.pm share_perl5_DATA += lib/Vyatta/SrcNatRule.pm + +share_vyos_perl5_DATA = lib/VyOS/Nptv6Rule.pm curver_DATA = cfg-version/nat@4 cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \ diff --git a/lib/VyOS/Nptv6Rule.pm b/lib/VyOS/Nptv6Rule.pm new file mode 100644 index 0000000..3166325 --- /dev/null +++ b/lib/VyOS/Nptv6Rule.pm @@ -0,0 +1,161 @@ +# +# VyOS::Nptv6Rule: Update SNPT/DNPT ip6tables rules +# +# Copyright (C) 2014 VyOS Development Group <maintainers@vyos.net> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +# USA + + +package VyOS::Nptv6Rule; + +use strict; +use lib "/opt/vyatta/share/perl5"; +require Vyatta::Config; +require Vyatta::IpTables::AddressFilter; +use Vyatta::Misc; +use Vyatta::TypeChecker; + +require Exporter; +our @ISA = qw(Exporter); +our @EXPORT = qw(is_disabled rule_str); + +my %fields = ( + _rule_number => undef, + _outside_if => undef, + _inside_pfx => undef, + _outside_pfx => undef, + _disable => undef, +); + +sub new { + my $that = shift; + my $class = ref ($that) || $that; + my $self = { + %fields, + }; + + bless $self, $class; + return $self; +} + +sub setup { + my ( $self, $level ) = @_; + my $config = new Vyatta::Config; + + $config->setLevel("$level"); + + $self->{_rule_number} = $config->returnParent(".."); + $self->{_inside_if} = $config->returnValue("inside-interface"); + $self->{_outside_if} = $config->returnValue("outside-interface"); + $self->{_inside_pfx} = $config->returnValue("inside-prefix"); + $self->{_outside_pfx} = $config->returnValue("outside-prefix"); + + $self->{_disable} = $config->exists("disable"); + + return 0; +} + +# Make SNPT ip6tables string +# POSTROUTING +# ip6tables -t mangle -I VYOS_NPT_HOOK -s inside-pfx -o outside-if -j SNPT --src-pfx inside-pfx --dst-pfx outside-pfx +sub make_snpt_string { + my ($self) = @_; + my $snpt_str = ""; + + # Construct ip6tables string + $snpt_str .= "-I VYOS_SNPT_HOOK "; + $snpt_str .= "-s "; + $snpt_str .= $self->{_inside_pfx}; + if(defined($self->{_outside_if})) { + $snpt_str .= " -o "; + $snpt_str .= $self->{_outside_if}; + } + $snpt_str .= " -j SNPT --src-pfx "; + $snpt_str .= $self->{_inside_pfx}; + $snpt_str .= " --dst-pfx "; + $snpt_str .= $self->{_outside_pfx}; + + return $snpt_str; +} + +# Make DNPT ip6tables string +# PREROUTING +# ip6tables -t mangle -I VYOS_NPT_HOOK -d outside-pfx -i outside-if -j DNPT --src-pfx outside-pfx --dst-pfx inside-pfx +sub make_dnpt_string { + my ($self) = @_; + my $dnpt_str = ""; + + # Construct ip6tables string + $dnpt_str .= "-I VYOS_DNPT_HOOK "; + $dnpt_str .= "-d "; + $dnpt_str .= $self->{_outside_pfx}; + if(defined($self->{_outside_if})) { + $dnpt_str .= " -i "; + $dnpt_str .= $self->{_outside_if}; + } + $dnpt_str .= " -j DNPT --src-pfx "; + $dnpt_str .= $self->{_outside_pfx}; + $dnpt_str .= " --dst-pfx "; + $dnpt_str .= $self->{_inside_pfx}; + + return $dnpt_str; +} + +# Tests if the rule is valid, returns false if valid, returns error string if invalid +sub is_invalid { + my ($self) = @_; + + # Validate prefixes + if(!defined($self->{_inside_pfx}) || $self->{_inside_pfx} eq '') { + return "inside-prefix must be set"; + } + + if(!defined($self->{_outside_pfx}) || $self->{_outside_pfx} eq '') { + return "outside-prefix must be set"; + } + + if(!Vyatta::TypeChecker::validateType('ipv6net', $self->{_inside_pfx}, 1)) { + return "inside-prefix is not a valid prefix"; + } + + if(!Vyatta::TypeChecker::validateType('ipv6net', $self->{_outside_pfx}, 1)) { + return "outside-prefix is not a valid prefix"; + } + + return 0; +} + +# Returns an array of ip6tables parameters (SNPT, DNPT) +sub rule_str { + my ($self) = @_; + my $err; + + $err = $self->is_invalid(); + if($err ne 0) { + return ($err, undef, undef); + } + + return (undef, $self->make_snpt_string(), $self->make_dnpt_string()); +} + +sub is_disabled { + my $self = shift; + return 1 if defined $self->{_disable}; + return 0; +} + +1; + diff --git a/scripts/vyos-update-nptv6.pl b/scripts/vyos-update-nptv6.pl new file mode 100755 index 0000000..5079a66 --- /dev/null +++ b/scripts/vyos-update-nptv6.pl @@ -0,0 +1,119 @@ +#!/usr/bin/perl +# +# vyos-update-nptv6.pl: Update SNPT/DNPT ip6tables rules +# +# Copyright (C) 2014 VyOS Development Group <maintainers@vyos.net> +# +# This library is free software; you can redistribute it and/or +# modify it under the terms of the GNU Lesser General Public +# License as published by the Free Software Foundation; either +# version 2.1 of the License, or (at your option) any later version. +# +# This library is distributed in the hope that it will be useful, +# but WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# Lesser General Public License for more details. +# +# You should have received a copy of the GNU Lesser General Public +# License along with this library; if not, write to the Free Software +# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 +# USA + +use strict; +use lib "/opt/vyatta/share/perl5/"; +use Vyatta::Config; +use VyOS::Nptv6Rule; +use Vyatta::IpTables::Mgr; + +my $CONFIG_LEVEL = "nat nptv6"; +my $IPTABLES = "/sbin/ip6tables"; + +sub numerically_desc { $b <=> $a; } + +my $config = new Vyatta::Config; + +my $all_deleted = 1; + +my $rule; +$config->setLevel($CONFIG_LEVEL." rule"); +my %rules = $config->listNodeStatus(); +for $rule (keys %rules) { + if ($rules{$rule} ne "deleted") { + $all_deleted = 0; + } +} + +my $debug = 0; +if ($debug) { + open(OUT, ">>/tmp/nat") or exit 1; +} else { + open(OUT, ">>/dev/null") or exit 1; +} + +# Send rule to iptables +sub send_iptables { + my @cmds = @_; + my $prepend = $IPTABLES . " -t mangle "; + my $cmd; + + for $cmd (@cmds) { + print OUT $prepend . ' ' . $cmd . "\n"; + if(system($prepend . ' ' . $cmd)) { + exit 1; + } + } + return 0; +} + +# Clean up function +sub raw_cleanup { + my @cmds = ("-F VYOS_SNPT_HOOK", "-F VYOS_DNPT_HOOK", "-A VYOS_SNPT_HOOK -j RETURN", "-A VYOS_DNPT_HOOK -j RETURN"); + send_iptables(@cmds); +} + +print OUT "========= NPTv6 list =========\n"; +my @rule_keys = sort numerically_desc keys %rules; + +# No rules, clean up +if ($#rule_keys < 0) { + raw_cleanup(); + exit 0; +} + +my @cmds; +# Loop through all loops, sorted numerically +for $rule (@rule_keys) { + print OUT "$rule: $rules{$rule}\n"; + my $tmp = `ip6tables -L -nv --line -t mangle`; + print OUT "iptables before:\n$tmp\n"; + + my $nrule = new VyOS::Nptv6Rule; + $nrule->setup($CONFIG_LEVEL." rule $rule"); + + if ($rules{$rule} eq "deleted" || $nrule->is_disabled()) { + next; + } + + my ($err, $snpt_rule, $dnpt_rule) = $nrule->rule_str(); + if (defined $err) { + # rule check failed => return error + print OUT "NPT configuration error in rule $rule: $err\n"; + print STDERR "NPT configuration error in rule $rule: $err\n"; + exit 5; + } + + push(@cmds, $snpt_rule); + push(@cmds, $dnpt_rule); +} + +raw_cleanup(); +send_iptables(@cmds); + +close OUT; +exit 0; + +# Local Variables: +# mode: perl +# indent-tabs-mode: nil +# perl-indent-level: 2 +# End: diff --git a/templates-cfg/nat/nptv6/node.def b/templates-cfg/nat/nptv6/node.def new file mode 100644 index 0000000..be59537 --- /dev/null +++ b/templates-cfg/nat/nptv6/node.def @@ -0,0 +1,3 @@ +help: NPTv6 settings + +end:expression: "sudo /opt/vyatta/sbin/vyos-update-nptv6.pl" diff --git a/templates-cfg/nat/nptv6/rule/node.def b/templates-cfg/nat/nptv6/rule/node.def new file mode 100644 index 0000000..c666be9 --- /dev/null +++ b/templates-cfg/nat/nptv6/rule/node.def @@ -0,0 +1,11 @@ +tag: + +type: u32 + +help: Rule number for NAT + +syntax:expression: ($VAR(@) > 0 && $VAR(@) < 10000) ; \ + "Rule number must be between 1 and 9999." + +val_help: u32:1-9999 ; Number for this NAT rule + diff --git a/templates-cfg/nat/nptv6/rule/node.tag/description/node.def b/templates-cfg/nat/nptv6/rule/node.tag/description/node.def new file mode 100644 index 0000000..90bf88b --- /dev/null +++ b/templates-cfg/nat/nptv6/rule/node.tag/description/node.def @@ -0,0 +1,3 @@ +type: txt + +help: Rule description diff --git a/templates-cfg/nat/nptv6/rule/node.tag/disable/node.def b/templates-cfg/nat/nptv6/rule/node.tag/disable/node.def new file mode 100644 index 0000000..c23fc5a --- /dev/null +++ b/templates-cfg/nat/nptv6/rule/node.tag/disable/node.def @@ -0,0 +1 @@ +help: Disable NAT rule diff --git a/templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def b/templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def new file mode 100644 index 0000000..7af7091 --- /dev/null +++ b/templates-cfg/nat/nptv6/rule/node.tag/inside-prefix/node.def @@ -0,0 +1,7 @@ +type: txt + +help: Inside prefix to be translated + +val_help: ipv6net; IPv6 prefix to match + +syntax:expression: exec "/opt/vyatta/sbin/vyatta-validate-type ipv6_addr_param $VAR(@)" diff --git a/templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def b/templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def new file mode 100644 index 0000000..d0954ad --- /dev/null +++ b/templates-cfg/nat/nptv6/rule/node.tag/outside-interface/node.def @@ -0,0 +1,30 @@ +type: txt + +help: Outside interface of NPTv6 traffic + +enumeration: existing-interfaces; echo "any" + +val_help: <interface> ; Interface name or "any" + +commit:expression: exec " + if [ \"any\" == \"$VAR(@)\" ] ; then + exit 0 + fi + intf_array=($(awk '$1 ~ /:/ { print $1 }' /proc/net/dev)) + intf_array_len=${#intf_array[*]} + i=0 + while [ $i -lt $intf_array_len ]; do + temp=${intf_array[$i]%:*} + if [ \"$temp\" == \"$VAR(@)\" ] ; then + exit 0 + fi + let i++ + done + intf_group_name_array=\"eth+ bond+ br+ peth+ vtun+ tun+ wlm+ wlan+\" + i=0 + for i in $intf_group_name_array; do + if [ \"$i\" == \"$VAR(@)\" ]; then + exit 0 + fi + done + echo NPTv6 configuration warning: interface $VAR(@) does not exist on this system " diff --git a/templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def b/templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def new file mode 100644 index 0000000..7af7091 --- /dev/null +++ b/templates-cfg/nat/nptv6/rule/node.tag/outside-prefix/node.def @@ -0,0 +1,7 @@ +type: txt + +help: Inside prefix to be translated + +val_help: ipv6net; IPv6 prefix to match + +syntax:expression: exec "/opt/vyatta/sbin/vyatta-validate-type ipv6_addr_param $VAR(@)" |