[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Headache with dual WAN and "source route verification"



I am running pf in an environment with two WAN connections, and pf is configured
to load-balance outgoing traffic. This worked nicely for quite a while, then one
ISP turned on "source route verification" on their DSL circuits. This causes any
packets coming into their equipment to get dropped if the source address is not
within the block that they have assigned. When state is established by an
incoming connection, none of my rules to redirect WAN traffic are effective and
some connections cannot be established.
What are my options to ensure that _only_ traffic with a source address
belonging to ext_if2 goes out ext_if2 ?
Sanitized pf.conf follows if of interest:
#################################################################################
# Macros and Tables (grouped here for convenience)
#################################################################################
int_if = "em0"
ext_if1 = "fxp0"
ext_if2 = "fxp1"
lan_net = "192.168.1.0/24"
ext_gw1 = a.a.a.193
ext_gw2 = b.b.b.1
# IP Addresses of sites allowed to access World Client email
table <mail_clients> const {    \
        c.c.c.c,                \
        d,d,d,d                 \
}
# IP Addresses of computers allowed to make outgoing SMTP connections
mail_servers = "{ 192.168.1.1, 192.168.1.2 }"
# Secondary DNS servers that will pull from our primary. Must also be listed
# in bind config files
isp1_dns = "{ a.a.a.5, a.a.a.10 }"
# TCP mail services open to incoming connections.
# Note that redirection is required to enable an incoming service to cross
# the NAT boundary.
mail_services = "{ https, smtp }"
# UDP Services
# Note that some services like DNS responses are already allowed by keeping
# state on outgoing UDP requests.
udp_services = "{ ntp, syslog, tftp, bootps }"
# ICMP Packets allowed to reach the firewall machine
icmp_types = "{ echoreq, unreach }"
# Blocked ports applied to outbound traffic
blocked_outbound_tcp_ports = "{                 \
        bootpc, bootps, epmap, microsoft-ds,    \
        netbios-dgm, netbios-ns, netbios-ssn,   \
        smtp, ssdp                              \
}"
blocked_outbound_udp_ports  = "{                \
        bootpc, bootps, epmap, microsoft-ds,    \
        netbios-dgm, netbios-ns, netbios-ssn,   \
        ssdp                                    \
}"
#################################################################################
# Options Section
# Note that only one interface can be monitored for statistics at a time
# Force state matching on an interface by interface basis
#################################################################################
set loginterface $ext_if1
set block-policy drop
#################################################################################
# Normalization Section
#################################################################################
scrub in all
#################################################################################
# Queueing Section
# Use a simple priority queue on upstream DSL to prioritize empty (no payload)
# TCP ACKs.
#################################################################################
altq on $ext_if1 priq bandwidth 520Kb queue { q_pri1, q_def1 }
queue q_pri1 priority 7
queue q_def1 priority 1 priq(default)
altq on $ext_if2 priq bandwidth 438Kb queue { q_pri2, q_def2 }
queue q_pri2 priority 7
queue q_def2 priority 1 priq(default)
#################################################################################
# Translation Section
# Specify how addresses are to be mapped or redirected.
#################################################################################
# nat: packets going out through $ext_if1 with source address $internal_net will
# get translated as coming from the address of $ext_if1, a state is created for
# such packets, and incoming packets will be redirected to the internal address.
# can't use $ext_if1 as a target since it will expand to all five addresses and
try
# to do outbound load balancing. A special rule is made to ensure that outgoing
mail
# appears to be from the mail address, .195
#
# NAT needs to be applied to each outgoing interface
nat on $ext_if1 from $lan_net to any port smtp -> a.a.a.195
nat on $ext_if1 from $lan_net to any port != smtp -> a.a.a.199
nat on $ext_if2 from $lan_net to any port != smtp -> b.b.b.246
#
# .195 - MAIL
# Direct unwanted visitors to spamd
# spamd-setup puts addresses to be redirected into table <spamd>.
#
table <spamd> persist
rdr on $ext_if1 proto tcp from <spamd> to any port smtp -> 127.0.0.1 port 8025
# SMTP: packets coming in on $ext_if1 with destination a.a.a.195:25 will
# be redirected to the mail server, port 25. A state is created for such
packets,
# and outgoing packets will be translated as coming from the external address.
rdr on $ext_if1 proto tcp from any to a.a.a.195 port smtp -> 192.168.1.1 port
smtp
# World Client: packets coming in on $ext_if1 for mail:443 are SSL
# encrypted packets for World Client access. Only allow ones that come from
# known addresses.
rdr on $ext_if1 proto tcp from <mail_clients> to a.a.a.195 port https ->
192.168.1.1 port https
# 196 - HTTP
# Packets coming in on $ext_if1 with destination a.a.a.196 will be
# redirected to httpd. A state is created for such packets, and
# outgoing packets will be translated as coming from the external address.
rdr on $ext_if1 proto tcp from any to a.a.a.196 port http -> 192.168.1.2 port
http
# .197 - FTP
# Packets coming in on $ext_if1 with destination a.a.a.197 will
# be redirected to ftpd. A state is created for such packets,
# and outgoing packets will be translated as coming from the external address.
#
rdr on $ext_if1 proto tcp from any to a.a.a.197 port ftp -> 192.168.1.2 port ftp
# FTP: send outgoing FTP requests to the ftp-proxy
rdr on $int_if proto tcp from any to any port ftp -> 127.0.0.1 port 8021
# Any incoming mail not to .195 is bogus and will get redirected to spamd
rdr on $ext_if1 proto tcp from any to ! a.a.a.195 port smtp -> 127.0.0.1 port
8025
rdr on $ext_if2 proto tcp from any to any port smtp -> 127.0.0.1 port 8025
#################################################################################
# Filter Section
#################################################################################
# Block everything by default
block return in log on $int_if all label "Blocked in on int_if"
block return out log on $int_if all label "Blocked out on int_if"
block in on $ext_if1 all label "Blocked in on ext_if1"
block out log on $ext_if1 all label "Blocked out on ext_if1"
block in on $ext_if2 all label "Blocked in on ext_if2"
block out log on $ext_if2 all label "Blocked out on ext_if2"
#
# Anti-spoofing
# Drop unroutable packets, avoid stopping genuine internal traffic
#
pass quick on lo0 all keep state
antispoof log for $int_if label "Spoofed packets on int_if"
antispoof log for $ext_if1 label "Spoofed packets on ext_if1"
antispoof log for $ext_if2 label "Spoofed packets on ext_if2"
#
# Allow incoming connections to specific TCP services
#
pass in on $ext_if1 inet proto tcp from any to 192.168.1.1 port $mail_services \
        flags S/SA keep state queue (q_def1, q_pri1) \
        label "Incoming mail connection to port $dstport"
pass in on $ext_if1 inet proto tcp from any to 192.168.1.2 port http \
        flags S/SA keep state queue (q_def1, q_pri1) \
        label "Incoming HTTP connection"
pass in on $ext_if1 inet proto tcp from any to 192.168.1.2 port ftp \
        flags S/SA keep state queue (q_def1, q_pri1) \
        label "Incoming FTP connection"
#
# Backchannel for ftp-proxy
#
pass in on $ext_if1 inet proto tcp from any to $ext_if1 port > 49151 \
        user proxy keep state queue (q_def1, q_pri1) \
        label "FTP-PROXY connection allowed on ext_if1"
#
# Allow spamd connections that have been redirected above
#
pass in on $ext_if1 inet proto tcp from any to 127.0.0.1 port 8025 \
        flags S/SA keep state queue (q_def1, q_pri1)
pass in on $ext_if2 inet proto tcp from any to 127.0.0.1 port 8025 \
        flags S/SA keep state queue (q_def1, q_pri1)
#
# Allow incoming DNS queries and zone transfers
#
pass in on $ext_if1 inet proto udp from any to a.a.a.198 port domain \
        keep state queue (q_def1, q_pri1) \
        label "UDP DNS request"
pass in on $ext_if1 inet proto tcp from $isp1_dns to a.a.a.198 port domain \
        keep state queue (q_def1, q_pri1) \
        label "TCP DNS request incoming from $srcaddr"
#
# Allow and block specific incoming ICMP.
# Return ICMP-unreachable for attempts to connect to port 113 (auth),
# which may avoid timeout of sendmail or other old progs that use auth/ident
#
pass in on $ext_if1 inet proto icmp all icmp-type $icmp_types keep state
pass in on $ext_if2 inet proto icmp all icmp-type $icmp_types keep state
block return-icmp in quick on $ext_if1 proto tcp from any to any port auth \
        label "Auth request on $ext_if1"
block return-icmp in quick on $ext_if2 proto tcp from any to any port auth \
        label "Auth request on $ext_if2"
#
# Rules for internal/lan interface
# pass all outgoing packets on internal interface, keep state to respond to
appropriate interface
# pass in quick any packet destined for the gateway itself
# route all outgoing smtp to ext_if1
# drop all outgoing packets with a disallowed destination port
# force packets local to the providers (especially domain svc and mail) to go to
them directly
# load balance other outgoing tcp traffic from internal network
# load balance outgoing udp and icmp traffic from internal network.
#
pass out on $int_if from any to $lan_net keep state
pass in quick on $int_if from $lan_net to $int_if keep state
pass in quick on $int_if proto tcp from $lan_net to 127.0.0.1 port = 8021 keep
state label ftp-proxy
#
# outgoing mail must always come from the publicly known address for our mail
server
#
pass in quick on $int_if route-to \
        ($ext_if1 $ext_gw1) \
        proto tcp from $mail_servers to any port = smtp flags S/SA keep state
# added 2/26/05 in attempt to make sure all responses go out the correct port.
pass in quick on $int_if route-to \
        ($ext_if1 $ext_gw1) \
        proto tcp from $mail_servers port smtp to any flags S/SA keep state
block in quick log on $int_if proto tcp from any to any port
$blocked_outbound_tcp_ports \
        label "Blocked outbound tcp traffic to port $dstport"
block in quick log on $int_if proto udp from any to any port
$blocked_outbound_udp_ports \
        label "Blocked outbound udp traffic to port $dstport"
# Round-robin all other TCP, UDP, and ICMP
pass in quick on $int_if \
        route-to { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
        proto tcp from $lan_net to any flags S/SA keep state
pass in quick on $int_if \
        route-to { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
        proto udp from $lan_net to any keep state
pass in quick on $int_if \
        route-to { ($ext_if1 $ext_gw1), ($ext_if2 $ext_gw2) } round-robin \
        proto icmp from $lan_net to any keep state
#
# Pass-out rules for external interfaces
# Allow all outgoing traffic, except limit outgoing smtp to mailservers.
# Keep state to enable responses and ICMP associated with the connection.
# Packets marked "lowdelay" or TCP ACKs w/o data will get priority
#
pass out on $ext_if1 proto tcp all flags S/SA keep state queue (q_def1, q_pri1)
pass out on $ext_if1 proto { udp, icmp } all keep state
pass out on $ext_if2 proto tcp all flags S/SA keep state queue (q_def2, q_pri2)
pass out on $ext_if2 proto { udp, icmp } all keep state
#
# route packets from any IPs on $ext_if1 to $ext_gw1
# and the same for ext_if2 to ext_gw2
#
pass out on $ext_if2 route-to ($ext_if1 $ext_gw1) from $ext_if1 to any keep
state
pass out on $ext_if1 route-to ($ext_if2 $ext_gw2) from $ext_if2 to any keep
state