diff options
-rw-r--r-- | Makefile.am | 1 | ||||
-rw-r--r-- | lib/Vyatta/IpTables/Mgr.pm | 101 | ||||
-rw-r--r-- | scripts/firewall/firewall.init.in | 16 | ||||
-rwxr-xr-x | scripts/firewall/vyatta-firewall.pl | 24 |
4 files changed, 122 insertions, 20 deletions
diff --git a/Makefile.am b/Makefile.am index 41aef8a..781965f 100644 --- a/Makefile.am +++ b/Makefile.am @@ -15,6 +15,7 @@ sbin_SCRIPTS += scripts/firewall/vyatta-ipset.pl share_perl5_DATA = lib/Vyatta/IpTables/Rule.pm share_perl5_DATA += lib/Vyatta/IpTables/AddressFilter.pm share_perl5_DATA += lib/Vyatta/IpTables/IpSet.pm +share_perl5_DATA += lib/Vyatta/IpTables/Mgr.pm cpiop = find . ! -regex '\(.*~\|.*\.bak\|.*\.swp\|.*\#.*\#\)' -print0 | \ cpio -0pdu diff --git a/lib/Vyatta/IpTables/Mgr.pm b/lib/Vyatta/IpTables/Mgr.pm new file mode 100644 index 0000000..5381d34 --- /dev/null +++ b/lib/Vyatta/IpTables/Mgr.pm @@ -0,0 +1,101 @@ +#!/usr/bin/perl +# +# Module: Vyatta::IpTables::Mgr.pm +# +# **** License **** +# This program is free software; you can redistribute it and/or modify +# it under the terms of the GNU General Public License version 2 as +# published by the Free Software Foundation. +# +# This program is distributed in the hope that it will be useful, but +# WITHOUT ANY WARRANTY; without even the implied warranty of +# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU +# General Public License for more details. +# +# This code was originally developed by Vyatta, Inc. +# Portions created by Vyatta are Copyright (C) 2010 Vyatta, Inc. +# All Rights Reserved. +# +# Author: Stig Thormodsrud +# Date: June 2010 +# Description: common iptables routines +# +# **** End License **** +# + +package Vyatta::IpTables::Mgr; + +use strict; +use warnings; + +use base 'Exporter'; +our @EXPORT = qw(ipt_find_chain_rule ipt_enable_conntrack + ipt_disable_conntrack); + + +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 = `$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; +} + +my %conntrack_hook_hash = + ('PREROUTING' => 'VYATTA_PRE_CT_PREROUTING_HOOK', + 'OUTPUT' => 'VYATTA_PRE_CT_OUTPUT_HOOK', + ); + +sub ipt_enable_conntrack { + my ($iptables_cmd, $chain) = @_; + + system("$iptables_cmd -t raw -L $chain -n >& /dev/null"); + + if ($? >> 8) { + # chain does not exist yet. set up conntrack. + system("$iptables_cmd -t raw -N $chain"); + system("$iptables_cmd -t raw -A $chain -j ACCEPT"); + + foreach my $label ('PREROUTING', 'OUTPUT') { + my $index; + my $conntrack_hook = $conntrack_hook_hash{$label}; + $index = ipt_find_chain_rule($iptables_cmd, 'raw', + $label, $conntrack_hook); + if (! defined($index)) { + print "Error: unable to find [$label] [$conntrack_hook]\n"; + return 1; + } + $index++; + system("$iptables_cmd -t raw -I $label $index -j $chain"); + } + } +} + +sub ipt_disable_conntrack { + my ($iptables_cmd, $chain) = @_; + + my @lines; + foreach my $label ('PREROUTING', 'OUTPUT') { + my $index; + my $conntrack_hook = $conntrack_hook_hash{$label}; + $index = ipt_find_chain_rule($iptables_cmd, 'raw', + $label, $conntrack_hook); + system("$iptables_cmd -t raw -D $label $index"); + } + + system("$iptables_cmd -t raw -F $chain >& /dev/null"); + system("$iptables_cmd -t raw -X $chain >& /dev/null"); +} + +1; diff --git a/scripts/firewall/firewall.init.in b/scripts/firewall/firewall.init.in index 22f48fd..040078b 100644 --- a/scripts/firewall/firewall.init.in +++ b/scripts/firewall/firewall.init.in @@ -51,13 +51,25 @@ start () { # set up notrack chains/rules for IPv4 # by default, nothing is tracked. + iptables -t raw -N VYATTA_PRE_CT_PREROUTING_HOOK + iptables -t raw -A VYATTA_PRE_CT_PREROUTING_HOOK -j RETURN + iptables -t raw -A PREROUTING -j VYATTA_PRE_CT_PREROUTING_HOOK iptables -t raw -A PREROUTING -j NOTRACK + iptables -t raw -N VYATTA_PRE_CT_OUTPUT_HOOK + iptables -t raw -A VYATTA_PRE_CT_OUTPUT_HOOK -j RETURN + iptables -t raw -A OUTPUT -j VYATTA_PRE_CT_OUTPUT_HOOK iptables -t raw -A OUTPUT -j NOTRACK if [ -d /proc/sys/net/ipv6 ] ; then # set up notrack chains/rules for IPv6 - ip6tables -t raw -A PREROUTING -j NOTRACK - ip6tables -t raw -A OUTPUT -j NOTRACK + ip6tables -t raw -N VYATTA_PRE_CT_PREROUTING_HOOK + ip6tables -t raw -A VYATTA_PRE_CT_PREROUTING_HOOK -j RETURN + ip6tables -t raw -A PREROUTING -j VYATTA_PRE_CT_PREROUTING_HOOK + ip6tables -t raw -A PREROUTING -j NOTRACK + ip6tables -t raw -N VYATTA_PRE_CT_OUTPUT_HOOK + ip6tables -t raw -A VYATTA_PRE_CT_OUTPUT_HOOK -j RETURN + ip6tables -t raw -A OUTPUT -j VYATTA_PRE_CT_OUTPUT_HOOK + ip6tables -t raw -A OUTPUT -j NOTRACK # set up post-firewall hook for IPv6 ip6tables -N VYATTA_POST_FW_HOOK diff --git a/scripts/firewall/vyatta-firewall.pl b/scripts/firewall/vyatta-firewall.pl index 1961541..925162c 100755 --- a/scripts/firewall/vyatta-firewall.pl +++ b/scripts/firewall/vyatta-firewall.pl @@ -7,9 +7,11 @@ use strict; use Vyatta::Config; use Vyatta::IpTables::Rule; use Vyatta::IpTables::AddressFilter; +use Vyatta::IpTables::Mgr; use Getopt::Long; use Vyatta::Zone; + # Send output of shell commands to syslog for debugging and so that # the user is not confused by it. Log at debug level, which is supressed # by default, so that we don't unnecessarily fill up the syslog file. @@ -178,15 +180,7 @@ if (defined $teardown) { teardown_iptables($table, $iptables_cmd); # remove the conntrack setup. - my $num; - foreach my $label ('PREROUTING', 'OUTPUT') { - $num = find_chain_rule($iptables_cmd, 'raw', $label, 'FW_CONNTRACK'); - if (defined $num and ! is_tree_in_use($other_tree{$teardown})) { - run_cmd("$iptables_cmd -t raw -D $label $num", 1, 1); - } - } - run_cmd("$iptables_cmd -t raw -F FW_CONNTRACK", 1, 1); - run_cmd("$iptables_cmd -t raw -X FW_CONNTRACK", 1, 1); + ipt_disable_conntrack($iptables_cmd, 'FW_CONNTRACK'); exit 0; } @@ -691,15 +685,9 @@ sub setup_iptables { } # by default, nothing is tracked (the last rule in raw/PREROUTING). - my $cnt = count_iptables_rules('raw', 'FW_CONNTRACK', $iptables_cmd); - if ($cnt == 0) { - run_cmd("$iptables_cmd -t raw -N FW_CONNTRACK", 1 , 1); - run_cmd("$iptables_cmd -t raw -A FW_CONNTRACK -j RETURN", 1, 1); - run_cmd("$iptables_cmd -t raw -I PREROUTING 1 -j FW_CONNTRACK", 1, 1); - run_cmd("$iptables_cmd -t raw -I OUTPUT 1 -j FW_CONNTRACK", 1, 1); - } else { - log_msg "FW_CONNTRACK exists $cnt\n"; - } + ipt_enable_conntrack($iptables_cmd, 'FW_CONNTRACK'); + disable_fw_conntrack($iptables_cmd); + return 0; } |