diff --git a/Shorewall/Perl/Shorewall/Config.pm b/Shorewall/Perl/Shorewall/Config.pm
index d41ae9613..c3460773d 100644
--- a/Shorewall/Perl/Shorewall/Config.pm
+++ b/Shorewall/Perl/Shorewall/Config.pm
@@ -4097,7 +4097,7 @@ sub get_configuration( $$$ ) {
fatal_error 'Invalid Packet Mark layout' if $config{ZONE_BITS} + $globals{ZONE_OFFSET} > 30;
$globals{EXCLUSION_MASK} = 1 << ( $globals{ZONE_OFFSET} + $config{ZONE_BITS} );
- $globals{TPROXY_MASK} = $globals{EXCLUSION_MASK} << 1;
+ $globals{TPROXY_MARK} = $globals{EXCLUSION_MASK} << 1;
$globals{PROVIDER_MIN} = 1 << $config{PROVIDER_OFFSET};
$globals{TC_MAX} = make_mask( $config{TC_BITS} );
diff --git a/Shorewall/Perl/Shorewall/Providers.pm b/Shorewall/Perl/Shorewall/Providers.pm
index 187a63638..2e1b057aa 100644
--- a/Shorewall/Perl/Shorewall/Providers.pm
+++ b/Shorewall/Perl/Shorewall/Providers.pm
@@ -396,8 +396,8 @@ sub process_a_provider() {
$gateway = '';
}
- my ( $loose, $track, $balance , $default, $default_balance, $optional, $mtu, $local , $load ) =
- (0, $config{TRACK_PROVIDERS}, 0 , 0, $config{USE_DEFAULT_RT} ? 1 : 0, interface_is_optional( $interface ), '' , 0 , 0 );
+ my ( $loose, $track, $balance , $default, $default_balance, $optional, $mtu, $tproxy , $load ) =
+ (0, $config{TRACK_PROVIDERS}, 0 , 0, $config{USE_DEFAULT_RT} ? 1 : 0, interface_is_optional( $interface ), '' , 0 , 0 );
unless ( $options eq '-' ) {
for my $option ( split_list $options, 'option' ) {
@@ -434,10 +434,10 @@ sub process_a_provider() {
} elsif ( $option eq 'fallback' ) {
$default = -1;
$default_balance = 0;
- } elsif ( $option eq 'local' ) {
- $local = 1;
- $track = 0 if $config{TRACK_PROVIDERS};
- $default_balance = 0 if $config{USE_DEFAULT_RT};
+ } elsif ( $option eq 'tproxy' ) {
+ $tproxy = 1;
+ $track = 0 if $config{TRACK_PROVIDERS};
+ $default_balance = 0 if $config{USE_DEFAULT_RT};
} elsif ( $option =~ /^load=(0?\.\d{1,8})/ ) {
$load = $1;
require_capability 'STATISTIC_MATCH', "load=$load", 's';
@@ -455,11 +455,12 @@ sub process_a_provider() {
$maxload += $load;
}
- if ( $local ) {
- fatal_error "GATEWAY not valid with 'local' provider" unless $gatewaycase eq 'none';
- fatal_error "'track' not valid with 'local'" if $track;
- fatal_error "DUPLICATE not valid with 'local'" if $duplicate ne '-';
- fatal_error "MARK required with 'local'" unless $mark;
+ if ( $tproxy ) {
+ fatal_error "GATEWAY not valid with 'tproxy' provider" unless $gatewaycase eq 'none';
+ fatal_error "'track' not valid with 'tproxy'" if $track;
+ fatal_error "DUPLICATE not valid with 'tproxy'" if $duplicate ne '-';
+ fatal_error "MARK not allowed with 'tproxy'" if $mark ne '-';
+ $mark = $globals{TPROXY_MARK};
}
my $val = 0;
@@ -471,24 +472,29 @@ sub process_a_provider() {
require_capability( 'MANGLE_ENABLED' , 'Provider marks' , '' );
- $val = numeric_value $mark;
+ if ( $tproxy ) {
+ $val = $globals{TPROXY_MARK};
+ $pref = 1;
+ } else {
+ $val = numeric_value $mark;
- fatal_error "Invalid Mark Value ($mark)" unless defined $val && $val;
+ fatal_error "Invalid Mark Value ($mark)" unless defined $val && $val;
- verify_mark $mark;
+ verify_mark $mark;
- fatal_error "Invalid Mark Value ($mark)" unless ( $val & $globals{PROVIDER_MASK} ) == $val;
+ fatal_error "Invalid Mark Value ($mark)" unless ( $val & $globals{PROVIDER_MASK} ) == $val;
- fatal_error "Provider MARK may not be specified when PROVIDER_BITS=0" unless $config{PROVIDER_BITS};
+ fatal_error "Provider MARK may not be specified when PROVIDER_BITS=0" unless $config{PROVIDER_BITS};
- for my $providerref ( values %providers ) {
- fatal_error "Duplicate mark value ($mark)" if numeric_value( $providerref->{mark} ) == $val;
+ for my $providerref ( values %providers ) {
+ fatal_error "Duplicate mark value ($mark)" if numeric_value( $providerref->{mark} ) == $val;
+ }
+
+ $lastmark = $val;
+
+ $pref = 10000 + $number - 1;
}
- $pref = 10000 + $number - 1;
-
- $lastmark = $val;
-
}
unless ( $loose ) {
@@ -526,7 +532,7 @@ sub process_a_provider() {
loose => $loose ,
duplicate => $duplicate ,
address => $address ,
- local => $local ,
+ tproxy => $tproxy ,
load => $load ,
rules => [] ,
routes => [] ,
@@ -578,7 +584,7 @@ sub add_a_provider( $$ ) {
my $loose = $providerref->{loose};
my $duplicate = $providerref->{duplicate};
my $address = $providerref->{address};
- my $local = $providerref->{local};
+ my $tproxy = $providerref->{tproxy};
my $load = $providerref->{load};
my $dev = chain_base $physical;
@@ -600,7 +606,7 @@ sub add_a_provider( $$ ) {
$provider_interfaces{$interface} = $table;
if ( $gatewaycase eq 'none' ) {
- if ( $local ) {
+ if ( $tproxy ) {
emit 'run_ip route add local ' . ALLIP . " dev $physical table $number";
} else {
emit "run_ip route add default dev $physical table $number";
@@ -632,12 +638,13 @@ CEOF
setup_interface_proc( $interface );
if ( $mark ne '-' ) {
- my $mask = have_capability 'FWMARK_RT_MASK' ? '/' . in_hex $globals{PROVIDER_MASK} : '';
+ my $hexmark = in_hex( $mark );
+ my $mask = have_capability 'FWMARK_RT_MASK' ? '/' . in_hex( $globals{ $tproxy ? 'TPROXY_MARK' : 'PROVIDER_MASK' } ) : '';
- emit ( "qt \$IP -$family rule del fwmark ${mark}${mask}" ) if $config{DELETE_THEN_ADD};
+ emit ( "qt \$IP -$family rule del fwmark ${hexmark}${mask}" ) if $config{DELETE_THEN_ADD};
- emit ( "run_ip rule add fwmark ${mark}${mask} pref $pref table $number",
- "echo \"qt \$IP -$family rule del fwmark ${mark}${mask}\" >> \${VARDIR}/undo_${table}_routing"
+ emit ( "run_ip rule add fwmark ${hexmark}${mask} pref $pref table $number",
+ "echo \"qt \$IP -$family rule del fwmark ${hexmark}${mask}\" >> \${VARDIR}/undo_${table}_routing"
);
}
@@ -697,7 +704,7 @@ CEOF
qq( qt \$IP -6 rule add from all table ) . DEFAULT_TABLE . qq( prio 32767\n) ,
qq(fi) ) if $family == F_IPV6;
- unless ( $local ) {
+ unless ( $tproxy ) {
emit '';
if ( $loose ) {
diff --git a/Shorewall/Perl/Shorewall/Tc.pm b/Shorewall/Perl/Shorewall/Tc.pm
index 6da363341..ed880fa75 100644
--- a/Shorewall/Perl/Shorewall/Tc.pm
+++ b/Shorewall/Perl/Shorewall/Tc.pm
@@ -163,18 +163,16 @@ my @tcclasses;
my %tcclasses;
my %restrictions = ( tcpre => PREROUTE_RESTRICT ,
+ tproxy => PREROUTE_RESTRICT ,
tcpost => POSTROUTE_RESTRICT ,
tcfor => NO_RESTRICT ,
tcin => INPUT_RESTRICT ,
- tcout => OUTPUT_RESTRICT );
+ tcout => OUTPUT_RESTRICT ,
+ );
my $family;
-#
-# Variables supporting DIVERT
-#
-my $divert; #Next chain sequence number
-my %diversions; #Map of marks -> chains. We use a hash rather than an array because mark values can be huge
+my $divertref; # DIVERT chain
#
# Rather than initializing globals in an INIT block or during declaration,
@@ -187,18 +185,17 @@ my %diversions; #Map of marks -> chains. We use a hash rather than an array
# able to re-initialize its dependent modules' state.
#
sub initialize( $ ) {
- $family = shift;
- %classids = ();
- @tcdevices = ();
- %tcdevices = ();
- @tcclasses = ();
- %tcclasses = ();
- %diversions = ();
- @devnums = ();
- $devnum = 0;
- $sticky = 0;
- $ipp2p = 0;
- $divert = 0;
+ $family = shift;
+ %classids = ();
+ @tcdevices = ();
+ %tcdevices = ();
+ @tcclasses = ();
+ %tcclasses = ();
+ @devnums = ();
+ $devnum = 0;
+ $sticky = 0;
+ $ipp2p = 0;
+ $divertref = 0;
}
sub process_tc_rule( ) {
@@ -305,30 +302,18 @@ sub process_tc_rule( ) {
},
DIVERT => sub() {
fatal_error "Invalid DIVERT specification( $cmd/$rest )" if $rest;
- fatal_error "DIVERT requires TC_EXPERT=Yes" unless $config{TC_EXPERT};
- $chain = 'tcpre';
+ $chain = 'tproxy';
- $cmd =~ /DIVERT\((.+?)\)$/;
+ $mark = in_hex( $globals{TPROXY_MARK} ) . '/' . in_hex( $globals{TPROXY_MARK} );
- $mark = $1;
-
- fatal_error "Invalid DIVERT specification( $cmd )" unless defined $mark;
-
- my $val = numeric_value( $mark );
-
- validate_mark $val . '/' . in_hex( $globals{PROVIDER_MASK} );
-
- my $divertref = $diversions{$val};
-
unless ( $divertref ) {
- $divertref = $diversions{$val} = new_chain( 'mangle', 'DIVERT' . ( $divert ? $divert : '' ) );
- $divert++;
- add_ijump( $divertref , j => 'MARK', targetopts => '--set-mark ' . in_hex( $val ) . '/' . in_hex( $globals{PROVIDER_MASK} ) );
+ $divertref = new_chain( 'mangle', 'divert' );
+ add_ijump( $divertref , j => 'MARK', targetopts => "--set-mark $mark" );
add_ijump( $divertref , j => 'ACCEPT' );
}
- $target = $divertref->{name};
+ $target = 'divert';
$matches = '! --tcp-flags FIN,SYN,RST,ACK SYN -m socket --transparent ';
},
@@ -337,7 +322,7 @@ sub process_tc_rule( ) {
fatal_error "Invalid TPROXY specification( $cmd/$rest )" if $rest;
- $chain = 'tcpre';
+ $chain = 'tproxy';
$cmd =~ /TPROXY\((.+?)\)$/;
@@ -345,7 +330,7 @@ sub process_tc_rule( ) {
fatal_error "Invalid TPROXY specification( $cmd )" unless defined $params;
- ( $mark, my $port, my $ip, my $bad ) = split ',', $params;
+ ( my $port, my $ip, my $bad ) = split ',', $params;
fatal_error "Invalid TPROXY specification( $cmd )" if defined $bad;
@@ -368,7 +353,7 @@ sub process_tc_rule( ) {
$target .= ' --tproxy-mark';
- $mark = "$mark/" . in_hex( $globals{PROVIDER_MASK} );
+ $mark = in_hex( $globals{TPROXY_MARK} ) . '/' . in_hex( $globals{TPROXY_MARK} );
},
TTL => sub() {
fatal_error "TTL is not supported in IPv6 - use HL instead" if $family == F_IPV6;
@@ -1958,6 +1943,7 @@ sub setup_tc() {
ensure_mangle_chain 'tcfor';
ensure_mangle_chain 'tcpost';
ensure_mangle_chain 'tcin';
+ ensure_mangle_chain 'tproxy';
}
my @mark_part;
@@ -1975,6 +1961,7 @@ sub setup_tc() {
}
}
+ add_ijump $mangle_table->{PREROUTING} , j => 'tproxy' if $mangle_table->{tproxy}{referenced};
add_ijump $mangle_table->{PREROUTING} , j => 'tcpre', @mark_part;
add_ijump $mangle_table->{OUTPUT} , j => 'tcout', @mark_part;
diff --git a/Shorewall/manpages/shorewall-providers.xml b/Shorewall/manpages/shorewall-providers.xml
index bf4d5be78..337a472a0 100644
--- a/Shorewall/manpages/shorewall-providers.xml
+++ b/Shorewall/manpages/shorewall-providers.xml
@@ -270,6 +270,19 @@
shorewall.conf.
+
+
+ tproxy
+
+
+ Added in Shorewall 4.5.4. Used for supporting the TPROXY
+ action in shorewall-tcrules(5). See http://www.shorewall.net/Shorewall_Squid_Usage.html.
+ When specified, the MARK, DUPLICATE and GATEWAY columns should
+ be empty, INTERFACE should be set to 'lo' and
+ should be the only OPTION.
+
+
diff --git a/Shorewall/manpages/shorewall-tcrules.xml b/Shorewall/manpages/shorewall-tcrules.xml
index 770a44d0c..299ea104a 100644
--- a/Shorewall/manpages/shorewall-tcrules.xml
+++ b/Shorewall/manpages/shorewall-tcrules.xml
@@ -408,36 +408,29 @@ SAME $FW 0.0.0.0/0 tcp 80,443
- DIVERT(mark)
+ DIVERT
- Added in Shorewall 4.5.3. A DIVERT rule should preceed
- each TPROXY rule and should specify the same
- mark value. DIVERT avoids sending
- packets to the TPROXY target once a socket connection to Squid3
- has been established by TPROXY. DIVERT marks the packet with the
- specified mark and exempts it from
- any rules that follow.
+ Added in Shorewall 4.5.3. Two DIVERT rule should preceed
+ the TPROXY rule and should select DEST PORT tcp 80 and SOURCE
+ PORT tcp 80 respectively (assuming that tcp port 80 is being
+ proxied). DIVERT avoids sending packets to the TPROXY target
+ once a socket connection to Squid3 has been established by
+ TPROXY. DIVERT marks the packet with a unique mark and exempts
+ it from any rules that follow.TPROXY(mark[,[port][,[address]]])
+ role="bold">TPROXY([port][,address])
Transparently redirects a packet without altering the IP
- header. Requires a local provider to be defined in shorewall-providers(5).
- There are three parameters to TPROXY - only the first
- (mark) is required:
+ There are three parameters to TPROXY - neither is
+ required:
-
- mark - the MARK value
- corresponding to the local provider in shorewall-providers(5).
-
-
port - the port on which
the proxy server is listening. If omitted, the original
@@ -451,12 +444,6 @@ SAME $FW 0.0.0.0/0 tcp 80,443
request arrives.
-
-
- A DIVERT rule specifying the same
- mark value and other column values
- should preceed each TPROXY rule.
-
diff --git a/Shorewall6/manpages/shorewall6-providers.xml b/Shorewall6/manpages/shorewall6-providers.xml
index 99c3b6f57..96d5cff99 100644
--- a/Shorewall6/manpages/shorewall6-providers.xml
+++ b/Shorewall6/manpages/shorewall6-providers.xml
@@ -245,6 +245,19 @@
column is assumed.
+
+
+ tproxy
+
+
+ Added in Shorewall 4.5.4. Used for supporting the TPROXY
+ action in shorewall-tcrules(5). See http://www.shorewall.net/Shorewall_Squid_Usage.html.
+ When specified, the MARK, DUPLICATE and GATEWAY columns should
+ be empty, INTERFACE should be set to 'lo' and
+ should be the only OPTION.
+
+
diff --git a/Shorewall6/manpages/shorewall6-tcrules.xml b/Shorewall6/manpages/shorewall6-tcrules.xml
index ada019d7d..d16945e3e 100644
--- a/Shorewall6/manpages/shorewall6-tcrules.xml
+++ b/Shorewall6/manpages/shorewall6-tcrules.xml
@@ -305,21 +305,20 @@ SAME $FW 0.0.0.0/0 tcp 80,443
- DIVERT(mark)
+ DIVERT
- Added in Shorewall 4.5.3. A DIVERT rule should preceed
- each TPROXY rule and should specify the same
- mark value. DIVERT avoids sending
- packets to the TPROXY target once a socket connection to Squid3
- has been established by TPROXY. DIVERT marks the packet with the
- specified mark and exempts it from
- any rules that follow.
+ Added in Shorewall 4.5.3. Two DIVERT rule should preceed
+ the TPROXY rule and should select DEST PORT tcp 80 and SOURCE
+ PORT tcp 80 respectively (assuming that tcp port 80 is being
+ proxied). DIVERT avoids sending packets to the TPROXY target
+ once a socket connection to Squid3 has been established by
+ TPROXY. DIVERT marks the packet with a unique mark and exempts
+ it from any rules that follow.TPROXY(mark][,[port][,[address]]])
+ role="bold">TPROXY([port][,[address]]])
Transparently redirects a packet without altering the IP
header. Requires a local provider to be defined in
(mark) is required:
-
- mark - the MARK value
- corresponding to the local provider in shorewall6-providers(5).
-
-
port - the port on which
the proxy server is listening. If omitted, the original
@@ -348,12 +341,6 @@ SAME $FW 0.0.0.0/0 tcp 80,443
request arrives.
-
-
- A DIVERT rule specifying the same
- mark value and other column values
- should preceed each TPROXY rule.
-
diff --git a/docs/PacketMarking.xml b/docs/PacketMarking.xml
index 6c8e4815b..d05f85d5d 100644
--- a/docs/PacketMarking.xml
+++ b/docs/PacketMarking.xml
@@ -398,6 +398,10 @@ tcp 6 19 TIME_WAIT src=206.124.146.176 dst=192.136.34.98 sport=58597 dport=
shorewall update (shorewall6 update)
command will set the above options based on the settings of WIDE_TC_MARKS
and HIGH_ROUTE_MARKS.
+
+ In Shorewall 4.5.4, a TPROXY mark was added
+ for TPROXY support. It is a single bit wide and is to the immediate left
+ of the exclusion mark.
diff --git a/docs/Shorewall_Squid_Usage.xml b/docs/Shorewall_Squid_Usage.xml
index 92e6f8851..1efbac6b8 100644
--- a/docs/Shorewall_Squid_Usage.xml
+++ b/docs/Shorewall_Squid_Usage.xml
@@ -312,15 +312,25 @@ ACCEPT $FW net tcp 80,443
Transparent with TPROXY
- Shorewall 4.4.7 contains support for TPROXY. TPROXY differs from
- REDIRECT in that it does not modify the IP header. Because the IP header
- stays intact, TPROXY requires policy routing to direct the packets to the
- proxy server running on the firewall. This approach requires TPROXY
- support in your kernel and iptables and Squid 3. See Shorewall 4.5.4 contains support for TPROXY. TPROXY differs from
+ REDIRECT in that it does not modify the IP header and requires Squid 3 or
+ later. Because the IP header stays intact, TPROXY requires policy routing
+ to direct the packets to the proxy server running on the firewall. This
+ approach requires TPROXY support in your kernel and iptables and Squid 3.
+ See http://wiki.squid-cache.org/Features/Tproxy4.
+
+ Support for the TPROXY action in shorewall-tcrules(5) and the
+ option in shorewall-providers(5) has been
+ available since Shoreall 4.4.7. That support required additional rules
+ to be added in the 'start' extention script to make it work
+ reliable.
+
+
The following configuration works with Squid running on the firewall
- itself (assume that Squid is listening on port 3128).
+ itself (assume that Squid is listening on port 3129 for TPROXY
+ connections).
/etc/shorewall/interfaces:
@@ -330,21 +340,25 @@ ACCEPT $FW net tcp 80,443
/etc/shorewall/providers:#NAME NUMBER MARK DUPLICATE INTERFACE GATEWAY OPTIONS COPY
-Tproxy 1 1 - lo - local
+Tproxy 1 - - lo - tproxy
+
+
+ Notice that the MARK, DUPLICATE and GATEWAY columns are empty and
+ that the only option is .
+ /etc/shorewall/tcrules (assume loc interface is
eth1):
- MARK SOURCE DEST PROTO PORT(S)
-DIVERT(1) eth1 0.0.0.0/0 tcp 80
-TPROXY(1,3128) eth1 0.0.0.0/0 tcp 80
+ MARK SOURCE DEST PROTO DEST SOURCE
+ PORT(S) PORT(S)
+DIVERT - 0.0.0.0/0 tcp 80
+DIVERT - 0.0.0.0/0 tcp - 80
+TPROXY(3129) eth1 0.0.0.0/0 tcp 80
-
- The DIVERT action was added in Shorewall 4.5.3; user's running
- earlier versions of Shorewall will need to use the start extension script to add the
- DIVERT logic mentioned in the Squid article linked above.
-
+ The DIVERT rules are used to avoid unnecessary invocation of TPROXY
+ for request packets after the connection is established and to direct
+ response packets back to Squid3./etc/shorewall/rules:
diff --git a/docs/images/MarkGeometry.dia b/docs/images/MarkGeometry.dia
index c8528dedc..f41ca2e8f 100644
Binary files a/docs/images/MarkGeometry.dia and b/docs/images/MarkGeometry.dia differ
diff --git a/docs/images/MarkGeometry.png b/docs/images/MarkGeometry.png
index fd921ee87..70cdbe112 100644
Binary files a/docs/images/MarkGeometry.png and b/docs/images/MarkGeometry.png differ