Solved Inline anchor parsing not accepting interface list

The pf.conf(5) man page defines the following syntax for anchor rules:
Code:
     anchor-rule    = "anchor" [ string ] [ ( "in" | "out" ) ] [ "on" ifspec ]
                      [ af ] [ protospec ] [ hosts ] [ filteropt-list ] [ "{" ]

     anchor-close   = "}"


     ifspec         = ( [ "!" ] ( interface-name | interface-group ) ) |
                      "{" interface-list "}"
     interface-list = [ "!" ] ( interface-name | interface-group )
                      [ [ "," ] interface-list ]

Based on this, I put the following in my pf.conf:

Code:
anchor on { igb0, igb0.1000 } {
        anchor in {
                block return quick proto {tcp, udp} from any to any port = domain-s             # Block DNS-over-TLS
                block return quick proto {tcp, udp} from any to <DOH_SERVERS> port = https      # Block DNS-over-HTTPS
                pass quick
        }
        anchor out {
                pass quick
        }
}

I was expecting this to result in the same rules for igb0 and igb0.1000, but pfctl -nvf is showing this:
Code:
anchor on igb0 all {
  anchor in all {
    block return quick proto tcp from any to any port = domain-s
    block return quick proto tcp from any to <DOH_SERVERS> port = https
    block return quick proto udp from any to any port = domain-s
    block return quick proto udp from any to <DOH_SERVERS> port = https
    pass quick all flags S/SA keep state (if-bound)
  }
  anchor out all {
    pass quick all flags S/SA keep state (if-bound)
  }
}
anchor on igb0.1000 all

igb0.1000 hasn't got any rules.

Have I misunderstood something about the syntax, or is this potentially a bug in pf's rule parsing?
 
I amended my rules to include the ifspec on the nested anchors as well:
Code:
anchor on { igb0, igb0.1000 } {
  anchor in on { igb0, igb0.1000 } {
    block return quick proto {tcp, udp} from any to any port = domain-s         # Block DNS-over-TLS
    block return quick proto {tcp, udp} from any to <DOH_SERVERS> port = https  # Block DNS-over-HTTPS
    pass quick
  }
  anchor out {
    pass quick
  }
}

resulting in:
Code:
anchor on igb0 all {
  anchor in on igb0 all {
    block return quick proto tcp from any to any port = domain-s
    block return quick proto tcp from any to <DOH_SERVERS> port = https
    block return quick proto udp from any to any port = domain-s
    block return quick proto udp from any to <DOH_SERVERS> port = https
    pass quick all flags S/SA keep state (if-bound)
  }
  anchor in on igb0.1000 all
  anchor out all {
    pass quick all flags S/SA keep state (if-bound)
  }
}
anchor on igb0.1000 all

It seems that the rules inside a nested anchor with an ifspec are only being applied to the first interface if the ifspec is an interface list.
 
It seems this is only a cosmetic issue when viewing the ruleset with pfctl -nvf /etc/pf.conf. If the ruleset is actually loaded, all the expected rules are present and correct according to pfctl -sr:
Code:
[root@router2 ~]# pfctl -sr
block drop log all
block drop in on igb1 all
anchor on igb0 all {
  anchor in all {
    block return quick proto tcp from any to any port = domain-s
    block return quick proto tcp from any to <DOH_SERVERS> port = https
    block return quick proto udp from any to any port = domain-s
    block return quick proto udp from any to <DOH_SERVERS> port = https
    pass quick all flags S/SA keep state (if-bound)
  }
  anchor out all {
    pass quick all flags S/SA keep state (if-bound)
  }
}
anchor on igb0.10 all {
  anchor in all {
    block return quick proto tcp from any to any port = domain-s
    block return quick proto tcp from any to <DOH_SERVERS> port = https
    block return quick proto udp from any to any port = domain-s
    block return quick proto udp from any to <DOH_SERVERS> port = https
    pass quick all flags S/SA keep state (if-bound)
  }
  anchor out all {
    pass quick all flags S/SA keep state (if-bound)
  }
}
 
Back
Top