Rework blacklisting

Signed-off-by: Tom Eastep <teastep@shorewall.net>
This commit is contained in:
Tom Eastep 2010-09-06 15:29:20 -07:00
parent c6f58ba924
commit f3255cd83a
8 changed files with 242 additions and 44 deletions

View File

@ -48,14 +48,10 @@ our @EXPORT = qw( process_tos
our @EXPORT_OK = qw( process_rule process_rule1 initialize );
our $VERSION = '4.4_13';
#
# Set to one if we find a SECTION
#
our $macro_nest_level;
our $current_param;
our @param_stack;
our $family;
#
# When splitting a line in the rules file, don't pad out the columns with '-' if the first column contains one of these
#
@ -217,16 +213,19 @@ sub add_rule_pair( $$$$ ) {
sub setup_blacklist() {
my $hosts = find_hosts_by_option 'blacklist';
my $hosts = find_hosts_by_option1 'blacklist', BL_IN;
my $hosts1 = find_hosts_by_option1 'blacklist', BL_OUT;
my $chainref;
my $chainref1;
my ( $level, $disposition ) = @config{'BLACKLIST_LOGLEVEL', 'BLACKLIST_DISPOSITION' };
my $target = $disposition eq 'REJECT' ? 'reject' : $disposition;
#
# We go ahead and generate the blacklist chain and jump to it, even if it turns out to be empty. That is necessary
# for 'refresh' to work properly.
#
if ( @$hosts ) {
$chainref = dont_delete new_standard_chain 'blacklst';
if ( @$hosts || @$hosts1 ) {
$chainref = dont_delete new_standard_chain 'blacklst' if @$hosts;
$chainref1 = dont_delete new_standard_chain 'blackout' if @$hosts1;
if ( defined $level && $level ne '' ) {
my $logchainref = new_standard_chain 'blacklog';
@ -250,7 +249,7 @@ sub setup_blacklist() {
while ( read_a_line ) {
if ( $first_entry ) {
unless ( @$hosts ) {
unless ( @$hosts || @$hosts1 ) {
warning_message qq(The entries in $fn have been ignored because there are no 'blacklist' interfaces);
close_file;
last BLACKLIST;
@ -265,6 +264,8 @@ sub setup_blacklist() {
$options = 'from' if $options eq '-';
warning_message "'$options' entry ignored because there are no matching interfaces", next unless @$hosts || $options eq 'to';
for ( split /,/, $options ) {
fatal_error "Invalid OPTION ($_)" unless /^(from|to)$/;
$direction = $_;
@ -274,19 +275,31 @@ sub setup_blacklist() {
$chainref ,
NO_RESTRICT ,
do_proto( $protocol , $ports, '' ) ,
$direction eq 'from' ? $networks : '',
$direction eq 'to' ? $networks : '',
$networks,
'',
'' ,
$target ,
'' ,
$target ,
'' );
'' ) if $chainref && $options eq 'from';
expand_rule(
$chainref1 ,
NO_RESTRICT ,
do_proto( $protocol , $ports, '' ) ,
$networks,
'',
'' ,
$target ,
'' ,
$target ,
'' ) if $chainref1 && $options eq 'to';
progress_message " \"$currentline\" added to blacklist";
}
warning_message q(There are interfaces or hosts with the 'blacklist' option but the 'blacklist' file is empty) if $first_entry && @$hosts;
} elsif ( @$hosts ) {
} elsif ( @$hosts || @$hosts1 ) {
warning_message q(There are interfaces or hosts with the 'blacklist' option, but the 'blacklist' file is either missing or has zero size);
}
@ -307,8 +320,27 @@ sub setup_blacklist() {
set_interface_option $interface, 'use_input_chain', 1;
set_interface_option $interface, 'use_forward_chain', 1;
progress_message " Blacklisting enabled on ${interface}:${network}";
progress_message " Type 1 blacklisting enabled on ${interface}:${network}";
}
for my $hostref ( @$hosts1 ) {
my $interface = $hostref->[0];
my $ipsec = $hostref->[1];
my $policy = have_ipsec ? "-m policy --pol $ipsec --dir in " : '';
my $network = $hostref->[2];
my $source = match_source_net $network;
my $target = source_exclusion( $hostref->[3], $chainref1 );
for my $chain ( first_chains $interface ) {
add_jump $filter_table->{$chain} , $target, 0, "${source}${state}${policy}";
}
set_interface_option $interface, 'use_input_chain', 1;
set_interface_option $interface, 'use_forward_chain', 1;
progress_message " Type 2 blacklisting enabled on ${interface}:${network}";
}
}
}
@ -1849,6 +1881,7 @@ sub generate_matrix() {
our %input_jump_added = ();
our %output_jump_added = ();
our %forward_jump_added = ();
my %needs_bl_jump = ();
progress_message2 'Generating Rule Matrix...';
#
@ -1977,7 +2010,8 @@ sub generate_matrix() {
my $ipsec_in_match = match_ipsec_in $zone , $hostref;
my $ipsec_out_match = match_ipsec_out $zone , $hostref;
my $exclusions = $hostref->{exclusions};
my $blacklist = $hostref->{options}{blacklist} & BL_OUT;
for my $net ( @{$hostref->{hosts}} ) {
my $dest = match_dest_net $net;
@ -1989,10 +2023,11 @@ sub generate_matrix() {
my $interfacematch = '';
my $use_output = 0;
if ( @vservers || use_output_chain( $interface, $interfacechainref ) || ( @{$interfacechainref->{rules}} && ! $chain1ref ) ) {
if ( @vservers || use_output_chain( $interface, $interfacechainref ) || ( ( $blacklist || @{$interfacechainref->{rules}} ) && ! $chain1ref ) ) {
$outputref = $interfacechainref;
add_jump $filter_table->{OUTPUT}, $outputref, 0, match_dest_dev( $interface ) unless $output_jump_added{$interface}++;
$use_output = 1;
$needs_bl_jump{output_chain $interface} = 1 if $blacklist;
unless ( lc $net eq IPv6_LINKLOCAL ) {
for my $vzone ( vserver_zones ) {
@ -2002,6 +2037,7 @@ sub generate_matrix() {
} else {
$outputref = $filter_table->{OUTPUT};
$interfacematch = match_dest_dev $interface;
$needs_bl_jump{output_chain $interface} = 1 if $blacklist;
}
add_jump $outputref , $nextchain, 0, join( '', $interfacematch, $dest, $ipsec_out_match );
@ -2255,6 +2291,7 @@ sub generate_matrix() {
add_jump $frwd_ref , $last_chain, 1 if $frwd_ref && $last_chain;
}
add_jump( $filter_table->{$_}, $filter_table->{blackout} , 0 , '' , 0 , 0 ) for keys %needs_bl_jump;
add_interface_jumps @interfaces unless $interface_jumps_added;
my %builtins = ( mangle => [ qw/PREROUTING INPUT FORWARD POSTROUTING/ ] ,

View File

@ -41,6 +41,8 @@ our @EXPORT = qw( NOTHING
IP
BPORT
IPSEC
BL_IN
BL_OUT
determine_zones
zone_report
@ -78,6 +80,7 @@ our @EXPORT = qw( NOTHING
compile_updown
validate_hosts_file
find_hosts_by_option
find_hosts_by_option1
all_ipsets
have_ipsec
);
@ -94,7 +97,12 @@ use constant { NOTHING => 'NOTHING',
IPSECPROTO => 'ah|esp|ipcomp',
IPSECMODE => 'tunnel|transport'
};
#
# blacklist option values
#
use constant {
BL_IN => 1 ,
BL_OUT => 2 };
#
# Zone Table.
#
@ -231,7 +239,7 @@ sub initialize( $ ) {
if ( $family == F_IPV4 ) {
%validinterfaceoptions = (arp_filter => BINARY_IF_OPTION,
arp_ignore => ENUM_IF_OPTION,
blacklist => SIMPLE_IF_OPTION + IF_OPTION_HOST,
blacklist => ENUM_IF_OPTION,
bridge => SIMPLE_IF_OPTION,
detectnets => OBSOLETE_IF_OPTION,
dhcp => SIMPLE_IF_OPTION,
@ -264,7 +272,7 @@ sub initialize( $ ) {
sourceonly => 1,
);
} else {
%validinterfaceoptions = ( blacklist => SIMPLE_IF_OPTION + IF_OPTION_HOST,
%validinterfaceoptions = ( blacklist => ENUM_IF_OPTION,
bridge => SIMPLE_IF_OPTION,
dhcp => SIMPLE_IF_OPTION,
maclist => SIMPLE_IF_OPTION + IF_OPTION_HOST,
@ -645,6 +653,8 @@ sub add_group_to_zone($$$$$)
$zoneref->{interfaces}{$interface} = 1;
$options->{blacklist} ||= 0;
my @newnetworks;
my @exclusions = ();
my $new = \@newnetworks;
@ -909,6 +919,7 @@ sub process_interface( $$ ) {
my %options;
$options{port} = 1 if $port;
$options{blacklist} = 0;
my $hostoptionsref = {};
@ -920,7 +931,7 @@ sub process_interface( $$ ) {
if ( $options ne '-' ) {
my %hostoptions = ( dynamic => 0 );
my %hostoptions = ( blacklist => 0, dynamic => 0 );
for my $option (split_list1 $options, 'option' ) {
next if $option eq '-';
@ -952,8 +963,8 @@ sub process_interface( $$ ) {
$options{$option} = $value;
$hostoptions{$option} = $value if $hostopt;
} elsif ( $type == ENUM_IF_OPTION ) {
fatal_error "The '$option' option may not be used with a wild-card interface name" if $wildcard;
if ( $option eq 'arp_ignore' ) {
fatal_error q(The 'arp_ignore' option may not be used with a wild-card interface name) if $wildcard;
if ( defined $value ) {
if ( $value =~ /^[1-3,8]$/ ) {
$options{arp_ignore} = $value;
@ -963,6 +974,11 @@ sub process_interface( $$ ) {
} else {
$options{arp_ignore} = 1;
}
} elsif ( $option eq 'blacklist' ) {
$value = BL_IN unless ( defined $value && $value != '' );
fatal_error "Invalid 'blacklist' value ( $value )" unless $value =~ /^[12]$/;
$options{blacklist} = $value eq 1 ? BL_IN | BL_OUT : BL_OUT;
$hostoptions{blacklist} = $options{blacklist} & BL_IN;
} else {
assert( 0 );
}
@ -1126,7 +1142,7 @@ sub validate_interfaces_file( $ ) {
number => $nextinum ,
root => $interface ,
broadcasts => undef ,
options => {} ,
options => { blacklist => 0 } ,
zone => '',
physical => 'lo',
};
@ -1665,11 +1681,11 @@ sub process_host( ) {
}
}
my $optionsref = { dynamic => 0 };
my $optionsref = { blacklist => 0, dynamic => 0 };
if ( $options ne '-' ) {
my @options = split_list $options, 'option';
my %options = ( dynamic => 0 );
my %options = ( blacklist => 0, dynamic => 0 );
for my $option ( @options ) {
if ( $option eq 'ipsec' ) {
@ -1783,6 +1799,33 @@ sub find_hosts_by_option( $ ) {
\@hosts;
}
sub find_hosts_by_option1( $$ ) {
my ($option, $bit ) = @_;
my @hosts;
for my $zone ( grep $zones{$_}{type} != FIREWALL , @zones ) {
while ( my ($type, $interfaceref) = each %{$zones{$zone}{hosts}} ) {
while ( my ( $interface, $arrayref) = ( each %{$interfaceref} ) ) {
for my $host ( @{$arrayref} ) {
if ( $host->{options}{$option} & $bit ) {
for my $net ( @{$host->{hosts}} ) {
push @hosts, [ $interface, $host->{ipsec} , $net , $host->{exclusions}];
}
}
}
}
}
}
for my $interface ( @interfaces ) {
if ( ! $interfaces{$interface}{zone} && $interfaces{$interface}{options}{$option} & $bit ) {
push @hosts, [ $interface, 'none', ALLIP , [] ];
}
}
\@hosts;
}
sub all_ipsets() {
sort keys %ipsets;
}

View File

@ -12,6 +12,8 @@ Changes in Shorewall 4.4.13
6) Add secmark config file.
7) Split in and out blacklisting.
Changes in Shorewall 4.4.12
1) Fix IPv6 shorecap program.

View File

@ -175,6 +175,21 @@ VI. PROBLEMS CORRECTED AND NEW FEATURES IN PRIOR RELEASES
As part of this change, the tcrules file now accepts chain
designators 'I' and 'CI' for marking packets in the input chain.
4) The 'blacklist' interface option may now have one of 2 values:
1 - Inbound blacklisting
2 - Outbond blacklisting
Inbound blacklisting is targeted for use on Internet-facing
interfaces. Incoming packets are passed against the blacklist
entries with the 'from' option (either explicitly or defaulted).
Traffic originating on the firewall is passed against the blacklist
entries with the 'to' option.
Outbound blacklisting is targeted for use on internal
interfaces. Packets arriving on these interfaces is passed against
the blacklist entries with the 'to' option.
----------------------------------------------------------------------------
I V. R E L E A S E 4 . 4 H I G H L I G H T S
----------------------------------------------------------------------------

View File

@ -84,30 +84,50 @@
then this column has no effect on the generated rule.</para>
<note>
<para>Blacklisting is still restricted to traffic
<emphasis>arriving</emphasis> on an interface that has the
<para>In Shorewall 4.4.12, blacklisting is still restricted to
traffic <emphasis>arriving</emphasis> on an interface that has the
'blacklist' option set. So to block traffic from your local
network to an internet host, you must specify
<option>blacklist</option> on your internal interface in <ulink
url="shorewall-interfaces.html">shorewall-interfaces</ulink>
(5).</para>
</note>
<note>
<para>Beginning with Shorewall 4.4.13, entries specifying
<emphasis role="bold">to</emphasis> are applied based on the
<emphasis role="bold">blacklist</emphasis> setting in <ulink
url="shorewall-interfaces.html">shorewall-interfaces</ulink>(5):</para>
<orderedlist>
<listitem>
<para>Input blacklisting (default if no value given). Traffic
entering this interface are passed against the entries in
<ulink
url="shorewall-blacklist.html">shorewall-blacklist</ulink>(5)
that have the <emphasis role="bold">from</emphasis> option
(specified or defaulted). Traffic originating on the firewall
and leaving by this interface is passed against the entries in
<ulink
url="shorewall-blacklist.html">shorewall-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
<listitem>
<para>Output blacklisting. Traffic entering on this interface
is passed against the entries in <ulink
url="shorewall-blacklist.html">shorewall-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
</orderedlist>
</note>
</listitem>
</varlistentry>
</variablelist>
<para>When a packet arrives on an interface that has the <emphasis
role="bold">blacklist</emphasis> option specified in <ulink
url="shorewall-interfaces.html">shorewall-interfaces</ulink>(5), its
source IP address and MAC address is checked against this file and
disposed of according to the <emphasis
role="bold">BLACKLIST_DISPOSITION</emphasis> and <emphasis
role="bold">BLACKLIST_LOGLEVEL</emphasis> variables in <ulink
url="shorewall.conf.html">shorewall.conf</ulink>(5). If <emphasis
role="bold">PROTOCOL</emphasis> or <emphasis
role="bold">PROTOCOL</emphasis> and <emphasis role="bold">PORTS</emphasis>
are supplied, only packets matching the protocol (and one of the ports if
<emphasis role="bold">PORTS</emphasis> supplied) are blocked.</para>
<para></para>
</refsect1>
<refsect1>

View File

@ -223,13 +223,39 @@ loc eth2 -</programlisting>
</varlistentry>
<varlistentry>
<term><emphasis role="bold">blacklist</emphasis></term>
<term><emphasis
role="bold">blacklist[=<replaceable>value</replaceable>]</emphasis></term>
<listitem>
<para>Check packets arriving on this interface against the
<ulink
url="shorewall-blacklist.html">shorewall-blacklist</ulink>(5)
file.</para>
file. The value may be specified when running Shorewall 4.4.13
or later and can have a value in the range 1-2</para>
<orderedlist>
<listitem>
<para>Input blacklisting (default if no value given).
Traffic entering this interface are passed against the
entries in <ulink
url="shorewall-blacklist.html">shorewall-blacklist</ulink>(5)
that have the <emphasis role="bold">from</emphasis> option
(specified or defaulted). Traffic originating on the
firewall and leaving by this interface is passed against
the entries in <ulink
url="shorewall-blacklist.html">shorewall-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
<listitem>
<para>Output blacklisting. Traffic entering on this
interface is passed against the entries in <ulink
url="shorewall-blacklist.html">shorewall-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
</orderedlist>
</listitem>
</varlistentry>

View File

@ -94,6 +94,38 @@
url="shorewall6-interfaces.html">shorewall6-interfaces</ulink>
(5).</para>
</note>
<note>
<para>Beginning with Shorewall 4.4.13, entries specifying
<emphasis role="bold">to</emphasis> are applied to traffic based
on the <emphasis role="bold">blacklist</emphasis> setting in
<ulink
url="shorewall6-interfaces.html">shorewall6-interfaces</ulink>(5).</para>
<orderedlist>
<listitem>
<para>Input blacklisting (default if no value given). Traffic
entering this interface are passed against the entries in
<ulink
url="shorewall6-blacklist.html">shorewall6-blacklist</ulink>(5)
that have the <emphasis role="bold">from</emphasis> option
(specified or defaulted). Traffic originating on the firewall
and leaving by this interface is passed against the entries in
<ulink
url="shorewall6-blacklist.html">shorewall6-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
<listitem>
<para>Output blacklisting. Traffic entering on this interface
is passed against the entries in <ulink
url="shorewall6-blacklist.html">shorewall6-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
</orderedlist>
</note>
</listitem>
</varlistentry>
</variablelist>

View File

@ -115,13 +115,36 @@ loc eth2 -</programlisting>
<variablelist>
<varlistentry>
<term><emphasis role="bold">blacklist</emphasis></term>
<term><emphasis
role="bold">blacklist[=<replaceable>value</replaceable>]</emphasis></term>
<listitem>
<para>Check packets arriving on this interface against the
<ulink
url="shorewall6-blacklist.html">shorewall6-blacklist</ulink>(5)
file.</para>
<para>The value may be specified when running Shorewall 4.4.13
or later and can have a value in the range 1-2</para>
<orderedlist>
<listitem>
<para>Input blacklisting (default if no value given).
Traffic entering this interface are passed against the
entries in <ulink
url="shorewall6-blacklist.html">shorewall6-blacklist</ulink>(5)
that have the <emphasis role="bold">from</emphasis> option
(specified or defaulted). Traffic originating on the
firewall and leaving by this interface is passed against
the entries in <ulink
url="shorewall6-blacklist.html">shorewall6-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
<listitem>
<para>Output blacklisting. Traffic entering on this
interface is passed against the entries in <ulink
url="shorewall6-blacklist.html">shorewall6-blacklist</ulink>(5)
that have the <emphasis role="bold">to</emphasis>
option.</para>
</listitem>
</orderedlist>
</listitem>
</varlistentry>