Hi Mike.

Here's a couple of points.

First, Windows uses ICMP only on traceroute (tracert) so there's
consistency between your Windows and FreeBSD internal hosts - it's an
ICMP blocked (in or out) issue.

http://technet.microsoft.com/en-us/library/cc940128.aspx

Can you ping and traceroute your router from your internal hosts?
Can you go the other way?

Second, and here we go into grey area, I'm no expert at the pf thing
and I do it slightly different to you.
However, I use a simple ruleset and don't explicitly allow ICMP ...
and yet it works from internal Windows and OpenBSD hosts.

Here is the basics (in case there's a clue there):

# options

set block-policy return
set debug urgent
set loginterface pppoe0
set optimization normal
set reassemble no
set require-order yes
set ruleset-optimization basic
set skip on lo
#set state-defaults
set state-policy if-bound
#set timeout

# traffic normalization

antispoof quick for lo inet
antispoof quick for vr1 inet
antispoof quick for vr2 inet

# packet filtering

block all

# pppoe0:network

match in log on pppoe0

pass out on pppoe0 inet from (pppoe0) to any
pass out on pppoe0 inet from vr1:network nat-to (pppoe0)
pass out on pppoe0 inet from vr2:network nat-to (pppoe0)

#pass in on pppoe0 inet proto icmp from any to (pppoe0) icmp-type 8 code 0

# vr1:network

pass in on vr1 inet from vr1:network to any
pass out on vr1 inet from vr1 to vr1:network
pass out on vr1 inet from vr2:network to vr1:network

# vr2:network

pass in on vr2 inet from vr2:network to any
pass out on vr2 inet from vr2 to vr2:network
pass out on vr2 inet from vr1:network to vr2:network

Most or all of the "options" are default.
The commented icmp line is to allow outsiders to icmp echo request
this machine and get a reply. I've commented it to make sure it's not
why mine works and yours doesn't.

There's a few items in the pf.conf man page that lead me to guess that
care needs to be taken with ICMP (as far as state and UDP and TCP
being directly referenced but ICMP requests requiring special care).

     For ICMP, pass out/in ping queries.  State matching is done on host
     addresses and ICMP ID (not type/code), so replies (like 0/0 for 8/0) will
     match queries.  ICMP error messages (which always refer to a TCP/UDP
     packet) are handled by the TCP/UDP states.

         pass on $ext_if inet proto icmp all icmp-type 8 code 0


     Furthermore, correct handling of ICMP error messages is critical to many
     protocols, particularly TCP.  pf(4) matches ICMP error messages to the
     correct connection, checks them against connection parameters, and passes
     them if appropriate.  For example if an ICMP source quench message
     referring to a stateful TCP connection arrives, it will be matched to the
     state and get passed.

           pass out inet proto icmp all icmp-type echoreq

Etcetera.

Like I said I'm guessing but it might be a state issue (a design
feature) and something to do with the order of your match/block versus
my block/pass - I notice in the man page that ICMP is treated as a
special case (see "block") and also this:

     set block-policy
             The block-policy option sets the default behaviour for the packet
             block action:

             drop      Packet is silently dropped.
             return    A TCP RST is returned for blocked TCP packets, an ICMP
                       UNREACHABLE is returned for blocked UDP packets, and
                       all other packets are silently dropped.

So on.

I'd try removing your "block in" for testing.
Consider adding a rule (flavour as necessary):
           pass out inet proto icmp all icmp-type echoreq

Best wishes.

Reply via email to