From 1e866eac2812bbb07b5a6fb013f3b10e7ab7556e Mon Sep 17 00:00:00 2001 From: Tom Eastep Date: Sat, 16 Mar 2013 08:20:52 -0700 Subject: [PATCH] Implement the other forms of NULL routing. Signed-off-by: Tom Eastep --- Shorewall/Perl/Shorewall/Config.pm | 6 +- Shorewall/Perl/Shorewall/Providers.pm | 19 +- Shorewall/manpages/shorewall-routes.xml | 14 +- Shorewall/manpages/shorewall.conf.xml | 12 +- Shorewall6/manpages/shorewall6-routes.xml | 12 +- docs/MultiISP.xml | 342 ++++++++++++++++++++++ 6 files changed, 389 insertions(+), 16 deletions(-) diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm index 8e9344a07..1f1342d70 100644 --- a/Shorewall/Perl/Shorewall/Config.pm +++ b/Shorewall/Perl/Shorewall/Config.pm @@ -5226,13 +5226,17 @@ sub get_configuration( $$$$ ) { default_yes_no 'MARK_IN_FORWARD_CHAIN' , ''; default_yes_no 'MANGLE_ENABLED' , have_capability( 'MANGLE_ENABLED' ) ? 'Yes' : ''; - default_yes_no 'NULL_ROUTE_RFC1918' , ''; default_yes_no 'USE_DEFAULT_RT' , ''; default_yes_no 'RESTORE_DEFAULT_ROUTE' , 'Yes'; default_yes_no 'AUTOMAKE' , ''; default_yes_no 'WIDE_TC_MARKS' , ''; default_yes_no 'TRACK_PROVIDERS' , ''; + unless ( ( $config{NULL_ROUTE_RFC1918} || '' ) =~ /^(?:blackhole|unreachable|prohibit)$/ ) { + default_yes_no( 'NULL_ROUTE_RFC1918', '' ); + $config{NULL_ROUTE_RFC1918} = 'blackhole' if $config{NULL_ROUTE_RFC1918}; + } + default_yes_no 'ACCOUNTING' , 'Yes'; default_yes_no 'OPTIMIZE_ACCOUNTING' , ''; diff --git a/Shorewall/Perl/Shorewall/Providers.pm b/Shorewall/Perl/Shorewall/Providers.pm index daf411084..e0bb1b214 100644 --- a/Shorewall/Perl/Shorewall/Providers.pm +++ b/Shorewall/Perl/Shorewall/Providers.pm @@ -1129,8 +1129,11 @@ sub add_a_route( ) { fatal_error 'DEST must be specified' if $dest eq '-'; $dest = validate_net ( $dest, 0 ); - if ( $gateway eq 'blackhole' ) { - fatal_error q('blackhole' routes may not specify a DEVICE) unless $device eq '-'; + my $null; + + if ( $gateway =~ /^(?:blackhole|unreachable|prohibit)$/ ) { + fatal_error q('$gateway' routes may not specify a DEVICE) unless $device eq '-'; + $null = $gateway; } else { validate_address ( $gateway, 1 ) if $gateway ne '-'; } @@ -1146,9 +1149,9 @@ sub add_a_route( ) { if ( $device ne '-' ) { push @$routes, qq(run_ip route add $dest via $gateway dev $physical table $number); push @$routes, q(echo "qt $IP ) . qq(-$family route del $dest via $gateway dev $physical table $number" >> \${VARDIR}/undo_${provider}_routing) if $number >= DEFAULT_TABLE; - } elsif ( $gateway eq 'blackhole' ) { - push @$routes, qq(run_ip route add blackhole $dest table $number); - push @$routes, q(echo "qt $IP ) . qq(-$family route del blackhole $dest table $number" >> \${VARDIR}/undo_${provider}_routing) if $number >= DEFAULT_TABLE; + } elsif ( $null ) { + push @$routes, qq(run_ip route add $null $dest table $number); + push @$routes, q(echo "qt $IP ) . qq(-$family route del $null $dest table $number" >> \${VARDIR}/undo_${provider}_routing) if $number >= DEFAULT_TABLE; } else { push @$routes, qq(run_ip route add $dest via $gateway table $number); push @$routes, q(echo "qt $IP ) . qq(-$family route del $dest via $gateway table $number" >> \${VARDIR}/undo_${provider}_routing) if $number >= DEFAULT_TABLE; @@ -1163,12 +1166,14 @@ sub add_a_route( ) { } sub setup_null_routing() { + my $type = $config{NULL_ROUTE_RFC1918}; + save_progress_message "Null Routing the RFC 1918 subnets"; emit "> \${VARDIR}/undo_rfc1918_routing\n"; for ( rfc1918_networks ) { emit( qq(if ! \$IP -4 route ls | grep -q '^$_.* dev '; then), - qq( run_ip route replace blackhole $_), - qq( echo "qt \$IP -4 route del blackhole $_" >> \${VARDIR}/undo_rfc1918_routing), + qq( run_ip route replace $type $_), + qq( echo "qt \$IP -4 route del $type $_" >> \${VARDIR}/undo_rfc1918_routing), qq(fi\n) ); } } diff --git a/Shorewall/manpages/shorewall-routes.xml b/Shorewall/manpages/shorewall-routes.xml index 299cfe361..f33fdb918 100644 --- a/Shorewall/manpages/shorewall-routes.xml +++ b/Shorewall/manpages/shorewall-routes.xml @@ -57,8 +57,13 @@ DEST. Beginning with Shorewall 4.5.14, you may specify - in this column to create a blackhole - route. + in this column to create a + blackhole route. + + Beginning with Shorewall 4.5.15, you may specify + or in this + column to create a prohibit or + unreachable route respectively. @@ -69,8 +74,9 @@ Specifies the device route. If neither DEVICE nor GATEWAY is given, then the INTERFACE specified for the PROVIDER in shorewall-providers (5). This - column must be omitted if is specified in - the GATEWAY column. + column must be omitted if , + or is + specified in the GATEWAY column. diff --git a/Shorewall/manpages/shorewall.conf.xml b/Shorewall/manpages/shorewall.conf.xml index 54b4ecbf1..df8d26471 100644 --- a/Shorewall/manpages/shorewall.conf.xml +++ b/Shorewall/manpages/shorewall.conf.xml @@ -1693,7 +1693,11 @@ LOG:info:,bar net fw NULL_ROUTE_RFC1918=[Yes|No] + role="bold">Yes|No|blackhole|unreachable|prohibit] When set to Yes, causes Shorewall to null-route the IPv4 @@ -1706,6 +1710,12 @@ LOG:info:,bar net fw this option ensures that packets with an RFC1918 source address are only accepted from interfaces having known routes to networks using such addresses. + + Beginning with Shorewall 4.5.15, you may specify + , or + to set the type of route to be created. + See http://www.shorewall.net/MultiISP.html#null_routing. diff --git a/Shorewall6/manpages/shorewall6-routes.xml b/Shorewall6/manpages/shorewall6-routes.xml index 8caaae5c3..21c905621 100644 --- a/Shorewall6/manpages/shorewall6-routes.xml +++ b/Shorewall6/manpages/shorewall6-routes.xml @@ -59,6 +59,11 @@ Beginning with Shorewall 4.5.14, you may specify in this column to create a blackhole route. + + Beginning with Shorewall 4.5.15, you may specify + or in this + column to create a prohibit or + unreachable route respectively. @@ -68,8 +73,9 @@ Specifies the device route. If neither DEVICE nor GATEWAY is given, then the INTERFACE specified for the PROVIDER in shorewall6-providers (5). - This column must be omitted if is + url="shorewall6-providers.html">shorewall6-providers + (5).This column must be omitted if , + or is specified in the GATEWAY column. @@ -77,7 +83,7 @@ - FILES + Files /etc/shorewall6/routes diff --git a/docs/MultiISP.xml b/docs/MultiISP.xml index ad3b84d5f..215bb9e80 100644 --- a/docs/MultiISP.xml +++ b/docs/MultiISP.xml @@ -1160,6 +1160,20 @@ gateway:~ #Note that because we used a priority of 1000, the If specified, gives the IP address of the gateway to the DEST. + + Beginning with Shorewall 4.5.14, you may specify + in this column to create a + blackhole route. When + is specified, the DEVICE column must be + empty. + + Beginning with Shorewall 4.5.15, you may specify + or to + create a prohibit or + unreachable route respectively. Again, the + DEVICE column must be empty. + + See the next section for additional information. @@ -1191,6 +1205,334 @@ Comcast 192.168.4.0/24 172.20.1.1 | ip -4 route add 1 Comcast 192.168.4.0/24 | ip -4 route add 192.168.4.0/24 dev eth2 table 1 +
+ Null Routing + + Null routing is a type of routing which discards a given packet + instead of directing it through a specific predefined route. Generally + speaking there are 3 different types of Null routing as indicated + below: + + + + Unreachable routes + + When used, a request for a routing decision returns a + destination with an unreachable route type, an ICMP unreachable is + generated (icmp code 3) and returned to the source address. + + Example: + + ip route add unreachable 10.22.0.12 +ip route add unreachable 192.168.14.0/26 +ip route add unreachable 82.32.0.0/12 + + + Unreachable routes are usually indicated by a dash ("-") in + the "Iface" column when "route -n" is executed: + + ~# route -n +Kernel IP routing table +Destination Gateway Genmask Flags Metric Ref Use Iface +10.22.0.12 - 255.255.255.255 !H 0 - 0 - +192.168.14.0 - 255.255.255.192 ! 0 - 0 - +82.32.0.0 - 255.240.0.0 ! 0 - 0 - + + + + + Prohibit routes + + Similar to "unreachable" routes above, when a request for a + routing decision returns a destination with a prohibit route type, + the kernel generates an ICMP prohibited to return to the source + address. + + Example: + + ip route add prohibit 10.22.0.12 +ip route add prohibit 192.168.14.0/26 +ip route add prohibit 82.32.0.0/12 + + "Prohibit" type routes are also indicated by a dash in the + "Iface" column as indicated above. + + + + Blackhole routes + + The difference between this type of routing and the previous + two listed above is that a packet matching a route with the route + type blackhole is discarded. No ICMP is sent and no packet is + forwarded. + + Example: + + ip route add blackhole 10.22.0.12 +ip route add blackhole 192.168.14.0/26 +ip route add blackhole 82.32.0.0/12 + + Blackhole routes are usually indicated with a start ("*") in + the "Iface" column: + + ~# route -n +Kernel IP routing table +Destination Gateway Genmask Flags Metric Ref Use Iface +10.22.0.12 0.0.0.0 255.255.255.255 UH 0 0 0 * +192.168.14.0 0.0.0.0 255.255.255.192 U 0 0 0 * +82.32.0.0 0.0.0.0 255.240.0.0 U 0 0 0 * + + + +
+ Null Routing Implementation in Shorewall + + As of Shorewall 4.5.14, the only type of null routing + implemented in Shorewall is "blackhole" routing. This can be specified + in two different ways as described below. + + + + Null Routing with NULL_ROUTE_RFC1918 shorewall.conf + configuration option. + + When NULL_ROUTE_RFC1918 is set to Yes, it causes Shorewall + to null-route the IPv4 address ranges reserved by RFC1918 (private + networks). + + When combined with route filtering (ROUTE_FILTER=Yes or + routefilter in shorewall-interfaces(5)), this option ensures that + packets with an RFC1918 source address are only accepted from + interfaces having known routes to networks using such + addresses. + + When this option is used, the blackhole routes for all + RFC1918 subnets are defined for the "main" routing table only. + These, however, can be copied over to different routing tables or + further customised and fine-tuned to suit individual needs by + using the "routes" file (see below). + + For example, by specifying NULL_ROUTE_RFC1918=Yes in + shorewall.conf, Shorewall generates 3 different route statements + to be executed at Shorewall startup: + + ip route replace blackhole 10.0.0.0/8 +ip route replace blackhole 172.16.0.0/12 +ip replace blackhole 192.168.0.0/16 + + + + When NULL_ROUTE_RFC1918=Yes is used, Shorewall creates a + shell script file in ${VARDIR}/undo_rfc1918_routing to undo the + null routing, if needed (see below as to some instances when + this may be necessary). + + + + + Null Routing Using Shorewall "routes" (added in Shorewall + 4.5.14) + + By definition, entries in this file are used to define + routes to be added to provider routing tables, including the + default routing table (main). + + This option allows for a better control over what is defined + as a null route in Shorewall and also allows for custom-defined + subnets (in addition to RFC1918 type networks) to be defined. + Blackhole routes defined in this way need to include the word + "blackhole" in the GATEWAY column and the DEVICE column must also + be ommitted (see example below). + + It is worth noting that blackhole routes created in such a + way cannot be "undone" automatically and have to be deleted + manually using the "ip route del" command. + + Example of use + (/etc/shorewall/routes): + + #PROVIDER DEST GATEWAY DEVICE +main 10.0.0.0/8 blackhole +dmz 82.32.0.0/12 blackhole +dmz 192.168.14.0/26 blackhole + + + The above generates the following 3 statements for execution + upon Shorewall startup: + + ip route replace blackhole 10.0.0.0/8 table main +ip route replace blackhole 82.32.0.0/12 table dmz +ip route replace blackhole 192.168.14.0/26 table dmz + + + + Beginning with Shorewall 4.5.15, Shorewall also supports + "unreachable" and "prohibit" routing. + + + + The NULL_ROUTE_RFC1918 option may be set to "blackhole", + "prohibit" or "unreachable" in addition to "Yes" and "No". + + Shorewall will create the three route statements using the + specified type type. For compatibility with earlier releases, + "Yes" is equivalent to "blackhole". + + For example, if NULL_ROUTE_RFC1918=prohibit, then the + following three route statements will be executed at Shorewall + startup: + + ip route replace prohibit 10.0.0.0/8 +ip route replace prohibit 172.16.0.0/12 +ip replace prohibit 192.168.0.0/16 + + + + + The words "prohibit" and "unreachable" may be placed in the + GATEWAY column of + /etc/shorewall/routes. + + The DEVICE column must be omitted. + + Example of use + (/etc/shorewall/routes): + + #PROVIDER DEST GATEWAY DEVICE +main 10.0.0.0/8 unreachable +dmz 82.32.0.0/12 unreachable +dmz 192.168.14.0/26 unreachable + + + The above generates the following 3 statements for execution + upon Shorewall startup: + + ip route replace unreachable 10.0.0.0/8 table main +ip route replace unreachable 82.32.0.0/12 table dmz +ip route replace unreachable 192.168.14.0/26 table dmz + + +
+ +
+ Important Points To Remember When Using Null Routing in + Shorewall + + + + In order to create "pinhole" in a particular blackhole + route, at least one route needs to be defined in addition to the + null route. + + Lets take the following example: We need to null-route all + addresses from the 10.0.0.0/8 range, *except* 10.1.0.0/24. In such + a case we need to define two routes in our "routes" file (assuming + the default "main" routing table is used and also assuming that + 10.1.0.0/24 is routed via the default gateway on eth0). + + /etc/shorewall/routes: + + #PROVIDER DEST GATEWAY DEVICE +main 10.0.0.0/8 blackhole +main 10.1.0.0/24 - eth0 + + The above will generate 2 statements for execution when + Shorewall starts: + + ip route replace blackhole 10.0.0.0/8 table main +ip route replace 10.1.0.0/24 table main + + + The order in which the two routes above are defined in + "routes" is not important, simply because, by definition, routes + with lower mask value are always traversed first. In that way, + packets originating from or destined to 10.1.0.0/24 will always be + processed before the 10.0.0.0/8 blackhole route. + + + + Null routes, by their definition, are not attached to any + network device. What this means in reality is that when the status + of a particular device changes (either going up or down), that has + absolutely NO effect on the null routes defined (as already + indicated, these are "static" and can only be removed by executing + "ip route del"). + + This sometimes may lead to undesirable side effect: when a + network interface goes down (even temporarily), then ALL routes + defined or attached to that interface are simply deleted from the + routing table by the kernel, while the blackhole routes are + untouched. + + Lets take our example above: when eth0 goes down, then the + route we defined in "routes" for our private subnet (10.1.0.0/24) + will be deleted from the routing table. As soon as eth0 goes back + up again, unless the route for our private 10.1.0.0/24 subnet is + defined again, all packets originating from or destined to + 10.1.0.0/24 will simply be dropped by the kernel! + + An indication of this type of behaviour is getting endless + "martian" packets reported in the system log, like so: + + IPv4: martian source 10.1.0.7 from 10.1.0.1, on dev eth0 + + There are currently two possible solutions to this + particular problem: + + + + Add all network-interface dependent routes (the ones + which are deleted when that interface goes down) to your + distribution's network configuration system. On Redhat and + derivatives, that would be + /etc/sysconfig/network-scripts/route-X + (where "X" is the name of the interface in question). On + Debian and derivatives, it is + /etc/network/interfaces. + + That way, when the network device goes back up, the + Linux OS will add these routes "automatically". Using our + example above - to add a route to 10.1.0.0/24 using the + default gateway on eth0 and also using the main routing table, + the following needs to be added to + /etc/sysconfig/network-scripts/route-eth0 + (Redhat and derivatives): + + 10.1.0.0/24 dev eth0 table main + + + On Debian and derivatives (in the eth0 stanza of + /etc/network/interfaces): + + post-up ip route add 10.1.0.0/24 dev eth0 table main + + + + A more elegant solution to this particular problem is, + in addition to the "standard" shorewall package + (shorewall-lite, shorewall, etc), to add shorewall-init to take care + of this automatically. + + With this approach, when the network interface is + brought back up, the OS passes control to /sbin/ifup-local, + which forms part of the shorewall-init package, and that + script, in turn, executes the appropriate command to reload + the network device settings in the already-compiled + ${VARDIR}/firewall file. + + When shorewall-init is used, all configuration settings + (routes, interface options etc) are kept in one place and do + not have to be defined separately (via + /etc/sysconfig/network-scripts/route-X for example), which + eases maintenance efforts quite considerably. + + + + +
+
+
Looking at the routing tables