Subject: Re: (Stupid?) fastrouting question
To: None <tech-net@NetBSD.org>
From: Alan Barrett <apb@cequrux.com>
List: tech-net
Date: 07/05/2007 10:59:15
On Thu, 05 Jul 2007, Lucio De Re wrote:
> The question: Given a net server running squid, bind and sendmail (I
> think that's about it), I want all "web" traffic (tcp ports 80 and
> 443) to go to a router other than the "default" and return by the
> same path (there's NAT on there, so that makes things a little more
> difficult).
  [...]
> Ideally, I'd want a squid appliance between the internal network and
> the ADSL link, but I'm not aware that such devices exist, so if anyone
> knows of one such, please point me to that.

Make your own "squid appliance".  Here's an attempt using "pf".
(Most of this is adapted from a working system, but some of it
is untested.)

# in squid.conf:

	#
	# act as an interception proxy
	#
	httpd_accel_host virtual
	httpd_accel_port 80
	httpd_accel_with_proxy on
	httpd_accel_uses_host_header on

# in pf.conf:

	#
	# There are some places where we are not allowed to use
	# the "self" keyword, but are allowed to use a table name.
	# So define a table to DTRT.
	#
	table <self> const { self }
	
	#
	# destinations for which port 80 connections should
	# not be molested:
	#
	table <allow80> { self, 192.0.2.0/24 }

	#
	# Other rules intercept traffic on TCP port 80 and divert it
	# to interface lo0 using 'pass out ... route to lo0 ... tag ...'
	# rules.  Here, we grab those packets and divert them to squid
	# using 'rdr on lo0' rules.
	#
	##rdr on lo0 \
	##	proto tcp from any to any \
	##	tagged "interceptsquid" \
	##	-> 127.0.0.1 port 3128
	# XXX: The above (commented out) rule doesn't work, so
	# we use the following rule as a crude approximation
	# to what we want (using 'to ! <self>' instead of 'tagged
	# "interceptsquid"')
	rdr on lo0 \
		proto tcp from any to ! <self> port 80 \
		-> 127.0.0.1 port 3128

	#
	# add "allow80" tag to port-80 traffic that should not be molested
	#
	pass out on ! lo0 \
		proto tcp from any to <allow80> port 80 \
		tag "allow80" \
		keep state
	pass out on ! lo0 \
		proto tcp from any to any port 80 \
		user { squid } \
		tag "allow80" \
		keep state

	#
        # TCP port 80 connections that were not tagged with "allow80"
        # above are now tagged with "interceptsquid" and diverted to the
        # lo0 interface.  A "rdr" rule will pick them up there.
	#
	pass out on ! lo0 route-to lo0 \
		proto tcp from any to any port 80 \
		! tagged "allow80" \
		tag "interceptsquid" \
		keep state

        #
        # Apply policy routing to "web" traffic on the
	# external interface.
	#
	pass out on $external_interface \
		route-to $special_interface $special_router \
		proto tcp from any to any port { 80, 443 } \
		keep state

--apb (Alan Barrett)