Hello,

in early January this year there was a discussion about the way ipfw
interacts with ipsec. Last November ipfw was changed to process ipsec
datagrams twice: Once before and a second time after the decoding
procedure. This makes life easier for people who use gif tunnels with
ipsec transport mode, but it makes life harder for people (like myself)
who use native ipsec tunnel mode.

Someone suggested to make the ipfw behavior adjustable through a sysctl,
another approach was to port the Open(/Net)BSD enc0 virtual interface.

I made up a refined sysctl solution for a FreeBSD machine that is acting
as a IPsec tunnel endpoint for roadwarriors in a WLAN environment. The idea
is simple: I introduced a new sysctl "net.inet.ip.fw.ipsec_reinject" which
defaults to "1". The value is an integer and defines at which rule number
ipsec datagrams should be reinjected into the ipfw ruleset. Set it to "0",
and it won't be reinjected at all. Set it to "1" (default) and the datagram
would be reinjected at the very beginning. You also can put your post ipsec
filter rules put at 10000+ and set the sysctl to "10000". Flexible?

This is a first patch against -STABLE to demonstrate the concept.

Any comments?

I may provide a patch that includes ip_fw2.c and check whether it applies
to -CURRENT.

  "
Bjorn Fischer

diff -ur sys/netinet/ip_fw.c /sys/netinet/ip_fw.c
--- sys/netinet/ip_fw.c Thu Nov 21 01:27:30 2002
+++ /sys/netinet/ip_fw.c        Wed Jan 15 17:48:23 2003
@@ -106,6 +106,8 @@
     &fw_verbose, 0, "Log matches to ipfw rules");
 SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, verbose_limit, CTLFLAG_RW, 
     &fw_verbose_limit, 0, "Set upper limit of matches of ipfw rules logged");
+SYSCTL_INT(_net_inet_ip_fw, OID_AUTO, ipsec_reinject, CTLFLAG_RW,
+    &fw_ipsec_reinject, 1, "Reinject decoded IPsec datagrams at this rule");
 
 /*
  * Extension for stateful ipfw.
@@ -1088,7 +1090,7 @@
        u_short src_port = 0, dst_port = 0;
        struct in_addr src_ip, dst_ip;
        u_int8_t proto= 0, flags = 0;
-       u_int16_t skipto;
+       u_int16_t skipto = 0;
        u_int16_t ip_len=0;
 
        int dyn_checked = 0 ; /* set after dyn.rules have been checked. */
@@ -1106,9 +1108,18 @@
        } else
                hlen = ip->ip_hl << 2;
 
+#ifdef IPSEC
+       if (ipsec_gethist(*m, NULL) &&
+           args->divert_rule == 0 &&
+           fw_ipsec_reinject > 1)
+               skipto = fw_ipsec_reinject - 1;
+#endif
+
        /* Grab and reset cookie */
-       skipto = *cookie;
-       *cookie = 0;
+       if (*cookie != 0) {
+               skipto = *cookie;
+               *cookie = 0;
+       }
 
 #define PULLUP_TO(len) do {                                            \
                            if ((*m)->m_len < (len)) {                  \
diff -ur sys/netinet/ip_fw.h /sys/netinet/ip_fw.h
--- sys/netinet/ip_fw.h Tue Jul  9 09:11:42 2002
+++ /sys/netinet/ip_fw.h        Wed Jan 15 16:56:38 2003
@@ -367,6 +367,7 @@
 extern ip_fw_ctl_t *ip_fw_ctl_ptr;
 extern int fw_one_pass;
 extern int fw_enable;
+extern int fw_ipsec_reinject;
 extern struct ipfw_flow_id last_pkt;
 #define IPFW_LOADED    (ip_fw_chk_ptr != NULL)
 #endif /* _KERNEL */
diff -ur sys/netinet/ip_input.c /sys/netinet/ip_input.c
--- sys/netinet/ip_input.c      Mon Nov 25 05:23:00 2002
+++ /sys/netinet/ip_input.c     Wed Jan 15 17:01:58 2003
@@ -193,6 +193,7 @@
 ip_fw_chk_t *ip_fw_chk_ptr;
 int fw_enable = 1 ;
 int fw_one_pass = 1;
+int fw_ipsec_reinject = 1;
 
 /* Dummynet hooks */
 ip_dn_io_t *ip_dn_io_ptr;
@@ -422,6 +423,11 @@
         * - Wrap: fake packet's addr/port <unimpl.>
         * - Encapsulate: put it in another IP and send out. <unimp.>
         */
+
+#ifdef IPSEC
+       if (ipsec_gethist(m, NULL) && fw_ipsec_reinject == 0)
+               goto pass;
+#endif
 
 iphack:
        /*

Reply via email to