Hello Everyone - hoping the right set of eyes looking at this will
find my mistake,
     Details below - quick synopsis is that I have a two interface
host running 3.7 (release from CD - no patches or updates) with both
interfaces as members of a bridge. On the "em1" (internal) interface I
have 3 tagged vlan's configured which allow me to segment traffic
between three networks, all on the same subnet, by putting hosts on a
given vlan on the switch connected to the em1 interface. From a bridge
perspective things work great - hosts all communicate fine. When pf is
enabled however, nfs traffic from certain hosts (not all of them) to
other hosts is being dropped, but I can't determine why. These are all
Solaris hosts with the exception of the OpenBSD box.

=== Things I'm generally unsure about ===
1) Is it a good assumption that if I have vlan0, vlan1, vlan2 I should
be able to filter between those vlan interfaces in pf?
2) Are there any known complications doing this when those interfaces
are also members of a bridge?
3) After looking at what I've done below, is there other debugging I
can do to find out where things are being dropped - so far I can't
find it.

=== Problem Details ===
Most of these hosts have some form of NFS mount to another host going
on. Here's a basic diagram:
*10.1.2.13 mounts files from 10.1.2.11 (this has problems)
10.1.2.13 mounts files from 10.1.2.14 (this has no problems - same vlan)
*10.1.2.14 mounts files from 10.1.2.11 (this has problems)
10.1.2.75 mounts files from 10.1.2.11 (this has no problems)
10.1.2.77 mounts files from 10.1.2.11 (this has no problems)
10.1.2.11 mounts files from 10.1.2.12 (no problems - same vlan)
*10.1.2.12 mounts files from 10.1.1.20 (host on public side of
firewall - has problems as well)

When we first implemented the firewall we moved only 10.1.2.13 &
10.1.2.14 onto vlan2 - the remaining hosts were on the public network
(off em0) and everything worked fine. NFS mounts from vlan2 to em0
were no problem and we could filter traffic. Next, we moved 10.1.2.75
& 10.1.2.77 to vlan1, these also had no problems and NFS mounts worked
fine. Last to move were 10.1.2.11 & 10.1.2.12 and they were moved to
vlan0, immediately the above problems happened.

I can only assume that there is some difference between pf enforcement
from vlan <> vlan that does not exist from vlan <> physical interface.

When I enable the firewall and capture traffic on both vlan0 & vlan2 I
see the following traffic appear on vlan2 but NOT on vlan0. Before
enabling the firewall and after disabling the firewall this same
traffic passes fine:

14:31:23.600109 10.1.2.13.751 > 10.1.2.11.2049: xid 0x4944be7e 156
fsstat [|nfs] (DF) (ttl 64, id 22328, len 196)
14:31:23.996376 10.1.2.13.751 > 10.1.2.11.2049: xid 0x4944be7e 156
fsstat [|nfs] (DF) (ttl 64, id 22329, len 196)
14:31:24.796405 10.1.2.13.751 > 10.1.2.11.2049: xid 0x4944be7e 156
fsstat [|nfs] (DF) (ttl 64, id 22330, len 196)
14:31:26.396463 10.1.2.13.751 > 10.1.2.11.2049: xid 0x4944be7e 156
fsstat [|nfs] (DF) (ttl 64, id 22331, len 196)
14:31:29.596454 10.1.2.13.751 > 10.1.2.11.2049: xid 0x4944be7e 156
fsstat [|nfs] (DF) (ttl 64, id 22332, len 196)

I've enabled logging where I can think it would make sense (see
pf.conf below) and still doing the following shows no traffic related
to NFS:
# tcpdump -e -n -ttt -i pflog0

I've set debug loud in the pf.conf as well and see no additional
detail, though I'm not positive I'm looking in the right place
(pflog).

These problems all go away if I perform a 'pfctl -d' and immediately
start upon issuing a 'pfctl -e' so I'm certain the firewall is
blocking the traffic - but I can't tell why.

I have tried the following:
- Commented out 'scrub in' which made no difference
- Added a specific pass rule before the 'block in' rule which should
allow NFS traffic regardless of state

The very interesting thing is that the NFS mounts between { 10.1.2.75
10.1.2.77 } -> 10.1.2.11 work just fine through all of this.
Additionally, NFS mounts from 10.1.1.20 to 10.1.2.11 fail during this
- which go through the firewall but not between vlan's.

I suspect there is some additional debugging/troubleshooting that I
could do so I'm looking for suggestions. I'm stumped at why I cannot
see the traffic being dropped in pflog - I'm sure if I could get that
to happen it would be painfully obvious where I've failed.

=== Topology ===
em0 - Public interface - connects to the rest of the network. 
em1 - Private interface - connected to a tagged port on a switch which
is configured for the 3 vlan's used to seperate networks.
- vlan0
- vlan1
- vlan2 
(All of the above are added to 'bridge0' except em1) -
/etc/bridgename.bridge0 looks like this:
bash-3.00# cat /etc/bridgename.bridge0
add em0
add vlan0
add vlan1
add vlan2
blocknonip em0
blocknonip vlan0
blocknonip vlan1
blocknonip vlan2
up

vlan 0 has two hosts connected:
10.1.2.11
10.1.2.12

vlan1 has two hosts connected:
10.1.2.75
10.1.2.77

vlan2 has two hosts connected:
10.1.2.13
10.1.2.14

===== PF Config =====

bash-3.00# cat /etc/pf.conf
#       $OpenBSD: pf.conf,v 1.28 2004/04/29 21:03:09 frantzen Exp $
#
# See pf.conf(5) and /usr/share/pf for syntax and examples.
# Remember to set net.inet.ip.forwarding=1 and/or net.inet6.ip6.forwarding=1
# in /etc/sysctl.conf if packets are to be forwarded between interfaces.

#*********************
# Variable definitions
#

ext_if="em0"

# If you want to create host-specific rules, please add an alias here so that
# the ruleset is easier to read and understand
althea="10.1.2.12"
atta="10.1.2.77"
europa="10.1.2.14"
flick="10.1.2.75"
miracle="10.1.2.11"
oldmiracle="10.1.2.13"
triton="10.1.2.15"
calypso="10.1.1.32"

#*******
# Tables
# This is a good way of defining multiple networks or hosts, it's very efficient
# from a performance perspective as well if you have many hosts
#

# General table of all hosts behind the firewall
table <protected_hosts> { $miracle $althea $oldmiracle $europa $atta $flick }

# Hosts specific db allowed tables (who is allowed to talk to these db's)
table <db_allow_europa>         { $althea $triton }
table <db_allow_oldmiracle>     { }
table <db_allow_althea>         { $calypso }
table <db_allow_miracle>        { }
table <db_allow_flick>          { }
table <db_allow_atta>           { }

#
# Service specific allow tables (add hosts here to allow given service)
#

# FTP
table <permit_ftp>      { $miracle $althea $oldmiracle $europa $atta $flick }

# TELNET
table <permit_telnet>   { $miracle $althea $oldmiracle $europa $atta $flick }

# HTTP
table <permit_http>     { $althea $europa $flick }

# Netbios (file sharing)
table <permit_nbt>      { $miracle $althea $oldmiracle $europa $atta $flick }

#****
# Options
#

set debug loud

#****
# normalize traffic in all directions - prevents malformed packets from passing
#

# Do not normalize NFS traffic from Sun hosts (experimental - seems to
make no difference)
#no scrub in log proto { tcp udp } from <protected_hosts> to
<protected_hosts> port nfs

# Normalize all traffic
scrub in log

#*****************************************************
# Standard blocking first (pass rules below will override)
# - this is also the point where any existing connections
# will be allowed, so if you want to block return traffic
# you need to do so above this or in the outbound rules below
#

# Block HSRP so it doesn't show up in logs
block in proto { tcp udp } to 224.0.0.2 port 1985

# Pass rule for NFS traffic (experimental)
pass quick proto { tcp udp } from <protected_hosts> to
<protected_hosts> port nfs

block in log
pass out keep state

# We want to pass all traffic on local interface
pass quick on { lo }

#***********************************
# Access policies for the firewall itself
#

pass in on $ext_if proto tcp to ($ext_if) port ssh keep state
pass in on $ext_if proto icmp to ($ext_if) keep state

#********************************************
# These are known pass rules which are not logged
#

#
# General pass rules for all hosts
#

# permit ping
pass in quick proto icmp to <protected_hosts> keep state

# permit ssh
pass in quick proto tcp to <protected_hosts> port ssh keep state

# permit telnet
pass in quick proto tcp to <permit_telnet> port telnet keep state

# permit http
pass in quick proto tcp to <permit_http> port 80 keep state

# permit netsaint
pass in quick proto tcp to <protected_hosts> port 1469 keep state

# Permit windows file sharing
pass in quick proto udp to <permit_nbt> port 137 keep state
pass in quick proto udp to <permit_nbt> port 138 keep state
pass in quick proto tcp to <permit_nbt> port 139 keep state
pass in quick proto tcp to <permit_nbt> port 445 keep state

# permit ftp
pass in quick proto tcp to <permit_ftp> port ftp keep state
pass in quick proto tcp to <permit_ftp> port ftp-data keep state

#
# Permit incoming db connections
#

# Permit db connections to Europa
pass in quick on $ext_if proto tcp from <db_allow_europa> to $europa
port >1024 keep state

# Permit db connections to OldMiracle
pass in quick on $ext_if proto tcp from <db_allow_oldmiracle> to
$oldmiracle port >1024 keep state

# Permit db connections to Althea
pass in quick on $ext_if proto tcp from <db_allow_althea> to $althea
port >1024 keep state

# Permit db connections to Miracle
pass in quick on $ext_if proto tcp from <db_allow_miracle> to $miracle
port >1024 keep state

# Permit db connections to Atta
pass in quick on $ext_if proto tcp from <db_allow_atta> to $atta port
>1024 keep state

# Permit db connections to Flick
pass in quick on $ext_if proto tcp from <db_allow_flick> to $flick
port >1024 keep state

#*****************************************************************
# Add restrictions here for now - these are blocked and not logged
#

# Europa db blocking (disabled for experimentation)
#block in quick log on $ext_if proto tcp to $europa port 2526
#block in quick log on $ext_if proto udp to $europa port 2526
#block in quick log on $ext_if proto tcp to $oldmiracle port 2960:2965
#block in quick log on $ext_if proto udp to $oldmiracle port 2960:2965

#********************************************************************************
# Make things wide open for now but log so we can see what we still
need to catch
#

# Allow and log all traffic to <protected_hosts>
pass in log to <protected_hosts> keep state

#**************************************
# Outbound Rules for vlan0 (Production)
#

pass in on vlan0 keep state

#***********************************
# Outbound Rules for vlan1 (Staging)
#

pass in on vlan1 keep state

#***************************************
# Outbound Rules for vlan2 (Development)
#

pass in on vlan2 keep state

==== END PF CONFIG ===

=== ifconfig output ===
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> mtu 33224
        inet 127.0.0.1 netmask 0xff000000
        inet6 ::1 prefixlen 128
        inet6 fe80::1%lo0 prefixlen 64 scopeid 0x6
em0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        address: 00:11:43:e6:4e:0c
        media: Ethernet autoselect (100baseTX full-duplex)
        status: active
        inet 10.1.2.32 netmask 0xffffff00 broadcast 10.1.2.255
        inet6 fe80::211:43ff:fee6:4e0c%em0 prefixlen 64 scopeid 0x1
em1: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        address: 00:11:43:e6:4e:0d
        media: Ethernet autoselect (100baseTX full-duplex)
        status: active
        inet6 fe80::211:43ff:fee6:4e0d%em1 prefixlen 64 scopeid 0x2
pflog0: flags=141<UP,RUNNING,PROMISC> mtu 33224
pfsync0: flags=0<> mtu 2020
enc0: flags=0<> mtu 1536
vlan0: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        address: 00:11:43:e6:4e:0d
        vlan: 1000 parent interface: em1
        inet6 fe80::211:43ff:fee6:4e0d%vlan0 prefixlen 64 scopeid 0x7
vlan1: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        address: 00:11:43:e6:4e:0d
        vlan: 1001 parent interface: em1
        inet6 fe80::211:43ff:fee6:4e0d%vlan1 prefixlen 64 scopeid 0x8
vlan2: flags=8943<UP,BROADCAST,RUNNING,PROMISC,SIMPLEX,MULTICAST> mtu 1500
        address: 00:11:43:e6:4e:0d
        vlan: 1002 parent interface: em1
        inet6 fe80::211:43ff:fee6:4e0d%vlan2 prefixlen 64 scopeid 0x9
bridge0: flags=41<UP,RUNNING> mtu 1500

=== end of ifconfig output ===

Reply via email to