Two things: One is a question regarding scrub and the other is a request for comments on my pf ruleset (If someone has actually started using something like wiki then a pointer in that direction would be nice too :)
 
First my goals and circumstances for my ruleset:
 
I have an OpenBSD-current machine acting as my gateway/firewall/NAT box. There are a few Windows (2000) boxes and one OpenBSD-current box behind the NAT.
The gateway runs dhcpd on the internal interface, and also acts as a caching name server and the internal authoriative name server for my local domain. It runs ftp-proxy and tircproxy, and I've added entries to /etc/services for the ports that both of these proxies use. I've also added a _tirc user which tircproxy runs as. /dev/pf has been made group read/writeable and I've added a pf group and chown'd it to root:pf, and added _tirc, proxy and _identd to this group. I'm using oidentd instead of identd and it runs as user _identd.
 
From the external interface point of view, I run sshd and I have oidentd open to only the list of ips given from a table. I currently connect via 28.8kbps modem (hopefully to change soon ;)
 
From the internal interface point of view, I run the above mentioned services and ftpd, although the internal interface protection is permissive enough to allow the internal machines to connect to any other service listening on the internal interface. The internal interface is a 100Mbps rl card.
 
My goals (other than to help prevent being hacked of course ;) are to stop spoofed packets (I looked at using antispoof but it didn't meet my requirements) from entering or leaving, to implement some sort of bandwidth priority and to otherwise to appear to not being running a firewall and to if possible mask what OS I'm running from fingerprinting. Currently I block icmp6.
 
My question regarding scrub is this: it would seem that scrub is stopping FIN, NULL and XMAS scans cold, and not returning anything at all. From my quick reading of the relevant RFC, an RST should be returned if the port is closed and an ACK should be returned if the port is open (although a number of OS's just return RSTs too). Either way, the scrub rule seems to drop the packet entirely, not passing it on to the filter rules giving me a chance to reply or not reply at my choosing. (I would prefer to reply with RST personally). I don't want to remove the scrub statement because then I'd lose the other benefits of scrub.
 
Also I've noticed when doing tcpdump's that when packets go through scrub the tcpdump's sometimes tend to mention that the packet has a bad IP checksum (well the TCP checksum was reported as ok, so I assume they mean the IP checksum). Is this known behaviour?
 
Anyway, here's my ruleset:
 
==================================
 
 
# Macros
int_if="rl1"
ext_if="tun0"
max_mss="1432"
min_highport="49152"
ext_bandwidth="28Kb"

# Tables
table <unrouteable> const { 0/8, 10/8, 127/8, 169.254/16, 172.16/12, 192.0.2/24, 192.168/16 }
table <noircproxy> persist file "/etc/pf/noircproxy" { }
table <allowedsmb> const { $int_if:network, 255.255.255.255 }
table <int_ok> const { $int_if:network, 255.255.255.255 }
table <bannedips> persist file "/etc/pf/bannedips" { }
table <identservers> persist file "/etc/pf/identservers" { }

# Options
set timeout tcp.closed 1

# Normalisation
scrub out on $ext_if all no-df max-mss $max_mss random-id
scrub out on $int_if inet from ! $int_if max-mss $max_mss
scrub log no-df

# Queues
altq on $ext_if cbq bandwidth $ext_bandwidth queue { std, bulk, medium, fast }
queue std cbq(default)
queue bulk priority 0
queue medium priority 4
queue fast priority 7

# Translation
nat on $ext_if inet from $int_if:network to ! $int_if:network -> $ext_if

rdr on $int_if inet proto tcp from $int_if:network to ! $int_if:network port 21 -> lo0 port ftpproxy

no rdr on $int_if inet proto tcp from $int_if:network to <noircproxy> port 6667
no rdr on $int_if inet proto tcp from $int_if to any port 6667
rdr on $int_if inet proto tcp from $int_if:network to ! $int_if port 6667 -> lo0 port ircproxy

# Filter Rules

# Default action is to block with return and log
block return log

# Don't log inet6
block return inet6

# Allow through unfiltered interfaces
pass quick on { lo0, lo1, enc0 }

# antispoof unfiltered interfaces
block in quick on ! lo0 inet from lo0:network

# Block non routeable packets
block log quick from no-route
block return log quick to no-route

# Block TCP connections with invalid flags
block quick proto tcp flags R/R

block return log quick proto tcp flags /S
block return log quick proto tcp flags A/A

# Internal Interface

# Incoming Internal

# Allow DHCP clients through to our DHCP server
pass in quick on $int_if inet proto udp from port = bootpc to { 255.255.255.255, $int_if } port = bootps keep state

# antispoof in for internal interfaces
block in log quick on ! $int_if inet from $int_if:network
block in quick on $int_if inet from { $int_if, ! $int_if:network }

# Restrict SMB to the internal network

block return in log quick on $int_if inet proto udp to ! <allowedsmb> port { 137, 138, 445 }
block return in log quick on $int_if inet proto tcp to ! <allowedsmb> port { 137, 139, 445 }

# Silently drop SMB packets for this machine (disable if using Samba)
block return in quick on $int_if inet proto udp to port { 137, 138, 445 }
block return in quick on $int_if inet proto tcp to port { 137, 139, 445 }

# Allow through redirected proxies
pass in quick on $int_if inet proto tcp to lo0 port = ftpproxy user = root keep state
pass in quick on $int_if inet proto tcp to lo0 port = ircproxy user { _tirc, root } keep state

# Allow TCP in
pass in quick on $int_if inet proto tcp to $int_if user { >= 0 } keep state
block return in log quick on $int_if inet proto tcp to $int_if
pass in quick on $int_if inet proto tcp to ! <unrouteable> modulate state

# Allow UDP in
pass in quick on $int_if inet proto udp to $int_if user { >= 0 } keep state (udp.first 10, udp.single 10 )
block return-icmp in log quick on $int_if inet proto udp to $int_if
pass in quick on $int_if inet proto udp to ! <unrouteable> keep state (udp.first 10, udp.single 10)

# Allow ICMP in
pass in quick on $int_if inet proto icmp to { $int_if, ! <unrouteable> } icmp-type 8 code 0 keep state

# Outgoing Internal

pass out quick on $int_if inet proto { tcp, udp, icmp } from $int_if to <int_ok> keep state
block out log quick on $int_if from <unrouteable>
pass out quick on $int_if inet proto tcp to <int_ok> modulate state
pass out quick on $int_if inet to <int_ok> keep state

# External Interface

# antispoof for external interface
block in log quick on $ext_if inet from { ($ext_if), <unrouteable>, 255.255.255.255 }

# Insert pass rules for external interface redirected packets here...

# Block packets sent to an invalid address
block return in log quick on $ext_if inet to !($ext_if)

# Silently block extra dns replies
block return in on $ext_if inet proto udp from port = domain to port = domain

# Allow incoming services

# Block banned ips

block return in log quick on $ext_if inet from <bannedips> label bannedips queue bulk

# TCP Services
pass in log quick on $ext_if inet proto tcp to port = ssh keep state label ssh queue(bulk, medium)

# Allow certain ident servers
pass in log quick on $ext_if inet proto tcp from <identservers> to port = auth label ident

# Open up the high ports for active mode type connections

# DCC traffic for tircproxy
pass in quick on $ext_if inet proto tcp to port >= $min_highport user { _tirc } keep state label dcctraffic queue bulk

# Active mode ftp traffic
pass in quick on $ext_if inet proto tcp to port >= $min_highport user { root } keep state label ftptraffic queue bulk

# Allow ping requests through
pass in quick on $ext_if inet proto icmp icmp-type 8 code 0 keep state label in_ping

# Outgoing External

# Block out from spoofed ip's
block out log quick on $ext_if inet from !($ext_if)

# Block out to unrouteable addresses
block return out log quick on $ext_if to <unrouteable>

# Allow outgoing

pass out quick on $ext_if inet proto tcp user = proxy keep state label ftptraffic queue bulk
pass out quick on $ext_if inet proto tcp to port = ssh keep state label ssh queue(bulk, fast)
pass out quick on $ext_if inet proto tcp to port = telnet keep state label telnet queue fast
pass out quick on $ext_if inet proto tcp keep state

pass out quick on $ext_if inet proto udp keep state label udp queue fast

pass out quick on $ext_if inet proto icmp keep state label icmp queue fast
 
==============================================================
 
 
Cheers,
 
Alistair Kerr

Reply via email to