From 6fc263b9cb71ca24dce60aec63aa453ef2b0000b Mon Sep 17 00:00:00 2001 From: sarthurdev <965089+sarthurdev@users.noreply.github.com> Date: Thu, 6 Jan 2022 15:16:55 +0100 Subject: conntrack: T4145: Remove `vyatta-cfg-firewall` dependency --- Makefile.am | 6 + debian/control | 1 + lib/Vyatta/Conntrack/ConntrackUtil.pm | 4 +- lib/Vyatta/IpTables/AddressFilter.pm | 289 ++++++++++++ lib/Vyatta/IpTables/IpSet.pm | 554 +++++++++++++++++++++++ lib/Vyatta/IpTables/Mgr.pm | 341 ++++++++++++++ lib/Vyatta/IpTables/Rule.pm | 818 ++++++++++++++++++++++++++++++++++ scripts/vyatta-conntrack-ignore.pl | 13 +- scripts/vyatta-conntrack-timeouts.pl | 14 +- scripts/vyatta-show-ignore.pl | 2 +- 10 files changed, 2025 insertions(+), 17 deletions(-) create mode 100644 lib/Vyatta/IpTables/AddressFilter.pm create mode 100644 lib/Vyatta/IpTables/IpSet.pm create mode 100644 lib/Vyatta/IpTables/Mgr.pm create mode 100644 lib/Vyatta/IpTables/Rule.pm diff --git a/Makefile.am b/Makefile.am index d35ad8e..f0bbd54 100644 --- a/Makefile.am +++ b/Makefile.am @@ -1,6 +1,7 @@ cfgdir = $(datadir)/vyatta-cfg/templates opdir = $(datadir)/vyatta-op/templates share_perl5dir = $(datarootdir)/perl5/Vyatta/Conntrack +ipt_share_perl5dir = $(datarootdir)/perl5/Vyatta/IpTables modprobedir = /etc/modprobe.d vprefix = /opt/vyatta @@ -18,6 +19,11 @@ share_perl5_DATA += lib/Vyatta/Conntrack/ConntrackUtil.pm share_perl5_DATA += lib/Vyatta/Conntrack/RuleCT.pm share_perl5_DATA += lib/Vyatta/Conntrack/RuleIgnore.pm +ipt_share_perl5_DATA = lib/Vyatta/IpTables/Rule.pm +ipt_share_perl5_DATA += lib/Vyatta/IpTables/AddressFilter.pm +ipt_share_perl5_DATA += lib/Vyatta/IpTables/IpSet.pm +ipt_share_perl5_DATA += lib/Vyatta/IpTables/Mgr.pm + sbin_SCRIPTS = scripts/vyatta-update-conntrack-log.pl bin_sudo_usersdir = $(bindir)/sudo-users bin_sudo_users_SCRIPTS = scripts/vyatta-show-conntrack.pl diff --git a/debian/control b/debian/control index 27d56f1..86f79b9 100644 --- a/debian/control +++ b/debian/control @@ -12,6 +12,7 @@ Depends: vyatta-cfg-system, vyatta-op, conntrack, conntrackd, + libswitch-perl, libxml-namespacesupport-perl, libxml-sax-base-perl, libxml-sax-perl, diff --git a/lib/Vyatta/Conntrack/ConntrackUtil.pm b/lib/Vyatta/Conntrack/ConntrackUtil.pm index 0ded3ef..daed392 100644 --- a/lib/Vyatta/Conntrack/ConntrackUtil.pm +++ b/lib/Vyatta/Conntrack/ConntrackUtil.pm @@ -50,7 +50,7 @@ our @EXPORT = qw(check_for_conntrack_hooks, process_protocols, check_and_add_hel #returns one if any hook is present sub check_for_conntrack_hooks { - my @output = `sudo iptables -L -t raw`; + my @output = `sudo iptables-nft -L -t raw`; foreach(@output) { if (($_ =~ m/WEBPROXY_CONNTRACK/)) { return 1; @@ -68,7 +68,7 @@ sub check_for_conntrack_hooks { sub check_ct_helper_rules { my $index; - my $cthelper_chain = "VYATTA_CT_HELPER"; + my $cthelper_chain = "VYOS_CT_HELPER"; foreach my $label ('PREROUTING', 'OUTPUT') { $index = ipt_find_chain_rule($iptables_cmd, 'raw', $label, $cthelper_chain); if (!defined($index)) { diff --git a/lib/Vyatta/IpTables/AddressFilter.pm b/lib/Vyatta/IpTables/AddressFilter.pm new file mode 100644 index 0000000..9b3be53 --- /dev/null +++ b/lib/Vyatta/IpTables/AddressFilter.pm @@ -0,0 +1,289 @@ +# Author: Vyatta +# Date: 2007 +# Description: IP tables address filter + +# **** 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) 2006-2009 Vyatta, Inc. +# All Rights Reserved. +# **** End License **** + +package Vyatta::IpTables::AddressFilter; + +require Vyatta::Config; +require Vyatta::IpTables::IpSet; +use Vyatta::Misc qw(getPortRuleString); +use Vyatta::TypeChecker; + +use strict; +use warnings; + +my %_protocolswithports = ( + tcp_udp => 1, + + # 'tcp_udp' is to be allowed for nat and firewall rules only. + # features should have syntax checks for allowing or forbiding + # the use of 'tcp_udp' as protocol. to allow tcp_udp see syntax check + # in protocol/node.def for NAT rules and to forbid tcp_udp see syntax + # check in protocol/node.def for load-balancing rules + # when allowed : tcp_udp creates 2 iptable rules - one for tcp, other for udp + tcp => 1, + udp => 1, + 6 => 1, + 17 => 1, +); + +my %fields = ( + _srcdst => undef, + _range_start => undef, + _range_stop => undef, + _network => undef, + _address => undef, + _port => undef, + _protocol => undef, + _src_mac => undef, + _ip_version => undef, + _address_group => undef, + _network_group => undef, + _port_group => undef, +); + +sub new { + my $that = shift; + my $class = ref($that) || $that; + my $self = {%fields,}; + + bless $self, $class; + return $self; +} + +sub set_ip_version { + my ($self, $ip_version) = @_; + + $self->{_ip_version} = $ip_version; +} + +sub setup_base { + my ($self, $level, $func) = @_; + my $config = new Vyatta::Config; + + $config->setLevel("$level"); + + # Default to IPv4. + $self->{_ip_version} = "ipv4"; + + # setup needed parent nodes + $self->{_srcdst} = $config->returnParent(".."); + $self->{_protocol} = $config->$func(".. protocol"); + + # setup address filter nodes + $self->{_address} = $config->$func("address"); + $self->{_network} = undef; + $self->{_range_start} = undef; + $self->{_range_stop} = undef; + if (defined($self->{_address})) { + if ($self->{_address} =~ /\//) { + $self->{_network} = $self->{_address}; + $self->{_address} = undef; + } elsif ($self->{_address} =~ /^([^-]+)-([^-]+)$/) { + $self->{_range_start} = $1; + $self->{_range_stop} = $2; + $self->{_address} = undef; + } + } + + $self->{_port} = $config->$func("port"); + $self->{_src_mac} = $config->$func("mac-address"); + $self->{_address_group} = $config->$func("group address-group"); + $self->{_network_group} = $config->$func("group network-group"); + $self->{_port_group} = $config->$func("group port-group"); + + return 0; +} + +sub setup { + my ($self, $level) = @_; + + $self->setup_base($level, 'returnValue'); + return 0; +} + +sub setupOrig { + my ($self, $level) = @_; + + $self->setup_base($level, 'returnOrigValue'); + return 0; +} + +sub print { + my ($self) = @_; + + print "srcdst: $self->{_srcdst}\n" if defined $self->{_srcdst}; + print "range start: $self->{_range_start}\n" if defined $self->{_range_start}; + print "range stop: $self->{_range_stop}\n" if defined $self->{_range_stop}; + print "network: $self->{_network}\n" if defined $self->{_network}; + print "address: $self->{_address}\n" if defined $self->{_address}; + print "port: $self->{_port}\n" if defined $self->{_port}; + print "protocol: $self->{_protocol}\n" if defined $self->{_protocol}; + print "src-mac: $self->{_src_mac}\n" if defined $self->{_src_mac}; + + return 0; +} + +sub rule { + my ($self) = @_; + my $rule = ""; + my $can_use_port = 1; + + my $addr_checker; + my $prefix_checker; + my $pure_addr_checker; + my $ip_term; + my $prefix_term; + + if ($self->{_ip_version} eq "ipv4") { + # This is an IPv4 rule + $addr_checker = 'ipv4_negate'; + $prefix_checker = 'ipv4net_negate'; + $pure_addr_checker = 'ipv4'; + $ip_term = "IPv4"; + $prefix_term = "subnet"; + } elsif ($self->{_ip_version} eq "ipv6") { + # This is an IPv6 rule + $addr_checker = 'ipv6_negate'; + $prefix_checker = 'ipv6net_negate'; + $pure_addr_checker = 'ipv6'; + $ip_term = "IPv6"; + $prefix_term = "prefix"; + } else { + return (undef, "Invalid IP version: $self->{_ip_version}"); + } + + if ( !defined($self->{_protocol}) + || !defined($_protocolswithports{$self->{_protocol}})) + { + $can_use_port = 0; + } + + if (($self->{_srcdst} eq "source") && (defined($self->{_src_mac}))) { + + # handle src mac + my $str = $self->{_src_mac}; + my $negate = ''; + if ($str =~ /^\!(.*)$/) { + $str = $1; + $negate = '! '; + } + $rule .= "-m mac $negate --mac-source $str "; + } + + my %group_ok; + foreach my $group_type ('address', 'network', 'port') { + $group_ok{$group_type} = 1; + } + + # set the address filter parameters + if (defined($self->{_network})) { + my $str = $self->{_network}; + return (undef, "\"$str\" is not a valid $ip_term $prefix_term") + if (!Vyatta::TypeChecker::validateType($prefix_checker, $str, 1)); + my $negate = ''; + if ($str =~ /^\!(.*)$/) { + $str = $1; + $negate = '! '; + } + $rule .= "$negate --$self->{_srcdst} $str "; + $group_ok{network} = 0; + } elsif (defined($self->{_address})) { + my $str = $self->{_address}; + return (undef, "\"$str\" is not a valid $ip_term address") + if (!Vyatta::TypeChecker::validateType($addr_checker, $str, 1)); + my $negate = ''; + if ($str =~ /^\!(.*)$/) { + $str = $1; + $negate = '! '; + } + $rule .= "$negate --$self->{_srcdst} $str "; + $group_ok{address} = 0; + } elsif ((defined $self->{_range_start}) && (defined $self->{_range_stop})) { + my $start = $self->{_range_start}; + my $stop = $self->{_range_stop}; + return (undef, "\"$start-$stop\" is not a valid IP range") + if ( !Vyatta::TypeChecker::validateType($addr_checker, $start, 1) + || !Vyatta::TypeChecker::validateType($pure_addr_checker, $stop, 1)); + my $negate = ''; + if ($self->{_range_start} =~ /^!(.*)$/) { + $start = $1; + $negate = '! '; + } + if ("$self->{_srcdst}" eq "source") { + $rule .= ("-m iprange $negate --src-range $start-$self->{_range_stop} "); + }elsif ("$self->{_srcdst}" eq "destination") { + $rule .= ("-m iprange $negate --dst-range $start-$self->{_range_stop} "); + } + $group_ok{address} = 0; + $group_ok{network} = 0; + } + + $group_ok{port} = 0 if defined $self->{_port}; + my ($port_str, $port_err)= getPortRuleString($self->{_port}, $can_use_port,($self->{_srcdst} eq "source") ? "s" : "d",$self->{_protocol}); + return (undef, $port_err) if (!defined($port_str)); + $rule .= $port_str; + # Handle groups last so we can check $group_ok + my %group_used = ('address' => 0, 'network' => 0); + foreach my $group_type ('address', 'network', 'port') { + my $var_name = '_' . $group_type . '_group'; + if (defined($self->{$var_name})) { + $group_used{$group_type} = 1; + my $name = $self->{$var_name}; + if (!$group_ok{$group_type}) { + return (undef, "Can't mix $self->{_srcdst} $group_type group [$name] and $group_type"); + } + my $group = new Vyatta::IpTables::IpSet($name, $group_type); + my ($set_rule, $err_str) = $group->rule($self->{_srcdst}); + return ($err_str,) if !defined $set_rule; + $rule .= $set_rule; + } + } + if ($group_used{address} and $group_used{network}) { + return (undef,"Can't combine network and address group for $self->{_srcdst}\n"); + } + return ($rule, undef); +} + +sub outputXmlElem { + my ($name, $value, $fh) = @_; + return if !defined $value; + print $fh " <$name>$value\n"; +} + +sub outputXml { + my ($self, $prefix, $fh) = @_; + if ( !defined($self->{_address}) + && !defined($self->{_network}) + && !defined($self->{_range_start}) + && !defined($self->{_range_stop})) + { + if (($self->{_ip_version} eq "ipv4")) { + $self->{_address} = "0.0.0.0/0"; + } else { + $self->{_address} = "::/0"; + } + } + outputXmlElem("${prefix}_addr", $self->{_address}, $fh); + outputXmlElem("${prefix}_net", $self->{_network}, $fh); + outputXmlElem("${prefix}_addr_start", $self->{_range_start}, $fh); + outputXmlElem("${prefix}_addr_stop", $self->{_range_stop}, $fh); + outputXmlElem("${prefix}_port", $self->{_port}, $fh); +} + +1; diff --git a/lib/Vyatta/IpTables/IpSet.pm b/lib/Vyatta/IpTables/IpSet.pm new file mode 100644 index 0000000..d7a014a --- /dev/null +++ b/lib/Vyatta/IpTables/IpSet.pm @@ -0,0 +1,554 @@ +# +# Module: IpSet.pm +# +# **** 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) 2009-2010 Vyatta, Inc. +# All Rights Reserved. +# +# Author: Stig Thormodsrud +# Date: January 2009 +# Description: vyatta interface to ipset +# +# **** End License **** +# + +package Vyatta::IpTables::IpSet; + +use Vyatta::Config; +use Vyatta::TypeChecker; +use Vyatta::Misc; +use NetAddr::IP; + +use strict; +use warnings; + +my %fields = ( + _name => undef, + _type => undef, # vyatta group type, not ipset type + _family => undef, + _exists => undef, + _negate => undef, + _debug => undef, +); + +our %grouptype_hash = ( + 'address' => 'hash:ip', + 'network' => 'hash:net', + 'port' => 'bitmap:port' +); + +my $logger = 'logger -t IpSet.pm -p local0.warn --'; + +# Currently we restrict an address range to a /24 even +# though ipset would support a /16. The main reason is +# due to the long time it takes to make that many calls +# to add each individual member to the set. +my $addr_range_mask = 24; +my $lockfile = "/opt/vyatta/config/.lock"; + +# remove lock file to avoid commit blockade on interrupt +# like CTRL+C. +sub INT_handler { + my $rc = system("sudo rm -f $lockfile >>/dev/null"); + exit(0); +} + +$SIG{'INT'} = 'INT_handler'; + +sub new { + my ($that, $name, $type, $family) = @_; + + my $class = ref($that) || $that; + my $self = {%fields,}; + if ($name =~ m/^!/) { + $self->{_negate} = 1; + $name =~ s/^!(.*)$/$1/; + } + $self->{_name} = $name; + $self->{_type} = $type; + $self->{_family} = $family; + + bless $self, $class; + return $self; +} + +sub debug { + my ($self, $onoff) = @_; + + $self->{_debug} = undef; + $self->{_debug} = 1 if $onoff eq "on"; +} + +sub run_cmd { + my ($self, $cmd) = @_; + + my $rc = system("sudo $cmd"); + if (defined $self->{_debug}) { + my $func = (caller(1))[3]; + system("$logger [$func] [$cmd] = [$rc]"); + } + return $rc; +} + +sub exists { + my ($self) = @_; + + return 1 if defined $self->{_exists}; + return 0 if !defined $self->{_name}; + my $cmd = "ipset -L $self->{_name} > /dev/null 2>&1"; + my $rc = $self->run_cmd($cmd); + if ($rc eq 0) { + $self->{_exists} = 1; + $self->get_type() if !defined $self->{_type}; + } + return $rc ? 0 : 1; +} + +sub get_type { + my ($self) = @_; + + return $self->{_type} if defined $self->{_type}; + return if !$self->exists(); + my @lines = `ipset -L $self->{_name}`; + my $type; + foreach my $line (@lines) { + if ($line =~ /^Type:\s+([\w:]+)$/) { + $type = $1; + last; + } + } + return if !defined $type; + foreach my $vtype (keys(%grouptype_hash)) { + if ($grouptype_hash{$vtype} eq $type) { + $self->{_type} = $vtype; + last; + } + } + return $self->{_type}; +} + +sub get_family { + my ($self) = @_; + return $self->{_family} if defined $self->{_family}; + return if !$self->exists(); + my @lines = `ipset -L $self->{_name}`; + my $family; + foreach my $line (@lines) { + if ($line =~ /^Header: family (\w+) hashsize/) { + $family = $1; + $self->{_family} = $family; + last; + } elsif ($line =~ /^Type: bitmap:port$/){ + $self->{_family} = "inet"; + last; + } + } + return $self->{_family}; +} + +sub alphanum_split { + my ($str) = @_; + my @list = split m/(?=(?<=\D)\d|(?<=\d)\D)/, $str; + return @list; +} + +sub natural_order { + my ($a, $b) = @_; + my @a = alphanum_split($a); + my @b = alphanum_split($b); + + while (@a && @b) { + my $a_seg = shift @a; + my $b_seg = shift @b; + my $val; + if (($a_seg =~ /\d/) && ($b_seg =~ /\d/)) { + $val = $a_seg <=> $b_seg; + } else { + $val = $a_seg cmp $b_seg; + } + if ($val != 0) { + return $val; + } + } + return @a <=> @b; +} + +sub get_members { + my ($self) = @_; + + my @members = (); + return @members if !$self->exists(); + + my @lines = `ipset -L $self->{_name} -s`; + foreach my $line (@lines) { + push @members, $line if $line =~ /^\d/; + } + if ($self->{_type} ne 'port') { + @members = sort {natural_order($a,$b)} @members; + } + return @members; +} + +sub create { + my ($self) = @_; + + return "Error: undefined group name" if !defined $self->{_name}; + return "Error: undefined group type" if !defined $self->{_type}; + return if $self->exists(); # treat as nop if already exists + + my $ipset_param = $grouptype_hash{$self->{_type}}; + return "Error: invalid group type\n" if !defined $ipset_param; + + my $cmd = "ipset -N $self->{_name} $ipset_param family $self->{_family}"; + + if ($self->{_type} eq 'port') { + $ipset_param .= ' --from 1 --to 65535'; + $cmd = "ipset -N $self->{_name} $ipset_param"; + } + + my $rc = $self->run_cmd($cmd); + return "Error: call to ipset failed [$rc]" if $rc; + return; # undef +} + +sub references { + my ($self) = @_; + + return 0 if !$self->exists(); + my @lines = `ipset -L $self->{_name}`; + foreach my $line (@lines) { + if ($line =~ /^References:\s+(\d+)$/) { + return $1; + } + } + return 0; +} + +sub flush { + my ($self) = @_; + my $cmd = "ipset flush $self->{_name}"; + my $rc = $self->run_cmd($cmd); + return "Error: call to ipset failed [$rc]" if $rc; + return; +} + +sub rebuild_ipset() { + my ($self) = @_; + my $name = $self->{_name}; + my $type = $self->{_type}; + my $config = new Vyatta::Config; + + my @members = $config->returnOrigValues("firewall group $type-group $name $type"); + + # go through the firewall group config with this name, + my $member; + foreach $member (@members) { + $self->add_member($member, $name); + } +} + +sub reset_ipset_named { + my ($self) = @_; + my $name = $self->{_name}; + + # flush the ipset group first, then re-build the group from configuration + $self->flush(); + + $self->rebuild_ipset(); +} + +sub reset_ipset_all { + my $config = new Vyatta::Config; + my @pgroups = $config->listOrigNodes("firewall group port-group"); + my @adgroups = $config->listOrigNodes("firewall group address-group"); + my @nwgroups = $config->listOrigNodes("firewall group network-group"); + my $group; + + foreach $group (@pgroups) { + my $grp = new Vyatta::IpTables::IpSet($group, "port"); + $grp->reset_ipset_named(); + } + foreach $group (@adgroups) { + my $grp = new Vyatta::IpTables::IpSet($group, "address"); + $grp->reset_ipset_named(); + } + foreach $group (@nwgroups) { + my $grp = new Vyatta::IpTables::IpSet($group, "network"); + $grp->reset_ipset_named(); + } +} + +sub reset_ipset { + + # main function to do the reset operation + my ($self) = @_; + my $name = $self->{_name}; + + my $lockcmd = "touch $lockfile"; + my $unlockcmd = "rm -f $lockfile"; + $self->run_cmd($lockcmd); + + # reset one rule or all? + if ($name eq 'all') { + $self->reset_ipset_all(); + } else { + $self->reset_ipset_named(); + } + my $rc = $self->run_cmd($unlockcmd); + return "Error: call to ipset failed [$rc]" if $rc; + return; # undef +} + +sub delete { + my ($self) = @_; + + return "Error: undefined group name" if !defined $self->{_name}; + return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists(); + + my $refs = $self->references(); + if ($refs > 0) { + + # still in use + if (scalar($self->get_firewall_references(1)) > 0) { + + # still referenced by config + return "Error: group [$self->{_name}] still in use.\n"; + } + + # not referenced by config => simultaneous deletes. just do flush. + return $self->flush(); + } + + my $cmd = "ipset -X $self->{_name}"; + my $rc = $self->run_cmd($cmd); + return "Error: call to ipset failed [$rc]" if $rc; + return; # undef +} + +sub check_member_address { + my $member = shift; + + if (!Vyatta::TypeChecker::validateType('ipv4', $member, 1)) { + return "Error: [$member] isn't valid IPv4 address\n"; + } + if ($member eq '0.0.0.0') { + return "Error: zero IP address not valid in address-group\n"; + } + return; +} + +sub check_member { + my ($self, $member) = @_; + + return "Error: undefined group name" if !defined $self->{_name}; + return "Error: undefined group type" if !defined $self->{_type}; + + # We can't call $self->member_exists() here since this is a + # syntax check and the group may not have been created yet + # if there hasn't been a commit yet on this group. Move the + # exists check to $self->add_member(). + + if ($self->{_type} eq 'address') { + if ($member =~ /^([^-]+)-([^-]+)$/) { + foreach my $address ($1, $2) { + my $rc = check_member_address($address); + return $rc if defined $rc; + } + my $start_ip = new NetAddr::IP($1); + my $stop_ip = new NetAddr::IP($2); + if ($stop_ip <= $start_ip) { + return "Error: $1 must be less than $2\n"; + } + my $start_net = new NetAddr::IP("$1/$addr_range_mask"); + if (!$start_net->contains($stop_ip)) { + return "Error: address range must be within /$addr_range_mask\n"; + } + + } else { + my $rc = check_member_address($member); + return $rc if defined $rc; + } + } elsif ($self->{_type} eq 'network') { + if (!Vyatta::TypeChecker::validateType('ipv4net', $member, 1)) { + return "Error: [$member] isn't a valid IPv4 network\n"; + } + if ($member =~ /([\d.]+)\/(\d+)/) { + my ($net, $mask) = ($1, $2); + return "Error: 0.0.0.0/0 invalid in network-group\n" + if (($net eq '0.0.0.0') and ($mask == 0)); + return "Error: invalid mask [$mask] - must be between 1-31\n" + if (($mask < 1) or ($mask > 31)); + } else { + return "Error: Invalid network group [$member]\n"; + } + } elsif ($self->{_type} eq 'port') { + my ($success, $err) = (undef, "invalid port [$member]"); + if ($member =~ /^(\d+)-(\d+)$/) { + ($success, $err) = Vyatta::Misc::isValidPortRange($member, '-'); + } elsif ($member =~ /^\d/) { + ($success, $err) = Vyatta::Misc::isValidPortNumber($member); + } else { + ($success, $err) = Vyatta::Misc::isValidPortName($member); + } + return "Error: $err\n" if defined $err; + } else { + return "Error: invalid set type [$self->{_type}]"; + } + return; #undef +} + +sub member_exists { + my ($self, $member) = @_; + + # check if a member is a port range and roll through all members it is + if ($member =~ /([\d]+)-([\d]+)/) { + foreach my $port ($1..$2) { + # test port with ipset + my $cmd = "ipset -T $self->{_name} $port -q"; + my $rc = $self->run_cmd($cmd); + # return true if port was found + return 1 if !$rc; + } + # return false if ports was not found in set + return 0; + } else { + my $cmd = "ipset -T $self->{_name} $member -q"; + my $rc = $self->run_cmd($cmd); + return $rc ? 0 : 1; + } +} + + +sub add_member { + my ($self, $member, $alias, $hyphenated_port) = @_; + + return "Error: undefined group name" if !defined $self->{_name}; + return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists(); + + if ($self->member_exists($member)) { + my $set_name = $alias; + $set_name = $self->{_name} if !defined $set_name; + return "Error: member [$member] already exists in [$set_name]\n"; + } + my $cmd = "ipset -A $self->{_name} $member"; + my $rc = $self->run_cmd($cmd); + return "Error: call to ipset failed [$rc]" if $rc; + return; # undef +} + +sub delete_member_range { + my ($self, $start, $stop) = @_; + + if ($self->{_type} eq 'port') { + foreach my $member ($start .. $stop) { + my $rc = $self->delete_member($member); + return $rc if defined $rc; + } + } elsif ($self->{_type} eq 'address') { + my $start_ip = new NetAddr::IP("$start/$addr_range_mask"); + my $stop_ip = new NetAddr::IP("$stop/$addr_range_mask"); + for (; $start_ip <= $stop_ip; $start_ip++) { + my $rc = $self->delete_member($start_ip->addr()); + return $rc if defined $rc; + last if $start_ip->cidr() eq $start_ip->broadcast(); + } + } + return; +} + +sub delete_member { + my ($self, $member, $hyphenated_port) = @_; + + return "Error: undefined group name" if !defined $self->{_name}; + return "Error: group [$self->{_name}] doesn't exists\n" if !$self->exists(); + + # service name or port name may contain a hyphen, which needs to be escaped + # using square brackets in ipset, to avoid confusion with port ranges + if (($member =~ /^([^-]+)-([^-]+)$/) and ((defined($hyphenated_port)) and ($hyphenated_port eq 'false'))) { + return $self->delete_member_range($1, $2); + } + + if (!$self->member_exists($member)) { + return "Error: member [$member] doesn't exists in [$self->{_name}]\n"; + } + my $cmd = "ipset -D $self->{_name} $member"; + my $rc = $self->run_cmd($cmd); + return "Error: call to ipset failed [$rc]" if $rc; + return; # undef +} + +sub get_description { + my ($self) = @_; + + return if !$self->exists(); + my $config = new Vyatta::Config; + my $group_type = "$self->{_type}-group"; + $config->setLevel("firewall group $group_type $self->{_name}"); + return $config->returnOrigValue('description'); +} + +sub get_firewall_references { + my ($self, $working) = @_; + my ($lfunc, $vfunc) = qw(listOrigNodes returnOrigValue); + if ($working) { + ($lfunc, $vfunc) = qw(listNodes returnValue); + } + my @fw_refs = (); + return @fw_refs if !$self->exists(); + my $config = new Vyatta::Config; + foreach my $tree ('name', 'ipv6-name', 'modify') { + my $path = "firewall $tree "; + $config->setLevel($path); + my @names = $config->$lfunc(); + foreach my $name (@names) { + my $name_path = "$path $name rule "; + $config->setLevel($name_path); + my @rules = $config->$lfunc(); + foreach my $rule (@rules) { + foreach my $dir ('source', 'destination') { + my $rule_path = "$name_path $rule $dir group"; + $config->setLevel($rule_path); + my $group_type = "$self->{_type}-group"; + my $value = $config->$vfunc($group_type); + $value =~ s/^!(.*)$/$1/ if defined $value; + if (defined $value and $self->{_name} eq $value) { + push @fw_refs, "$name-$rule-$dir"; + } + } # foreach $dir + } # foreach $rule + } # foreach $name + } # foreach $tree + return @fw_refs; +} + +sub rule { + my ($self, $direction) = @_; + + if (!$self->exists()) { + my $name = $self->{_name}; + $name = 'undefined' if !defined $name; + return (undef, "Undefined group [$name]"); + } + + my $srcdst; + my $grp = $self->{_name}; + $srcdst = 'src' if $direction eq 'source'; + $srcdst = 'dst' if $direction eq 'destination'; + + return (undef, "Invalid direction [$direction]") if !defined $srcdst; + my $opt = ''; + $opt = '!' if $self->{_negate}; + return (" -m set $opt --match-set $grp $srcdst ",); +} + +1; diff --git a/lib/Vyatta/IpTables/Mgr.pm b/lib/Vyatta/IpTables/Mgr.pm new file mode 100644 index 0000000..39a03f1 --- /dev/null +++ b/lib/Vyatta/IpTables/Mgr.pm @@ -0,0 +1,341 @@ +# +# Module: Vyatta::IpTables::Mgr.pm +# +# **** 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) 2010 Vyatta, Inc. +# All Rights Reserved. +# +# Author: Stig Thormodsrud +# Date: June 2010 +# Description: common iptables routines +# +# **** End License **** +# + +package Vyatta::IpTables::Mgr; + +use strict; +use warnings; + +use base 'Exporter'; +our @EXPORT = qw(ipt_find_chain_rule ipt_enable_conntrack + ipt_disable_conntrack count_iptables_rules + chain_referenced ipt_get_queue_target + run_ipt_cmd create_ipt_chain delete_ipt_chain + flush_ipt_chain insert_ipt_rule append_ipt_rule + delete_ipt_rule delete_ipt_rulenum ipt_find_comment_rule); + +## TODO - in future, we could use perl's libiptc module instead of +## running system commands in the following function for iptables. +## However, that would need integrating the libiptc module into the system +## and also adding other functionality to it, including IPv6 support. +sub run_ipt_cmd { + my ($cmd) = shift; + my $error = system("$cmd"); + + my $debug = "false"; + my $syslog = "false"; + my $logger = "sudo logger -t Vyatta::IPTables::Mgr -p local0.warn --"; + + if ($syslog eq "true") { + my $func = (caller(1))[3]; + system("$logger [$func] [$cmd] = [$error]"); + } + if ($debug eq "true") { + my $func = (caller(1))[3]; + print "\n[$func] [$cmd] = [$error]"; + } + return $error; +} + +sub create_ipt_chain { + my ($ipt_cmd, $table, $chain) = @_; + my ($cmd, $error); + + $cmd = "sudo $ipt_cmd -t $table -N $chain"; + $error = run_ipt_cmd($cmd); + return "create_ipt_chain [$ipt_cmd -t $table -N $chain] failed: [error code - $error]" if $error; + + return; +} + +sub flush_ipt_chain { + my ($ipt_cmd, $table, $chain) = @_; + my ($cmd, $error); + + $cmd = "sudo $ipt_cmd -t $table -F $chain"; + $error = run_ipt_cmd($cmd); + return "flush_ipt_chain [$ipt_cmd -t $table -F $chain] failed: [error code - $error]" if $error; + + return; +} + +sub delete_ipt_chain { + my ($ipt_cmd, $table, $chain) = @_; + my ($cmd, $error); + + $cmd = "sudo $ipt_cmd -t $table -X $chain"; + $error = run_ipt_cmd($cmd); + return "delete_ipt_chain [$ipt_cmd -t $table -X $chain] failed: [error code - $error]" if $error; + + return; +} + +sub insert_ipt_rule { + my ($ipt_cmd, $table, $chain, $jump_target, $insert_num, $append_options) = @_; + my ($cmd, $error); + + $insert_num = 1 if (!defined $insert_num); + $cmd = "sudo $ipt_cmd -t $table -I $chain $insert_num -j $jump_target "; + $cmd .= $append_options if defined $append_options; + $error = run_ipt_cmd($cmd); + return "insert_ipt_rule [$ipt_cmd -t $table -I $chain $insert_num -j $jump_target] failed: [error code - $error]" if $error; + + return; +} + +sub append_ipt_rule { + my ($ipt_cmd, $table, $chain, $jump_target, $append_options) = @_; + my ($cmd, $error); + + $cmd = "sudo $ipt_cmd -t $table -A $chain -j $jump_target "; + $cmd .= $append_options if defined $append_options; + $error = run_ipt_cmd($cmd); + return "append_ipt_rule [$ipt_cmd -t $table -A $chain -j $jump_target] failed: [error code - $error]" if $error; + + return; +} + +# delete rule based on jump target. should only be used if jump_target is unique in that chain +sub delete_ipt_rule { + my ($ipt_cmd, $table, $chain, $jump_target) = @_; + my ($cmd, $error); + + $cmd = "sudo $ipt_cmd -t $table -D $chain -j $jump_target"; + $error = run_ipt_cmd($cmd); + return "delete_ipt_rule [$ipt_cmd -t $table -D $chain -j $jump_target] failed: [error code - $error]" if $error; + + return; +} + +# delete rule based on rule number +sub delete_ipt_rulenum { + my ($ipt_cmd, $table, $chain, $delete_num) = @_; + my ($cmd, $error); + + $cmd = "sudo $ipt_cmd -t $table -D $chain $delete_num"; + $error = run_ipt_cmd($cmd); + return "delete_ipt_rulenum [$ipt_cmd -t $table -D $chain $delete_num] failed: [error code - $error]" if $error; + + return; +} + +# searches and returns first found rule based on jump target +sub ipt_find_chain_rule { + my ($iptables_cmd, $table, $chain, $search) = @_; + + my ($num, $chain2) = (undef, undef); + my $cmd = "$iptables_cmd -t $table -L $chain -vn --line"; + my @lines = `sudo $cmd 2> /dev/null | egrep ^[0-9]`; + if (scalar(@lines) < 1) { + return; + } + foreach my $line (@lines) { + ($num, undef, undef, $chain2) = split /\s+/, $line; + last if $chain2 eq $search; + ($num, $chain2) = (undef, undef); + } + + return $num if defined $num; + return; +} + +# searches and returns first found rule based on matching text in rule comment +sub ipt_find_comment_rule { + my ($iptables_cmd, $table, $chain, $search) = @_; + + my $cmd = "$iptables_cmd -t $table -L $chain -vn --line"; + my @lines = `sudo $cmd 2> /dev/null | egrep ^[0-9]`; + if (scalar(@lines) < 1) { + return; + } + + my ($num, $rule_txt, $comment) = (undef, undef); + foreach my $line (@lines) { + ($rule_txt, $comment) = split /\/\*/, $line; + + #print "rule_txt : $rule_txt, comment : $comment\n"; + if (defined $comment && $comment =~ m/$search/) { + + #print "found $search in $comment \n"; + ($num) = split /\s+/, $rule_txt if defined $rule_txt; + return $num; + } + ($rule_txt, $comment) = (undef, undef); + } + return; +} +my %conntrack_hook_hash =( + 'PREROUTING' => 'VYATTA_CT_PREROUTING_HOOK', + 'OUTPUT' => 'VYATTA_CT_OUTPUT_HOOK', +); + +sub ipt_enable_conntrack { + my ($iptables_cmd, $chain) = @_; + my $hookCtHelper = 'false'; + + if (($chain eq 'FW_CONNTRACK') or ($chain eq 'NAT_CONNTRACK')) { + $hookCtHelper = 'true'; + } + + system("sudo $iptables_cmd -t raw -L $chain -n >& /dev/null"); + if ($? >> 8) { + + # chain does not exist yet. set up conntrack. + system("sudo $iptables_cmd -t raw -N $chain"); + system("sudo $iptables_cmd -t raw -A $chain -j ACCEPT"); + + foreach my $label ('PREROUTING', 'OUTPUT') { + my $index; + my $conntrack_hook = $conntrack_hook_hash{$label}; + $index = ipt_find_chain_rule($iptables_cmd, 'raw',$label, $conntrack_hook); + if (!defined($index)) { + print "Error: unable to find [$label] [$conntrack_hook]\n"; + return 1; + } + $index++; + system("sudo $iptables_cmd -t raw -I $label $index -j $chain"); + + if ($hookCtHelper eq 'true') { + + # we want helper hook only for Firewall / NAT. + $conntrack_hook = "VYATTA_CT_HELPER"; + $index = ipt_find_chain_rule($iptables_cmd, 'raw',$label, $conntrack_hook); + if (!defined($index)) { + + # this index does not change now but maybe later we change it, so being defensive. + my $cttimeout_index = ipt_find_chain_rule($iptables_cmd, 'raw', $label, "VYATTA_CT_TIMEOUT"); + if (defined($cttimeout_index)) { + + # $cttimeout_index++; fixing 8173 + # currently we have cttimeout at 1 index, it might change in future. + # helper chain should be before timeout chain + system("sudo $iptables_cmd -t raw -I $label $cttimeout_index -j VYATTA_CT_HELPER"); + } + } + } + } + } + return 0; +} + +sub remove_cthelper_hook { + my ($iptables_cmd, $label, $chain) =@_; + + #label is PREROUTING / OUTPUT, chain is FW_CONNTRACK/NAT_CONNTRACK etc. + my $index; + + # find if we need to remove VYATTA_CT_HELPER + my $cthelper_index = ipt_find_chain_rule($iptables_cmd, 'raw',$label, 'VYATTA_CT_HELPER'); + if(!defined($cthelper_index)) { + + # not an error: this hook is only for FW / NAT + return 0; + } + + # if this chain is FW_CONNTRACK, look if NAT is using it, else remove + if ($chain eq 'FW_CONNTRACK') { + $index = ipt_find_chain_rule($iptables_cmd, 'raw',$label, 'NAT_CONNTRACK'); + if (!defined($index)) { + + # NAT, only other user of helpers, not enabled, can remove VYATTA_CT_HELPER + system("sudo $iptables_cmd -t raw -D $label $cthelper_index"); + return 0; + } + } elsif ($chain eq 'NAT_CONNTRACK') { + $index = ipt_find_chain_rule($iptables_cmd, 'raw',$label, 'FW_CONNTRACK'); + if (!defined($index)) { + + # Firewall, only other user of helpers, not enabled, can remove VYATTA_CT_HELPER + system("sudo $iptables_cmd -t raw -D $label $cthelper_index"); + return 0; + } + } +} + +sub ipt_disable_conntrack { + my ($iptables_cmd, $chain) = @_; + + my $debug = 0; + my @lines; + foreach my $label ('PREROUTING', 'OUTPUT') { + my $index; + my $conntrack_hook = $conntrack_hook_hash{$label}; + $index = ipt_find_chain_rule($iptables_cmd, 'raw',$label, $chain); + if (!defined($index)) { + if ($debug > 0) { + print "Error: ipt_disable_conntrack failed to find ". "[$label][$chain]\n"; + } + return 1; + } + system("sudo $iptables_cmd -t raw -D $label $index"); + + remove_cthelper_hook($iptables_cmd, $label, $chain); + } + + system("sudo $iptables_cmd -t raw -F $chain >& /dev/null"); + system("sudo $iptables_cmd -t raw -X $chain >& /dev/null"); + + return 0; +} + +my %queue_target_hash =( + 'SNORT' => 'NFQUEUE', + 'VG_HTTPS' => 'NFQUEUE --queue-num 1', +); + +sub ipt_get_queue_target { + my ($app) = @_; + + my $target = $queue_target_hash{$app}; + return $target; +} + +sub count_iptables_rules { + my ($iptables_cmd, $table, $chain) = @_; + + my $cmd = "$iptables_cmd -t $table -L $chain -n --line"; + my @lines = `sudo $cmd 2> /dev/null`; + my $cnt = 0; + foreach my $line (@lines) { + $cnt++ if $line =~ /^\d/; + } + return $cnt; +} + +sub chain_referenced { + my ($table, $chain, $iptables_cmd) = @_; + + my $cmd = "$iptables_cmd -t $table -n -L $chain"; + my $line = `sudo $cmd 2>/dev/null |head -n1`; + chomp $line; + my $found = 0; + if ($line =~ m/^Chain $chain \((\d+) references\)$/) { + if ($1 > 0) { + $found = 1; + } + } + return $found; +} + +1; diff --git a/lib/Vyatta/IpTables/Rule.pm b/lib/Vyatta/IpTables/Rule.pm new file mode 100644 index 0000000..5f1e0a4 --- /dev/null +++ b/lib/Vyatta/IpTables/Rule.pm @@ -0,0 +1,818 @@ +package Vyatta::IpTables::Rule; + +use strict; +use Vyatta::Config; +use Vyatta::IpTables::Mgr; +require Vyatta::IpTables::AddressFilter; + +my $src = new Vyatta::IpTables::AddressFilter; +my $dst = new Vyatta::IpTables::AddressFilter; + +my %fields = ( + _name => undef, + _rule_number => undef, + _protocol => undef, + _state => { + _established => undef, + _new => undef, + _related => undef, + _invalid => undef, + }, + _action => undef, + _log => undef, + _tcp_flags => undef, + _icmp_code => undef, + _icmp_type => undef, + _icmp_name => undef, + _icmpv6_type => undef, + _mod_mark => undef, + _mod_table => undef, + _mod_dscp => undef, + _mod_tcpmss => undef, + _ipsec => undef, + _non_ipsec => undef, + _frag => undef, + _non_frag => undef, + _recent_time => undef, + _recent_cnt => undef, + _p2p => { + _all => undef, + _apple => undef, + _bit => undef, + _dc => undef, + _edk => undef, + _gnu => undef, + _kazaa => undef, + }, + _time => { + _startdate => undef, + _stopdate => undef, + _starttime => undef, + _stoptime => undef, + _monthdays => undef, + _weekdays => undef, + _utc => undef, + }, + _limit => { + _rate => undef, + _burst => undef, + }, + _disable => undef, + _ip_version => undef, + _comment => undef, + _hop_limit => { + _eq => undef, + _lt => undef, + _gt => undef, + } +); + +my %dummy_rule = ( + _rule_number => 10000, + _protocol => "all", + _state => { + _established => undef, + _new => undef, + _related => undef, + _invalid => undef, + }, + _action => "DROP", + _log => undef, + _tcp_flags => undef, + _icmp_code => undef, + _icmp_type => undef, + _icmp_name => undef, + _icmpv6_type => undef, + _mod_mark => undef, + _mod_table => undef, + _mod_dscp => undef, + _mod_tcpmss => undef, + _ipsec => undef, + _non_ipsec => undef, + _frag => undef, + _non_frag => undef, + _recent_time => undef, + _recent_cnt => undef, + _p2p => { + _all => undef, + _apple => undef, + _bit => undef, + _dc => undef, + _edk => undef, + _gnu => undef, + _kazaa => undef, + }, + _time => { + _startdate => undef, + _stopdate => undef, + _starttime => undef, + _stoptime => undef, + _monthdays => undef, + _weekdays => undef, + _utc => undef, + }, + _limit => { + _rate => undef, + _burst => undef, + }, + _disable => undef, + _ip_version => undef, + _comment => undef, + _hop_limit => { + _eq => undef, + _lt => undef, + _gt => undef, + } +); + +my $DEBUG = 'false'; + +sub new { + my $that = shift; + my $class = ref($that) || $that; + my $self = {%fields,}; + + bless $self, $class; + return $self; +} + +sub setupDummy { + my ($self, $level) = @_; + + %{$self} = %dummy_rule; + $src = new Vyatta::IpTables::AddressFilter; + $dst = new Vyatta::IpTables::AddressFilter; + + # set the default policy + my $config = new Vyatta::Config; + $config->setLevel("$level"); + my $policy = $config->returnOrigValue('default-action'); + $policy = 'drop' if !defined $policy; + $self->{_action} = $policy; + my $log = $config->existsOrig('enable-default-log'); + $log = 'enable' if defined $log; + $self->{_log} = $log; +} + +sub setup_base { + my ($self, $level, $val_func, $exists_func, $addr_setup) = @_; + my $config = new Vyatta::Config; + + $self->{_comment} = $level; + $config->setLevel("$level"); + + # for documentation sake. nodes returns an array so must transform + # and ".. .. .." means go up three levels in the current hierarchy + $self->{_name} = $config->returnParent(".. .. .."); + $self->{_rule_number} = $config->returnParent(".."); + + $self->{_protocol} = $config->$val_func("protocol"); + + $self->{_state}->{_established} = $config->$val_func("state established"); + $self->{_state}->{_new} = $config->$val_func("state new"); + $self->{_state}->{_related} = $config->$val_func("state related"); + $self->{_state}->{_invalid} = $config->$val_func("state invalid"); + + $self->{_action} = $config->$val_func("action"); + $self->{_log} = $config->$val_func("log"); + $self->{_tcp_flags} = $config->$val_func("tcp flags"); + $self->{_icmp_code} = $config->$val_func("icmp code"); + $self->{_icmp_type} = $config->$val_func("icmp type"); + $self->{_icmp_name} = $config->$val_func("icmp type-name"); + $self->{_icmpv6_type} = $config->$val_func("icmpv6 type"); + $self->{_mod_mark} = $config->$val_func("set mark"); + $self->{_mod_table} = $config->$val_func("set table"); + + if ($self->{_mod_table} eq 'main') { + $self->{_mod_table} = 254; + } + $self->{_mod_dscp} = $config->$val_func("set dscp"); + $self->{_mod_tcpmss} = $config->$val_func("set tcp-mss"); + $self->{_ipsec} = $config->$exists_func("ipsec match-ipsec"); + $self->{_non_ipsec} = $config->$exists_func("ipsec match-none"); + $self->{_frag} = $config->$exists_func("fragment match-frag"); + $self->{_non_frag} = $config->$exists_func("fragment match-non-frag"); + $self->{_recent_time} = $config->$val_func('recent time'); + $self->{_recent_cnt} = $config->$val_func('recent count'); + + $self->{_p2p}->{_all} = $config->$exists_func("p2p all"); + $self->{_p2p}->{_apple} = $config->$exists_func("p2p applejuice"); + $self->{_p2p}->{_bit} = $config->$exists_func("p2p bittorrent"); + $self->{_p2p}->{_dc} = $config->$exists_func("p2p directconnect"); + $self->{_p2p}->{_edk} = $config->$exists_func("p2p edonkey"); + $self->{_p2p}->{_gnu} = $config->$exists_func("p2p gnutella"); + $self->{_p2p}->{_kazaa} = $config->$exists_func("p2p kazaa"); + + $self->{_time}->{_startdate} = $config->$val_func("time startdate"); + $self->{_time}->{_stopdate} = $config->$val_func("time stopdate"); + $self->{_time}->{_starttime} = $config->$val_func("time starttime"); + $self->{_time}->{_stoptime} = $config->$val_func("time stoptime"); + $self->{_time}->{_monthdays} = $config->$val_func("time monthdays"); + $self->{_time}->{_weekdays} = $config->$val_func("time weekdays"); + $self->{_time}->{_utc} = $config->$exists_func("time utc"); + + $self->{_limit}->{_rate} = $config->$val_func("limit rate"); + $self->{_limit}->{_burst} = $config->$val_func("limit burst"); + + $self->{_disable} = $config->$exists_func("disable"); + + $self->{_hop_limit}->{_eq} = $config->$val_func("hop-limit eq"); + $self->{_hop_limit}->{_lt} = $config->$val_func("hop-limit lt"); + $self->{_hop_limit}->{_gt} = $config->$val_func("hop-limit gt"); + + # TODO: need $config->exists("$level source") in Vyatta::Config.pm + $src->$addr_setup("$level source"); + $dst->$addr_setup("$level destination"); + + # Default to IPv4 + $self->{_ip_version} = "ipv4"; + return 0; +} + +sub setup { + my ($self, $level) = @_; + + $self->setup_base($level, 'returnValue', 'exists', 'setup'); + return 0; +} + +sub setupOrig { + my ($self, $level) = @_; + + $self->setup_base($level, 'returnOrigValue', 'existsOrig', 'setupOrig'); + + $self->{_ip_version} = "ipv4"; + return 0; +} + +sub set_ip_version { + my ($self, $ip_version) = @_; + + $self->{_ip_version} = $ip_version; + $src->set_ip_version($ip_version); + $dst->set_ip_version($ip_version); +} + +sub print { + my ($self) = @_; + + print "name: $self->{_name}\n" if defined $self->{_name}; + print "rulenum: $self->{_rule_number}\n" if defined $self->{_rule_number}; + print "protocol: $self->{_protocol}\n" if defined $self->{_protocol}; + print "state: $self->{_state}\n" if defined $self->{_state}; + print "action: $self->{_action}\n" if defined $self->{_action}; + print "log: $self->{_log}\n" if defined $self->{_log}; + print "icmp code: $self->{_icmp_code}\n" if defined $self->{_icmp_code}; + print "icmp type: $self->{_icmp_type}\n" if defined $self->{_icmp_type}; + print "icmpv6 type: $self->{_icmpv6_type}\n" if defined $self->{_icmpv6_type}; + print "mod mark: $self->{_mod_mark}\n" if defined $self->{_mod_mark}; + print "mod table: $self->{_mod_table}\n" if defined $self->{_mod_table}; + print "mod dscp: $self->{_mod_dscp}\n" if defined $self->{_mod_dscp}; + print "mod tcp-mss: $self->{_mod_tcpmss}\n" if defined $self->{_mod_tcpmss}; + print "hop-limit: $self->{_hop_limit}\n" if defined $self->{_hop_limit}; + + $src->print(); + $dst->print(); + +} + +sub is_stateful { + my $self = shift; + return 0 if defined $self->{_disable}; + my @states = qw(established new related invalid); + foreach (@states) { + if ( defined($self->{_state}->{"_$_"}) + && $self->{_state}->{"_$_"} eq "enable") { + return 1; + } + } + return 0; +} + +sub is_disabled { + my $self = shift; + return 1 if defined $self->{_disable}; + return 0; +} + +sub is_route_table { + my $self = shift; + return $self->{_mod_table}; +} + +sub get_state_str { + my $self = shift; + my @states = qw(established new related invalid); + my @add_states = (); + foreach (@states) { + if ( defined($self->{_state}->{"_$_"}) + && $self->{_state}->{"_$_"} eq "enable") { + push @add_states, $_; + } + } + if ($#add_states >= 0) { + my $str = join ',', @add_states; + return $str; + } else { + return ""; + } +} + +sub get_log_prefix { + my ($chain, $rule_num, $action) = @_; + + # In iptables it allows a 29 character log_prefix, but we ideally + # want to include "[$chain-$rule_num-$action] " but that would require + # 1 29 1 4 1 1 11 = 39 + # so truncate the chain name so that it'll all fit. + my $action_char = uc(substr($action, 0, 1)); + if (length($chain) > 19) { + $chain = substr($chain, 0, 19); + printf STDERR "Firewall config warning: rule $rule_num logging prefix will be truncated to [$chain-$rule_num-$action_char]\n"; + } + my $log_prefix = "[$chain-$rule_num-$action_char] "; + return $log_prefix; +} + +sub get_num_ipt_rules { + my $self = shift; + my $ipt_rules = 1; + return 0 if defined $self->{_disable}; + my $protocol_tcpudp = 0; + if (defined $self->{_protocol} && $self->{_protocol} eq 'tcp_udp') { + $ipt_rules++; + $protocol_tcpudp = 1; + } + + if (( "$self->{_log}" eq "enable") + && ( ("$self->{_action}" eq "drop") + ||("$self->{_action}" eq "accept") + ||("$self->{_action}" eq "reject") + ||("$self->{_action}" eq "inspect") + ||("$self->{_action}" eq "modify"))){ + $ipt_rules += 1; + $ipt_rules++ if $protocol_tcpudp == 1; + } + if (defined($self->{_recent_time}) || defined($self->{_recent_cnt})) { + $ipt_rules += 1; + $ipt_rules++ if $protocol_tcpudp == 1; + } + return $ipt_rules; +} + +sub rule { + my ($self) = @_; + my ($rule, $srcrule, $dstrule, $err_str); + my $tcp_and_udp = 0; + + # set CLI rule num as comment + my @level_nodes = split(' ', $self->{_comment}); + $rule .= "-m comment --comment \"$level_nodes[2]-$level_nodes[4]\" "; + + # set the protocol + if (defined($self->{_protocol})) { + my $str = $self->{_protocol}; + my $negate = ''; + if ($str =~ /^\!(.*)$/) { + $str = $1; + $negate = '! '; + } + if ($str eq 'tcp_udp') { + $tcp_and_udp = 1; + $rule .= " $negate -p tcp "; # we'll add the '-p udp' to 2nd rule later + } else { + $rule .= " $negate -p $str "; + } + } + + my $state_str = uc(get_state_str($self)); + if ($state_str ne "") { + $rule .= "-m state --state $state_str "; + } + + # set tcp flags if applicable + my $tcp_flags = undef; + if (defined $self->{_tcp_flags}) { + if (($self->{_protocol} eq "tcp") || ($self->{_protocol} eq "6")) { + $tcp_flags = get_tcp_flags_string($self->{_tcp_flags}); + } else { + return ("TCP flags can only be set if protocol is set to TCP",); + } + } + if (defined($tcp_flags)) { + $rule .= " -m tcp --tcp-flags $tcp_flags "; + } + + # set the icmp code and type if applicable + if (($self->{_protocol} eq "icmp") || ($self->{_protocol} eq "1")) { + if (defined $self->{_icmp_name}) { + if (defined($self->{_icmp_type}) || defined($self->{_icmp_code})){ + return ("Cannot use ICMP type/code with ICMP type-name",); + } + $rule .= "--icmp-type $self->{_icmp_name} "; + } elsif (defined $self->{_icmp_type}) { + $rule .= "--icmp-type $self->{_icmp_type}"; + if (defined $self->{_icmp_code}) { + $rule .= "/$self->{_icmp_code}"; + } + $rule .= " "; + } elsif (defined $self->{_icmp_code}) { + return ("ICMP code can only be defined if ICMP type is defined",); + } + } elsif (defined($self->{_icmp_type}) + || defined($self->{_icmp_code}) + || defined($self->{_icmp_name})) + { + return ("ICMP type/code or type-name can only be defined if protocol is ICMP",); + } + + # Setup ICMPv6 rule if configured + # ICMPv6 parameters are only valid if the rule is matching on the + # ICMPv6 protocol ID. + # + if ( ($self->{_protocol} eq "icmpv6") + ||($self->{_protocol} eq "ipv6-icmp") + ||($self->{_protocol} eq "58")) { + if (defined($self->{_icmpv6_type})) { + $rule .= "-m icmpv6 --icmpv6-type $self->{_icmpv6_type}"; + } + } + + # Setup HL rule if configured + # + if ( defined($self->{_hop_limit}->{_eq}) ) { + $rule .= " -m hl --hl-eq $self->{_hop_limit}->{_eq}"; + } elsif ( defined($self->{_hop_limit}->{_lt}) ) { + $rule .= " -m hl --hl-lt $self->{_hop_limit}->{_lt}"; + } elsif ( defined($self->{_hop_limit}->{_gt}) ) { + $rule .= " -m hl --hl-gt $self->{_hop_limit}->{_gt}"; + } + + # add the source and destination rules + ($srcrule, $err_str) = $src->rule(); + return ($err_str,) if (!defined($srcrule)); + ($dstrule, $err_str) = $dst->rule(); + return ($err_str,) if (!defined($dstrule)); + + # make sure multiport is always behind single port option + if ((grep /multiport/, $srcrule)) { + $rule .= " $dstrule $srcrule "; + } elsif ((grep /multiport/, $dstrule)) { + $rule .= " $srcrule $dstrule "; + } else { + $rule .= " $srcrule $dstrule "; + } + + return ('Cannot specify both "match-frag" and "match-non-frag"',) + if (defined($self->{_frag}) && defined($self->{_non_frag})); + if (defined($self->{_frag})) { + $rule .= ' -f '; + } elsif (defined($self->{_non_frag})) { + $rule .= ' ! -f '; + } + + # note: "out" is not valid in the INPUT chain. + return ('Cannot specify both "match-ipsec" and "match-none"',) + if (defined($self->{_ipsec}) && defined($self->{_non_ipsec})); + if (defined($self->{_ipsec})) { + $rule .= ' -m policy --pol ipsec --dir in '; + } elsif (defined($self->{_non_ipsec})) { + $rule .= ' -m policy --pol none --dir in '; + } + + my $p2p = undef; + if (defined($self->{_p2p}->{_all})) { + $p2p = '--apple --bit --dc --edk --gnu --kazaa '; + } else { + my @apps = qw(apple bit dc edk gnu kazaa); + foreach (@apps) { + if (defined($self->{_p2p}->{"_$_"})) { + $p2p .= "--$_ "; + } + } + } + if (defined($p2p)) { + $rule .= " -m ipp2p $p2p "; + } + + my $time = undef; + if (defined($self->{_time}->{_utc})) { + $time .= " --utc "; + } + if (defined($self->{_time}->{_startdate})) { + my $check_date = validate_date($self->{_time}->{_startdate}, "startdate"); + if (!($check_date eq "")) { + return ($check_date,); + } + $time .= " --datestart $self->{_time}->{_startdate} "; + } + if (defined($self->{_time}->{_stopdate})) { + my $check_date = validate_date($self->{_time}->{_stopdate}, "stopdate"); + if (!($check_date eq "")) { + return ($check_date,); + } + $time .= " --datestop $self->{_time}->{_stopdate} "; + } + if (defined($self->{_time}->{_starttime})) { + return ("Invalid starttime $self->{_time}->{_starttime}. Time should use 24 hour notation hh:mm:ss and lie in between 00:00:00 and 23:59:59", ) + if (!validate_timevalues($self->{_time}->{_starttime}, "time")); + $time .= " --timestart $self->{_time}->{_starttime} "; + } + if (defined($self->{_time}->{_stoptime})) { + return ("Invalid stoptime $self->{_time}->{_stoptime}. Time should use 24 hour notation hh:mm:ss and lie in between 00:00:00 and 23:59:59", ) + if (!validate_timevalues($self->{_time}->{_stoptime}, "time")); + $time .= " --timestop $self->{_time}->{_stoptime} "; + } + if (defined($self->{_time}->{_monthdays})) { + my $negate = " "; + if ($self->{_time}->{_monthdays} =~ m/^!/) { + $negate = "! "; + $self->{_time}->{_monthdays} = substr $self->{_time}->{_monthdays}, 1; + } + return ("Invalid monthdays value $self->{_time}->{_monthdays}. Monthdays should have values between 1 and 31 with multiple days separated by commas eg. 2,12,21 For negation, add ! in front eg. !2,12,21", ) + if (!validate_timevalues($self->{_time}->{_monthdays}, "monthdays")); + $time .= " $negate --monthdays $self->{_time}->{_monthdays} "; + } + if (defined($self->{_time}->{_weekdays})) { + my $negate = " "; + if ($self->{_time}->{_weekdays} =~ m/^!/) { + $negate = "! "; + $self->{_time}->{_weekdays} = substr $self->{_time}->{_weekdays}, 1; + } + return ("Invalid weekdays value $self->{_time}->{_weekdays}. Weekdays should be specified using the first three characters of the day with the +first character capitalized eg. Mon,Thu,Sat For negation, add ! in front eg. !Mon,Thu,Sat", ) + if (!validate_timevalues($self->{_time}->{_weekdays}, "weekdays")); + $time .= " $negate --weekdays $self->{_time}->{_weekdays} "; + } + if (defined($time)) { + $rule .= " -m time $time "; + } + + my $limit = undef; + if (defined $self->{_limit}->{_rate}) { + my $rate_integer = $self->{_limit}->{_rate}; + $rate_integer =~ s/\/(second|minute|hour|day)//; + if ($rate_integer < 1) { + return ("integer value in rate cannot be less than 1",); + } + $limit = "--limit $self->{_limit}->{_rate} --limit-burst $self->{_limit}->{_burst}"; + } + $rule .= " -m limit $limit " if defined $limit; + + # recent match condition SHOULD BE DONE IN THE LAST so + # all options in $rule are copied to $recent_rule below + my $recent_rule = undef; + if (defined($self->{_recent_time}) || defined($self->{_recent_cnt})) { + my $recent_rule1 = undef; + my $recent_rule2 = undef; + $recent_rule1 .= ' -m recent --update '; + $recent_rule2 .= ' -m recent --set '; + if (defined($self->{_recent_time})) { + $recent_rule1 .= " --seconds $self->{_recent_time} "; + } + if (defined($self->{_recent_cnt})) { + $recent_rule1 .= " --hitcount $self->{_recent_cnt} "; + } + + $recent_rule1 .= " --name $self->{_name}-$self->{_rule_number} "; + $recent_rule2 .= " --name $self->{_name}-$self->{_rule_number} "; + + $recent_rule = $rule; + + if ($rule =~ m/\-m\s+set\s+\-\-match\-set/) { + + # firewall group being used in this rule. iptables complains if recent + # match condition is placed after group match conditions [see bug 5744] + # so instead of appending recent match place it before group match + my @split_rules = (); + + @split_rules = split(/(\-m\s+set\s+\-\-match\-set)/, $rule, 2); + $rule = $split_rules[0] . $recent_rule1 .$split_rules[1] . $split_rules[2]; + + @split_rules = split(/(\-m\s+set\s+\-\-match\-set)/, $recent_rule, 2); + $recent_rule = $split_rules[0] . $recent_rule2 .$split_rules[1] . $split_rules[2]; + } else { + + # append recent match conditions to the two rules needed for recent match + $rule .= $recent_rule1; + $recent_rule .= $recent_rule2; + } + } + + my $chain = $self->{_name}; + my $rule_num = $self->{_rule_number}; + my $rule2 = undef; + + # set the jump target. Depends on action and log + if ("$self->{_log}" eq "enable") { + $rule2 = $rule; + my $log_prefix = get_log_prefix($chain, $rule_num, $self->{_action}); + $rule2 .= "-j LOG --log-prefix \"$log_prefix\" "; + } + if ("$self->{_action}" eq "drop") { + $rule .= "-j DROP "; + } elsif ("$self->{_action}" eq "accept") { + $rule .= "-j RETURN "; + } elsif ("$self->{_action}" eq "reject") { + $rule .= "-j REJECT "; + } elsif ("$self->{_action}" eq 'inspect') { + my $target = ipt_get_queue_target('SNORT'); + return ('Undefined target for inspect',) if !defined $target; + $rule .= "-j $target "; + } elsif ($self->{_comment} =~ m/^policy/) { + + # mangle actions + my $count = 0; + if (defined($self->{_mod_mark})) { + # MARK + $rule .= "-j MARK --set-mark $self->{_mod_mark} "; + $count++; + } + if (defined($self->{_mod_table})) { + # Route table + $rule .= "-j VYATTA_PBR_$self->{_mod_table} "; + $count++; + } + if (defined($self->{_mod_dscp})) { + # DSCP + $rule .= "-j DSCP --set-dscp $self->{_mod_dscp} "; + $count++; + } + if (defined($self->{_mod_tcpmss})) { + # TCP-MSS + # check for SYN flag + if ( !defined $self->{_tcp_flags} + ||!(($self->{_tcp_flags} =~ m/SYN/) && !($self->{_tcp_flags} =~ m/!SYN/))) + { + return ('need to set TCP SYN flag to modify TCP MSS',); + } + + if ($self->{_mod_tcpmss} =~ m/\d/) { + $rule .= "-j TCPMSS --set-mss $self->{_mod_tcpmss} "; + } else { + $rule .= "-j TCPMSS --clamp-mss-to-pmtu "; + } + $count++; + } + + # others + if ($count == 0) { + return ('Policy route requires "action drop" or "set" parameters be defined.'); + } elsif ($count > 1) { + return ('Can not define more than one "set" parameter per policy route'); + } + } else { + return ("\"action\" must be defined in rule $rule_num",); + } + if (defined($rule2)) { + my $tmp = $rule2; + $rule2 = $rule; + $rule = $tmp; + } elsif (defined($recent_rule)) { + $rule2 = $recent_rule; + $recent_rule = undef; + } + + return (undef, undef) if defined $self->{_disable}; + + my ($udp_rule, $udp_rule2, $udp_recent_rule) = (undef, undef, undef); + if ($tcp_and_udp == 1) { + + # create udp rules + $udp_rule = $rule; + $udp_rule2 = $rule2 if defined $rule2; + $udp_recent_rule = $recent_rule if defined $recent_rule; + foreach my $each_udprule ($udp_rule, $udp_rule2, $udp_recent_rule) { + $each_udprule =~ s/ \-p tcp / -p udp / if defined $each_udprule; + } + } + + if ($DEBUG eq 'true') { + + # print all potential iptables rules that could be formed for + # a single CLI rule. see get_num_ipt_rules to see exact count + print "rule :\n$rule\n" if defined $rule; + print "rule2 :\n$rule2\n" if defined $rule2; + print "recent rule :\n$recent_rule\n" if defined $recent_rule; + print "udp rule :\n$udp_rule\n" if defined $udp_rule; + print "udp rule2 :\n$udp_rule2\n" if defined $udp_rule2; + print "udp recent rule :\n$udp_recent_rule\n" if defined $udp_recent_rule; + } + + return (undef, $rule, $rule2, $recent_rule, $udp_rule, $udp_rule2, $udp_recent_rule); +} + +sub outputXmlElem { + my ($name, $value, $fh) = @_; + print $fh " <$name>$value\n"; +} + +sub outputXml { + my ($self, $fh) = @_; + if (!defined($self->{_protocol})) { + $self->{_protocol} = "all"; + } + outputXmlElem("protocol", $self->{_protocol}, $fh); + my $state_str = get_state_str($self); + if ($state_str ne "") { + $state_str =~ s/,/%2C/g; + $state_str .= "+"; + } + outputXmlElem("state", $state_str, $fh); + outputXmlElem("action", uc($self->{_action}), $fh); + outputXmlElem("log", $self->{_log}, $fh); + outputXmlElem("icmp_type", $self->{_icmp_type}, $fh); + outputXmlElem("icmp_code", $self->{_icmp_code}, $fh); + + $src->outputXml("src", $fh); + $dst->outputXml("dst", $fh); +} + +sub validate_timevalues { + my ($string, $type) = @_; + use Switch; + use Time::Local; + switch ($type) { + case "date" { + $string =~ s/-//g; + my ($year, $month, $day) = unpack "A4 A2 A2", $string; + eval { + timelocal(0,0,0,$day, $month-1, $year); + 1; + } or return 0; + } + + case "time" { + $string =~ s/://g; + my ($hour, $min, $sec) = unpack "A2 A2 A2", $string; + eval { + timelocal($sec,$min,$hour, 1, 0, 1970); + 1; + } or return 0; + } + + case "monthdays" { + while($string =~ m/(\d+)/g) { + if ($1 < 1 || $1 > 31) { + return 0; + } + } + } + + case "weekdays" { + my @weekdays = ("Mon", "Tue", "Wed", "Thu", "Fri", "Sat", "Sun"); + while($string =~ m/(\w+)/g) { + if (!grep(/$1/,@weekdays)) { + return 0; + } + } + } + + else { + print"Invalid type '$type' passed to sub validate_timevalues()\n"; + return 0; + } + } + return 1; +} + +sub validate_date { + + my ($date, $string) = @_; + if ($date =~ m/T/) { + my $actualdate = substr $date, 0, 10; + my $datetime = substr $date, 11; + return ("Invalid $string $actualdate. Date should use yyyy-mm-dd format and lie in between 1970-01-01 and 2038-01-19") + if (!validate_timevalues($actualdate, "date")); + return ("Invalid time $datetime for $string $actualdate. Time should use 24 hour notation hh:mm:ss and lie in between 00:00:00 and 23:59:59") + if (!validate_timevalues($datetime, "time")); + } else { + return ("Invalid $string $date. Date should use yyyy-mm-dd format and lie in between 1970-01-01 and 2038-01-19") + if (!validate_timevalues($date, "date")); + } + return (""); +} + +sub get_tcp_flags_string { + + my $string = shift; + my @list_of_flags = (); # list of tcp flags to be examined + my @list_of_set_flags = (); # list of flags which must be set + + my @string_list = split(/,/, $string); + while(@string_list) { + if (!grep(/!/,$string_list[0])) { + push @list_of_flags, $string_list[0]; + push @list_of_set_flags, $string_list[0]; + } else { + $string_list[0] =~ s/!//g; + push @list_of_flags, $string_list[0]; + } + shift(@string_list); + } + + push @list_of_set_flags, 'NONE' if @list_of_set_flags == (); + return join(",",@list_of_flags) . " " . join(",",@list_of_set_flags); +} + +1; diff --git a/scripts/vyatta-conntrack-ignore.pl b/scripts/vyatta-conntrack-ignore.pl index 7d07604..a103173 100644 --- a/scripts/vyatta-conntrack-ignore.pl +++ b/scripts/vyatta-conntrack-ignore.pl @@ -10,12 +10,11 @@ use Vyatta::Conntrack::RuleIgnore; use Vyatta::IpTables::AddressFilter; use Vyatta::Conntrack::ConntrackUtil; use Getopt::Long; -use Vyatta::Zone; use Sys::Syslog qw(:standard :macros); #for future use when v6 ignore s need to be set -my %cmd_hash = ( 'ipv4' => 'iptables', - 'ipv6' => 'ip6tables'); +my %cmd_hash = ( 'ipv4' => 'iptables-nft', + 'ipv6' => 'ip6tables-nft'); # Enable printing debug output to stdout. my $debug_flag = 0; @@ -35,8 +34,8 @@ openlog("vyatta-conntrack", "pid", "local0"); sub remove_ignore_policy { my ($rule_string) = @_; - my $iptables_cmd1 = "iptables -D VYATTA_CT_IGNORE -t raw $rule_string -j CT --notrack"; - my $iptables_cmd2 = "iptables -D VYATTA_CT_IGNORE -t raw $rule_string -j RETURN"; + my $iptables_cmd1 = "iptables-nft -D VYOS_CT_IGNORE -t raw $rule_string -j CT --notrack"; + my $iptables_cmd2 = "iptables-nft -D VYOS_CT_IGNORE -t raw $rule_string -j RETURN"; run_cmd($iptables_cmd2); if ($? >> 8) { print "$CTERROR failed to run $iptables_cmd2\n"; @@ -51,9 +50,9 @@ sub remove_ignore_policy { sub apply_ignore_policy { my ($rule_string, $rule, $num_rules) = @_; # insert at num_rules + 1 as there are so many rules already. - my $iptables_cmd1 = "iptables -I VYATTA_CT_IGNORE $num_rules -t raw $rule_string -j CT --notrack"; + my $iptables_cmd1 = "iptables-nft -I VYOS_CT_IGNORE $num_rules -t raw $rule_string -j CT --notrack"; $num_rules +=1; - my $iptables_cmd2 = "iptables -I VYATTA_CT_IGNORE $num_rules -t raw $rule_string -j RETURN"; + my $iptables_cmd2 = "iptables-nft -I VYOS_CT_IGNORE $num_rules -t raw $rule_string -j RETURN"; run_cmd($iptables_cmd1); if ($? >> 8) { print "$CTERROR failed to run $iptables_cmd1\n"; diff --git a/scripts/vyatta-conntrack-timeouts.pl b/scripts/vyatta-conntrack-timeouts.pl index 557f4eb..7394945 100644 --- a/scripts/vyatta-conntrack-timeouts.pl +++ b/scripts/vyatta-conntrack-timeouts.pl @@ -13,8 +13,8 @@ use Vyatta::Zone; use Sys::Syslog qw(:standard :macros); #for future use when v6 timeouts need to be set -my %cmd_hash = ( 'ipv4' => 'iptables', - 'ipv6' => 'ip6tables'); +my %cmd_hash = ( 'ipv4' => 'iptables-nft', + 'ipv6' => 'ip6tables-nft'); # Enable printing debug output to stdout. my $debug_flag = 0; @@ -36,8 +36,8 @@ sub remove_timeout_policy { my ($rule_string, $timeout_policy) = @_; my @tokens = split (' ', $timeout_policy); # First remove the iptables rules before removing policy. - my $iptables_cmd1 = "iptables -D VYATTA_CT_TIMEOUT -t raw $rule_string -j CT --timeout $tokens[0]"; - my $iptables_cmd2 = "iptables -D VYATTA_CT_TIMEOUT -t raw $rule_string -j RETURN"; + my $iptables_cmd1 = "iptables-nft -D VYOS_CT_TIMEOUT -t raw $rule_string -j CT --timeout $tokens[0]"; + my $iptables_cmd2 = "iptables-nft -D VYOS_CT_TIMEOUT -t raw $rule_string -j RETURN"; my $nfct_timeout_cmd = "$nfct timeout delete $timeout_policy"; run_cmd($iptables_cmd2); if ($? >> 8) { @@ -66,9 +66,9 @@ sub apply_timeout_policy { my $nfct_timeout_cmd = "$nfct timeout add $timeout_policy"; my @tokens = split (' ', $timeout_policy); # insert at num_rules + 1 as there are so many rules already. - my $iptables_cmd1 = "iptables -I VYATTA_CT_TIMEOUT $num_rules -t raw $rule_string -j CT --timeout $tokens[0]"; + my $iptables_cmd1 = "iptables-nft -I VYATTA_CT_TIMEOUT $num_rules -t raw $rule_string -j CT --timeout $tokens[0]"; $num_rules +=1; - my $iptables_cmd2 = "iptables -I VYATTA_CT_TIMEOUT $num_rules -t raw $rule_string -j RETURN"; + my $iptables_cmd2 = "iptables-nft -I VYATTA_CT_TIMEOUT $num_rules -t raw $rule_string -j RETURN"; run_cmd($nfct_timeout_cmd); if ($? >> 8) { print "$CTERROR failed to run $nfct_timeout_cmd\n"; @@ -84,7 +84,7 @@ sub apply_timeout_policy { run_cmd($iptables_cmd2); if ($? >> 8) { run_cmd("nfct timeout delete policy_timeout_$rule"); - run_cmd("iptables -D PREROUTING -t raw $rule_string -j CT --timeout $tokens[0]"); + run_cmd("iptables-nft -D PREROUTING -t raw $rule_string -j CT --timeout $tokens[0]"); print "$CTERROR failed to run $iptables_cmd2\n"; exit 1; } diff --git a/scripts/vyatta-show-ignore.pl b/scripts/vyatta-show-ignore.pl index 40efa8f..e650bf1 100644 --- a/scripts/vyatta-show-ignore.pl +++ b/scripts/vyatta-show-ignore.pl @@ -43,7 +43,7 @@ sub print_ignore_rules { $config->setLevel("system conntrack ignore rule"); my @rules = sort numerically $config->listOrigNodes(); - my @rules_in_chain = `sudo iptables -L VYATTA_CT_IGNORE -t raw -nv`; + my @rules_in_chain = `sudo iptables-nft -L VYOS_CT_IGNORE -t raw -nv`; if (!(@rules_in_chain)){ die "Error: no ignore rules configured\n"; } -- cgit v1.2.3