From aff6ce143e177645829b4cbe76839e90c515258d Mon Sep 17 00:00:00 2001 From: Alex Harpin Date: Sat, 12 Dec 2015 14:53:20 +0000 Subject: vyatta-cfg-firewall: formatting changes for style consistency Update lib/Vyatta/Iptables/AddressFilter.pm, IpSet.pm, Mgr.pm and Rule.pm to maintain style and consistency. --- lib/Vyatta/IpTables/AddressFilter.pm | 448 ++++++----- lib/Vyatta/IpTables/IpSet.pm | 412 +++++----- lib/Vyatta/IpTables/Mgr.pm | 377 +++++---- lib/Vyatta/IpTables/Rule.pm | 1404 +++++++++++++++++----------------- 4 files changed, 1314 insertions(+), 1327 deletions(-) diff --git a/lib/Vyatta/IpTables/AddressFilter.pm b/lib/Vyatta/IpTables/AddressFilter.pm index 8916712..9100c24 100755 --- a/lib/Vyatta/IpTables/AddressFilter.pm +++ b/lib/Vyatta/IpTables/AddressFilter.pm @@ -6,12 +6,12 @@ # 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. @@ -28,276 +28,268 @@ 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, + 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, + _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; + my $that = shift; + my $class = ref($that) || $that; + my $self = {%fields,}; + + bless $self, $class; + return $self; } sub set_ip_version { - my ($self, $ip_version) = @_; + my ($self, $ip_version) = @_; - $self->{_ip_version} = $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; + 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"); + $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; + return 0; } sub setup { - my ($self, $level) = @_; + my ($self, $level) = @_; - $self->setup_base($level, 'returnValue'); - return 0; + $self->setup_base($level, 'returnValue'); + return 0; } sub setupOrig { - my ($self, $level) = @_; + my ($self, $level) = @_; - $self->setup_base($level, 'returnOrigValue'); - return 0; + $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; + 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 = '! '; + 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}"); } - $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 = '! '; + + if ( !defined($self->{_protocol}) + || !defined($_protocolswithports{$self->{_protocol}})) + { + $can_use_port = 0; } - $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") && (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 "; } - if ("$self->{_srcdst}" eq "source") { - $rule .= ("-m iprange $negate --src-range $start-$self->{_range_stop} "); + + my %group_ok; + foreach my $group_type ('address', 'network', 'port') { + $group_ok{$group_type} = 1; } - elsif ("$self->{_srcdst}" eq "destination") { - $rule .= ("-m iprange $negate --dst-range $start-$self->{_range_stop} "); + + # 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{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 - if ($self->{_ip_version} eq "ipv4") { - # so far ipset only supports IPv4 - 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"); + + $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 + if ($self->{_ip_version} eq "ipv4") { + + # so far ipset only supports IPv4 + 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"); } - 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); + return ($rule, undef); } sub outputXmlElem { - my ($name, $value, $fh) = @_; - return if ! defined $value; - print $fh " <$name>$value\n"; + 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); + 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; - -# Local Variables: -# mode: perl -# indent-tabs-mode: nil -# perl-indent-level: 2 -# End: diff --git a/lib/Vyatta/IpTables/IpSet.pm b/lib/Vyatta/IpTables/IpSet.pm index 5222edc..37bbb37 100755 --- a/lib/Vyatta/IpTables/IpSet.pm +++ b/lib/Vyatta/IpTables/IpSet.pm @@ -1,24 +1,24 @@ # # 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 **** # @@ -48,7 +48,7 @@ our %grouptype_hash = ( my $logger = 'logger -t IpSet.pm -p local0.warn --'; -# Currently we restrict an address range to a /24 even +# 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. @@ -67,17 +67,15 @@ $SIG{'INT'} = 'INT_handler'; sub new { my ($that, $name, $type) = @_; - my $class = ref ($that) || $that; - my $self = { - %fields, - }; + my $class = ref($that) || $that; + my $self = {%fields,}; if ($name =~ m/^!/) { - $self->{_negate} = 1; - $name =~ s/^!(.*)$/$1/; + $self->{_negate} = 1; + $name =~ s/^!(.*)$/$1/; } $self->{_name} = $name; $self->{_type} = $type; - + bless $self, $class; return $self; } @@ -94,8 +92,8 @@ sub run_cmd { my $rc = system("sudo $cmd"); if (defined $self->{_debug}) { - my $func = (caller(1))[3]; - system("$logger [$func] [$cmd] = [$rc]"); + my $func = (caller(1))[3]; + system("$logger [$func] [$cmd] = [$rc]"); } return $rc; } @@ -104,12 +102,12 @@ sub exists { my ($self) = @_; return 1 if defined $self->{_exists}; - return 0 if ! defined $self->{_name}; + 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}; + $self->{_exists} = 1; + $self->get_type() if !defined $self->{_type}; } return $rc ? 0 : 1; } @@ -118,21 +116,21 @@ sub get_type { my ($self) = @_; return $self->{_type} if defined $self->{_type}; - return if ! $self->exists(); + return if !$self->exists(); my @lines = `ipset -L $self->{_name}`; my $type; foreach my $line (@lines) { - if ($line =~ /^Type:\s+([\w:]+)$/) { - $type = $1; - last; - } + if ($line =~ /^Type:\s+([\w:]+)$/) { + $type = $1; + last; + } } - return if ! defined $type; + return if !defined $type; foreach my $vtype (keys(%grouptype_hash)) { - if ($grouptype_hash{$vtype} eq $type) { - $self->{_type} = $vtype; - last; - } + if ($grouptype_hash{$vtype} eq $type) { + $self->{_type} = $vtype; + last; + } } return $self->{_type}; } @@ -147,54 +145,54 @@ 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; - } + 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(); + return @members if !$self->exists(); my @lines = `ipset -L $self->{_name} -s`; foreach my $line (@lines) { - push @members, $line if $line =~ /^\d/; + push @members, $line if $line =~ /^\d/; } if ($self->{_type} ne 'port') { - @members = sort { natural_order($a,$b) } @members; + @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 "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; + return "Error: invalid group type\n" if !defined $ipset_param; if ($self->{_type} eq 'port') { - $ipset_param .= ' --from 1 --to 65535'; - } + $ipset_param .= ' --from 1 --to 65535'; + } - my $cmd = "ipset -N $self->{_name} $ipset_param"; + my $cmd = "ipset -N $self->{_name} $ipset_param"; my $rc = $self->run_cmd($cmd); return "Error: call to ipset failed [$rc]" if $rc; return; # undef @@ -203,45 +201,47 @@ sub create { sub references { my ($self) = @_; - return 0 if ! $self->exists(); + return 0 if !$self->exists(); my @lines = `ipset -L $self->{_name}`; foreach my $line (@lines) { - if ($line =~ /^References:\s+(\d+)$/) { - return $1; - } + 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; + 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); - } + 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(); + 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 { @@ -249,57 +249,61 @@ sub reset_ipset_all { 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; + my $group; foreach $group (@pgroups) { - my $grp = new Vyatta::IpTables::IpSet($group, "port"); - $grp->reset_ipset_named(); + 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(); + 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(); + 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 + + # 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: 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(); + + # 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}"; @@ -312,10 +316,10 @@ sub check_member_address { my $member = shift; if (!Vyatta::TypeChecker::validateType('ipv4', $member, 1)) { - return "Error: [$member] isn't valid IPv4 address\n"; + 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 "Error: zero IP address not valid in address-group\n"; } return; } @@ -323,8 +327,8 @@ sub check_member_address { sub check_member { my ($self, $member) = @_; - return "Error: undefined group name" if ! defined $self->{_name}; - return "Error: undefined group type" if ! defined $self->{_type}; + 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 @@ -332,72 +336,72 @@ sub check_member { # 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; - } + 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: zero net invalid in network-group\n" - if $net eq '0.0.0.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"; - } + 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: zero net invalid in network-group\n" + if $net eq '0.0.0.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; + 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 "Error: invalid set type [$self->{_type}]"; } - return; #undef + return; #undef } sub member_exists { my ($self, $member) = @_; - + my $cmd = "ipset -T $self->{_name} $member -q"; my $rc = $self->run_cmd($cmd); - return $rc ? 0 : 1; + return $rc ? 0 : 1; } sub add_member { my ($self, $member, $alias, $hyphenated_port) = @_; - return "Error: undefined group name" if ! defined $self->{_name}; + 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"; + $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); @@ -406,21 +410,21 @@ sub add_member { } sub delete_member_range { - my ($self, $start, $stop) = @_; - + 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; - } + 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; + 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; } @@ -428,17 +432,17 @@ sub delete_member_range { sub delete_member { my ($self, $member, $hyphenated_port) = @_; - return "Error: undefined group name" if ! defined $self->{_name}; + 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); + return $self->delete_member_range($1, $2); } if (!$self->member_exists($member)) { - return "Error: member [$member] doesn't exists in [$self->{_name}]\n"; + return "Error: member [$member] doesn't exists in [$self->{_name}]\n"; } my $cmd = "ipset -D $self->{_name} $member"; my $rc = $self->run_cmd($cmd); @@ -449,10 +453,10 @@ sub delete_member { sub get_description { my ($self) = @_; - return if ! $self->exists(); + return if !$self->exists(); my $config = new Vyatta::Config; my $group_type = "$self->{_type}-group"; - $config->setLevel("firewall group $group_type $self->{_name}"); + $config->setLevel("firewall group $group_type $self->{_name}"); return $config->returnOrigValue('description'); } @@ -463,29 +467,29 @@ sub get_firewall_references { ($lfunc, $vfunc) = qw(listNodes returnValue); } my @fw_refs = (); - return @fw_refs if ! $self->exists(); + return @fw_refs if !$self->exists(); my $config = new Vyatta::Config; foreach my $tree ('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 + 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; } @@ -493,10 +497,10 @@ sub get_firewall_references { sub rule { my ($self, $direction) = @_; - if (! $self->exists()) { - my $name = $self->{_name}; - $name = 'undefined' if ! defined $name; - return (undef, "Undefined group [$name]"); + if (!$self->exists()) { + my $name = $self->{_name}; + $name = 'undefined' if !defined $name; + return (undef, "Undefined group [$name]"); } my $srcdst; @@ -504,10 +508,10 @@ sub rule { $srcdst = 'src' if $direction eq 'source'; $srcdst = 'dst' if $direction eq 'destination'; - return (undef, "Invalid direction [$direction]") if ! defined $srcdst; + return (undef, "Invalid direction [$direction]") if !defined $srcdst; my $opt = ''; $opt = '!' if $self->{_negate}; - return (" -m set $opt --match-set $grp $srcdst ", ); + return (" -m set $opt --match-set $grp $srcdst ",); } 1; diff --git a/lib/Vyatta/IpTables/Mgr.pm b/lib/Vyatta/IpTables/Mgr.pm index 6723bc3..39a03f1 100755 --- a/lib/Vyatta/IpTables/Mgr.pm +++ b/lib/Vyatta/IpTables/Mgr.pm @@ -1,24 +1,24 @@ # # 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 **** # @@ -29,251 +29,248 @@ 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); + 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; + 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); + 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; + $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; + return; } sub flush_ipt_chain { - my ($ipt_cmd, $table, $chain) = @_; - my ($cmd, $error); + 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; + $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; + return; } sub delete_ipt_chain { - my ($ipt_cmd, $table, $chain) = @_; - my ($cmd, $error); + 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; + $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; + return; } sub insert_ipt_rule { - my ($ipt_cmd, $table, $chain, $jump_target, $insert_num, $append_options) = @_; - my ($cmd, $error); + 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; + $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; + return; } sub append_ipt_rule { - my ($ipt_cmd, $table, $chain, $jump_target, $append_options) = @_; - my ($cmd, $error); + 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; + $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; + 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); + 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; + $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; + return; } # delete rule based on rule number sub delete_ipt_rulenum { - my ($ipt_cmd, $table, $chain, $delete_num) = @_; - my ($cmd, $error); + 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; + $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; + 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) { + 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; - } - 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 ($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; + 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); } - ($rule_txt, $comment) = (undef, undef); - } - return; + return; } -my %conntrack_hook_hash = - ('PREROUTING' => 'VYATTA_CT_PREROUTING_HOOK', +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'; + $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"); - + + # 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)) { + $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"); + + # 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; +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; + } } - } 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 { @@ -284,34 +281,32 @@ sub ipt_disable_conntrack { 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)) { + $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"; + 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', +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; } @@ -323,24 +318,24 @@ sub count_iptables_rules { my @lines = `sudo $cmd 2> /dev/null`; my $cnt = 0; foreach my $line (@lines) { - $cnt++ if $line =~ /^\d/; + $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; + 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; + return $found; } 1; diff --git a/lib/Vyatta/IpTables/Rule.pm b/lib/Vyatta/IpTables/Rule.pm index 3c266f6..08772a1 100755 --- a/lib/Vyatta/IpTables/Rule.pm +++ b/lib/Vyatta/IpTables/Rule.pm @@ -9,786 +9,782 @@ 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 + _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 ); 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 + _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 ); my $DEBUG = 'false'; sub new { - my $that = shift; - my $class = ref ($that) || $that; - my $self = { - %fields, - }; - - bless $self, $class; - return $self; + 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; + 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"); - - # 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; + 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"); + + # 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) = @_; + my ($self, $level) = @_; - $self->setup_base($level, 'returnValue', 'exists', 'setup'); - return 0; + $self->setup_base($level, 'returnValue', 'exists', 'setup'); + return 0; } sub setupOrig { - my ($self, $level) = @_; + my ($self, $level) = @_; - $self->setup_base($level, 'returnOrigValue', 'existsOrig', 'setupOrig'); + $self->setup_base($level, 'returnOrigValue', 'existsOrig', 'setupOrig'); - $self->{_ip_version} = "ipv4"; - return 0; + $self->{_ip_version} = "ipv4"; + return 0; } sub set_ip_version { - my ($self, $ip_version) = @_; + my ($self, $ip_version) = @_; - $self->{_ip_version} = $ip_version; - $src->set_ip_version($ip_version); - $dst->set_ip_version($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}; - - $src->print(); - $dst->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}; + + $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; + 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; + my $self = shift; + return 1 if defined $self->{_disable}; + return 0; } sub is_route_table { - my $self = shift; - return $self->{_mod_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 ""; - } + 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; + 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; + 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 + 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}"; + } + } + + # 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 .= " $negate -p $str "; + $rule .= " $srcrule $dstrule "; } - } - my $state_str = uc (get_state_str($self)); - if ($state_str ne "") { - $rule .= "-m state --state $state_str "; - } + 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 '; + } - # 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}); + # 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 { - 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}"; - } - } - - # 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 + 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_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]; + 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_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 { - # 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); + 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"; + 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); + 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; + 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 (""); + 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); + 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; - -# Local Variables: -# mode: perl -# indent-tabs-mode: nil -# perl-indent-level: 2 -# End: -- cgit v1.2.3