diff options
Diffstat (limited to 'src')
-rwxr-xr-x | src/op_mode/show_nat_statistics.py | 63 | ||||
-rwxr-xr-x | src/op_mode/to_be_migrated/vyatta-nat-translations.pl | 267 |
2 files changed, 330 insertions, 0 deletions
diff --git a/src/op_mode/show_nat_statistics.py b/src/op_mode/show_nat_statistics.py new file mode 100755 index 000000000..b77693e19 --- /dev/null +++ b/src/op_mode/show_nat_statistics.py @@ -0,0 +1,63 @@ +#!/usr/bin/env python3 +# +# Copyright (C) 2018 VyOS maintainers and contributors +# +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 or later as +# published by the Free Software Foundation. +# +# This program 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 General Public License for more details. +# +# You should have received a copy of the GNU General Public License +# along with this program. If not, see <http://www.gnu.org/licenses/>. + +import jmespath +import json + +from argparse import ArgumentParser +from jinja2 import Template +from sys import exit +from vyos.util import cmd + +OUT_TMPL_SRC=""" +rule pkts bytes interface +---- ---- ----- --------- +{% for r in output %} +{%- if r.comment -%} +{%- set packets = r.counter.packets -%} +{%- set bytes = r.counter.bytes -%} +{%- set interface = r.interface -%} +{# remove rule comment prefix #} +{%- set comment = r.comment | replace('SRC-NAT-', '') | replace('DST-NAT-', '') -%} +{{ "%-4s" | format(comment) }} {{ "%9s" | format(packets) }} {{ "%12s" | format(bytes) }} {{ interface }} +{%- endif %} +{% endfor %} +""" + +parser = ArgumentParser() +group = parser.add_mutually_exclusive_group() +group.add_argument("--source", help="Show statistics for configured source NAT rules", action="store_true") +group.add_argument("--destination", help="Show statistics for configured destination NAT rules", action="store_true") +args = parser.parse_args() + +if args.source or args.destination: + tmp = cmd('sudo nft -j list table nat') + tmp = json.loads(tmp) + + source = r"nftables[?rule.chain=='POSTROUTING'].rule.{chain: chain, handle: handle, comment: comment, counter: expr[].counter | [0], interface: expr[].match.right | [0] }" + destination = r"nftables[?rule.chain=='PREROUTING'].rule.{chain: chain, handle: handle, comment: comment, counter: expr[].counter | [0], interface: expr[].match.right | [0] }" + data = { + 'output' : jmespath.search(source if args.source else destination, tmp), + 'direction' : 'source' if args.source else 'destination' + } + + tmpl = Template(OUT_TMPL_SRC, lstrip_blocks=True) + print(tmpl.render(data)) + exit(0) +else: + parser.print_help() + exit(1) + diff --git a/src/op_mode/to_be_migrated/vyatta-nat-translations.pl b/src/op_mode/to_be_migrated/vyatta-nat-translations.pl new file mode 100755 index 000000000..94ed74bad --- /dev/null +++ b/src/op_mode/to_be_migrated/vyatta-nat-translations.pl @@ -0,0 +1,267 @@ +#!/usr/bin/perl +# +# Module: vyatta-nat-translate.pl +# +# **** License **** +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program 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 +# General Public License for more details. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2007 Vyatta, Inc. +# All Rights Reserved. +# +# Author: Stig Thormodsrud +# Date: July 2008 +# Description: Script to display nat translations +# +# **** End License **** +# + +use Getopt::Long; +use XML::Simple; +use Data::Dumper; +use POSIX; + +use warnings; +use strict; + +my $dump = 0; +my ($xml_file, $verbose, $proto, $stats, $ipaddr, $pipe); +my $type; +my $verbose_format = "%-20s %-18s %-20s %-18s\n"; +my $format = "%-20s %-20s %-4s %-8s"; + +sub add_xml_root { + my $xml = shift; + + $xml = '<data>' . $xml . '</data>'; + return $xml; +} + + +sub read_xml_file { + my $file = shift; + + local($/, *FD); # slurp mode + open FD, "<", $file or die "Couldn't open $file\n"; + my $xml = <FD>; + close FD; + return $xml; +} + +sub print_xml { + my $data = shift; + print Dumper($data); +} + +sub guess_snat_dnat { + my ($src, $dst) = @_; + + if ($src->{original} eq $dst->{reply}) { + return "dnat"; + } + if ($dst->{original} eq $src->{reply}) { + return "snat"; + } + return "unkn"; +} + +sub nat_print_xml { + my ($data, $type) = @_; + + my $flow = 0; + + my %flowh; + while (1) { + my $meta = 0; + last if ! defined $data->{flow}[$flow]; + my $flow_ref = $data->{flow}[$flow]; + my $flow_type = $flow_ref->{type}; + my (%src, %dst, %sport, %dport, %proto); + my (%packets, %bytes); + my $timeout = undef; + my $uses = undef; + while (1) { + my $meta_ref = $flow_ref->{meta}[$meta]; + last if ! defined $meta_ref; + my $dir = $meta_ref->{direction}; + if ($dir eq 'original' or $dir eq 'reply') { + my $l3_ref = $meta_ref->{layer3}[0]; + my $l4_ref = $meta_ref->{layer4}[0]; + my $count_ref = $meta_ref->{counters}[0]; + if (defined $l3_ref) { + $src{$dir} = $l3_ref->{src}[0]; + $dst{$dir} = $l3_ref->{dst}[0]; + if (defined $l4_ref) { + $sport{$dir} = $l4_ref->{sport}[0]; + $dport{$dir} = $l4_ref->{dport}[0]; + $proto{$dir} = $l4_ref->{protoname}; + } + } + if (defined $stats and defined $count_ref) { + $packets{$dir} = $count_ref->{packets}[0]; + $bytes{$dir} = $count_ref->{bytes}[0]; + } + } elsif ($dir eq 'independent') { + $timeout = $meta_ref->{timeout}[0]; + $uses = $meta_ref->{'use'}[0]; + } + $meta++; + } + my ($proto, $in_src, $in_dst, $out_src, $out_dst); + $proto = $proto{original}; + $in_src = "$src{original}"; + $in_src .= ":$sport{original}" if defined $sport{original}; + $in_dst = "$dst{original}"; + $in_dst .= ":$dport{original}" if defined $dport{original}; + $out_src = "$dst{reply}"; + $out_src .= ":$dport{reply}" if defined $dport{reply}; + $out_dst = "$src{reply}"; + $out_dst .= ":$sport{reply}" if defined $sport{reply}; + if (defined $verbose) { + printf($verbose_format, $in_src, $in_dst, $out_src, $out_dst); + } +# if (! defined $type) { +# $type = guess_snat_dnat(\%src, \%dst); +# } + if (defined $type) { + my ($from, $to); + if ($type eq 'source') { + $from = "$src{original}"; + $to = "$dst{reply}"; + if (defined $sport{original} and defined $dport{reply}) { + if ($sport{original} ne $dport{reply}) { + $from .= ":$sport{original}"; + $to .= ":$dport{reply}"; + } + } + } else { + $from = "$dst{original}"; + $to = "$src{reply}"; + if (defined $dport{original} and defined $sport{reply}) { + if ($dport{original} ne $sport{reply}) { + $from .= ":$dport{original}"; + $to .= ":$sport{reply}"; + } + } + } + if (defined $verbose) { + print " $proto: $from ==> $to"; + } else { + my $timeout2 = ""; + if (defined $timeout) { + $timeout2 = $timeout; + } + printf($format, $from, $to, $proto, $timeout2); + print " $flow_type" if defined $flow_type; + print "\n"; + } + } + if (defined $verbose) { + print " timeout: $timeout" if defined $timeout; + print " use: $uses " if defined $uses; + print " type: $flow_type" if defined $flow_type; + print "\n"; + } + if (defined $stats) { + foreach my $dir ('original', 'reply') { + if (defined $packets{$dir}) { + printf(" %-8s: packets %s, bytes %s\n", + $dir, $packets{$dir}, $bytes{$dir}); + } + } + } + $flow++; + } + return $flow; +} + + +# +# main +# +GetOptions("verbose" => \$verbose, + "proto=s" => \$proto, + "file=s" => \$xml_file, + "stats" => \$stats, + "type=s" => \$type, + "ipaddr=s" => \$ipaddr, + "pipe" => \$pipe, +); + +my $conntrack = '/usr/sbin/conntrack'; +if (! -f $conntrack) { + die "Package [conntrack] not installed"; +} + +die "Must specify NAT type!" if !defined($type); +die "Unknown NAT type!" if (($type ne 'source') && ($type ne 'destination')); + +my $xs = XML::Simple->new(ForceArray => 1, KeepRoot => 0); +my ($xml, $data); + +# flush stdout after every write for pipe mode +$| = 1 if defined $pipe; + +if (defined $verbose) { + printf($verbose_format, 'Pre-NAT src', 'Pre-NAT dst', + 'Post-NAT src', 'Post-NAT dst'); +} else { + printf($format, 'Pre-NAT', 'Post-NAT', 'Prot', 'Timeout'); + print " Type" if defined $pipe; + print "\n"; +} + +if (defined $xml_file) { + $xml = read_xml_file($xml_file); + $data = $xs->XMLin($xml); + if ($dump) { + print_xml($data); + exit; + } + nat_print_xml($data, 'snat'); + +} elsif (defined $pipe) { + while ($xml = <STDIN>) { + $xml =~ s/\<\?xml version=\"1\.0\" encoding=\"utf-8\"\?\>//; + $xml =~ s/\<conntrack\>//; + $xml = add_xml_root($xml); + $data = $xs->XMLin($xml); + nat_print_xml($data, $type); + } +} else { + if (defined $proto) { + $proto = "-p $proto" + } else { + $proto = ""; + } + if ($type eq 'source') { + my $ipopt = ""; + if (defined $ipaddr) { + $ipopt = "--orig-src $ipaddr"; + } + $xml = `sudo $conntrack -L -n $ipopt -o xml $proto 2>/dev/null`; + chomp $xml; + $data = undef; + $data = $xs->XMLin($xml) if ! $xml eq ''; + } + if ($type eq 'destination') { + my $ipopt = ""; + if (defined $ipaddr) { + $ipopt = "--orig-dst $ipaddr"; + } + $xml = `sudo $conntrack -L -g $ipopt -o xml $proto 2>/dev/null`; + chomp $xml; + $data = undef; + $data = $xs->XMLin($xml) if ! $xml eq ''; + } + nat_print_xml($data, $type) if defined $data; +} + +# end of file |