summaryrefslogtreecommitdiff
path: root/scripts
diff options
context:
space:
mode:
authorMohit Mehta <mohit@vyatta.com>2011-12-01 05:33:44 -0800
committerMohit Mehta <mohit@vyatta.com>2011-12-01 05:33:44 -0800
commit25364db4c400b2a05bbfca65e98f8b27271f962f (patch)
tree7408500e09cbc06d7909ae301611f4e198a8e05a /scripts
parentd5d88ed8f5323361f938a8f0b7454a8c73dd6c12 (diff)
downloadvyatta-cfg-firewall-25364db4c400b2a05bbfca65e98f8b27271f962f.tar.gz
vyatta-cfg-firewall-25364db4c400b2a05bbfca65e98f8b27271f962f.zip
Bug 6063 ENH: Provide option(s) to globally allow stateful return traffic
* add code to set global policy for established, related, invalid states
Diffstat (limited to 'scripts')
-rw-r--r--scripts/firewall/firewall.init.in45
-rwxr-xr-xscripts/firewall/vyatta-firewall.pl8
-rwxr-xr-xscripts/firewall/vyatta-fw-global-state-policy.pl304
3 files changed, 343 insertions, 14 deletions
diff --git a/scripts/firewall/firewall.init.in b/scripts/firewall/firewall.init.in
index 403dfc8..07c32f8 100644
--- a/scripts/firewall/firewall.init.in
+++ b/scripts/firewall/firewall.init.in
@@ -60,6 +60,29 @@ start () {
iptables -t raw -A OUTPUT -j VYATTA_CT_OUTPUT_HOOK
iptables -t raw -A OUTPUT -j NOTRACK
+ # set up pre-firewall hooks for IPv4
+ iptables -N VYATTA_PRE_FW_IN_HOOK
+ iptables -N VYATTA_PRE_FW_FWD_HOOK
+ iptables -N VYATTA_PRE_FW_OUT_HOOK
+ iptables -A VYATTA_PRE_FW_IN_HOOK -j RETURN
+ iptables -A VYATTA_PRE_FW_FWD_HOOK -j RETURN
+ iptables -A VYATTA_PRE_FW_OUT_HOOK -j RETURN
+ iptables -I INPUT -j VYATTA_PRE_FW_IN_HOOK
+ iptables -I FORWARD -j VYATTA_PRE_FW_FWD_HOOK
+ iptables -I OUTPUT -j VYATTA_PRE_FW_OUT_HOOK
+
+ # set up post-firewall hooks for IPv4
+ iptables -N VYATTA_POST_FW_IN_HOOK
+ iptables -N VYATTA_POST_FW_FWD_HOOK
+ iptables -N VYATTA_POST_FW_OUT_HOOK
+ iptables -A VYATTA_POST_FW_IN_HOOK -j ACCEPT
+ iptables -A VYATTA_POST_FW_FWD_HOOK -j ACCEPT
+ iptables -A VYATTA_POST_FW_OUT_HOOK -j ACCEPT
+ iptables -A INPUT -j VYATTA_POST_FW_IN_HOOK
+ iptables -A FORWARD -j VYATTA_POST_FW_FWD_HOOK
+ iptables -A OUTPUT -j VYATTA_POST_FW_OUT_HOOK
+
+ # set up IPV6 notrack and pre, post fw rules
if [ -d /proc/sys/net/ipv6 ] ; then
# set up notrack chains/rules for IPv6
ip6tables -t raw -N VYATTA_CT_PREROUTING_HOOK
@@ -71,6 +94,17 @@ start () {
ip6tables -t raw -A OUTPUT -j VYATTA_CT_OUTPUT_HOOK
ip6tables -t raw -A OUTPUT -j NOTRACK
+ # set up pre-firewall hooks for IPv6
+ ip6tables -N VYATTA_PRE_FW_IN_HOOK
+ ip6tables -N VYATTA_PRE_FW_FWD_HOOK
+ ip6tables -N VYATTA_PRE_FW_OUT_HOOK
+ ip6tables -A VYATTA_PRE_FW_IN_HOOK -j RETURN
+ ip6tables -A VYATTA_PRE_FW_FWD_HOOK -j RETURN
+ ip6tables -A VYATTA_PRE_FW_OUT_HOOK -j RETURN
+ ip6tables -I INPUT -j VYATTA_PRE_FW_IN_HOOK
+ ip6tables -I FORWARD -j VYATTA_PRE_FW_FWD_HOOK
+ ip6tables -I OUTPUT -j VYATTA_PRE_FW_OUT_HOOK
+
# set up post-firewall hooks for IPv6
ip6tables -N VYATTA_POST_FW_IN_HOOK
ip6tables -N VYATTA_POST_FW_FWD_HOOK
@@ -85,17 +119,6 @@ start () {
logger -t "Vyatta firewall init" -p warning "Kernel IPv6 support disabled. Not initializing IPv6 firewall"
fi
- # set up post-firewall hooks for IPv4
- iptables -N VYATTA_POST_FW_IN_HOOK
- iptables -N VYATTA_POST_FW_FWD_HOOK
- iptables -N VYATTA_POST_FW_OUT_HOOK
- iptables -A VYATTA_POST_FW_IN_HOOK -j ACCEPT
- iptables -A VYATTA_POST_FW_FWD_HOOK -j ACCEPT
- iptables -A VYATTA_POST_FW_OUT_HOOK -j ACCEPT
- iptables -A INPUT -j VYATTA_POST_FW_IN_HOOK
- iptables -A FORWARD -j VYATTA_POST_FW_FWD_HOOK
- iptables -A OUTPUT -j VYATTA_POST_FW_OUT_HOOK
-
# set up pre-DNAT hook
iptables -t nat -N VYATTA_PRE_DNAT_HOOK
iptables -t nat -A VYATTA_PRE_DNAT_HOOK -j RETURN
diff --git a/scripts/firewall/vyatta-firewall.pl b/scripts/firewall/vyatta-firewall.pl
index d3ac47e..ae9f723 100755
--- a/scripts/firewall/vyatta-firewall.pl
+++ b/scripts/firewall/vyatta-firewall.pl
@@ -719,15 +719,17 @@ sub setup_iptables {
# add VYATTA_FW_(IN|OUT)_HOOK
my $num = find_chain_rule($iptables_cmd, $table, $ohook, $FW_OUT_HOOK);
if (! defined $num) {
+ my $insert_at = 1;
+ $insert_at = 2 if ($table eq 'filter'); # insert after VYATTA_PRE_FW_*_HOOK
run_cmd("$iptables_cmd -t $table -N $FW_OUT_HOOK", 1);
- run_cmd("$iptables_cmd -t $table -I $ohook 1 -j $FW_OUT_HOOK", 1);
+ run_cmd("$iptables_cmd -t $table -I $ohook $insert_at -j $FW_OUT_HOOK", 1);
run_cmd("$iptables_cmd -t $table -N $FW_IN_HOOK", 1);
- run_cmd("$iptables_cmd -t $table -I $ihook 1 -j $FW_IN_HOOK", 1);
+ run_cmd("$iptables_cmd -t $table -I $ihook $insert_at -j $FW_IN_HOOK", 1);
# add VYATTA_FW_LOCAL_HOOK only in filter table
if ($table eq 'filter') {
my $lhook = $localhook_hash{$table};
run_cmd("$iptables_cmd -t $table -N $FW_LOCAL_HOOK", 1);
- run_cmd("$iptables_cmd -t $table -I $lhook 1 -j $FW_LOCAL_HOOK", 1);
+ run_cmd("$iptables_cmd -t $table -I $lhook $insert_at -j $FW_LOCAL_HOOK", 1);
}
}
diff --git a/scripts/firewall/vyatta-fw-global-state-policy.pl b/scripts/firewall/vyatta-fw-global-state-policy.pl
new file mode 100755
index 0000000..526c1a1
--- /dev/null
+++ b/scripts/firewall/vyatta-fw-global-state-policy.pl
@@ -0,0 +1,304 @@
+#!/usr/bin/perl
+#
+# Module: vyatta-fw-global-state-policy.pl
+#
+# **** License ****
+# This program is free software; you can redistribute it and/or modify
+# it under the terms of the GNU General Public License version 2 as
+# published by the Free Software Foundation.
+#
+# This program is distributed in the hope that it will be useful, but
+# WITHOUT ANY WARRANTY; without even the implied warranty of
+# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
+# General Public License for more details.
+#
+# This code was originally developed by Vyatta, Inc.
+# Portions created by Vyatta are Copyright (C) 2011 Vyatta, Inc.
+# All Rights Reserved.
+#
+# Author: Mohit Mehta
+# Date: November 2011
+# Description: Script for setting/changing/removing global FW state-policy
+#
+# **** End License ****
+#
+
+use lib "/opt/vyatta/share/perl5";
+use warnings;
+use strict;
+use Switch;
+use Vyatta::Config;
+use Vyatta::IpTables::Mgr;
+use Getopt::Long;
+use Sys::Syslog qw(:standard :macros);
+
+# mapping from config node to iptables command
+our %cmd_hash = ( 'name' => '/sbin/iptables',
+ 'ipv6-name' => '/sbin/ip6tables');
+
+# mapping from config node to iptables/ip6tables table
+our %table_hash = ( 'name' => 'filter',
+ 'ipv6-name' => 'filter');
+
+# pre FW hooks in iptables' INPUT, OUTPUT and FORWARD chains
+our %pre_fw_hooks_hash = ( 'INPUT' => 'VYATTA_PRE_FW_IN_HOOK',
+ 'FORWARD' => 'VYATTA_PRE_FW_FWD_HOOK',
+ 'OUTPUT' => 'VYATTA_PRE_FW_OUT_HOOK');
+
+# post FW hooks in iptables' INPUT, OUTPUT and FORWARD chains
+our %post_fw_hooks_hash = ( 'INPUT' => 'VYATTA_POST_FW_IN_HOOK',
+ 'FORWARD' => 'VYATTA_POST_FW_FWD_HOOK',
+ 'OUTPUT' => 'VYATTA_POST_FW_OUT_HOOK');
+
+# state policy chains in iptables' INPUT, OUTPUT and FORWARD chains
+our %state_policy_chains_hash = ( 'INPUT' => 'VYATTA_STATE_POLICY_IN_HOOK',
+ 'FORWARD' => 'VYATTA_STATE_POLICY_FWD_HOOK',
+ 'OUTPUT' => 'VYATTA_STATE_POLICY_OUT_HOOK');
+
+# state actions
+our %state_action_hash = ( 'drop' => 'DROP',
+ 'reject' => 'REJECT',
+ 'accept' => 'JUMP_TO_INDIVIDUAL_POST_FW_HOOK',
+ 'log' => 'LOG');
+
+# state actions' log abbreviations
+our %state_log_abbr_hash = ( 'drop' => 'D',
+ 'reject' => 'R',
+ 'accept' => 'A');
+
+# imp to maintain order of this array since this is the
+# order we want to insert rules into state-policy chains
+my @fw_states = ('invalid', 'established', 'related');
+
+# log prefix - FW_STATE_POL-$STATE-$ACTION_ABBREVIATION
+my $fw_log_prefix = 'FW-STATE_POL';
+
+# this function performs the following functions:
+# 1. sets up VYATTA_FW_*_STATE_POLICY chains i.e. for INPUT, OUTPUT, FORWARD hooks
+# 2. adds rules in VYATTA_PRE_FW_*_HOOK hooks to jump to VYATTA_FW_*_STATE_POLICY
+sub setup_state_policy {
+ my ($cmd, $error);
+
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # create VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::create_ipt_chain ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+
+ # append RETURN to VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain}, 'RETURN');
+ return ($error, ) if $error;
+
+ # insert rule in VYATTA_PRE_FW_*_HOOK to jump to VYATTA_FW_*_STATE_POLICY
+ $error = Vyatta::IpTables::Mgr::insert_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $pre_fw_hooks_hash{$iptables_chain},
+$state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+ }
+ }
+
+ return;
+}
+
+# this function reverts the operations done in setup_state_policy():
+# 1. removes rules from VYATTA_PRE_FW_*_HOOK hooks to jump to VYATTA_FW_*_STATE_POLICY
+# 2. deletes VYATTA_FW_STATE_POLICY chains i.e. for IN, OUT, FWD hooks
+sub teardown_state_policy {
+ my ($cmd, $error);
+
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # remove rule in VYATTA_PRE_FW_*_HOOK to jump to VYATTA_FW_*_STATE_POLICY
+ $error = Vyatta::IpTables::Mgr::delete_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $pre_fw_hooks_hash{$iptables_chain},
+$state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+
+ # flush all rules from VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::flush_ipt_chain($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+
+ # delete VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::delete_ipt_chain($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+ }
+ }
+
+ return;
+}
+
+# set all state actions and their log rules
+# Flush all previous rules and then set rules in the following order:
+# INVALID - log rule followed by action rule
+# ESTABLISHED - log rule followed by action rule
+# RELATED - log rule followed by action rule
+# Keep appending rules and then append RETURN rule at the end
+sub set_state_actions {
+ my ($cmd, $error);
+
+ my $config = new Vyatta::Config;
+ # skip steps below if state-policy deleted
+ return if (!defined $config->exists("firewall state-policy"));
+
+ # flush state_policy_chains
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # flush all rules from VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::flush_ipt_chain($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain});
+ return ($error, ) if $error;
+ }
+ }
+
+ # check config for each states in this order: invalid, established, related
+ # insert rules for log and action for each state
+ foreach my $state (@fw_states) {
+ $config->setLevel("firewall state-policy $state");
+ my ($action, $log_enabled) = (undef, undef);
+ $log_enabled = $config->exists("log enable");
+ $action = $config->returnValue("action");
+ my $uc_action = uc($action) if defined $action;
+ my $uc_state = uc ($state) if defined $state;
+ if (defined $log_enabled) {
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # insert rule in VYATTA_FW_*_STATE_POLICY
+ my $jump_target = "LOG --log-prefix \"[$fw_log_prefix-$uc_state-$state_log_abbr_hash{$action}]\" ";
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain}, $jump_target, "-m state --state $uc_state");
+ return ($error, ) if $error;
+ }
+ }
+ }
+ if (defined $action) {
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # if action is accept then jump target shold be post_fw_hooks post_fw_hooks_hash
+ if ($action eq 'accept') {
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain},
+$post_fw_hooks_hash{$iptables_chain}, "-m state --state $uc_state");
+ } else {
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain},
+$uc_action, "-m state --state $uc_state");
+ }
+ return ($error, ) if $error;
+ }
+ }
+ }
+ }
+
+ # append rule with target RETURN at the end
+ foreach my $tree (keys %cmd_hash) {
+ foreach my $iptables_chain (keys %state_policy_chains_hash) {
+ # append RETURN to VYATTA_FW_*_STATE_POLICY chains
+ $error = Vyatta::IpTables::Mgr::append_ipt_rule ($cmd_hash{$tree},
+$table_hash{$tree}, $state_policy_chains_hash{$iptables_chain}, 'RETURN');
+ return ($error, ) if $error;
+ }
+ }
+
+ return;
+}
+
+sub enable_disable_conntrack {
+ my ($cmd, $error);
+
+ my $conntrack_enabled = 'false';
+ foreach my $state (@fw_states) {
+ my $config = new Vyatta::Config;
+ $config->setLevel("firewall state-policy $state");
+ my ($action) = (undef);
+ $action = $config->returnOrigValue("action");
+ if (defined $action) {
+ $conntrack_enabled = 'true';
+ last;
+ }
+ }
+ if ($conntrack_enabled eq 'true') {
+ foreach my $tree (keys %cmd_hash) {
+ Vyatta::IpTables::Mgr::ipt_disable_conntrack($cmd_hash{$tree}, 'FW_STATE_POLICY_CONNTRACK');
+ }
+ }
+
+ my $enable_conntrack = 'false';
+ foreach my $state (@fw_states) {
+ my $config = new Vyatta::Config;
+ $config->setLevel("firewall state-policy $state");
+ my ($action) = (undef);
+ $action = $config->returnValue("action");
+ if (defined $action) {
+ $enable_conntrack = 'true';
+ last;
+ }
+ }
+ if ($enable_conntrack eq 'true') {
+ foreach my $tree (keys %cmd_hash) {
+ Vyatta::IpTables::Mgr::ipt_enable_conntrack($cmd_hash{$tree}, 'FW_STATE_POLICY_CONNTRACK');
+ }
+ }
+
+ return;
+}
+
+sub state_policy_validity_checks {
+ my ($cmd, $error);
+
+ foreach my $state (@fw_states) {
+ my $config = new Vyatta::Config;
+ $config->setLevel("firewall state-policy $state");
+ my ($action, $log_enabled) = (undef, undef);
+ $log_enabled = $config->exists("log enable");
+ $action = $config->returnValue("action");
+ if (defined $log_enabled && !defined $action) {
+ $error = "log enabled but action not configured for state: $state\n" .
+"action is required to log packets\n";
+ return $error;
+ }
+ }
+
+ return;
+}
+
+#
+# main
+#
+
+my ($action, $state, $state_action);
+
+GetOptions("action=s" => \$action,
+ "state=s" => \$state,
+ "state-action=s" => \$state_action,
+);
+
+die "undefined action" if ! defined $action;
+
+my ($error, $warning);
+
+($error, $warning) = setup_state_policy() if $action eq 'setup-state-policy';
+
+($error, $warning) = teardown_state_policy() if $action eq 'teardown-state-policy';
+
+($error, $warning) = set_state_actions() if $action eq 'set-state-actions';
+
+($error, $warning) = enable_disable_conntrack($state) if $action eq 'enable-disable-conntrack';
+
+($error, $warning) = state_policy_validity_checks($state) if $action eq 'state-policy-validity-checks';
+
+if (defined $warning) {
+ print "$warning\n";
+}
+
+if (defined $error) {
+ print "$error\n";
+ exit 1;
+}
+
+exit 0;
+
+# end of file