Subject: Re: Non-IPSec Processing Point for ipf
To: Curt Sampson <cjs@cynic.net>
From: Greg Troxel <gdt@ir.bbn.com>
List: tech-net
Date: 04/18/2003 13:20:38
  So I was talking with Darren about NetBSD's inability to use ipf on
  packets from another host if you're doing IPSec with that host, and we
  eventually came round to the idea of adding another ipf processing point
  before (on output) or after (on input) IPSec processing. This could
  fairly easily be specified as another interface (though of course it
  wouldn't really be an interface that you could assign an IP address to).

I would be hesitant to model it as an additional interface, but I like
the notion of an interface having two pfil hook places.  Another
approach is to have 2 incoming (and outgoing) rulesets, where one is
run before IPsec and the other after.

I don't see how having a way to specify ex0/wire-side-of-IPsec and and
ex0/host-side-of-IPsec would break any v6 scoping rules, although I
don't really understand the rules.  I would envision no creation of
pseudo-interfaces, and no changing of rcvif.  One would add a pfil
call somewhere in esp_input, perhaps adding a flag to specify that
this is the host-side check.  I think this sidesteps all the issues
about v6 scoping and the creation of extra interfaces.

There is a related issue with filtering flexibility, which is being
able to have separate treatment for packets that are destined for the
host or are being forwarded.

Lame ASCII art:

                         Packet delivery and origination
                         |                         |
                         I/host               O/host
                         |                         |
                        /                           \
 -- I/W -- IPsec -- I/H -- I/F -- ipforward -- O/F -- O/H -- IPsec -- O/W --


Here, there are a number of filter points:

  I/W: input, wire side of IPsec
  I/H: input, host side of IPsec
  I/F: input, before forwarding
  I/host: input, before delivery to host via a pcb

For machines which are both hosts and routers, I often want to block
ports on the host (usually due to services which aren't quite safe),
but I don't always want to block transit traffic, or a different set.
I know I could try to do this by matching all local interface
addresses, but this is not robust against changes and is awkward.

Perhaps this could all be ifdefed on PFIL_MULTIPLE_ENTRIES or
something, so that only those who want the flexibility of 4 input
lists pay the cost.  I suppose there could also be a bitmask for each
rule that specifies for which processing points it is invoked.

A related issue is how to get bpf to grab packets at the I/H point
rather than the I/W point above.

Finally, our SPD is deficient; RFC2401 requires that the SPD be (at
least notionally) per interface.  I think this is hard to fix without
breaking PF_KEYv2 compliance, although there could be an optional
message that had an interface spec, with * being the default if it is
not present.  Currently, NetBSD effectively only supports SPD entries
with a * in the interface field.  I have not felt a big need to
specify per-interface SPD entries.

   But there are other issues that come up as I start to look at the input
   code. It looks to me as if you can do multiple levels of encapsulation,
   so if a user specifies "esp/tunnel/X-Y/require ah/tunnel/X-Y/require" as
   his SPD, were going to get a packet that looks like:

       +-----+----+-----+-----+-----+---------+
       | IP1 | AH | IP2 | ESP | IP3 | payload |
       +-----+----+-----+-----+-----+---------+

This is a funny case, since I don't think it is really a sensible
thing to do.  But I suppose if X-Y were different on esp and ah it
might make sense.  Having only two filter points might be a good
compromise between the complexity of infinite flexibility and not
being able to do what you want in typical cases.

        Greg Troxel <gdt@ir.bbn.com>