PF on two gateways

Paul J. Pathiakis pathiaki at pathiaki.com
Sun Dec 12 06:29:53 PST 2004


Hi,

	There is more than just PF questions here.  However, I ask of the list 
what could be accomplished with PF.  It seems highly versatile, stateful, and 
may be able to solve things that I am not aware of due to light exposure to
the PF technology.

	I want/need to revamp my gateway.

I have a machine with the following interfaces:

	rl0 - interface to ISP cable modem
	rl1 - interface to ISP DSL modem (also, due to PPPoE, tun0)
	re0 - interface to internal 10.1.1.0/24 internal client/servers network
	re1 - interface to internal 10.1.2.0/24 internal servers network

	(Yes, the servers on the two networks 10.1.{1,2}.0/24 are the same
machines with two NICs in them.  The servers are dual function at this 
time and support various services on the different networks)

	I have two gateways.  Both are DHCP addresses.

	1) Cable modem rl0   (3 Mb down, 256 Kb up)
	2) DSL modem rl1     (1.5 Mb down, 384 Kb up)

	Cable modem is simplistic, bang I'm up and running.
	DSL requires PPPoE, bang that's now working.  (I believe that I should 
just leave this connection wide open with regards to ppp filters and let pf
handle this interface, yes?  Also, which interface will I be addressing with pf, 
tun0 or rl1?)

	The big issue is how to firewall this configuration.  I believe that I should 
just use one firewall.  After researching, I find that my IPFW has been 
pseudo-obsoleted and IPfilter may be going the same route.  It seems that 
pf (with ALTQ if shaping/limiting is needed, have to read about ALTQ too) 
is the way to go now.  

	The first issue encountered is that of default routes:

	Depending on which interface comes up last, I get that interface's default
route. Is there a way to load balance outbound connections?  Simple Round 
Robin or something like it?  Or, can FreeBSD support multiple default routes 
now?  If so, how?  Or can I load balance/failover with PF (and CARP is it?).  If 
I lose one interface due to the ISP having issues, can I redirect traffic to the 
other?  
	I believe that this would involve something similar to a cluster where I 
have a "default route address"  like 10.1.1.1 that all my internal desktop/client
machines would have as their default route in  their routing tables which would 
be mapped/balanced to the two outbound interfaces.  How would I accomplish 
this?  (Do this make sense?  Is it possible?)

	Since both use DHCP, I believe I need to parse the leases file to acquire 
any info like default routes, nameservers for resolv.conf (<-After 127.0.0.1, how 
should these be put in the file?  Alternating from one provider to the next?)
Does PF require IPs in all cases or can generic interface names be used?

	Next, I have my first cut at my firewall, please hack as you see fit.  It tries to do
all the right things, including the load balancing on the outbound.  Is there a better 
way to do all these things?  Any reordering?

# Define gateway int and ext i/fs, int nets, ext gw
lan_net1 = "10.1.1.0/24"
lan_net2 = "10.1.2.0/24
int_if1 = "re0"
int_if2 = "re1"
ext_if1 = "rl0"
ext_if2 = "rl1"
ext_gw1 = "68.146.224.1"  (anyone got a script to parse dhclient_leases?)
ext_gw2 = "142.59.76.1"   (anyone got a script to parse dhclient_leases?)

# Define tcp services needed/provided
tcp_services = "{ 22 25 53 110 123 143 389 9102 9103 }"

# Define udp services needed/provided
udp_services = "{ 53 8880 33435-33524 58800 }"

# Define icmp services needed for internal traceroute and ping
icmp_services = "{ return-rst return-icmp echoreply }"

# Define tables for faster lookups, int addresses, rfc1918, spammers, firewall
# state/rules to be kept in memory
table <goodguys> { 10.1.1.0/24, 10.1.2.0/24 }
table <rfc1918> const { 192.168.0.0/16, 172.16.0.0/12, 10.0.0.0/8 }
table <spammers> persist file "/etc/spammers"
table <firewall> const { self }

# Block any rfc1918 and spammers trying to get in on outside i/fs
block in on $ext_if1 from { <rfc1918>, <spammers> } to any
block in on $ext_if2 from { <rfc1918>, <spammers> } to any

# Block any internal addresses knocking on the front door
pass in on $ext_if1 from <goodguys> to any
pass in on $ext_if2 from <goodguys> to any

# Scrub incoming packets
scrub in all

# Nat outgoing connections on each internet interface
nat on $ext_if1 from $lan_net1 to any -> ($ext_if1)
nat on $ext_if1 from $lan_net2 to any -> ($ext_if1)
nat on $ext_if2 from $lan_net1 to any -> ($ext_if2)
nat on $ext_if2 from $lan_net2 to any -> ($ext_if2)

# Default deny
block all

# pass traffic on the loopback interface in either direction
pass quick on lo0 all

# Antispoof
antispoof log quick for $int_if1 inet
antispoof log quick for $int_if2 inet

# Pass all outgoing packets on internal interfaces
pass out on $int_if1 from any to $lan_net1
pass out on $int_if2 from any to $lan_net2

# Pass in quick any packets destined for the gateway itself
pass in quick on $int_if1 from $lan_net1 to $int_if1
pass in quick on $int_if2 from $lan_net2 to $int_if2

# Pass all traffic to and from the local networks
pass in  on $int_if1 from $lan_net1 to any
pass out on $int_if1 from any to $lan_net1
pass in  on $int_if2 from $lan_net2 to any
pass out on $int_if2 from any to $lan_net2

# Load balance outgoing tcp and udp traffic from internal network1. 
pass in on $int_if1 route-to \
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
    proto tcp from $lan_net1 to any flags S/SA modulate state

pass in on $int_if1 route-to \
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
    proto { udp, icmp } from $lan_net1 to any keep state
    
# Load balance outgoing tcp and udp traffic from internal network2. 
pass in on $int_if2 route-to \
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
    proto tcp from $lan_net2 to any flags S/SA modulate state

pass in on $int_if2 route-to \
    { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
    proto { udp, icmp } from $lan_net2 to any keep state

# Allow connection to provided TCP services on both external i/fs        
pass in on $ext_if1 inet proto tcp from any to ($ext_if1) \
   port $tcp_services flags S/SA keep state
pass in on $ext_if2 inet proto tcp from any to ($ext_if2) \
   port $tcp_services flags S/SA keep state

# Allow access to provided UDP services on both external i/fs
pass in on $ext_if1 inet proto udp from any to ($ext_if1) \
   port $udp_services flags S/SA keep state
pass in on $ext_if2 inet proto udp from any to ($ext_if2) \
   port $udp_services flags S/SA keep state
   
# Allo "pass out" rules for both external interfaces
pass out on $ext_if1 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if1 proto { udp, icmp } from any to any keep state
pass out on $ext_if2 proto tcp from any to any flags S/SA modulate state
pass out on $ext_if2 proto { udp, icmp } from any to any keep state

#  Route packets from any IPs on $ext_if1 to $ext_gw1 and the same for
#  $ext_if2 and $ext_gw2
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any 
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any


Thank you,

Paul Pathiakis


	



More information about the freebsd-pf mailing list