diff options
Diffstat (limited to 'lib/Vyatta/IpTables/Mgr.pm')
-rwxr-xr-x | lib/Vyatta/IpTables/Mgr.pm | 377 |
1 files changed, 186 insertions, 191 deletions
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; |