Hi All

I came across this problem a few months ago, and its mpact is actually
greater than expected.  I have ttached a patch below which I have been
running on our production firewalls for 3 months now with no issues to speak
of.  The patch includes a sysctl to turn off the reinjection action.

The problem is caused by rows 401-404 in ip_input.c (the particular version
I am working with is from the RELENG_4_4. By my understanding, is the packet
comming in was previously an IPSEC encapsulated, packet, the pass rule is
hit, rather than the normal action of being re-injected into the stack, and
subject to another pass through the ruleset.

* $FreeBSD: src/sys/netinet/ip_input.c,v 1.130.2.25 2001/08/29 21:41:37
jesper Exp $


#ifdef IPSEC
        if (ipsec_gethist(m, NULL))
                goto pass;
#endif

This action was NOT present in the 4.3 Release code, but ufortunately I have
not had time to tract down exactly when it was introduced.

The case where I came across the problem is that I have a Firewall
performing NAT, and the resultant NAT packets are injected into an IPSEC
tunnel to a business partner.  The problem comes when a packet is received
from the partner, and decapsulated, since it is not being re-injected into
the stack, the ipfw/ipfilter rules cannot pick it up for further processing. 
Thus I was unable to get the packet passed onto the NATD for processing. 
What drew my attention to this (in addition to connections not working) was
the fact that I was getting lots of traffic logged in vain on the firewall
Nat address itself.  The ports corresponded to the port used by the client
system.

The patch below introduces a sysctl net.inet.ip.ipsecinject, which wraps the
offending lines of code with an if conditional.  By default it skips these
and the packet injection continues as normal.  This was instituted so that a
backout could be performed if I experienced problems ( the machines in
question were sitting about 20 000km away :> ) 

I believe that the current implementation is incorrect as it stands.  A
better method in my opinion is to possibly do a comparison of the address in
the packet following decapsulation, if the address is an address local to
the system then it shoudl be re-injected. Although this still doesnt address
the problem of one wanting to do filtering.  Yes it does induce a slight
performance hit, but I certainly do not want to trust the security of my
network to that of my bsiness partners.  How about a sysctl similar to
net.inet.ip.fw.one_pass , which is on by default causing packets to be
passed through the rules prior to, and that an informed administrator can
explicityly turn off if he does not want this function.

This problem is still present in the RELENG_4 branch being used for 4.5.
* $FreeBSD: src/sys/netinet/ip_input.c,v 1.130.2.30 2001/12/14 20:08:22
jlemon Exp $
 
Although I dont think any changes will make it into 4.5 would be nice to get
a commit in soon after release to fix this.

Other thought I had is that the 'correct' place for the sysctl is probably
under the ipsec tree, unfortunately I dont have a box handy to make the
change on and run a test, so here is the patch anyway.

Cheers

Barry

-- 
Barry Irwin
Systems Administrator: Networks and Security
Itouch Labs                     [EMAIL PROTECTED]

PATCH agains 4.4-SECURITY branch.

bash-2.05# diff -u ip_input.c.orig  ip_input.c
--- ip_input.c.orig     Sun Oct 28 20:25:38 2001
+++ ip_input.c  Sun Oct 28 20:25:12 2001
@@ -129,6 +129,12 @@
        &ip_maxfragpackets, 0,
        "Maximum number of IPv4 fragment reassembly queue entries");
 
+static int      ip_ipsecinject = 1;
+SYSCTL_INT(_net_inet_ip, OID_AUTO, ipsecinject, CTLFLAG_RW,
+        &ip_ipsecinject,  0,
+                "Enable IPSEC reinject to fw stack fixes NAT");
+                
+
 /*
  * XXX - Setting ip_checkinterface mostly implements the receive side of
  * the Strong ES model described in RFC 1122, but since the routing table
@@ -399,8 +405,10 @@
        }
 
 #ifdef IPSEC
-       if (ipsec_gethist(m, NULL))
-               goto pass;
+       if (!ip_ipsecinject) {
+               if (ipsec_gethist(m, NULL))
+                       goto pass;
+       }
 #endif
 
        /*
bash-2.05# 


To Unsubscribe: send mail to [EMAIL PROTECTED]
with "unsubscribe freebsd-net" in the body of the message

Reply via email to