2009-02-22 18:30:14 +01:00
#
2010-12-15 20:57:51 +01:00
# Shorewall 4.4 -- /usr/share/shorewall/Shorewall/Misc.pm
2009-02-22 18:30:14 +01:00
#
# This program is under GPL [http://www.gnu.org/licenses/old-licenses/gpl-2.0.txt]
#
2011-05-23 19:06:56 +02:00
# (c) 2007,2008,2009,2010,2011 - Tom Eastep (teastep@shorewall.net)
2009-02-22 18:30:14 +01:00
#
# Complete documentation is available at http://shorewall.net
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of Version 2 of the GNU General Public License
# as published by the Free Software Foundation.
#
# This program is distributed in the hope that it will be useful,
2011-02-21 00:35:58 +01:00
# but WITHOUT ANY WARRANTY; without even the implied warranty ofs
2009-02-22 18:30:14 +01:00
# MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
# GNU General Public License for more details.
#
# You should have received a copy of the GNU General Public License
# along with this program; if not, write to the Free Software
# Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA.
#
2010-12-29 02:18:43 +01:00
# This module contains those routines that don't seem to fit well elsewhere. It
# was carved from the Rules module in 4.4.16.
2009-02-22 18:30:14 +01:00
#
2010-12-15 20:57:51 +01:00
package Shorewall::Misc ;
2009-02-22 18:30:14 +01:00
require Exporter ;
2009-11-02 16:15:20 +01:00
2009-02-22 18:30:14 +01:00
use Shorewall::Config qw( :DEFAULT :internal ) ;
use Shorewall::IPAddrs ;
use Shorewall::Zones ;
use Shorewall::Chains qw( :DEFAULT :internal ) ;
2011-02-20 20:28:47 +01:00
use Shorewall::Rules ;
2009-02-22 18:30:14 +01:00
use Shorewall::Proc ;
use strict ;
our @ ISA = qw( Exporter ) ;
our @ EXPORT = qw( process_tos
setup_ecn
add_common_rules
setup_mac_lists
2009-09-08 21:54:23 +02:00
process_routestopped
2009-03-28 20:22:15 +01:00
compile_stop_firewall
2010-12-15 20:57:51 +01:00
generate_matrix
2009-02-22 18:30:14 +01:00
) ;
2010-12-12 02:16:50 +01:00
our @ EXPORT_OK = qw( initialize ) ;
2011-07-11 00:10:27 +02:00
our $ VERSION = 'MODULEVERSION' ;
2009-02-22 18:30:14 +01:00
2011-05-14 22:21:31 +02:00
my $ family ;
2010-12-12 02:16:50 +01:00
2009-02-22 18:30:14 +01:00
#
2009-08-20 23:32:15 +02:00
# Rather than initializing globals in an INIT block or during declaration,
2009-08-16 18:24:51 +02:00
# we initialize them in a function. This is done for two reasons:
#
2009-08-17 19:45:46 +02:00
# 1. Proper initialization depends on the address family which isn't
2009-08-16 18:24:51 +02:00
# known until the compiler has started.
#
# 2. The compiler can run multiple times in the same process so it has to be
2009-08-17 19:45:46 +02:00
# able to re-initialize its dependent modules' state.
2009-02-22 18:30:14 +01:00
#
sub initialize ( $ ) {
$ family = shift ;
}
sub process_tos () {
2010-01-25 16:56:16 +01:00
my $ chain = have_capability ( 'MANGLE_FORWARD' ) ? 'fortos' : 'pretos' ;
my $ stdchain = have_capability ( 'MANGLE_FORWARD' ) ? 'FORWARD' : 'PREROUTING' ;
2009-02-22 18:30:14 +01:00
my % tosoptions = ( 'minimize-delay' = > 0x10 ,
'maximize-throughput' = > 0x08 ,
'maximize-reliability' = > 0x04 ,
'minimize-cost' = > 0x02 ,
'normal-service' = > 0x00 ) ;
if ( my $ fn = open_file 'tos' ) {
my $ first_entry = 1 ;
my ( $ pretosref , $ outtosref ) ;
first_entry ( sub { progress_message2 "$doing $fn..." ; $ pretosref = ensure_chain 'mangle' , $ chain ; $ outtosref = ensure_chain 'mangle' , 'outtos' ; } ) ;
while ( read_a_line ) {
2011-10-01 18:56:25 +02:00
my ( $ src , $ dst , $ proto , $ ports , $ sports , $ tos , $ mark ) = split_line 7 , 'tos file entry' , { source = > 0 , dest = > 1 , proto = > 2 , dport = > 3 , sport = > 4 , tos = > 5 , mark = > 6 } ;
2009-02-22 18:30:14 +01:00
$ first_entry = 0 ;
fatal_error 'A value must be supplied in the TOS column' if $ tos eq '-' ;
if ( defined ( my $ tosval = $ tosoptions { "\L$tos" } ) ) {
$ tos = $ tosval ;
} else {
my $ val = numeric_value ( $ tos ) ;
fatal_error "Invalid TOS value ($tos)" unless defined ( $ val ) && $ val < 0x1f ;
}
my $ chainref ;
my $ restriction = NO_RESTRICT ;
my ( $ srczone , $ source , $ remainder ) ;
if ( $ family == F_IPV4 ) {
( $ srczone , $ source , $ remainder ) = split ( /:/ , $ src , 3 ) ;
fatal_error 'Invalid SOURCE' if defined $ remainder ;
2010-01-08 22:54:31 +01:00
} elsif ( $ src =~ /^(.+?):<(.*)>\s*$/ || $ src =~ /^(.+?):\[(.*)\]\s*$/ ) {
2009-02-22 18:30:14 +01:00
$ srczone = $ 1 ;
$ source = $ 2 ;
} else {
$ srczone = $ src ;
}
if ( $ srczone eq firewall_zone ) {
$ chainref = $ outtosref ;
$ src = $ source || '-' ;
$ restriction = OUTPUT_RESTRICT ;
} else {
$ chainref = $ pretosref ;
$ src =~ s/^all:?// ;
}
$ dst =~ s/^all:?// ;
expand_rule
$ chainref ,
$ restriction ,
2010-01-13 19:50:14 +01:00
do_proto ( $ proto , $ ports , $ sports ) . do_test ( $ mark , $ globals { TC_MASK } ) ,
2009-02-22 18:30:14 +01:00
$ src ,
$ dst ,
'' ,
2010-08-26 19:37:07 +02:00
"TOS --set-tos $tos" ,
2009-02-22 18:30:14 +01:00
'' ,
2010-08-26 17:40:24 +02:00
'TOS' ,
2009-02-22 18:30:14 +01:00
'' ;
}
unless ( $ first_entry ) {
2011-07-18 00:12:58 +02:00
add_ijump ( $ mangle_table - > { $ stdchain } , j = > $ chain ) if $ pretosref - > { referenced } ;
add_ijump ( $ mangle_table - > { OUTPUT } , j = > 'outtos' ) if $ outtosref - > { referenced } ;
2009-02-22 18:30:14 +01:00
}
}
}
#
# Setup ECN disabling rules
#
sub setup_ecn ()
{
my % interfaces ;
my @ hosts ;
if ( my $ fn = open_file 'ecn' ) {
2011-08-10 18:34:15 +02:00
first_entry ( sub { progress_message2 "$doing $fn..." ;
require_capability 'MANGLE_ENABLED' , 'Entries in the ecn file' , '' ;
warning_message 'ECN will not be applied to forwarded packets' unless have_capability 'MANGLE_FORWARD' ;
} ) ;
2009-02-22 18:30:14 +01:00
while ( read_a_line ) {
2011-10-01 18:56:25 +02:00
my ( $ interface , $ hosts ) = split_line 2 , 'ecn file entry' , { interface = > 0 , hosts = > 1 } ;
2009-02-22 18:30:14 +01:00
2011-10-01 18:56:25 +02:00
fatal_error 'INTERFACE must be specified' if $ interface eq '-' ;
2010-08-31 01:47:45 +02:00
fatal_error "Unknown interface ($interface)" unless known_interface $ interface ;
2009-02-22 18:30:14 +01:00
$ interfaces { $ interface } = 1 ;
$ hosts = ALLIP if $ hosts eq '-' ;
for my $ host ( split_list $ hosts , 'address' ) {
validate_host ( $ host , 1 ) ;
push @ hosts , [ $ interface , $ host ] ;
}
}
if ( @ hosts ) {
my @ interfaces = ( keys % interfaces ) ;
progress_message "$doing ECN control on @interfaces..." ;
for my $ interface ( @ interfaces ) {
my $ chainref = ensure_chain 'mangle' , ecn_chain ( $ interface ) ;
2011-08-10 18:34:15 +02:00
add_ijump $ mangle_table - > { POSTROUTING } , j = > $ chainref , p = > 'tcp' , imatch_dest_dev ( $ interface ) if have_capability 'MANGLE_FORWARD' ;
2011-07-18 16:24:21 +02:00
add_ijump $ mangle_table - > { OUTPUT } , j = > $ chainref , p = > 'tcp' , imatch_dest_dev ( $ interface ) ;
2009-02-22 18:30:14 +01:00
}
for my $ host ( @ hosts ) {
2011-08-13 18:56:14 +02:00
add_ijump ( $ mangle_table - > { ecn_chain $ host - > [ 0 ] } , j = > 'ECN' , targetopts = > '--ecn-tcp-remove' , p = > 'tcp' , imatch_dest_net ( $ host - > [ 1 ] ) ) ;
2009-02-22 18:30:14 +01:00
}
}
}
}
sub add_rule_pair ( $$$$ ) {
my ( $ chainref , $ predicate , $ target , $ level ) = @ _ ;
2011-06-12 01:14:31 +02:00
log_rule ( $ level , $ chainref , "\U$target" , $ predicate ) if supplied $ level ;
2010-01-16 18:53:53 +01:00
add_jump ( $ chainref , $ target , 0 , $ predicate ) ;
2009-02-22 18:30:14 +01:00
}
sub setup_blacklist () {
2010-09-16 18:40:28 +02:00
my $ zones = find_zones_by_option 'blacklist' , 'in' ;
my $ zones1 = find_zones_by_option 'blacklist' , 'out' ;
2009-02-22 18:30:14 +01:00
my $ chainref ;
2010-09-16 18:40:28 +02:00
my $ chainref1 ;
2009-02-22 18:30:14 +01:00
my ( $ level , $ disposition ) = @ config { 'BLACKLIST_LOGLEVEL' , 'BLACKLIST_DISPOSITION' } ;
2011-06-04 17:45:23 +02:00
my $ audit = $ disposition =~ /^A_/ ;
2011-05-31 01:37:56 +02:00
my $ target = $ disposition eq 'REJECT' ? 'reject' : $ disposition ;
my $ orig_target = $ target ;
2010-03-21 15:24:29 +01:00
#
2010-09-16 18:40:28 +02:00
# We go ahead and generate the blacklist chains and jump to them, even if they turn out to be empty. That is necessary
2010-03-21 15:24:29 +01:00
# for 'refresh' to work properly.
#
2010-09-16 18:40:28 +02:00
if ( @$ zones || @$ zones1 ) {
$ chainref = dont_delete new_standard_chain 'blacklst' if @$ zones ;
$ chainref1 = dont_delete new_standard_chain 'blackout' if @$ zones1 ;
2009-02-22 18:30:14 +01:00
2011-06-12 01:14:31 +02:00
if ( supplied $ level ) {
2009-02-22 18:30:14 +01:00
my $ logchainref = new_standard_chain 'blacklog' ;
2011-06-04 17:45:23 +02:00
$ target =~ s/A_// ;
$ target = 'reject' if $ target eq 'REJECT' ;
2009-02-22 18:30:14 +01:00
log_rule_limit ( $ level , $ logchainref , 'blacklst' , $ disposition , "$globals{LOGLIMIT}" , '' , 'add' , '' ) ;
2011-08-13 18:56:14 +02:00
add_ijump ( $ logchainref , j = > 'AUDIT' , targetopts = > '--type ' . lc $ target ) if $ audit ;
2011-07-18 00:12:58 +02:00
add_ijump ( $ logchainref , g = > $ target ) ;
2009-02-22 18:30:14 +01:00
$ target = 'blacklog' ;
2011-05-22 00:02:04 +02:00
} elsif ( $ audit ) {
require_capability 'AUDIT_TARGET' , "BLACKLIST_DISPOSITION=$disposition" , 's' ;
2011-06-04 17:45:23 +02:00
$ target = verify_audit ( $ disposition ) ;
2011-05-22 00:02:04 +02:00
}
2009-02-22 18:30:14 +01:00
}
BLACKLIST:
{
if ( my $ fn = open_file 'blacklist' ) {
my $ first_entry = 1 ;
first_entry "$doing $fn..." ;
while ( read_a_line ) {
if ( $ first_entry ) {
2010-09-16 18:40:28 +02:00
unless ( @$ zones || @$ zones1 ) {
warning_message qq( The entries in $fn have been ignored because there are no 'blacklist' zones ) ;
2009-02-22 18:30:14 +01:00
close_file ;
last BLACKLIST ;
}
$ first_entry = 0 ;
}
2011-10-01 18:56:25 +02:00
my ( $ networks , $ protocol , $ ports , $ options ) = split_line 4 , 'blacklist file' , { networks = > 0 , proto = > 1 , port = > 2 , options = > 3 } ;
2010-03-19 18:01:02 +01:00
2011-06-04 17:45:23 +02:00
if ( $ options eq '-' ) {
$ options = 'src' ;
} elsif ( $ options eq 'audit' ) {
$ options = 'audit,src' ;
}
2009-02-22 18:30:14 +01:00
2011-05-21 18:25:58 +02:00
my ( $ to , $ from , $ whitelist , $ auditone ) = ( 0 , 0 , 0 , 0 ) ;
2009-02-22 18:30:14 +01:00
2011-05-18 17:30:01 +02:00
my @ options = split_list $ options , 'option' ;
for ( @ options ) {
$ whitelist + + if $ _ eq 'whitelist' ;
2011-05-21 18:25:58 +02:00
$ auditone + + if $ _ eq 'audit' ;
2011-05-18 17:30:01 +02:00
}
warning_message "Duplicate 'whitelist' option ignored" if $ whitelist > 1 ;
my $ tgt = $ whitelist ? 'RETURN' : $ target ;
2011-05-21 18:25:58 +02:00
if ( $ auditone ) {
fatal_error "'audit' not allowed in whitelist entries" if $ whitelist ;
if ( $ audit ) {
warning_message "Superfluous 'audit' option ignored" ;
} else {
warning_message "Duplicate 'audit' option ignored" if $ auditone > 1 ;
2011-05-31 01:37:56 +02:00
2011-06-04 17:45:23 +02:00
$ tgt = verify_audit ( 'A_' . $ target , $ orig_target , $ target ) ;
2011-05-21 18:25:58 +02:00
}
}
2011-05-18 17:30:01 +02:00
for ( @ options ) {
2011-05-18 20:13:03 +02:00
if ( $ _ =~ /^(?:src|from)$/ ) {
2010-09-16 18:40:28 +02:00
if ( $ from + + ) {
warning_message "Duplicate 'src' ignored" ;
} else {
if ( @$ zones ) {
expand_rule (
$ chainref ,
NO_RESTRICT ,
do_proto ( $ protocol , $ ports , '' ) ,
$ networks ,
'' ,
'' ,
2011-05-18 17:30:01 +02:00
$ tgt ,
2010-09-16 18:40:28 +02:00
'' ,
2011-05-18 17:30:01 +02:00
$ tgt ,
2010-09-16 18:40:28 +02:00
'' ) ;
} else {
2010-09-17 21:35:34 +02:00
warning_message '"src" entry ignored because there are no "blacklist in" zones' ;
2010-09-16 18:40:28 +02:00
}
}
} elsif ( $ _ =~ /^(?:dst|to)$/ ) {
if ( $ to + + ) {
warning_message "Duplicate 'dst' ignored" ;
} else {
if ( @$ zones1 ) {
expand_rule (
$ chainref1 ,
NO_RESTRICT ,
do_proto ( $ protocol , $ ports , '' ) ,
'' ,
$ networks ,
'' ,
2011-05-18 17:30:01 +02:00
$ tgt ,
2010-09-16 18:40:28 +02:00
'' ,
2011-05-18 17:30:01 +02:00
$ tgt ,
2010-09-16 18:40:28 +02:00
'' ) ;
} else {
2010-09-17 21:35:34 +02:00
warning_message '"dst" entry ignored because there are no "blacklist out" zones' ;
2010-09-16 18:40:28 +02:00
}
}
2011-05-18 20:13:03 +02:00
} else {
2011-05-21 18:25:58 +02:00
fatal_error "Invalid blacklist option($_)" unless $ _ eq 'whitelist' || $ _ eq 'audit' ;
2010-09-16 18:40:28 +02:00
}
}
2009-02-22 18:30:14 +01:00
2010-09-16 18:40:28 +02:00
progress_message " \"$currentline\" added to blacklist" ;
2009-02-22 18:30:14 +01:00
}
2010-09-16 18:40:28 +02:00
warning_message q( There are interfaces or zones with the 'blacklist' option but the 'blacklist' file is empty ) if $ first_entry && @$ zones ;
} elsif ( @$ zones || @$ zones1 ) {
warning_message q( There are interfaces or zones with the 'blacklist' option, but the 'blacklist' file is either missing or has zero size ) ;
2009-02-22 18:30:14 +01:00
}
}
}
sub process_routestopped () {
2010-09-28 19:48:44 +02:00
if ( my $ fn = open_file 'routestopped' ) {
my ( @ allhosts , % source , % dest , % notrack , @ rule ) ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
my $ seq = 0 ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
first_entry "$doing $fn..." ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
while ( read_a_line ) {
2009-02-22 18:30:14 +01:00
2011-09-26 02:08:53 +02:00
my ( $ interface , $ hosts , $ options , $ proto , $ ports , $ sports ) =
2011-10-01 18:56:25 +02:00
split_line 6 , 'routestopped file' , { interface = > 1 , hosts = > 2 , options = > 3 , proto = > 4 , dport = > 5 , sport = > 6 } ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
my $ interfaceref ;
2009-02-22 18:30:14 +01:00
2011-10-01 18:56:25 +02:00
fatal_error 'INTERFACE must be specified' if $ interface eq '-' ;
2010-09-28 19:48:44 +02:00
fatal_error "Unknown interface ($interface)" unless $ interfaceref = known_interface $ interface ;
$ hosts = ALLIP unless $ hosts && $ hosts ne '-' ;
2010-05-03 21:31:11 +02:00
2010-09-28 19:48:44 +02:00
my $ routeback = 0 ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
my @ hosts ;
2010-05-03 21:31:11 +02:00
2010-09-28 19:48:44 +02:00
$ seq + + ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
my $ rule = do_proto ( $ proto , $ ports , $ sports , 0 ) ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
for my $ host ( split /,/ , $ hosts ) {
fatal_error "Ipsets not allowed with SAVE_IPSETS=Yes" if $ host =~ /^!?\+/ && $ config { SAVE_IPSETS } ;
validate_host $ host , 1 ;
push @ hosts , "$interface|$host|$seq" ;
push @ rule , $ rule ;
}
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
unless ( $ options eq '-' ) {
for my $ option ( split /,/ , $ options ) {
if ( $ option eq 'routeback' ) {
if ( $ routeback ) {
warning_message "Duplicate 'routeback' option ignored" ;
} else {
$ routeback = 1 ;
}
} elsif ( $ option eq 'source' ) {
for my $ host ( split /,/ , $ hosts ) {
$ source { "$interface|$host|$seq" } = 1 ;
}
} elsif ( $ option eq 'dest' ) {
for my $ host ( split /,/ , $ hosts ) {
$ dest { "$interface|$host|$seq" } = 1 ;
}
} elsif ( $ option eq 'notrack' ) {
for my $ host ( split /,/ , $ hosts ) {
$ notrack { "$interface|$host|$seq" } = 1 ;
}
2009-02-22 18:30:14 +01:00
} else {
2010-09-28 19:48:44 +02:00
warning_message "Unknown routestopped option ( $option ) ignored" unless $ option eq 'critical' ;
warning_message "The 'critical' option is no longer supported (or needed)" ;
2009-02-22 18:30:14 +01:00
}
}
}
2010-09-28 19:48:44 +02:00
if ( $ routeback || $ interfaceref - > { options } { routeback } ) {
my $ chainref = $ filter_table - > { FORWARD } ;
2010-05-03 21:31:11 +02:00
2010-09-28 19:48:44 +02:00
for my $ host ( split /,/ , $ hosts ) {
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref ,
j = > 'ACCEPT' ,
imatch_source_dev ( $ interface ) ,
imatch_dest_dev ( $ interface ) ,
imatch_source_net ( $ host ) ,
imatch_dest_net ( $ host ) ) ;
2010-09-28 19:48:44 +02:00
clearrule ;
}
2010-05-03 21:31:11 +02:00
}
2010-09-28 19:48:44 +02:00
push @ allhosts , @ hosts ;
}
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
for my $ host ( @ allhosts ) {
my ( $ interface , $ h , $ seq ) = split /\|/ , $ host ;
my $ source = match_source_net $ h ;
my $ dest = match_dest_net $ h ;
my $ sourcei = match_source_dev $ interface ;
my $ desti = match_dest_dev $ interface ;
my $ rule = shift @ rule ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
add_rule $ filter_table - > { INPUT } , "$sourcei $source $rule -j ACCEPT" , 1 ;
add_rule $ filter_table - > { OUTPUT } , "$desti $dest $rule -j ACCEPT" , 1 unless $ config { ADMINISABSENTMINDED } ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
my $ matched = 0 ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
if ( $ source { $ host } ) {
add_rule $ filter_table - > { FORWARD } , "$sourcei $source $rule -j ACCEPT" , 1 ;
$ matched = 1 ;
}
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
if ( $ dest { $ host } ) {
add_rule $ filter_table - > { FORWARD } , "$desti $dest $rule -j ACCEPT" , 1 ;
$ matched = 1 ;
}
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
if ( $ notrack { $ host } ) {
add_rule $ raw_table - > { PREROUTING } , "$sourcei $source $rule -j NOTRACK" , 1 ;
add_rule $ raw_table - > { OUTPUT } , "$desti $dest $rule -j NOTRACK" , 1 ;
}
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
unless ( $ matched ) {
for my $ host1 ( @ allhosts ) {
unless ( $ host eq $ host1 ) {
my ( $ interface1 , $ h1 , $ seq1 ) = split /\|/ , $ host1 ;
my $ dest1 = match_dest_net $ h1 ;
my $ desti1 = match_dest_dev $ interface1 ;
add_rule $ filter_table - > { FORWARD } , "$sourcei $desti1 $source $dest1 $rule -j ACCEPT" , 1 ;
clearrule ;
}
2009-02-22 18:30:14 +01:00
}
}
}
}
}
sub setup_mss () ;
sub add_common_rules () {
my $ interface ;
my $ chainref ;
my $ target ;
2011-06-09 18:57:45 +02:00
my $ target1 ;
2009-02-22 18:30:14 +01:00
my $ rule ;
my $ list ;
my $ chain ;
2011-05-26 22:38:44 +02:00
my $ dynamicref ;
2009-02-22 18:30:14 +01:00
2011-07-18 00:12:58 +02:00
my @ state = $ config { BLACKLISTNEWONLY } ? $ globals { UNTRACKED } ? state_imatch 'NEW,INVALID,UNTRACKED' : state_imatch 'NEW,INVALID' : ( ) ;
2010-01-16 18:53:53 +01:00
my $ level = $ config { BLACKLIST_LOGLEVEL } ;
2011-05-24 05:59:33 +02:00
my $ rejectref = $ filter_table - > { reject } ;
2009-02-22 18:30:14 +01:00
2010-01-16 18:53:53 +01:00
if ( $ config { DYNAMIC_BLACKLIST } ) {
2011-07-16 18:41:53 +02:00
add_rule_pair dont_delete ( new_standard_chain ( 'logdrop' ) ) , '' , 'DROP' , $ level ;
add_rule_pair dont_delete ( new_standard_chain ( 'logreject' ) ) , '' , 'reject' , $ level ;
2011-05-26 22:38:44 +02:00
$ dynamicref = dont_optimize ( new_standard_chain ( 'dynamic' ) ) ;
2011-07-18 00:12:58 +02:00
add_ijump $ filter_table - > { INPUT } , j = > $ dynamicref , @ state ;
2011-05-26 22:38:44 +02:00
add_commands ( $ dynamicref , '[ -f ${VARDIR}/.dynamic ] && cat ${VARDIR}/.dynamic >&3' ) ;
2010-01-16 18:53:53 +01:00
}
2009-02-22 18:30:14 +01:00
setup_mss ;
2011-07-20 16:30:49 +02:00
add_ijump ( $ filter_table - > { OUTPUT } , j = > 'ACCEPT' , state_imatch 'ESTABLISHED,RELATED' ) if ( $ config { FASTACCEPT } ) ;
2011-05-26 22:38:44 +02:00
2011-05-28 04:42:09 +02:00
my $ policy = $ config { SFILTER_DISPOSITION } ;
$ level = $ config { SFILTER_LOG_LEVEL } ;
2011-05-26 22:38:44 +02:00
my $ audit = $ policy =~ s/^A_// ;
2011-07-18 00:12:58 +02:00
my @ ipsec = have_ipsec ? ( policy = > '--pol none --dir in' ) : ( ) ;
2011-05-26 22:38:44 +02:00
2011-09-01 23:15:15 +02:00
if ( $ level || $ audit ) {
#
2011-09-02 17:41:42 +02:00
# Create a chain to log and/or audit and apply the policy
2011-09-01 23:15:15 +02:00
#
2011-05-28 04:42:09 +02:00
$ chainref = new_standard_chain 'sfilter' ;
2011-05-26 22:38:44 +02:00
log_rule $ level , $ chainref , $ policy , '' if $ level ne '' ;
2011-08-13 18:56:14 +02:00
add_ijump ( $ chainref , j = > 'AUDIT' , targetopts = > '--type ' . lc $ policy ) if $ audit ;
2011-05-26 22:38:44 +02:00
2011-07-18 00:12:58 +02:00
add_ijump $ chainref , g = > $ policy eq 'REJECT' ? 'reject' : $ policy ;
2011-05-26 22:38:44 +02:00
2011-05-28 04:42:09 +02:00
$ target = 'sfilter' ;
2011-09-02 17:41:42 +02:00
} else {
$ target = $ policy eq 'REJECT' ? 'reject' : $ policy ;
2011-09-01 23:15:15 +02:00
}
2011-06-09 18:57:45 +02:00
2011-09-01 23:15:15 +02:00
if ( @ ipsec ) {
#
# sfilter1 will be used in the FORWARD chain where we allow traffic entering the interface
# to leave the interface encrypted. We need a separate chain because '--dir out' cannot be
# used in the input chain
#
$ chainref = new_standard_chain 'sfilter1' ;
2011-06-09 18:57:45 +02:00
2011-09-01 23:15:15 +02:00
add_ijump ( $ chainref , j = > 'RETURN' , policy = > '--pol ipsec --dir out' ) ;
log_rule $ level , $ chainref , $ policy , '' if $ level ne '' ;
2011-06-09 18:57:45 +02:00
2011-09-01 23:15:15 +02:00
add_ijump ( $ chainref , j = > 'AUDIT' , targetopts = > '--type ' . lc $ policy ) if $ audit ;
2011-06-09 18:57:45 +02:00
2011-09-01 23:15:15 +02:00
add_ijump $ chainref , g = > $ policy eq 'REJECT' ? 'reject' : $ policy ;
2011-06-09 18:57:45 +02:00
2011-09-01 23:15:15 +02:00
$ target1 = 'sfilter1' ;
} else {
#
# No IPSEC -- use the same target in both INPUT and FORWARD
#
$ target1 = $ target ;
2009-02-22 18:30:14 +01:00
}
2010-07-01 05:35:46 +02:00
for $ interface ( grep $ _ ne '%vserver%' , all_interfaces ) {
2009-02-22 18:30:14 +01:00
ensure_chain ( 'filter' , $ _ ) for first_chains ( $ interface ) , output_chain ( $ interface ) ;
2011-05-26 22:38:44 +02:00
my $ interfaceref = find_interface $ interface ;
unless ( $ interfaceref - > { options } { ignore } ) {
my @ filters = @ { $ interfaceref - > { filter } } ;
$ chainref = $ filter_table - > { forward_chain $ interface } ;
if ( @ filters ) {
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , @ ipsec ? 'j' : 'g' = > $ target1 , imatch_source_net ( $ _ ) , @ ipsec ) , $ chainref - > { filtered } + + for @ filters ;
2011-09-05 15:23:18 +02:00
$ interfaceref - > { options } { use_forward_chain } = 1 ;
2011-06-09 18:57:45 +02:00
} elsif ( $ interfaceref - > { bridge } eq $ interface ) {
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , @ ipsec ? 'j' : 'g' = > $ target1 , imatch_dest_dev ( $ interface ) , @ ipsec ) , $ chainref - > { filtered } + +
2011-09-07 21:19:13 +02:00
unless ( $ config { ROUTE_FILTER } eq 'on' ||
$ interfaceref - > { options } { routeback } ||
$ interfaceref - > { options } { routefilter } ||
$ interfaceref - > { physical } eq '+' ) ;
2011-09-05 15:23:18 +02:00
$ interfaceref - > { options } { use_forward_chain } = 1 ;
2011-06-09 18:57:45 +02:00
}
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'ACCEPT' , state_imatch 'ESTABLISHED,RELATED' ) , $ chainref - > { filtered } + + if $ config { FASTACCEPT } ;
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , j = > $ dynamicref , @ state ) , $ chainref - > { filtered } + + if $ dynamicref ;
2011-06-09 18:57:45 +02:00
$ chainref = $ filter_table - > { input_chain $ interface } ;
if ( @ filters ) {
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , g = > $ target , imatch_source_net ( $ _ ) , @ ipsec ) , $ chainref - > { filtered } + + for @ filters ;
2011-09-05 15:23:18 +02:00
$ interfaceref - > { options } { use_input_chain } = 1 ;
2011-05-26 22:38:44 +02:00
}
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'ACCEPT' , state_imatch 'ESTABLISHED,RELATED' ) , $ chainref - > { filtered } + + if $ config { FASTACCEPT } ;
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , j = > $ dynamicref , @ state ) , $ chainref - > { filtered } + + if $ dynamicref ;
2011-05-26 22:38:44 +02:00
}
2009-02-22 18:30:14 +01:00
}
2011-05-28 04:56:54 +02:00
#
2011-06-10 02:09:53 +02:00
# Delete 'sfilter' chains unless there are referenced to them
2011-05-28 04:56:54 +02:00
#
2011-06-10 02:09:53 +02:00
for ( qw/sfilter sfilter1/ ) {
if ( $ chainref = $ filter_table - > { $ _ } ) {
$ chainref - > { referenced } = 0 unless keys % { $ chainref - > { references } } ;
}
}
2011-05-28 04:56:54 +02:00
2009-02-22 18:30:14 +01:00
run_user_exit1 'initdone' ;
setup_blacklist ;
$ list = find_hosts_by_option 'nosmurfs' ;
2010-02-04 00:03:15 +01:00
if ( @$ list ) {
progress_message2 'Adding Anti-smurf Rules' ;
$ chainref = new_standard_chain 'smurfs' ;
2010-06-07 16:30:56 +02:00
2011-05-22 00:02:04 +02:00
my $ smurfdest = $ config { SMURF_DISPOSITION } ;
2010-02-04 00:03:15 +01:00
2011-06-12 01:14:31 +02:00
if ( supplied $ config { SMURF_LOG_LEVEL } ) {
2011-05-22 00:02:04 +02:00
my $ smurfref = new_chain ( 'filter' , 'smurflog' ) ;
2010-06-07 16:30:56 +02:00
2010-02-04 00:03:15 +01:00
log_rule_limit ( $ config { SMURF_LOG_LEVEL } ,
$ smurfref ,
'smurfs' ,
'DROP' ,
$ globals { LOGLIMIT } ,
2010-06-07 16:30:56 +02:00
'' ,
2010-02-04 00:03:15 +01:00
'add' ,
'' ) ;
2011-08-13 18:56:14 +02:00
add_ijump ( $ smurfref , j = > 'AUDIT' , targetopts = > '--type drop' ) if $ smurfdest eq 'A_DROP' ;
2011-07-20 16:30:49 +02:00
add_ijump ( $ smurfref , j = > 'DROP' ) ;
2011-05-22 00:02:04 +02:00
$ smurfdest = 'smurflog' ;
2010-02-04 00:03:15 +01:00
} else {
2011-05-22 00:02:04 +02:00
verify_audit ( $ smurfdest ) if $ smurfdest eq 'A_DROP' ;
2010-02-04 00:03:15 +01:00
}
if ( have_capability ( 'ADDRTYPE' ) ) {
2010-02-07 17:43:31 +01:00
if ( $ family == F_IPV4 ) {
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , s = > '0.0.0.0' ; ;
2010-02-07 17:43:31 +01:00
} else {
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , s = > '::' ;
2010-02-07 17:43:31 +01:00
}
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , g = > $ smurfdest , addrtype = > '--src-type BROADCAST' ) ;
2010-02-04 00:03:15 +01:00
} else {
if ( $ family == F_IPV4 ) {
add_commands $ chainref , 'for address in $ALL_BCASTS; do' ;
} else {
add_commands $ chainref , 'for address in $ALL_ACASTS; do' ;
}
2010-06-07 16:30:56 +02:00
2010-02-04 00:03:15 +01:00
incr_cmd_level $ chainref ;
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , g = > $ smurfdest , s = > '$address' ) ;
2010-02-04 00:03:15 +01:00
decr_cmd_level $ chainref ;
add_commands $ chainref , 'done' ;
}
2009-02-22 18:30:14 +01:00
if ( $ family == F_IPV4 ) {
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , g = > $ smurfdest , s = > '224.0.0.0/4' ) ;
2009-02-22 18:30:14 +01:00
} else {
2011-07-18 00:12:58 +02:00
add_ijump ( $ chainref , g = > $ smurfdest , s = > IPv6_MULTICAST ) ;
2009-02-22 18:30:14 +01:00
}
2011-07-18 00:12:58 +02:00
my @ state = $ globals { UNTRACKED } ? state_imatch 'NEW,INVALID,UNTRACKED' : state_imatch 'NEW,INVALID' ;
2009-02-22 18:30:14 +01:00
2010-02-04 00:03:15 +01:00
for my $ hostref ( @$ list ) {
$ interface = $ hostref - > [ 0 ] ;
my $ ipsec = $ hostref - > [ 1 ] ;
2011-07-18 00:12:58 +02:00
my @ policy = have_ipsec ? ( policy = > "--pol $ipsec --dir in" ) : ( ) ;
2010-02-04 00:03:15 +01:00
my $ target = source_exclusion ( $ hostref - > [ 3 ] , $ chainref ) ;
for $ chain ( first_chains $ interface ) {
2011-07-18 00:12:58 +02:00
add_ijump ( $ filter_table - > { $ chain } , j = > $ target , @ state , imatch_source_net ( $ hostref - > [ 2 ] ) , @ policy ) ;
2010-02-04 00:03:15 +01:00
}
set_interface_option $ interface , 'use_input_chain' , 1 ;
set_interface_option $ interface , 'use_forward_chain' , 1 ;
}
2009-02-22 18:30:14 +01:00
}
2010-01-25 16:56:16 +01:00
if ( have_capability ( 'ADDRTYPE' ) ) {
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'DROP' , addrtype = > '--src-type BROADCAST' ;
2009-02-22 18:30:14 +01:00
} else {
if ( $ family == F_IPV4 ) {
2009-07-07 03:38:39 +02:00
add_commands $ rejectref , 'for address in $ALL_BCASTS; do' ;
2009-02-22 18:30:14 +01:00
} else {
2009-07-07 03:38:39 +02:00
add_commands $ rejectref , 'for address in $ALL_ACASTS; do' ;
2009-02-22 18:30:14 +01:00
}
incr_cmd_level $ rejectref ;
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'DROP' , d = > '$address' ;
2009-02-22 18:30:14 +01:00
decr_cmd_level $ rejectref ;
2009-07-07 03:38:39 +02:00
add_commands $ rejectref , 'done' ;
2009-02-22 18:30:14 +01:00
}
if ( $ family == F_IPV4 ) {
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'DROP' , s = > '224.0.0.0/4' ;
2009-02-22 18:30:14 +01:00
} else {
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'DROP' , s = > IPv6_MULTICAST ;
2009-02-22 18:30:14 +01:00
}
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'DROP' , p = > 2 ;
2011-08-13 18:56:14 +02:00
add_ijump $ rejectref , j = > 'REJECT' , targetopts = > '--reject-with tcp-reset' , p = > 6 ;
2009-02-22 18:30:14 +01:00
2010-01-25 16:56:16 +01:00
if ( have_capability ( 'ENHANCED_REJECT' ) ) {
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'REJECT' , p = > 17 ;
2009-02-22 18:30:14 +01:00
if ( $ family == F_IPV4 ) {
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'REJECT --reject-with icmp-host-unreachable' , p = > 1 ;
add_ijump $ rejectref , j = > 'REJECT --reject-with icmp-host-prohibited' ;
2009-02-22 18:30:14 +01:00
} else {
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'REJECT --reject-with icmp6-addr-unreachable' , p = > 58 ;
add_ijump $ rejectref , j = > 'REJECT --reject-with icmp6-adm-prohibited' ;
2009-02-22 18:30:14 +01:00
}
} else {
2011-07-20 16:30:49 +02:00
add_ijump $ rejectref , j = > 'REJECT' ;
2009-02-22 18:30:14 +01:00
}
$ list = find_interfaces_by_option 'dhcp' ;
if ( @$ list ) {
progress_message2 'Adding rules for DHCP' ;
my $ ports = $ family == F_IPV4 ? '67:68' : '546:547' ;
for $ interface ( @$ list ) {
set_interface_option $ interface , 'use_input_chain' , 1 ;
set_interface_option $ interface , 'use_forward_chain' , 1 ;
2011-07-17 01:31:29 +02:00
2011-07-20 16:30:49 +02:00
set_rule_option ( add_ijump ( $ filter_table - > { $ _ } , j = > 'ACCEPT' , p = > "udp --dport $ports" ) ,
2011-07-17 01:31:29 +02:00
'dhcp' ,
1 ) for input_chain ( $ interface ) , output_chain ( $ interface ) ;
2009-02-22 18:30:14 +01:00
2011-07-20 16:30:49 +02:00
add_ijump ( $ filter_table - > { forward_chain $ interface } ,
2011-07-18 00:12:58 +02:00
j = > 'ACCEPT' ,
p = > "udp --dport $ports" ,
imatch_dest_dev ( $ interface ) )
2009-11-06 22:10:19 +01:00
if get_interface_option ( $ interface , 'bridge' ) ;
2009-02-22 18:30:14 +01:00
}
}
$ list = find_hosts_by_option 'tcpflags' ;
if ( @$ list ) {
2011-05-21 18:25:58 +02:00
my $ level = $ config { TCP_FLAGS_LOG_LEVEL } ;
my $ disposition = $ config { TCP_FLAGS_DISPOSITION } ;
2011-05-22 00:02:04 +02:00
my $ audit = $ disposition =~ /^A_/ ;
2009-02-22 18:30:14 +01:00
progress_message2 "$doing TCP Flags filtering..." ;
$ chainref = new_standard_chain 'tcpflags' ;
2011-05-22 00:02:04 +02:00
if ( $ level ) {
2009-02-22 18:30:14 +01:00
my $ logflagsref = new_standard_chain 'logflags' ;
2011-05-22 00:02:04 +02:00
my $ savelogparms = $ globals { LOGPARMS } ;
2009-02-22 18:30:14 +01:00
2011-05-22 00:02:04 +02:00
$ globals { LOGPARMS } = "$globals{LOGPARMS}--log-ip-options " ;
2009-02-22 18:30:14 +01:00
2011-05-22 00:02:04 +02:00
log_rule $ level , $ logflagsref , $ config { TCP_FLAGS_DISPOSITION } , '' ;
$ globals { LOGPARMS } = $ savelogparms ;
2009-02-22 18:30:14 +01:00
2011-05-22 00:02:04 +02:00
if ( $ audit ) {
$ disposition =~ s/^A_// ;
2011-08-13 18:56:14 +02:00
add_ijump ( $ logflagsref , j = > 'AUDIT' , targetopts = > '--type ' . lc $ disposition ) ;
2011-05-21 18:25:58 +02:00
}
2011-05-22 00:02:04 +02:00
if ( $ disposition eq 'REJECT' ) {
2011-08-13 18:56:14 +02:00
add_ijump $ logflagsref , j = > 'REJECT' , targetopts = > '--reject-with tcp-reset' , p = > 6 ;
2009-02-22 18:30:14 +01:00
} else {
2011-07-20 16:30:49 +02:00
add_ijump $ logflagsref , j = > $ disposition ;
2009-02-22 18:30:14 +01:00
}
$ disposition = 'logflags' ;
2011-05-22 00:02:04 +02:00
} elsif ( $ audit ) {
require_capability ( 'AUDIT_TARGET' , "TCP_FLAGS_DISPOSITION=$disposition" , 's' ) ;
verify_audit ( $ disposition ) ;
2009-02-22 18:30:14 +01:00
}
2011-07-18 00:12:58 +02:00
add_ijump $ chainref , g = > $ disposition , p = > 'tcp --tcp-flags ALL FIN,URG,PSH' ;
add_ijump $ chainref , g = > $ disposition , p = > 'tcp --tcp-flags ALL NONE' ;
add_ijump $ chainref , g = > $ disposition , p = > 'tcp --tcp-flags SYN,RST SYN,RST' ;
add_ijump $ chainref , g = > $ disposition , p = > 'tcp --tcp-flags SYN,FIN SYN,FIN' ;
add_ijump $ chainref , g = > $ disposition , p = > 'tcp --syn --sport 0' ;
2009-02-22 18:30:14 +01:00
for my $ hostref ( @$ list ) {
my $ interface = $ hostref - > [ 0 ] ;
my $ target = source_exclusion ( $ hostref - > [ 3 ] , $ chainref ) ;
2011-07-18 00:12:58 +02:00
my @ policy = have_ipsec ? ( policy = > "--pol $hostref->[1] --dir in" ) : ( ) ;
2009-02-22 18:30:14 +01:00
for $ chain ( first_chains $ interface ) {
2011-07-18 00:12:58 +02:00
add_ijump ( $ filter_table - > { $ chain } , j = > $ target , p = > 'tcp' , imatch_source_net ( $ hostref - > [ 2 ] ) , @ policy ) ;
2009-02-22 18:30:14 +01:00
}
set_interface_option $ interface , 'use_input_chain' , 1 ;
set_interface_option $ interface , 'use_forward_chain' , 1 ;
}
}
if ( $ family == F_IPV4 ) {
2009-06-15 22:34:35 +02:00
my $ announced = 0 ;
2009-02-22 18:30:14 +01:00
$ list = find_interfaces_by_option 'upnp' ;
if ( @$ list ) {
progress_message2 "$doing UPnP" ;
2010-06-06 22:10:28 +02:00
$ chainref = dont_optimize new_nat_chain ( 'UPnP' ) ;
2010-06-07 16:18:21 +02:00
add_commands ( $ chainref , '[ -s /${VARDIR}/.UPnP ] && cat ${VARDIR}/.UPnP >&3' ) ;
2009-02-22 18:30:14 +01:00
2009-06-15 22:34:35 +02:00
$ announced = 1 ;
2009-02-22 18:30:14 +01:00
for $ interface ( @$ list ) {
2011-07-18 00:12:58 +02:00
add_ijump $ nat_table - > { PREROUTING } , j = > 'UPnP' , imatch_source_dev ( $ interface ) ;
2009-02-22 18:30:14 +01:00
}
}
2009-06-15 22:34:35 +02:00
$ list = find_interfaces_by_option 'upnpclient' ;
if ( @$ list ) {
progress_message2 "$doing UPnP" unless $ announced ;
for $ interface ( @$ list ) {
my $ chainref = $ filter_table - > { input_chain $ interface } ;
2010-08-28 23:18:48 +02:00
my $ base = uc chain_base get_physical $ interface ;
2009-06-15 22:34:35 +02:00
my $ variable = get_interface_gateway $ interface ;
2009-08-11 17:31:58 +02:00
if ( interface_is_optional $ interface ) {
2009-08-20 23:32:15 +02:00
add_commands ( $ chainref ,
2011-07-17 01:31:29 +02:00
qq( if [ -n "SW_\$${base}_IS_USABLE" -a -n "$variable" ]; then ) ) ;
incr_cmd_level ( $ chainref ) ;
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'ACCEPT' , imatch_source_dev ( $ interface ) , s = > $ variable , p = > 'udp' ) ;
2011-07-17 01:31:29 +02:00
decr_cmd_level ( $ chainref ) ;
add_commands ( $ chainref , 'fi' ) ;
2009-08-11 17:31:58 +02:00
} else {
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'ACCEPT' , imatch_source_dev ( $ interface ) , s = > $ variable , p = > 'udp' ) ;
2009-08-11 17:31:58 +02:00
}
2009-06-15 22:34:35 +02:00
}
}
2009-02-22 18:30:14 +01:00
}
setup_syn_flood_chains ;
}
my % maclist_targets = ( ACCEPT = > { target = > 'RETURN' , mangle = > 1 } ,
REJECT = > { target = > 'reject' , mangle = > 0 } ,
DROP = > { target = > 'DROP' , mangle = > 1 } ) ;
sub setup_mac_lists ( $ ) {
my $ phase = $ _ [ 0 ] ;
my % maclist_interfaces ;
my $ table = $ config { MACLIST_TABLE } ;
my $ maclist_hosts = find_hosts_by_option 'maclist' ;
my $ target = $ globals { MACLIST_TARGET } ;
my $ level = $ config { MACLIST_LOG_LEVEL } ;
my $ disposition = $ config { MACLIST_DISPOSITION } ;
2011-05-21 18:25:58 +02:00
my $ audit = $ disposition =~ /^A_/ ;
2009-02-22 18:30:14 +01:00
my $ ttl = $ config { MACLIST_TTL } ;
progress_message2 "$doing MAC Filtration -- Phase $phase..." ;
for my $ hostref ( @$ maclist_hosts ) {
$ maclist_interfaces { $ hostref - > [ 0 ] } = 1 ;
}
my @ maclist_interfaces = ( sort keys % maclist_interfaces ) ;
if ( $ phase == 1 ) {
for my $ interface ( @ maclist_interfaces ) {
my $ chainref = new_chain $ table , mac_chain $ interface ;
if ( $ family == F_IPV4 ) {
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , s = > '0.0.0.0' , d = > '255.255.255.255' , p = > 'udp --dport 67:68'
2009-02-22 18:30:14 +01:00
if $ table eq 'mangle' && get_interface_option ( $ interface , 'dhcp' ) ;
} else {
#
# Accept any packet with a link-level source or destination address
#
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , s = > 'ff80::/10' ;
add_ijump $ chainref , j = > 'RETURN' , d = > 'ff80::/10' ;
2009-02-22 18:30:14 +01:00
#
# Accept Multicast
#
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , d = > IPv6_MULTICAST ;
2009-02-22 18:30:14 +01:00
}
if ( $ ttl ) {
my $ chain1ref = new_chain $ table , macrecent_target $ interface ;
my $ chain = $ chainref - > { name } ;
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , recent = > "--rcheck --seconds $ttl --name $chain" ;
2011-07-18 00:12:58 +02:00
add_ijump $ chainref , j = > $ chain1ref ;
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , recent = > "--update --name $chain" ;
add_irule $ chainref , recent = > "--set --name $chain" ;
2009-02-22 18:30:14 +01:00
}
}
2010-09-28 19:48:44 +02:00
if ( my $ fn = open_file 'maclist' ) {
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
first_entry "$doing $fn..." ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
while ( read_a_line ) {
2009-02-22 18:30:14 +01:00
2011-10-01 18:56:25 +02:00
my ( $ original_disposition , $ interface , $ mac , $ addresses ) = split_line1 4 , 'maclist file' , { disposition = > 0 , interface = > 1 , mac = > 2 , addresses = > 3 } ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
if ( $ original_disposition eq 'COMMENT' ) {
process_comment ;
} else {
my ( $ disposition , $ level , $ remainder ) = split ( /:/ , $ original_disposition , 3 ) ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
fatal_error "Invalid DISPOSITION ($original_disposition)" if defined $ remainder || ! $ disposition ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
my $ targetref = $ maclist_targets { $ disposition } ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
fatal_error "Invalid DISPOSITION ($original_disposition)" if ! $ targetref || ( ( $ table eq 'mangle' ) && ! $ targetref - > { mangle } ) ;
fatal_error "Unknown Interface ($interface)" unless known_interface ( $ interface ) ;
fatal_error "No hosts on $interface have the maclist option specified" unless $ maclist_interfaces { $ interface } ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
my $ chainref = $ chain_table { $ table } { ( $ ttl ? macrecent_target $ interface : mac_chain $ interface ) } ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
$ mac = '' unless $ mac && ( $ mac ne '-' ) ;
$ addresses = '' unless defined $ addresses && ( $ addresses ne '-' ) ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
fatal_error "You must specify a MAC address or an IP address" unless $ mac || $ addresses ;
2009-02-22 18:30:14 +01:00
2011-07-17 17:35:09 +02:00
$ mac = do_mac $ mac if $ mac ;
2009-02-22 18:30:14 +01:00
2010-09-28 19:48:44 +02:00
if ( $ addresses ) {
for my $ address ( split ',' , $ addresses ) {
my $ source = match_source_net $ address ;
log_rule_limit $ level , $ chainref , mac_chain ( $ interface ) , $ disposition , '' , '' , 'add' , "${mac}${source}"
2011-06-12 01:14:31 +02:00
if supplied $ level ;
2011-05-23 02:42:50 +02:00
2011-08-13 18:56:14 +02:00
add_ijump ( $ chainref , j = > 'AUDIT' , targetopts = > '--type ' . lc $ disposition ) if $ audit && $ disposition ne 'ACCEPT' ;
2011-07-17 17:35:09 +02:00
add_jump ( $ chainref , $ targetref - > { target } , 0 , "${mac}${source}" ) ;
2010-09-28 19:48:44 +02:00
}
} else {
log_rule_limit $ level , $ chainref , mac_chain ( $ interface ) , $ disposition , '' , '' , 'add' , $ mac
2011-06-12 01:14:31 +02:00
if supplied $ level ;
2011-05-23 02:42:50 +02:00
2011-08-13 18:56:14 +02:00
add_ijump ( $ chainref , j = > 'AUDIT' , targetopts = > '--type ' . lc $ disposition ) if $ audit && $ disposition ne 'ACCEPT' ;
2011-07-17 17:35:09 +02:00
add_jump ( $ chainref , $ targetref - > { target } , 0 , "$mac" ) ;
2009-02-22 18:30:14 +01:00
}
2010-09-28 19:48:44 +02:00
progress_message " Maclist entry \"$currentline\" $done" ;
}
2009-02-22 18:30:14 +01:00
}
2010-09-28 19:48:44 +02:00
clear_comment ;
}
2009-02-22 18:30:14 +01:00
#
# Generate jumps from the input and forward chains
#
for my $ hostref ( @$ maclist_hosts ) {
my $ interface = $ hostref - > [ 0 ] ;
my $ ipsec = $ hostref - > [ 1 ] ;
2011-07-18 00:12:58 +02:00
my @ policy = have_ipsec ? ( policy = > "--pol $ipsec --dir in" ) : ( ) ;
my @ source = imatch_source_net $ hostref - > [ 2 ] ;
2009-02-22 18:30:14 +01:00
2011-07-18 00:12:58 +02:00
my @ state = $ globals { UNTRACKED } ? state_imatch 'NEW,UNTRACKED' : state_imatch 'NEW' ;
2009-02-22 18:30:14 +01:00
if ( $ table eq 'filter' ) {
my $ chainref = source_exclusion ( $ hostref - > [ 3 ] , $ filter_table - > { mac_chain $ interface } ) ;
for my $ chain ( first_chains $ interface ) {
2011-07-18 00:12:58 +02:00
add_ijump $ filter_table - > { $ chain } , j = > $ chainref , @ source , @ state , @ policy ;
2009-02-22 18:30:14 +01:00
}
set_interface_option $ interface , 'use_input_chain' , 1 ;
set_interface_option $ interface , 'use_forward_chain' , 1 ;
} else {
my $ chainref = source_exclusion ( $ hostref - > [ 3 ] , $ mangle_table - > { mac_chain $ interface } ) ;
2011-07-18 00:12:58 +02:00
add_ijump $ mangle_table - > { PREROUTING } , j = > $ chainref , imatch_source_dev ( $ interface ) , @ source , @ state , @ policy ;
2009-02-22 18:30:14 +01:00
}
}
} else {
2009-09-10 23:56:23 +02:00
#
# Phase II
#
2009-02-22 18:30:14 +01:00
for my $ interface ( @ maclist_interfaces ) {
my $ chainref = $ chain_table { $ table } { ( $ ttl ? macrecent_target $ interface : mac_chain $ interface ) } ;
my $ chain = $ chainref - > { name } ;
if ( $ family == F_IPV4 ) {
if ( $ level ne '' || $ disposition ne 'ACCEPT' ) {
my $ variable = get_interface_addresses source_port_to_bridge ( $ interface ) ;
2010-01-25 16:56:16 +01:00
if ( have_capability ( 'ADDRTYPE' ) ) {
2011-07-16 18:41:53 +02:00
add_commands ( $ chainref , "for address in $variable; do" ) ;
incr_cmd_level ( $ chainref ) ;
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'RETURN' , s = > '$address' , addrtype = > '--dst-type BROADCAST' ) ;
add_ijump ( $ chainref , j = > 'RETURN' , s = > '$address' , d = > '224.0.0.0/4' ) ;
2011-07-16 18:41:53 +02:00
decr_cmd_level ( $ chainref ) ;
add_commands ( $ chainref , 'done' ) ;
2009-02-22 18:30:14 +01:00
} else {
my $ bridge = source_port_to_bridge ( $ interface ) ;
my $ bridgeref = find_interface ( $ bridge ) ;
add_commands ( $ chainref ,
"for address in $variable; do" ) ;
2011-07-17 01:31:29 +02:00
incr_cmd_level ( $ chainref ) ;
2009-02-22 18:30:14 +01:00
if ( $ bridgeref - > { broadcasts } ) {
for my $ address ( @ { $ bridgeref - > { broadcasts } } , '255.255.255.255' ) {
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'RETURN' , s = > '$address' , d = > $ address ) ;
2009-02-22 18:30:14 +01:00
}
} else {
my $ variable1 = get_interface_bcasts $ bridge ;
2009-08-20 23:32:15 +02:00
add_commands ( $ chainref ,
2011-07-17 01:31:29 +02:00
" for address1 in $variable1; do" ) ;
incr_cmd_level ( $ chainref ) ;
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'RETURN' , s = > '$address' , d = > '$address1' ) ;
2011-07-17 01:31:29 +02:00
decr_cmd_level ( $ chainref ) ;
add_commands ( $ chainref , 'done' ) ;
2009-02-22 18:30:14 +01:00
}
2011-07-20 16:30:49 +02:00
add_ijump ( $ chainref , j = > 'RETURN' , s = > '$address' , d = > '224.0.0.0/4' ) ;
2011-07-17 01:31:29 +02:00
decr_cmd_level ( $ chainref ) ;
add_commands ( $ chainref , 'done' ) ;
2009-02-22 18:30:14 +01:00
}
}
}
run_user_exit2 ( 'maclog' , $ chainref ) ;
log_rule_limit $ level , $ chainref , $ chain , $ disposition , '' , '' , 'add' , '' if $ level ne '' ;
2011-07-18 00:12:58 +02:00
add_ijump $ chainref , j = > $ target ;
2009-02-22 18:30:14 +01:00
}
}
}
2010-12-15 21:57:55 +01:00
#
# Helper functions for generate_matrix()
#-----------------------------------------
#
# Return the target for rules from $zone to $zone1.
#
sub rules_target ( $$ ) {
my ( $ zone , $ zone1 ) = @ _ ;
my $ chain = rules_chain ( $ { zone } , $ { zone1 } ) ;
my $ chainref = $ filter_table - > { $ chain } ;
return $ chain if $ chainref && $ chainref - > { referenced } ;
return 'ACCEPT' if $ zone eq $ zone1 ;
assert ( $ chainref ) ;
if ( $ chainref - > { policy } ne 'CONTINUE' ) {
my $ policyref = $ filter_table - > { $ chainref - > { policychain } } ;
assert ( $ policyref ) ;
return $ policyref - > { name } if $ policyref ne $ chainref ;
return $ chainref - > { policy } eq 'REJECT' ? 'reject' : $ chainref - > { policy } ;
}
'' ; # CONTINUE policy
}
2010-07-01 05:35:46 +02:00
#
2010-07-07 15:43:07 +02:00
# Generate rules for one destination zone
2010-07-01 05:35:46 +02:00
#
2011-07-18 16:24:21 +02:00
sub generate_dest_rules ( $$$;@ ) {
my ( $ chainref , $ chain , $ z2 , @ matches ) = @ _ ;
2010-07-01 05:35:46 +02:00
my $ z2ref = find_zone ( $ z2 ) ;
my $ type2 = $ z2ref - > { type } ;
if ( $ type2 == VSERVER ) {
2010-07-09 02:11:27 +02:00
for my $ hostref ( @ { $ z2ref - > { hosts } { ip } { '%vserver%' } } ) {
2010-09-28 19:48:44 +02:00
my $ exclusion = dest_exclusion ( $ hostref - > { exclusions } , $ chain ) ;
2010-07-09 02:11:27 +02:00
for my $ net ( @ { $ hostref - > { hosts } } ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ chainref ,
j = > $ exclusion ,
imatch_dest_net ( $ net ) ,
@ matches ) ;
2010-07-01 05:35:46 +02:00
}
}
} else {
2011-07-18 16:24:21 +02:00
add_ijump ( $ chainref , j = > $ chain , @ matches ) ;
2010-07-01 05:35:46 +02:00
}
}
#
2010-07-09 02:45:18 +02:00
# Generate rules for one vserver source zone
2010-07-01 05:35:46 +02:00
#
2011-07-18 16:24:21 +02:00
sub generate_source_rules ( $$$;@ ) {
my ( $ outchainref , $ z1 , $ z2 , @ matches ) = @ _ ;
2010-07-01 05:35:46 +02:00
my $ chain = rules_target ( $ z1 , $ z2 ) ;
2010-09-27 20:16:18 +02:00
2010-07-01 05:35:46 +02:00
if ( $ chain ) {
#
# Not a CONTINUE policy with no rules
#
2010-07-09 02:11:27 +02:00
for my $ hostref ( @ { defined_zone ( $ z1 ) - > { hosts } { ip } { '%vserver%' } } ) {
2011-07-18 16:24:21 +02:00
my @ ipsec_match = match_ipsec_in $ z1 , $ hostref ;
2010-07-09 02:11:27 +02:00
my $ exclusion = source_exclusion ( $ hostref - > { exclusions } , $ chain ) ;
2010-09-27 20:16:18 +02:00
2010-07-09 02:11:27 +02:00
for my $ net ( @ { $ hostref - > { hosts } } ) {
generate_dest_rules ( $ outchainref ,
$ exclusion ,
2010-09-27 20:16:18 +02:00
$ z2 ,
2011-07-18 16:24:21 +02:00
imatch_source_net ( $ net ) ,
@ matches ,
@ ipsec_match
2010-07-09 02:11:27 +02:00
) ;
2010-09-27 20:16:18 +02:00
}
2010-07-01 05:35:46 +02:00
}
2010-09-27 20:16:18 +02:00
}
2010-07-01 05:35:46 +02:00
}
#
2010-09-28 19:48:44 +02:00
# Loopback traffic -- this is where we assemble the intra-firewall chains
2010-07-01 05:35:46 +02:00
#
sub handle_loopback_traffic () {
my @ zones = ( vserver_zones , firewall_zone ) ;
my $ natout = $ nat_table - > { OUTPUT } ;
my $ rulenum = 0 ;
my $ outchainref ;
2011-07-18 16:24:21 +02:00
my @ rule ;
2010-07-01 05:35:46 +02:00
if ( @ zones > 1 ) {
$ outchainref = new_standard_chain 'loopback' ;
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { OUTPUT } , j = > $ outchainref , o = > 'lo' ;
2010-07-01 05:35:46 +02:00
} else {
$ outchainref = $ filter_table - > { OUTPUT } ;
2011-07-18 16:24:21 +02:00
@ rule = ( o = > 'lo' ) ;
2010-07-01 05:35:46 +02:00
}
for my $ z1 ( @ zones ) {
my $ z1ref = find_zone ( $ z1 ) ;
my $ type1 = $ z1ref - > { type } ;
my $ natref = $ nat_table - > { dnat_chain $ z1 } ;
if ( $ type1 == FIREWALL ) {
for my $ z2 ( @ zones ) {
my $ chain = rules_target ( $ z1 , $ z2 ) ;
2011-07-18 16:24:21 +02:00
generate_dest_rules ( $ outchainref , $ chain , $ z2 , @ rule ) if $ chain ;
2010-07-01 05:35:46 +02:00
}
} else {
for my $ z2 ( @ zones ) {
2011-07-18 16:24:21 +02:00
generate_source_rules ( $ outchainref , $ z1 , $ z2 , @ rule ) ;
2010-07-01 05:35:46 +02:00
}
}
if ( $ natref && $ natref - > { referenced } ) {
my $ source_hosts_ref = defined_zone ( $ z1 ) - > { hosts } ;
for my $ typeref ( values % { $ source_hosts_ref } ) {
for my $ hostref ( @ { $ typeref - > { '%vserver%' } } ) {
my $ exclusion = source_exclusion ( $ hostref - > { exclusions } , $ natref ) ;
2010-09-27 20:16:18 +02:00
2010-07-01 05:35:46 +02:00
for my $ net ( @ { $ hostref - > { hosts } } ) {
2011-07-18 16:24:21 +02:00
insert_ijump ( $ natout ,
j = > $ exclusion ,
$ rulenum + + ,
imatch_source_net ( $ net , 0 , ) ) ;
2010-07-01 05:35:46 +02:00
}
2010-09-27 20:16:18 +02:00
}
2010-07-01 05:35:46 +02:00
}
}
}
2011-07-20 16:30:49 +02:00
add_ijump $ filter_table - > { INPUT } , j = > 'ACCEPT' , i = > 'lo' ;
2010-07-01 05:35:46 +02:00
}
2009-02-22 18:30:14 +01:00
#
# Add jumps from the builtin chains to the interface-chains that are used by this configuration
#
sub add_interface_jumps {
2009-10-17 19:59:41 +02:00
our % input_jump_added ;
our % output_jump_added ;
our % forward_jump_added ;
2009-02-22 18:30:14 +01:00
#
# Add Nat jumps
#
for my $ interface ( @ _ ) {
2011-07-19 20:58:10 +02:00
addnatjump 'POSTROUTING' , snat_chain ( $ interface ) , imatch_dest_dev ( $ interface ) ;
2009-02-22 18:30:14 +01:00
}
2011-07-19 20:58:10 +02:00
addnatjump 'PREROUTING' , 'nat_in' ;
addnatjump 'POSTROUTING' , 'nat_out' ;
addnatjump 'PREROUTING' , 'dnat' ;
2009-02-22 18:30:14 +01:00
2010-07-01 05:35:46 +02:00
for my $ interface ( grep $ _ ne '%vserver%' , @ _ ) {
2011-07-19 20:58:10 +02:00
addnatjump 'PREROUTING' , input_chain ( $ interface ) , imatch_source_dev ( $ interface ) ;
addnatjump 'POSTROUTING' , output_chain ( $ interface ) , imatch_dest_dev ( $ interface ) ;
addnatjump 'POSTROUTING' , masq_chain ( $ interface ) , imatch_dest_dev ( $ interface ) ;
2011-08-14 21:01:17 +02:00
if ( have_capability 'RAWPOST_TABLE' ) {
insert_ijump ( $ rawpost_table - > { POSTROUTING } , j = > postrouting_chain ( $ interface ) , 0 , imatch_dest_dev ( $ interface ) ) if $ rawpost_table - > { postrouting_chain $ interface } ;
insert_ijump ( $ raw_table - > { PREROUTING } , j = > prerouting_chain ( $ interface ) , 0 , imatch_source_dev ( $ interface ) ) if $ raw_table - > { prerouting_chain $ interface } ;
insert_ijump ( $ raw_table - > { OUTPUT } , j = > output_chain ( $ interface ) , 0 , imatch_dest_dev ( $ interface ) ) if $ raw_table - > { output_chain $ interface } ;
}
2009-02-22 18:30:14 +01:00
}
#
# Add the jumps to the interface chains from filter FORWARD, INPUT, OUTPUT
#
2010-07-01 05:35:46 +02:00
for my $ interface ( grep $ _ ne '%vserver%' , @ _ ) {
2010-04-27 21:26:58 +02:00
my $ forwardref = $ filter_table - > { forward_chain $ interface } ;
my $ inputref = $ filter_table - > { input_chain $ interface } ;
my $ outputref = $ filter_table - > { output_chain $ interface } ;
my $ interfaceref = find_interface ( $ interface ) ;
2011-04-03 18:56:30 +02:00
if ( $ interfaceref - > { options } { port } ) {
my $ bridge = $ interfaceref - > { bridge } ;
2011-07-20 16:30:49 +02:00
add_ijump ( $ filter_table - > { forward_chain $ bridge } ,
2011-07-18 00:12:58 +02:00
j = > 'ACCEPT' ,
imatch_source_dev ( $ interface , 1 ) ,
imatch_dest_dev ( $ interface , 1 )
2011-04-03 18:56:30 +02:00
) unless $ interfaceref - > { nets } || ! $ interfaceref - > { options } { bridge } ;
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { forward_chain $ bridge } ,
j = > $ forwardref ,
imatch_source_dev ( $ interface , 1 )
) unless $ forward_jump_added { $ interface } || ! use_forward_chain $ interface , $ forwardref ;
2011-04-03 18:56:30 +02:00
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { input_chain $ bridge } ,
j = > $ inputref ,
imatch_source_dev ( $ interface , 1 )
2011-04-03 18:56:30 +02:00
) unless $ input_jump_added { $ interface } || ! use_input_chain $ interface , $ inputref ;
unless ( $ output_jump_added { $ interface } || ! use_output_chain $ interface , $ outputref ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { output_chain $ bridge } ,
j = > $ outputref ,
imatch_dest_dev ( $ interface , 1 ) )
2011-04-03 18:56:30 +02:00
unless get_interface_option ( $ interface , 'port' ) ;
}
} else {
2011-07-20 16:30:49 +02:00
add_ijump ( $ filter_table - > { FORWARD } , j = > 'ACCEPT' , imatch_source_dev ( $ interface ) , imatch_dest_dev ( $ interface ) ) unless $ interfaceref - > { nets } || ! $ interfaceref - > { options } { bridge } ;
2009-02-22 18:30:14 +01:00
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { FORWARD } , j = > $ forwardref , imatch_source_dev ( $ interface ) ) unless $ forward_jump_added { $ interface } || ! use_forward_chain $ interface , $ forwardref ;
add_ijump ( $ filter_table - > { INPUT } , j = > $ inputref , imatch_source_dev ( $ interface ) ) unless $ input_jump_added { $ interface } || ! use_input_chain $ interface , $ inputref ;
2010-03-11 02:25:06 +01:00
2011-04-03 18:56:30 +02:00
unless ( $ output_jump_added { $ interface } || ! use_output_chain $ interface , $ outputref ) {
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { OUTPUT } , j = > $ outputref , imatch_dest_dev ( $ interface ) unless get_interface_option ( $ interface , 'port' ) ;
2011-04-03 18:56:30 +02:00
}
2009-02-22 18:30:14 +01:00
}
}
2010-07-01 05:35:46 +02:00
handle_loopback_traffic ;
2009-02-22 18:30:14 +01:00
}
# Generate the rules matrix.
#
2009-10-20 21:24:28 +02:00
# Stealing a comment from the Burroughs B6700 MCP Operating System source, "generate_matrix makes a sow's ear out of a silk purse".
2009-02-22 18:30:14 +01:00
#
# The biggest disadvantage of the zone-policy-rule model used by Shorewall is that it doesn't scale well as the number of zones increases (Order N**2 where N = number of zones).
# A major goal of the rewrite of the compiler in Perl was to restrict those scaling effects to this function and the rules that it generates.
#
2010-12-29 02:18:43 +01:00
# The function traverses the full "source-zone by destination-zone" matrix and generates the rules necessary to direct traffic through the right set of filter-table and
# nat-table rules.
2009-02-22 18:30:14 +01:00
#
sub generate_matrix () {
my @ interfaces = ( all_interfaces ) ;
2010-12-18 05:16:09 +01:00
#
# Should this be the real PREROUTING chain?
#
2009-02-22 18:30:14 +01:00
my $ preroutingref = ensure_chain 'nat' , 'dnat' ;
2010-12-18 05:16:09 +01:00
my $ fw = firewall_zone ;
my @ zones = off_firewall_zones ;
my @ vservers = vserver_zones ;
2009-02-22 18:30:14 +01:00
my $ notrackref = $ raw_table - > { notrack_chain $ fw } ;
2011-07-18 16:24:21 +02:00
my @ state = $ config { BLACKLISTNEWONLY } ? $ globals { UNTRACKED } ? state_imatch 'NEW,INVALID,UNTRACKED' : state_imatch 'NEW,INVALID' : ( ) ;
2009-02-22 18:30:14 +01:00
my $ interface_jumps_added = 0 ;
2010-12-18 05:16:09 +01:00
2009-10-17 19:59:41 +02:00
our % input_jump_added = ( ) ;
our % output_jump_added = ( ) ;
our % forward_jump_added = ( ) ;
2011-04-03 18:56:30 +02:00
my % ipsec_jump_added = ( ) ;
2009-02-22 18:30:14 +01:00
2010-03-08 22:11:10 +01:00
progress_message2 'Generating Rule Matrix...' ;
2010-09-26 01:07:56 +02:00
progress_message ' Handling blacklisting and complex zones...' ;
2011-05-23 02:42:50 +02:00
2009-02-22 18:30:14 +01:00
#
2010-09-25 00:25:57 +02:00
# Special processing for complex and/or blacklisting configurations
2009-02-22 18:30:14 +01:00
#
for my $ zone ( @ zones ) {
2009-10-18 17:47:20 +02:00
my $ zoneref = find_zone ( $ zone ) ;
2010-09-25 00:25:57 +02:00
my $ simple = @ zones <= 2 && ! $ zoneref - > { options } { complex } ;
#
# Handle blacklisting first
#
2010-09-16 18:40:28 +02:00
if ( $ zoneref - > { options } { in } { blacklist } ) {
my $ blackref = $ filter_table - > { blacklst } ;
2011-07-18 16:24:21 +02:00
insert_ijump ensure_rules_chain ( rules_chain ( $ zone , $ _ ) ) , j = > $ blackref , - 1 , @ state for firewall_zone , @ vservers ;
2010-09-27 20:16:18 +02:00
2010-09-25 00:25:57 +02:00
if ( $ simple ) {
2010-09-26 01:07:56 +02:00
#
# We won't create a zone forwarding chain for this zone so we must add blacklisting jumps to the rules chains
#
2010-09-25 00:25:57 +02:00
for my $ zone1 ( @ zones ) {
my $ ruleschain = rules_chain ( $ zone , $ zone1 ) ;
my $ ruleschainref = $ filter_table - > { $ ruleschain } ;
2010-09-27 20:16:18 +02:00
2010-09-26 01:07:56 +02:00
if ( ( $ zone ne $ zone1 || $ ruleschainref - > { referenced } ) && $ ruleschainref - > { policy } ne 'NONE' ) {
2011-07-18 16:24:21 +02:00
insert_ijump ( ensure_rules_chain ( $ ruleschain ) , j = > $ blackref , - 1 , @ state ) ;
2010-09-25 00:25:57 +02:00
}
}
}
2010-09-16 18:40:28 +02:00
}
if ( $ zoneref - > { options } { out } { blacklist } ) {
my $ blackref = $ filter_table - > { blackout } ;
2011-07-18 16:24:21 +02:00
insert_ijump ensure_rules_chain ( rules_chain ( firewall_zone , $ zone ) ) , j = > $ blackref , - 1 , @ state ;
2010-09-16 18:40:28 +02:00
2010-09-18 01:38:34 +02:00
for my $ zone1 ( @ zones , @ vservers ) {
2010-09-17 03:19:16 +02:00
my $ ruleschain = rules_chain ( $ zone1 , $ zone ) ;
my $ ruleschainref = $ filter_table - > { $ ruleschain } ;
2010-09-26 01:07:56 +02:00
if ( ( $ zone ne $ zone1 || $ ruleschainref - > { referenced } ) && $ ruleschainref - > { policy } ne 'NONE' ) {
2011-07-18 16:24:21 +02:00
insert_ijump ( ensure_rules_chain ( $ ruleschain ) , j = > $ blackref , - 1 , @ state ) ;
2010-09-27 20:16:18 +02:00
}
2010-09-16 18:40:28 +02:00
}
}
2010-09-16 15:55:48 +02:00
2010-09-25 00:25:57 +02:00
next if $ simple ;
2010-09-27 20:16:18 +02:00
2010-09-24 20:16:31 +02:00
#
# Complex zone or we have more than one non-firewall zone -- create a zone forwarding chain
#
my $ frwd_ref = new_standard_chain zone_forward_chain ( $ zone ) ;
2011-07-18 16:24:21 +02:00
insert_ijump $ frwd_ref , j = > $ filter_table - > { blacklst } , - 1 , @ state if $ zoneref - > { options } { in } { blacklist } ;
2010-09-24 20:16:31 +02:00
2010-01-25 17:13:22 +01:00
if ( have_ipsec ) {
2009-10-20 21:24:28 +02:00
#
# Because policy match only matches an 'in' or an 'out' policy (but not both), we have to place the
# '--pol ipsec --dir in' rules at the front of the (interface) forwarding chains. Otherwise, decrypted packets
# can match '--pol none --dir out' rules and send the packets down the wrong rules chain.
#
2009-02-22 18:30:14 +01:00
my $ type = $ zoneref - > { type } ;
my $ source_ref = ( $ zoneref - > { hosts } { ipsec } ) || { } ;
for my $ interface ( sort { interface_number ( $ a ) <=> interface_number ( $ b ) } keys %$ source_ref ) {
2010-03-11 02:25:06 +01:00
my $ sourcechainref = $ filter_table - > { forward_chain $ interface } ;
2011-07-18 16:24:21 +02:00
my @ interfacematch ;
2011-04-03 18:56:30 +02:00
my $ interfaceref = find_interface $ interface ;
2009-02-22 18:30:14 +01:00
2010-03-11 02:25:06 +01:00
if ( use_forward_chain ( $ interface , $ sourcechainref ) ) {
2011-04-03 18:56:30 +02:00
if ( $ interfaceref - > { ports } && $ interfaceref - > { options } { bridge } ) {
2011-07-18 16:24:21 +02:00
@ interfacematch = imatch_source_dev $ interface ;
2011-04-03 18:56:30 +02:00
copy_rules ( $ sourcechainref , $ frwd_ref , 1 ) unless $ ipsec_jump_added { $ zone } + + ;
$ sourcechainref = $ filter_table - > { FORWARD } ;
} elsif ( $ interfaceref - > { options } { port } ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { forward_chain $ interfaceref - > { bridge } } ,
j = > $ sourcechainref ,
imatch_source_dev ( $ interface , 1 ) )
2011-04-03 18:56:30 +02:00
unless $ forward_jump_added { $ interface } + + ;
} else {
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { FORWARD } , j = > $ sourcechainref , imatch_source_dev ( $ interface ) unless $ forward_jump_added { $ interface } + + ;
2011-04-03 18:56:30 +02:00
}
2009-02-22 18:30:14 +01:00
} else {
2011-04-03 18:56:30 +02:00
if ( $ interfaceref - > { options } { port } ) {
$ sourcechainref = $ filter_table - > { forward_chain $ interfaceref - > { bridge } } ;
2011-07-18 16:24:21 +02:00
@ interfacematch = imatch_source_dev $ interface , 1 ;
2011-04-03 18:56:30 +02:00
} else {
$ sourcechainref = $ filter_table - > { FORWARD } ;
2011-07-18 16:24:21 +02:00
@ interfacematch = imatch_source_dev $ interface ;
2011-04-03 18:56:30 +02:00
}
2009-02-22 18:30:14 +01:00
move_rules ( $ filter_table - > { forward_chain $ interface } , $ frwd_ref ) ;
}
my $ arrayref = $ source_ref - > { $ interface } ;
for my $ hostref ( @ { $ arrayref } ) {
2011-07-18 16:24:21 +02:00
my @ ipsec_match = match_ipsec_in $ zone , $ hostref ;
2009-02-22 18:30:14 +01:00
for my $ net ( @ { $ hostref - > { hosts } } ) {
2011-07-18 16:24:21 +02:00
add_ijump (
$ sourcechainref ,
@ { $ zoneref - > { parents } } ? 'j' : 'g' = > source_exclusion ( $ hostref - > { exclusions } , $ frwd_ref ) ,
@ interfacematch ,
imatch_source_net ( $ net ) ,
@ ipsec_match
) ;
2009-02-22 18:30:14 +01:00
}
}
}
}
}
#
# NOTRACK from firewall
#
2011-07-18 16:24:21 +02:00
add_ijump $ raw_table - > { OUTPUT } , j = > $ notrackref if $ notrackref - > { referenced } ;
2009-02-22 18:30:14 +01:00
#
# Main source-zone matrix-generation loop
#
2010-09-26 01:07:56 +02:00
progress_message ' Entering main matrix-generation loop...' ;
2009-02-22 18:30:14 +01:00
for my $ zone ( @ zones ) {
my $ zoneref = find_zone ( $ zone ) ;
my $ source_hosts_ref = $ zoneref - > { hosts } ;
my $ chain1 = rules_target firewall_zone , $ zone ;
my $ chain2 = rules_target $ zone , firewall_zone ;
my $ complex = $ zoneref - > { options } { complex } || 0 ;
my $ type = $ zoneref - > { type } ;
my $ frwd_ref = $ filter_table - > { zone_forward_chain $ zone } ;
my $ chain = 0 ;
my $ dnatref = ensure_chain 'nat' , dnat_chain ( $ zone ) ;
my $ notrackref = ensure_chain 'raw' , notrack_chain ( $ zone ) ;
my $ nested = $ zoneref - > { options } { nested } ;
my $ parenthasnat = 0 ;
my $ parenthasnotrack = 0 ;
if ( $ nested ) {
#
# This is a sub-zone. We need to determine if
#
# a) A parent zone defines DNAT/REDIRECT or notrack rules; and
# b) The current zone has a CONTINUE policy to some other zone.
#
# If a) but not b), then we must avoid sending packets from this
# zone through the DNAT/REDIRECT or notrack chain for the parent.
#
for my $ parent ( @ { $ zoneref - > { parents } } ) {
my $ ref1 = $ nat_table - > { dnat_chain $ parent } || { } ;
my $ ref2 = $ raw_table - > { notrack_chain $ parent } || { } ;
$ parenthasnat = 1 if $ ref1 - > { referenced } ;
$ parenthasnotrack = 1 if $ ref2 - > { referenced } ;
last if $ parenthasnat && $ parenthasnotrack ;
}
if ( $ parenthasnat || $ parenthasnotrack ) {
for my $ zone1 ( all_zones ) {
2009-11-14 16:07:19 +01:00
if ( $ filter_table - > { rules_chain ( $ { zone } , $ { zone1 } ) } - > { policy } eq 'CONTINUE' ) {
2009-02-22 18:30:14 +01:00
#
# This zone has a continue policy to another zone. We must
# send packets from this zone through the parent's DNAT/REDIRECT/NOTRACK chain.
#
$ nested = 0 ;
last ;
}
}
} else {
#
# No parent has DNAT or notrack so there is nothing to worry about. Don't bother to generate needless RETURN rules in the 'dnat' or 'notrack' chain.
#
$ nested = 0 ;
}
}
#
# Take care of PREROUTING, INPUT and OUTPUT jumps
#
for my $ typeref ( values %$ source_hosts_ref ) {
for my $ interface ( sort { interface_number ( $ a ) <=> interface_number ( $ b ) } keys %$ typeref ) {
my $ arrayref = $ typeref - > { $ interface } ;
2011-04-03 18:56:30 +02:00
my $ interfaceref = find_interface $ interface ;
my $ isport = $ interfaceref - > { options } { port } ;
my $ bridge = $ interfaceref - > { bridge } ;
2009-02-22 18:30:14 +01:00
2010-07-31 19:49:49 +02:00
if ( get_physical ( $ interface ) eq '+' ) {
2009-02-22 18:30:14 +01:00
#
# Insert the interface-specific jumps before this one which is not interface-specific
#
add_interface_jumps ( @ interfaces ) unless $ interface_jumps_added + + ;
}
for my $ hostref ( @$ arrayref ) {
2011-07-18 16:24:21 +02:00
my @ ipsec_in_match = match_ipsec_in $ zone , $ hostref ;
my @ ipsec_out_match = match_ipsec_out $ zone , $ hostref ;
2009-02-22 18:30:14 +01:00
my $ exclusions = $ hostref - > { exclusions } ;
2010-09-27 20:16:18 +02:00
2009-02-22 18:30:14 +01:00
for my $ net ( @ { $ hostref - > { hosts } } ) {
2011-07-18 16:24:21 +02:00
my @ dest = imatch_dest_net $ net ;
2009-02-22 18:30:14 +01:00
2010-04-16 18:56:11 +02:00
if ( $ chain1 && zone_type ( $ zone ) != BPORT ) {
2010-02-03 15:57:51 +01:00
my $ chain1ref = $ filter_table - > { $ chain1 } ;
2009-02-22 18:30:14 +01:00
my $ nextchain = dest_exclusion ( $ exclusions , $ chain1 ) ;
my $ outputref ;
2010-02-03 15:57:51 +01:00
my $ interfacechainref = $ filter_table - > { output_chain $ interface } ;
2011-07-18 16:24:21 +02:00
my @ interfacematch ;
2010-02-03 04:42:54 +01:00
my $ use_output = 0 ;
2009-02-22 18:30:14 +01:00
2010-09-15 16:38:20 +02:00
if ( @ vservers || use_output_chain ( $ interface , $ interfacechainref ) || ( @ { $ interfacechainref - > { rules } } && ! $ chain1ref ) ) {
2010-02-03 15:57:51 +01:00
$ outputref = $ interfacechainref ;
2011-04-03 18:56:30 +02:00
if ( $ isport ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { output_chain $ bridge } ,
j = > $ outputref ,
imatch_dest_dev ( $ interface , 1 ) )
2011-04-03 18:56:30 +02:00
unless $ output_jump_added { $ interface } + + ;
} else {
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { OUTPUT } , j = > $ outputref , imatch_dest_dev ( $ interface ) unless $ output_jump_added { $ interface } + + ;
2011-04-03 18:56:30 +02:00
}
2010-02-03 04:42:54 +01:00
$ use_output = 1 ;
2010-07-01 05:35:46 +02:00
2010-07-16 19:06:29 +02:00
unless ( lc $ net eq IPv6_LINKLOCAL ) {
2010-07-12 21:39:51 +02:00
for my $ vzone ( vserver_zones ) {
2011-07-18 16:24:21 +02:00
generate_source_rules ( $ outputref , $ vzone , $ zone , @ dest ) ;
2010-07-12 21:39:51 +02:00
}
}
2011-04-03 18:56:30 +02:00
} elsif ( $ isport ) {
$ outputref = $ filter_table - > { output_chain $ bridge } ;
2011-07-18 16:24:21 +02:00
@ interfacematch = imatch_dest_dev $ interface , 1 ;
2009-02-22 18:30:14 +01:00
} else {
$ outputref = $ filter_table - > { OUTPUT } ;
2011-07-18 16:24:21 +02:00
@ interfacematch = imatch_dest_dev $ interface ;
2009-02-22 18:30:14 +01:00
}
2011-07-18 16:24:21 +02:00
add_ijump $ outputref , j = > $ nextchain , @ interfacematch , @ dest , @ ipsec_out_match ;
2009-02-22 18:30:14 +01:00
2011-07-18 16:24:21 +02:00
add_ijump ( $ outputref , j = > $ nextchain , @ interfacematch , d = > '255.255.255.255' , @ ipsec_out_match )
2010-07-12 04:52:18 +02:00
if $ family == F_IPV4 && $ hostref - > { options } { broadcast } ;
2009-02-22 18:30:14 +01:00
2010-02-03 15:57:51 +01:00
move_rules ( $ interfacechainref , $ chain1ref ) unless $ use_output ;
2009-02-22 18:30:14 +01:00
}
clearrule ;
2009-08-20 23:32:15 +02:00
next if $ hostref - > { options } { destonly } ;
2009-02-22 18:30:14 +01:00
2011-07-18 16:24:21 +02:00
my @ source = imatch_source_net $ net ;
2009-02-22 18:30:14 +01:00
if ( $ dnatref - > { referenced } ) {
#
# There are DNAT/REDIRECT rules with this zone as the source.
# Add a jump from this source network to this zone's DNAT/REDIRECT chain
#
2011-07-18 16:24:21 +02:00
add_ijump ( $ preroutingref ,
j = > source_exclusion ( $ exclusions , $ dnatref ) ,
imatch_source_dev ( $ interface ) ,
@ source ,
@ ipsec_in_match ) ;
2011-04-07 00:14:39 +02:00
if ( get_physical ( $ interface ) eq '+' ) {
#
2011-04-08 16:50:54 +02:00
# The jump from the PREROUTING chain to dnat may not have been added above
2011-04-07 00:14:39 +02:00
#
2011-07-19 20:58:10 +02:00
addnatjump 'PREROUTING' , 'dnat' unless $ preroutingref - > { references } { PREROUTING } ;
2011-04-07 00:14:39 +02:00
}
2011-07-18 16:24:21 +02:00
check_optimization ( $ dnatref ) if @ source ;
2009-02-22 18:30:14 +01:00
}
if ( $ notrackref - > { referenced } ) {
#
# There are notrack rules with this zone as the source.
# Add a jump from this source network to this zone's notrack chain
#
2011-07-18 16:24:21 +02:00
add_ijump $ raw_table - > { PREROUTING } , j = > source_exclusion ( $ exclusions , $ notrackref ) , imatch_source_dev ( $ interface ) , @ source , @ ipsec_in_match ;
2009-02-22 18:30:14 +01:00
}
2010-02-01 23:24:07 +01:00
2009-02-22 18:30:14 +01:00
#
# If this zone has parents with DNAT/REDIRECT or notrack rules and there are no CONTINUE polcies with this zone as the source
# then add a RETURN jump for this source network.
#
if ( $ nested ) {
2011-07-20 16:30:49 +02:00
add_ijump $ preroutingref , j = > 'RETURN' , imatch_source_dev ( $ interface ) , @ source , @ ipsec_in_match if $ parenthasnat ;
add_ijump $ raw_table - > { PREROUTING } , j = > 'RETURN' , imatch_source_dev ( $ interface ) , @ source , @ ipsec_in_match if $ parenthasnotrack ;
2009-02-22 18:30:14 +01:00
}
2010-02-03 15:57:51 +01:00
my $ chain2ref = $ filter_table - > { $ chain2 } ;
2009-02-22 18:30:14 +01:00
my $ inputchainref ;
2010-02-03 15:57:51 +01:00
my $ interfacechainref = $ filter_table - > { input_chain $ interface } ;
2011-07-18 16:24:21 +02:00
my @ interfacematch ;
2010-02-03 04:42:54 +01:00
my $ use_input ;
2010-09-16 18:40:28 +02:00
my $ blacklist = $ zoneref - > { options } { in } { blacklist } ;
2009-02-22 18:30:14 +01:00
2010-07-01 05:35:46 +02:00
if ( @ vservers || use_input_chain ( $ interface , $ interfacechainref ) || ! $ chain2 || ( @ { $ interfacechainref - > { rules } } && ! $ chain2ref ) ) {
2010-02-03 15:57:51 +01:00
$ inputchainref = $ interfacechainref ;
2011-04-03 18:56:30 +02:00
if ( $ isport ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { input_chain $ bridge } ,
j = > $ inputchainref ,
imatch_source_dev ( $ interface , 1 ) )
2011-04-03 18:56:30 +02:00
unless $ input_jump_added { $ interface } + + ;
} else {
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { INPUT } , j = > $ inputchainref , imatch_source_dev ( $ interface ) unless $ input_jump_added { $ interface } + + ;
2011-04-03 18:56:30 +02:00
}
2010-02-03 04:42:54 +01:00
$ use_input = 1 ;
2010-07-01 05:35:46 +02:00
2010-07-16 19:06:29 +02:00
unless ( lc $ net eq IPv6_LINKLOCAL ) {
2010-07-12 20:52:56 +02:00
for my $ vzone ( @ vservers ) {
my $ target = rules_target ( $ zone , $ vzone ) ;
2011-07-18 16:24:21 +02:00
generate_dest_rules ( $ inputchainref , $ target , $ vzone , @ source , @ ipsec_in_match ) if $ target ;
2010-07-12 20:52:56 +02:00
}
2010-07-01 05:35:46 +02:00
}
2011-04-03 18:56:30 +02:00
} elsif ( $ isport ) {
$ inputchainref = $ filter_table - > { input_chain $ bridge } ;
2011-07-18 16:24:21 +02:00
@ interfacematch = imatch_source_dev $ interface , 1 ;
2009-02-22 18:30:14 +01:00
} else {
$ inputchainref = $ filter_table - > { INPUT } ;
2011-07-18 16:24:21 +02:00
@ interfacematch = imatch_source_dev $ interface ;
2009-02-22 18:30:14 +01:00
}
if ( $ chain2 ) {
2011-07-18 16:24:21 +02:00
add_ijump $ inputchainref , j = > source_exclusion ( $ exclusions , $ chain2 ) , @ interfacematch , @ source , @ ipsec_in_match ;
2010-02-03 15:57:51 +01:00
move_rules ( $ interfacechainref , $ chain2ref ) unless $ use_input ;
2009-02-22 18:30:14 +01:00
}
if ( $ frwd_ref && $ hostref - > { ipsec } ne 'ipsec' ) {
my $ ref = source_exclusion ( $ exclusions , $ frwd_ref ) ;
2010-03-11 02:25:06 +01:00
my $ forwardref = $ filter_table - > { forward_chain $ interface } ;
2011-04-03 18:56:30 +02:00
2010-03-11 02:25:06 +01:00
if ( use_forward_chain $ interface , $ forwardref ) {
2011-07-18 16:24:21 +02:00
add_ijump $ forwardref , j = > $ ref , @ source , @ ipsec_in_match ;
2011-04-03 18:56:30 +02:00
if ( $ isport ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { forward_chain $ bridge } ,
j = > $ forwardref ,
imatch_source_dev ( $ interface , 1 ) )
2011-04-03 18:56:30 +02:00
unless $ forward_jump_added { $ interface } + + ;
} else {
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { FORWARD } , j = > $ forwardref , imatch_source_dev ( $ interface ) unless $ forward_jump_added { $ interface } + + ;
2011-04-03 18:56:30 +02:00
}
2009-02-22 18:30:14 +01:00
} else {
2011-04-03 18:56:30 +02:00
if ( $ isport ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { forward_chain $ bridge } ,
j = > $ ref ,
imatch_source_dev ( $ interface , 1 ) ,
@ source ,
@ ipsec_in_match ) ;
2011-04-03 18:56:30 +02:00
} else {
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { FORWARD } , j = > $ ref , imatch_source_dev ( $ interface ) , @ source , @ ipsec_in_match ;
2011-04-03 18:56:30 +02:00
}
2010-03-11 02:25:06 +01:00
move_rules ( $ forwardref , $ frwd_ref ) ;
2009-02-22 18:30:14 +01:00
}
}
}
}
}
}
#
# F O R W A R D I N G
#
my @ dest_zones ;
my $ last_chain = '' ;
2010-01-16 18:53:53 +01:00
if ( $ config { OPTIMIZE } & 1 ) {
2009-02-22 18:30:14 +01:00
my @ temp_zones ;
for my $ zone1 ( @ zones ) {
my $ zone1ref = find_zone ( $ zone1 ) ;
2009-11-14 16:07:19 +01:00
my $ policy = $ filter_table - > { rules_chain ( $ { zone } , $ { zone1 } ) } - > { policy } ;
2009-02-22 18:30:14 +01:00
2009-11-03 18:28:34 +01:00
next if $ policy eq 'NONE' ;
2009-02-22 18:30:14 +01:00
my $ chain = rules_target $ zone , $ zone1 ;
next unless $ chain ;
if ( $ zone eq $ zone1 ) {
next if ( scalar ( keys ( % { $ zoneref - > { interfaces } } ) ) < 2 ) && ! $ zoneref - > { options } { in_out } { routeback } ;
}
2009-03-13 23:59:49 +01:00
if ( $ zone1ref - > { type } == BPORT ) {
2009-02-22 18:30:14 +01:00
next unless $ zoneref - > { bridge } eq $ zone1ref - > { bridge } ;
}
2009-11-12 21:30:08 +01:00
if ( $ chain =~ /(2all|-all)$/ ) {
2009-02-22 18:30:14 +01:00
if ( $ chain ne $ last_chain ) {
$ last_chain = $ chain ;
push @ dest_zones , @ temp_zones ;
@ temp_zones = ( $ zone1 ) ;
} elsif ( $ policy eq 'ACCEPT' ) {
push @ temp_zones , $ zone1 ;
} else {
$ last_chain = $ chain ;
@ temp_zones = ( $ zone1 ) ;
}
} else {
push @ dest_zones , @ temp_zones , $ zone1 ;
@ temp_zones = ( ) ;
$ last_chain = '' ;
}
}
if ( $ last_chain && @ temp_zones == 1 ) {
push @ dest_zones , @ temp_zones ;
$ last_chain = '' ;
}
} else {
@ dest_zones = @ zones ;
}
#
# Here it is -- THE BIG UGLY!!!!!!!!!!!!
#
# We now loop through the destination zones creating jumps to the rules chain for each source/dest combination.
# @dest_zones is the list of destination zones that we need to handle from this source zone
#
for my $ zone1 ( @ dest_zones ) {
my $ zone1ref = find_zone ( $ zone1 ) ;
2009-11-14 16:07:19 +01:00
next if $ filter_table - > { rules_chain ( $ { zone } , $ { zone1 } ) } - > { policy } eq 'NONE' ;
2009-02-22 18:30:14 +01:00
my $ chain = rules_target $ zone , $ zone1 ;
next unless $ chain ; # CONTINUE policy with no rules
my $ num_ifaces = 0 ;
if ( $ zone eq $ zone1 ) {
2009-10-18 17:47:20 +02:00
next if ( $ num_ifaces = scalar ( keys ( % { $ zoneref - > { interfaces } } ) ) ) < 2 && ! $ zoneref - > { options } { in_out } { routeback } ;
2009-02-22 18:30:14 +01:00
}
2009-03-13 23:59:49 +01:00
if ( $ zone1ref - > { type } == BPORT ) {
2009-10-18 17:47:20 +02:00
next unless $ zoneref - > { bridge } eq $ zone1ref - > { bridge } ;
2009-02-22 18:30:14 +01:00
}
2009-11-03 18:28:34 +01:00
my $ chainref = $ filter_table - > { $ chain } ; #Will be null if $chain is a Netfilter Built-in target like ACCEPT
2009-02-22 18:30:14 +01:00
if ( $ frwd_ref ) {
2009-11-03 18:28:34 +01:00
#
# Simple case -- the source zone has it's own forwarding chain
#
for my $ typeref ( values % { $ zone1ref - > { hosts } } ) {
2009-02-22 18:30:14 +01:00
for my $ interface ( sort { interface_number ( $ a ) <=> interface_number ( $ b ) } keys %$ typeref ) {
2009-11-03 18:28:34 +01:00
for my $ hostref ( @ { $ typeref - > { $ interface } } ) {
2009-02-22 18:30:14 +01:00
next if $ hostref - > { options } { sourceonly } ;
if ( $ zone ne $ zone1 || $ num_ifaces > 1 || $ hostref - > { options } { routeback } ) {
2011-07-18 16:24:21 +02:00
my @ ipsec_out_match = match_ipsec_out $ zone1 , $ hostref ;
2009-11-28 16:25:31 +01:00
my $ dest_exclusion = dest_exclusion ( $ hostref - > { exclusions } , $ chain ) ;
2009-02-22 18:30:14 +01:00
for my $ net ( @ { $ hostref - > { hosts } } ) {
2011-07-18 16:24:21 +02:00
add_ijump $ frwd_ref , j = > $ dest_exclusion , imatch_dest_dev ( $ interface ) , imatch_dest_net ( $ net ) , @ ipsec_out_match ;
2009-02-22 18:30:14 +01:00
}
}
}
}
}
} else {
2009-11-03 18:28:34 +01:00
#
# More compilcated case. If the interface is associated with a single simple zone, we try to combine the interface's forwarding chain with the rules chain
#
2009-02-22 18:30:14 +01:00
for my $ typeref ( values %$ source_hosts_ref ) {
for my $ interface ( keys %$ typeref ) {
2011-04-03 18:56:30 +02:00
my $ interfaceref = find_interface $ interface ;
2009-02-22 18:30:14 +01:00
my $ chain3ref ;
2011-07-18 16:24:21 +02:00
my @ match_source_dev ;
2009-11-02 16:15:20 +01:00
my $ forwardchainref = $ filter_table - > { forward_chain $ interface } ;
2009-02-22 18:30:14 +01:00
2010-03-11 02:25:06 +01:00
if ( use_forward_chain ( $ interface , $ forwardchainref ) || ( @ { $ forwardchainref - > { rules } } && ! $ chainref ) ) {
2009-11-02 16:15:20 +01:00
#
# Either we must use the interface's forwarding chain or that chain has rules and we have nowhere to move them
#
$ chain3ref = $ forwardchainref ;
2011-04-03 18:56:30 +02:00
if ( $ interfaceref - > { options } { port } ) {
2011-07-18 16:24:21 +02:00
add_ijump ( $ filter_table - > { forward_chain $ interfaceref - > { bridge } } ,
j = > $ chain3ref ,
imatch_source_dev ( $ interface , 1 ) )
2011-04-03 18:56:30 +02:00
unless $ forward_jump_added { $ interface } + + ;
} else {
2011-07-18 16:24:21 +02:00
add_ijump $ filter_table - > { FORWARD } , j = > $ chain3ref , imatch_source_dev ( $ interface ) unless $ forward_jump_added { $ interface } + + ;
2011-04-03 18:56:30 +02:00
}
2009-02-22 18:30:14 +01:00
} else {
2009-11-03 18:28:34 +01:00
#
# Don't use the interface's forward chain -- move any rules in that chain to this rules chain
#
2011-04-03 18:56:30 +02:00
if ( $ interfaceref - > { options } { port } ) {
$ chain3ref = $ filter_table - > { forward_chain $ interfaceref - > { bridge } } ;
2011-07-18 16:24:21 +02:00
@ match_source_dev = imatch_source_dev $ interface , 1 ;
2011-04-03 18:56:30 +02:00
} else {
$ chain3ref = $ filter_table - > { FORWARD } ;
2011-07-18 16:24:21 +02:00
@ match_source_dev = imatch_source_dev $ interface ;
2011-04-03 18:56:30 +02:00
}
2009-11-03 00:35:00 +01:00
move_rules $ forwardchainref , $ chainref ;
2009-02-22 18:30:14 +01:00
}
2009-11-03 18:28:34 +01:00
for my $ hostref ( @ { $ typeref - > { $ interface } } ) {
2009-02-22 18:30:14 +01:00
next if $ hostref - > { options } { destonly } ;
my $ excl3ref = source_exclusion ( $ hostref - > { exclusions } , $ chain3ref ) ;
for my $ net ( @ { $ hostref - > { hosts } } ) {
2009-11-03 18:28:34 +01:00
for my $ type1ref ( values % { $ zone1ref - > { hosts } } ) {
2009-02-22 18:30:14 +01:00
for my $ interface1 ( keys %$ type1ref ) {
my $ array1ref = $ type1ref - > { $ interface1 } ;
for my $ host1ref ( @$ array1ref ) {
next if $ host1ref - > { options } { sourceonly } ;
2011-07-18 16:24:21 +02:00
my @ ipsec_out_match = match_ipsec_out $ zone1 , $ host1ref ;
2009-11-28 16:25:31 +01:00
my $ dest_exclusion = dest_exclusion ( $ host1ref - > { exclusions } , $ chain ) ;
2009-02-22 18:30:14 +01:00
for my $ net1 ( @ { $ host1ref - > { hosts } } ) {
unless ( $ interface eq $ interface1 && $ net eq $ net1 && ! $ host1ref - > { options } { routeback } ) {
#
# We defer evaluation of the source net match to accomodate systems without $capabilities{KLUDEFREE};
#
2011-07-18 16:24:21 +02:00
add_ijump (
$ excl3ref ,
j = > $ dest_exclusion ,
@ match_source_dev ,
imatch_dest_dev ( $ interface1 ) ,
imatch_source_net ( $ net ) ,
imatch_dest_net ( $ net1 ) ,
@ ipsec_out_match
) ;
2009-02-22 18:30:14 +01:00
}
}
}
}
}
}
}
}
}
}
}
2009-11-03 18:28:34 +01:00
#
# E N D F O R W A R D I N G
#
# Now add an unconditional jump to the last unique policy-only chain determined above, if any
#
2011-07-18 16:24:21 +02:00
add_ijump $ frwd_ref , g = > $ last_chain if $ frwd_ref && $ last_chain ;
2009-02-22 18:30:14 +01:00
}
2010-09-26 01:07:56 +02:00
progress_message ' Finishing matrix...' ;
2009-02-22 18:30:14 +01:00
add_interface_jumps @ interfaces unless $ interface_jumps_added ;
2010-09-18 17:36:59 +02:00
promote_blacklist_rules ;
2009-02-22 18:30:14 +01:00
my % builtins = ( mangle = > [ qw/PREROUTING INPUT FORWARD POSTROUTING/ ] ,
nat = > [ qw/PREROUTING OUTPUT POSTROUTING/ ] ,
filter = > [ qw/INPUT FORWARD OUTPUT/ ] ) ;
2010-08-01 17:36:56 +02:00
unless ( $ config { COMPLETE } ) {
complete_standard_chain $ filter_table - > { INPUT } , 'all' , firewall_zone , 'DROP' ;
complete_standard_chain $ filter_table - > { OUTPUT } , firewall_zone , 'all' , 'REJECT' ;
complete_standard_chain $ filter_table - > { FORWARD } , 'all' , 'all' , 'REJECT' ;
}
2009-02-22 18:30:14 +01:00
if ( $ config { LOGALLNEW } ) {
2011-06-13 15:39:38 +02:00
for my $ table ( qw/mangle nat filter/ ) {
2009-02-22 18:30:14 +01:00
for my $ chain ( @ { $ builtins { $ table } } ) {
log_rule_limit
$ config { LOGALLNEW } ,
$ chain_table { $ table } { $ chain } ,
$ table ,
$ chain ,
'' ,
'' ,
'insert' ,
2010-04-25 22:35:41 +02:00
"$globals{STATEMATCH} NEW " ;
2009-02-22 18:30:14 +01:00
}
}
}
}
sub setup_mss ( ) {
my $ clampmss = $ config { CLAMPMSS } ;
my $ option ;
2011-07-18 00:12:58 +02:00
my @ match ;
2009-02-22 18:30:14 +01:00
my $ chainref = $ filter_table - > { FORWARD } ;
if ( $ clampmss ) {
if ( "\L$clampmss" eq 'yes' ) {
2011-08-13 18:56:14 +02:00
$ option = '--clamp-mss-to-pmtu' ;
2009-02-22 18:30:14 +01:00
} else {
2011-07-18 00:12:58 +02:00
@ match = ( tcpmss = > "--mss $clampmss:" ) if have_capability ( 'TCPMSS_MATCH' ) ;
2011-08-13 18:56:14 +02:00
$ option = "--set-mss $clampmss" ;
2009-02-22 18:30:14 +01:00
}
2011-07-18 00:12:58 +02:00
push @ match , ( policy = > '--pol none --dir out' ) if have_ipsec ;
2009-02-22 18:30:14 +01:00
}
my $ interfaces = find_interfaces_by_option ( 'mss' ) ;
if ( @$ interfaces ) {
#
# Since we will need multiple rules, we create a separate chain
#
$ chainref = new_chain 'filter' , 'settcpmss' ;
#
# Send all forwarded SYN packets to the 'settcpmss' chain
#
2011-07-19 20:58:10 +02:00
add_ijump $ filter_table - > { FORWARD } , j = > $ chainref , p = > 'tcp --tcp-flags SYN,RST SYN' ;
2009-02-22 18:30:14 +01:00
2011-07-18 00:12:58 +02:00
my @ in_match = ( ) ;
my @ out_match = ( ) ;
2009-02-22 18:30:14 +01:00
2010-01-25 17:13:22 +01:00
if ( have_ipsec ) {
2011-07-18 00:12:58 +02:00
@ in_match = ( policy = > '--pol none --dir in' ) ;
@ out_match = ( policy = > '--pol none --dir out' ) ;
2009-08-20 23:32:15 +02:00
}
2009-02-22 18:30:14 +01:00
for ( @$ interfaces ) {
my $ mss = get_interface_option ( $ _ , 'mss' ) ;
2011-07-18 00:12:58 +02:00
my @ mssmatch = have_capability ( 'TCPMSS_MATCH' ) ? ( tcpmss = > "--mss $mss:" ) : ( ) ;
my @ source = imatch_source_dev $ _ ;
my @ dest = imatch_dest_dev $ _ ;
2011-08-13 18:56:14 +02:00
add_ijump $ chainref , j = > 'TCPMSS' , targetopts = > "--set-mss $mss" , @ dest , p = > 'tcp --tcp-flags SYN,RST SYN' , @ mssmatch , @ out_match ;
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , @ dest if $ clampmss ;
2011-08-13 18:56:14 +02:00
add_ijump $ chainref , j = > 'TCPMSS' , targetopts = > "--set-mss $mss" , @ source , p = > 'tcp --tcp-flags SYN,RST SYN' , @ mssmatch , @ in_match ;
2011-07-20 16:30:49 +02:00
add_ijump $ chainref , j = > 'RETURN' , @ source if $ clampmss ;
2009-02-22 18:30:14 +01:00
}
}
2011-08-13 18:56:14 +02:00
add_ijump $ chainref , j = > 'TCPMSS' , targetopts = > $ option , p = > 'tcp --tcp-flags SYN,RST SYN' , @ match if $ clampmss ;
2009-02-22 18:30:14 +01:00
}
2009-03-28 20:22:15 +01:00
#
# Compile the stop_firewall() function
#
2010-01-16 18:53:53 +01:00
sub compile_stop_firewall ( $$ ) {
my ( $ test , $ export ) = @ _ ;
2009-03-28 20:22:15 +01:00
2009-04-01 00:42:37 +02:00
my $ input = $ filter_table - > { INPUT } ;
my $ output = $ filter_table - > { OUTPUT } ;
my $ forward = $ filter_table - > { FORWARD } ;
2009-03-28 20:22:15 +01:00
emit << 'EOF' ;
#
# Stop/restore the firewall after an error or because of a 'stop' or 'clear' command
#
stop_firewall ( ) {
2010-01-04 19:14:36 +01:00
local hack
2009-03-28 20:22:15 +01:00
EOF
2009-04-01 00:42:37 +02:00
$ output - > { policy } = 'ACCEPT' if $ config { ADMINISABSENTMINDED } ;
2009-03-30 02:49:00 +02:00
2009-03-28 20:22:15 +01:00
if ( $ family == F_IPV4 ) {
2010-09-17 03:19:16 +02:00
emit << 'EOF' ;
deletechain ( ) {
qt $ IPTABLES - L $ 1 - n && qt $ IPTABLES - F $ 1 && qt $ IPTABLES - X $ 1
2009-03-28 20:22:15 +01:00
}
case $ COMMAND in
2010-09-17 03:19:16 +02:00
stop | clear | restore )
2010-09-16 21:17:04 +02:00
if chain_exists dynamic ; then
2010-09-17 03:19:16 +02:00
$ { IPTABLES } - save - t filter | grep '^-A dynamic' > $ { VARDIR } / . dynamic
fi
; ;
* )
set + x
2010-09-16 21:17:04 +02:00
EOF
} else {
2010-09-17 03:19:16 +02:00
emit << 'EOF' ;
deletechain ( ) {
qt $ IPTABLES - L $ 1 - n && qt $ IPTABLES - F $ 1 && qt $ IPTABLES - X $ 1
2010-09-16 21:17:04 +02:00
}
2010-09-17 03:19:16 +02:00
case $ COMMAND in
stop | clear | restore )
if chain_exists dynamic ; then
$ { IP6TABLES } - save - t filter | grep '^-A dynamic' > $ { VARDIR } / . dynamic
2010-09-16 21:17:04 +02:00
fi
2010-09-17 03:19:16 +02:00
; ;
* )
set + x
EOF
}
2009-03-28 20:22:15 +01:00
2010-09-17 03:19:16 +02:00
emit << 'EOF' ;
2009-03-28 20:22:15 +01:00
case $ COMMAND in
start )
2010-03-02 21:34:36 +01:00
logger - p kern . err "ERROR:$g_product start failed"
2009-03-28 20:22:15 +01:00
; ;
restart )
2010-03-02 21:34:36 +01:00
logger - p kern . err "ERROR:$g_product restart failed"
2009-03-28 20:22:15 +01:00
; ;
2010-01-06 17:01:06 +01:00
refresh )
2010-03-02 21:34:36 +01:00
logger - p kern . err "ERROR:$g_product refresh failed"
2009-03-28 20:22:15 +01:00
; ;
2011-08-26 01:00:27 +02:00
enable )
2011-08-26 20:02:42 +02:00
logger - p kern . err "ERROR:$g_product 'enable $g_interface' failed"
2011-08-26 01:00:27 +02:00
; ;
2009-03-28 20:22:15 +01:00
esac
if [ "$RESTOREFILE" = NONE ] ; then
COMMAND = clear
clear_firewall
2010-03-02 21:34:36 +01:00
echo "$g_product Cleared"
2009-03-28 20:22:15 +01:00
kill $$
exit 2
else
2010-02-26 17:35:50 +01:00
g_restorepath = $ { VARDIR } / $ RESTOREFILE
2009-03-28 20:22:15 +01:00
2010-02-26 17:35:50 +01:00
if [ - x $ g_restorepath ] ; then
2010-03-02 21:34:36 +01:00
echo Restoring $ { g_product: = Shorewall } ...
2010-06-07 16:30:56 +02:00
2010-03-03 18:50:07 +01:00
g_recovering = Yes
2009-03-28 20:22:15 +01:00
2010-03-03 17:59:58 +01:00
if run_it $ g_restorepath restore ; then
2010-03-02 21:34:36 +01:00
echo "$g_product restored from $g_restorepath"
2010-03-17 18:10:56 +01:00
set_state "Restored from $g_restorepath"
2009-03-28 20:22:15 +01:00
else
set_state "Unknown"
fi
kill $$
exit 2
fi
fi
; ;
esac
2010-03-02 16:37:30 +01:00
if [ - n "$g_stopping" ] ; then
kill $$
exit 1
fi
2009-03-28 20:22:15 +01:00
2010-03-02 16:37:30 +01:00
set_state "Stopping"
2009-03-28 20:22:15 +01:00
2010-03-02 16:37:30 +01:00
g_stopping = "Yes"
2009-03-28 20:22:15 +01:00
deletechain shorewall
run_stop_exit
EOF
2010-01-25 16:56:16 +01:00
if ( have_capability ( 'NAT_ENABLED' ) ) {
2009-03-30 02:49:00 +02:00
emit << 'EOF' ;
if [ - f $ { VARDIR } / nat ] ; then
while read external interface ; do
del_ip_addr $ external $ interface
done < $ { VARDIR } / nat
rm - f $ { VARDIR } / nat
fi
2009-03-28 20:22:15 +01:00
EOF
}
if ( $ family == F_IPV4 ) {
emit << 'EOF' ;
if [ - f $ { VARDIR } / proxyarp ] ; then
while read address interface external haveroute ; do
2011-08-03 01:51:49 +02:00
qtnoin $ IP - 4 neigh del proxy $ address dev $ external
[ - z "${haveroute}${g_noroutes}" ] && qtnoin $ IP - 4 route del $ address / 32 dev $ interface
2009-03-28 20:22:15 +01:00
f = /proc/s ys /net/i pv4 /conf/ $ interface / proxy_arp
[ - f $ f ] && echo 0 > $ f
done < $ { VARDIR } / proxyarp
2009-03-30 02:49:00 +02:00
2010-12-11 16:10:50 +01:00
rm - f $ { VARDIR } / proxyarp
2009-03-28 20:22:15 +01:00
fi
EOF
2010-12-11 04:06:44 +01:00
} else {
emit << 'EOF' ;
if [ - f $ { VARDIR } / proxyndp ] ; then
while read address interface external haveroute ; do
2011-08-03 01:51:49 +02:00
qtnoin $ IP - 6 neigh del proxy $ address dev $ external
[ - z "${haveroute}${g_noroutes}" ] && qtnoin $ IP - 6 route del $ address / 128 dev $ interface
2010-12-11 04:06:44 +01:00
f = /proc/s ys /net/i pv4 /conf/ $ interface / proxy_ndp
[ - f $ f ] && echo 0 > $ f
done < $ { VARDIR } / proxyndp
2010-12-11 16:10:50 +01:00
rm - f $ { VARDIR } / proxyndp
2010-12-11 04:06:44 +01:00
fi
2010-12-11 16:10:50 +01:00
EOF
}
2009-03-28 20:22:15 +01:00
push_indent ;
emit 'delete_tc1' if $ config { CLEAR_TC } ;
emit ( 'undo_routing' ,
2011-04-14 21:17:46 +02:00
"restore_default_route $config{USE_DEFAULT_RT}"
2009-03-28 20:22:15 +01:00
) ;
2009-03-30 02:49:00 +02:00
my @ chains = $ config { ADMINISABSENTMINDED } ? qw/INPUT FORWARD/ : qw/INPUT OUTPUT FORWARD/ ;
2009-08-20 23:32:15 +02:00
2011-07-20 16:30:49 +02:00
add_ijump $ filter_table - > { $ _ } , j = > 'ACCEPT' , state_imatch 'ESTABLISHED,RELATED' for @ chains ;
2009-03-28 20:22:15 +01:00
if ( $ family == F_IPV6 ) {
2011-07-20 16:30:49 +02:00
add_ijump $ input , j = > 'ACCEPT' , s = > IPv6_LINKLOCAL ;
add_ijump $ input , j = > 'ACCEPT' , d = > IPv6_LINKLOCAL ;
add_ijump $ input , j = > 'ACCEPT' , d = > IPv6_MULTICAST ;
2009-03-28 20:22:15 +01:00
2009-03-30 02:49:00 +02:00
unless ( $ config { ADMINISABSENTMINDED } ) {
2011-07-20 16:30:49 +02:00
add_ijump $ output , j = > 'ACCEPT' , d = > IPv6_LINKLOCAL ;
add_ijump $ output , j = > 'ACCEPT' , d = > IPv6_MULTICAST ;
2009-03-30 02:49:00 +02:00
}
2009-03-28 20:22:15 +01:00
}
process_routestopped ;
2011-07-20 16:30:49 +02:00
add_ijump $ input , j = > 'ACCEPT' , i = > 'lo' ;
add_ijump $ output , j = > 'ACCEPT' , o = > 'lo' unless $ config { ADMINISABSENTMINDED } ;
2009-03-28 20:22:15 +01:00
my $ interfaces = find_interfaces_by_option 'dhcp' ;
if ( @$ interfaces ) {
my $ ports = $ family == F_IPV4 ? '67:68' : '546:547' ;
for my $ interface ( @$ interfaces ) {
2011-07-20 16:30:49 +02:00
add_ijump $ input , j = > 'ACCEPT' , p = > "udp --dport $ports" , imatch_source_dev ( $ interface ) ;
add_ijump $ output , j = > 'ACCEPT' , p = > "udp --dport $ports" , imatch_dest_dev ( $ interface ) unless $ config { ADMINISABSENTMINDED } ;
2009-03-28 20:22:15 +01:00
#
# This might be a bridge
#
2011-07-20 16:30:49 +02:00
add_ijump $ forward , j = > 'ACCEPT' , p = > "udp --dport $ports" , imatch_source_dev ( $ interface ) , imatch_dest_dev ( $ interface ) ;
2009-03-28 20:22:15 +01:00
}
}
emit '' ;
2009-03-30 02:49:00 +02:00
create_stop_load $ test ;
2009-03-28 20:22:15 +01:00
if ( $ family == F_IPV4 ) {
if ( $ config { IP_FORWARDING } eq 'on' ) {
emit ( 'echo 1 > /proc/sys/net/ipv4/ip_forward' ,
'progress_message2 IPv4 Forwarding Enabled' ) ;
} elsif ( $ config { IP_FORWARDING } eq 'off' ) {
emit ( 'echo 0 > /proc/sys/net/ipv4/ip_forward' ,
'progress_message2 IPv4 Forwarding Disabled!'
) ;
}
} else {
for my $ interface ( all_bridges ) {
2009-11-22 17:20:07 +01:00
emit "do_iptables -A FORWARD -p 58 " . match_source_dev ( $ interface ) . match_dest_dev ( $ interface ) . "-j ACCEPT" ;
2009-08-20 23:32:15 +02:00
}
2009-03-28 20:22:15 +01:00
if ( $ config { IP_FORWARDING } eq 'on' ) {
emit ( 'echo 1 > /proc/sys/net/ipv6/conf/all/forwarding' ,
'progress_message2 IPv6 Forwarding Enabled' ) ;
} elsif ( $ config { IP_FORWARDING } eq 'off' ) {
emit ( 'echo 0 > /proc/sys/net/ipv6/conf/all/forwarding' ,
'progress_message2 IPv6 Forwarding Disabled!'
) ;
}
}
pop_indent ;
emit '
run_stopped_exit ' ;
2009-08-20 23:32:15 +02:00
my @ ipsets = all_ipsets ;
2009-03-28 20:22:15 +01:00
2010-10-30 19:35:52 +02:00
if ( @ ipsets || ( $ config { SAVE_IPSETS } && have_ipset_rules ) ) {
2009-03-30 02:49:00 +02:00
emit << 'EOF' ;
2009-03-28 20:22:15 +01:00
2010-01-04 19:14:36 +01:00
case $ IPSET in
* / * )
if [ ! - x "$IPSET" ] ; then
error_message "ERROR: IPSET=$IPSET does not exist or is not executable - ipsets are not saved"
IPSET =
fi
; ;
* )
IPSET = "$(mywhich $IPSET)"
[ - n "$IPSET" ] || error_message "ERROR: The ipset utility cannot be located - ipsets are not saved"
; ;
esac
if [ - n "$IPSET" ] ; then
if [ - f /etc/ debian_version ] && [ $ ( cat /etc/ debian_version ) = 5.0 .3 ] ; then
#
# The 'grep -v' is a hack for a bug in ipset's nethash implementation when xtables-addons is applied to Lenny
#
hack = '| grep -v /31'
else
hack =
fi
if eval $ IPSET - S $ hack > $ { VARDIR } / ipsets . tmp ; then
2009-03-28 20:22:15 +01:00
#
# Don't save an 'empty' file
#
2011-06-19 23:06:42 +02:00
grep - qE '^(-N|create )' $ { VARDIR } /ipsets.tmp && mv -f ${VARDIR}/i psets . tmp $ { VARDIR } / ipsets . save
2010-01-04 19:14:36 +01:00
fi
2009-03-30 20:00:23 +02:00
fi
2009-03-28 20:22:15 +01:00
EOF
}
2009-08-20 23:32:15 +02:00
emit '
2009-03-28 20:22:15 +01:00
2010-05-17 00:31:41 +02:00
set_state "Stopped"
logger - p kern . info "$g_product Stopped"
2009-03-28 20:22:15 +01:00
case $ COMMAND in
stop | clear )
; ;
* )
#
# The firewall is being stopped when we were trying to do something
# else. Kill the shell in case we\'re running in a subshell
#
kill $$
; ;
esac
}
' ;
}
2009-02-22 18:30:14 +01:00
1 ;