enc0 patch for ipsec



Hi,


I have a patch attached that implements the much requested feature of
packet filtering ipsec connections.

This is a device to expose packets going in/out of ipsec and comes
from OpenBSD. There are two functions, a bpf tap which has a basic
header with the SPI number which our current tcpdump knows how to
display, and handoff to pfil(9) for packet filtering.

They way I have hooked it in is compiling it in with fast_ipsec and
the extra work is only done when the enc0 interface is created. The
interface is not created by default so its a minimal hit, the user
will need to 'ifconfig enc0 create' in order to activate it. I
believe the locking is correct so it can be created and destroyed at
runtime.

PRs 98219 and 94829 are requesting this feature.



Andrew
Index: share/man/man4/enc.4
===================================================================
RCS file: share/man/man4/enc.4
diff -N share/man/man4/enc.4
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ share/man/man4/enc.4 15 Jun 2006 22:08:24 -0000
@@ -0,0 +1,111 @@
+.\" $OpenBSD: enc.4,v 1.22 2006/05/26 08:51:29 jmc Exp $
+.\"
+.\" Copyright (c) 1999 Angelos D. Keromytis
+.\" All rights reserved.
+.\"
+.\" Redistribution and use in source and binary forms, with or without
+.\" modification, are permitted provided that the following conditions
+.\" are met:
+.\"
+.\" 1. Redistributions of source code must retain the above copyright
+.\" notice, this list of conditions and the following disclaimer.
+.\" 2. Redistributions in binary form must reproduce the above copyright
+.\" notice, this list of conditions and the following disclaimer in the
+.\" documentation and/or other materials provided with the distribution.
+.\" 3. All advertising materials mentioning features or use of this software
+.\" must display the following acknowledgement:
+.\" This product includes software developed by Angelos D. Keromytis.
+.\" 4. The name of the author may not be used to endorse or promote products
+.\" derived from this software without specific prior written permission.
+.\"
+.\" THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY EXPRESS OR
+.\" IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES
+.\" OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED.
+.\" IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT,
+.\" INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT
+.\" NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE,
+.\" DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY
+.\" THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
+.\" (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE OF
+.\" THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
+.\"
+.\" $FreeBSD$
+.\"
+.Dd June 16, 2006
+.Dt ENC 4
+.Os
+.Sh NAME
+.Nm enc
+.Nd Encapsulating Interface
+.Sh DESCRIPTION
+The
+.Nm
+interface is a software loopback mechanism that allows hosts or
+firewalls to filter
+.Xr fast_ipsec 4
+traffic using any firewall package that hooks in via the
+.Xr pfil 9
+framework.
+.Pp
+In order to enable packet handoff to
+.Xr pfil 9
+and
+.Xr bpf 4 ,
+the
+.Dq enc0
+interface needs to be created and marked up.
+This is most easily done with the
+.Xr ifconfig 8
+.Cm create
+command or using the
+.Va cloned_interfaces
+variable in
+.Xr rc.conf 5 .
+The interface can also be destroyed at runtime, this will disable packet
+interception and filtering.
+.Pp
+The
+.Nm
+interface allows an administrator
+to see outgoing packets before they have been processed by
+.Xr fast_ipsec 4 ,
+or incoming packets after they have been similarly processed, via
+.Xr tcpdump 8 .
+.Pp
+The
+.Dq enc0
+interface inherits all IPsec traffic.
+Thus all IPsec traffic can be filtered based on
+.Dq enc0 ,
+and all IPsec traffic could be seen by invoking
+.Xr tcpdump 8
+on the
+.Dq enc0
+interface.
+.Sh EXAMPLES
+To create the interface and enable IPsec packet filtering:
+.Pp
+.Bd -literal -offset indent
+ifconfig enc0 create up
+.Ed
+.Pp
+To see all outgoing packets before they have been processed via
+.Xr fast_ipsec 4 ,
+or all incoming packets after they have been similarly processed:
+.Pp
+.Bd -literal -offset indent
+tcpdump -i enc0
+.Ed
+.Pp
+To disable packet filtering:
+.Pp
+.Bd -literal -offset indent
+ifconfig enc0 destroy
+.Ed
+.Sh SEE ALSO
+.Xr bpf 4 ,
+.Xr fast_ipsec 4 ,
+.Xr ipf 4 ,
+.Xr ipfw 4 ,
+.Xr pf 4 ,
+.Xr tcpdump 8
Index: share/man/man4/fast_ipsec.4
===================================================================
RCS file: /home/ncvs/src/share/man/man4/fast_ipsec.4,v
retrieving revision 1.3
diff -u -p -r1.3 fast_ipsec.4
--- share/man/man4/fast_ipsec.4 21 Jan 2005 08:36:37 -0000 1.3
+++ share/man/man4/fast_ipsec.4 15 Jun 2006 22:32:58 -0000
@@ -78,10 +78,16 @@ When the
protocols are configured for use, all protocols are included in the system.
To selectively enable/disable protocols, use
.Xr sysctl 8 .
+.Pp
+The packets can be passed to a virtual interface,
+.Dq enc0 ,
+to perform packet filtering before outbound encryption and after decapsulation
+inbound.
.Sh DIAGNOSTICS
To be added.
.Sh SEE ALSO
.Xr crypto 4 ,
+.Xr enc 4 ,
.Xr ipsec 4 ,
.Xr setkey 8 ,
.Xr sysctl 8
Index: sys/conf/files
===================================================================
RCS file: /home/ncvs/src/sys/conf/files,v
retrieving revision 1.1125
diff -u -p -r1.1125 files
--- sys/conf/files 14 Jun 2006 03:03:08 -0000 1.1125
+++ sys/conf/files 15 Jun 2006 21:38:18 -0000
@@ -1459,6 +1459,7 @@ net/if_bridge.c optional if_bridge
net/if_clone.c standard
net/if_disc.c optional disc
net/if_ef.c optional ef
+net/if_enc.c optional fast_ipsec
net/if_ethersubr.c optional ether
net/if_faith.c optional faith
net/if_fddisubr.c optional fddi
Index: sys/net/if_enc.c
===================================================================
RCS file: sys/net/if_enc.c
diff -N sys/net/if_enc.c
--- /dev/null 1 Jan 1970 00:00:00 -0000
+++ sys/net/if_enc.c 15 Jun 2006 21:38:18 -0000
@@ -0,0 +1,323 @@
+/*-
+ * Copyright (c) 2006 Andrew Thompson
+ *
+ * Redistribution and use in source and binary forms, with or without
+ * modification, are permitted provided that the following conditions
+ * are met:
+ *
+ * 1. Redistributions of source code must retain the above copyright
+ * notice, this list of conditions and the following disclaimer.
+ * 2. Redistributions in binary form must reproduce the above copyright
+ * notice, this list of conditions and the following disclaimer in the
+ * documentation and/or other materials provided with the distribution.
+ * 3. Neither the name of Broadcom Corporation nor the name of its contributors
+ * may be used to endorse or promote products derived from this software
+ * without specific prior written consent.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS'
+ * AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
+ * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
+ * ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS
+ * BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR
+ * CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
+ * SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
+ * INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
+ * CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
+ * ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF
+ * THE POSSIBILITY OF SUCH DAMAGE.
+ */
+
+#include <sys/param.h>
+#include <sys/systm.h>
+#include <sys/kernel.h>
+#include <sys/malloc.h>
+#include <sys/mbuf.h>
+#include <sys/module.h>
+#include <machine/bus.h>
+#include <sys/rman.h>
+#include <sys/socket.h>
+#include <sys/sockio.h>
+#include <sys/sysctl.h>
+
+#include <net/if.h>
+#include <net/if_clone.h>
+#include <net/if_types.h>
+#include <net/pfil.h>
+#include <net/route.h>
+#include <net/netisr.h>
+#include <net/bpf.h>
+#include <net/bpfdesc.h>
+
+#include <netinet/in.h>
+#include <netinet/in_systm.h>
+#include <netinet/ip.h>
+#include <netinet/ip_var.h>
+#include <netinet/in_var.h>
+#include "opt_inet6.h"
+
+#ifdef INET6
+#include <netinet/ip6.h>
+#include <netinet6/ip6_var.h>
+#endif
+
+#include <netipsec/ipsec.h>
+
+#define ENCMTU (1024+512)
+#define ENC_HDRLEN 12
+
+/* XXX this define must have the same value as in OpenBSD */
+#define M_CONF 0x0400 /* payload was encrypted (ESP-transport) */
+#define M_AUTH 0x0800 /* payload was authenticated (AH or ESP auth) */
+#define M_AUTH_AH 0x2000 /* header was authenticated (AH) */
+
+struct enchdr {
+ u_int32_t af;
+ u_int32_t spi;
+ u_int32_t flags;
+};
+
+struct ifnet *encif;
+struct mtx enc_mtx;
+
+struct enc_softc {
+ struct ifnet *sc_ifp;
+};
+
+int encioctl(struct ifnet *, u_long, caddr_t);
+int encoutput(struct ifnet *ifp, struct mbuf *m,
+ struct sockaddr *dst, struct rtentry *rt);
+static int enc_clone_create(struct if_clone *, int);
+static void enc_clone_destroy(struct ifnet *);
+
+IFC_SIMPLE_DECLARE(enc, 0);
+
+static void
+enc_clone_destroy(struct ifnet *ifp)
+{
+
+ KASSERT(encif == ifp, ("%s: unknown ifnet", __func__));
+
+ mtx_lock(&enc_mtx);
+ encif = NULL;
+ mtx_unlock(&enc_mtx);
+
+ bpfdetach(ifp);
+ if_detach(ifp);
+ if_free(ifp);
+
+}
+
+static int
+enc_clone_create(struct if_clone *ifc, int unit)
+{
+ struct ifnet *ifp;
+ struct enc_softc *sc;
+
+ mtx_lock(&enc_mtx);
+ if (encif != NULL)
+ return (EBUSY);
+ mtx_unlock(&enc_mtx);
+
+ sc = malloc(sizeof(*sc), M_DEVBUF, M_WAITOK|M_ZERO);
+ ifp = sc->sc_ifp = if_alloc(IFT_ENC);
+ if (ifp == NULL) {
+ free(sc, M_DEVBUF);
+ return (ENOSPC);
+ }
+
+ if_initname(ifp, ifc->ifc_name, unit);
+ ifp->if_mtu = ENCMTU;
+ ifp->if_ioctl = encioctl;
+ ifp->if_output = encoutput;
+ ifp->if_snd.ifq_maxlen = ifqmaxlen;
+ ifp->if_softc = sc;
+ if_attach(ifp);
+ bpfattach(ifp, DLT_ENC, ENC_HDRLEN);
+
+ mtx_lock(&enc_mtx);
+ encif = ifp;
+ mtx_unlock(&enc_mtx);
+
+ return (0);
+}
+
+static int
+enc_modevent(module_t mod, int type, void *data)
+{
+ switch (type) {
+ case MOD_LOAD:
+ mtx_init(&enc_mtx, "enc mtx", NULL, MTX_DEF);
+ if_clone_attach(&enc_cloner);
+ break;
+ case MOD_UNLOAD:
+ printf("enc module unload - not possible for this module\n");
+ return (EINVAL);
+ default:
+ return (EOPNOTSUPP);
+ }
+ return (0);
+}
+
+static moduledata_t enc_mod = {
+ "enc",
+ enc_modevent,
+ 0
+};
+
+DECLARE_MODULE(enc, enc_mod, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY);
+
+int
+encoutput(struct ifnet *ifp, struct mbuf *m, struct sockaddr *dst,
+ struct rtentry *rt)
+{
+ m_freem(m);
+ return (0);
+}
+
+/*
+ * Process an ioctl request.
+ */
+/* ARGSUSED */
+int
+encioctl(struct ifnet *ifp, u_long cmd, caddr_t data)
+{
+ int error = 0;
+
+ switch (cmd) {
+
+ case SIOCSIFFLAGS:
+ if (ifp->if_flags & IFF_UP)
+ ifp->if_drv_flags |= IFF_DRV_RUNNING;
+ else
+ ifp->if_drv_flags &= ~IFF_DRV_RUNNING;
+
+ break;
+
+ default:
+ error = EINVAL;
+ }
+ return (error);
+}
+
+int
+ipsec_filter(struct mbuf **mp, int dir)
+{
+ int error, i;
+ struct ip *ip;
+
+ mtx_lock(&enc_mtx);
+ if (encif == NULL || (encif->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ mtx_unlock(&enc_mtx);
+ return (0);
+ }
+
+ /* Skip pfil(9) if no filters are loaded */
+ if (inet_pfil_hook.ph_busy_count < 0
+#ifdef INET6
+ && inet6_pfil_hook.ph_busy_count < 0
+#endif
+ ) {
+ mtx_unlock(&enc_mtx);
+ return (0);
+ }
+
+ i = min((*mp)->m_pkthdr.len, max_protohdr);
+ if ((*mp)->m_len < i) {
+ *mp = m_pullup(*mp, i);
+ if (*mp == NULL) {
+ printf("%s: m_pullup failed\n", __func__);
+ mtx_unlock(&enc_mtx);
+ return (-1);
+ }
+ }
+
+ error = 0;
+ ip = mtod(*mp, struct ip *);
+ switch (ip->ip_v) {
+ case 4:
+ /*
+ * before calling the firewall, swap fields the same as
+ * IP does. here we assume the header is contiguous
+ */
+ ip->ip_len = ntohs(ip->ip_len);
+ ip->ip_off = ntohs(ip->ip_off);
+
+ error = pfil_run_hooks(&inet_pfil_hook, mp,
+ encif, dir, NULL);
+
+ if (*mp == NULL || error != 0)
+ break;
+
+ /* restore byte ordering */
+ ip = mtod(*mp, struct ip *);
+ ip->ip_len = htons(ip->ip_len);
+ ip->ip_off = htons(ip->ip_off);
+ break;
+
+#ifdef INET6
+ case 6:
+ error = pfil_run_hooks(&inet6_pfil_hook, mp,
+ encif, dir, NULL);
+ break;
+#endif
+ default:
+ printf("%s: unknown IP version\n", __func__);
+ }
+
+ mtx_unlock(&enc_mtx);
+ if (*mp == NULL)
+ return (error);
+ if (error != 0)
+ goto bad;
+
+ return (error);
+
+bad:
+ mtx_unlock(&enc_mtx);
+ m_freem(*mp);
+ *mp = NULL;
+ return (error);
+}
+
+void
+ipsec_bpf(struct mbuf *m, struct secasvar *sav, int af)
+{
+ int flags;
+ struct enchdr hdr;
+ struct mbuf m1;
+
+ KASSERT(sav != NULL, ("%s: sav is null", __func__));
+
+ mtx_lock(&enc_mtx);
+ if (encif == NULL || (encif->if_drv_flags & IFF_DRV_RUNNING) == 0) {
+ mtx_unlock(&enc_mtx);
+ return;
+ }
+
+ if (encif->if_bpf) {
+ flags = 0;
+ if (sav->alg_enc != SADB_EALG_NONE)
+ flags |= M_CONF;
+ if (sav->alg_auth != SADB_AALG_NONE)
+ flags |= M_AUTH;
+
+ /*
+ * We need to prepend the address family as a four byte
+ * field. Cons up a dummy header to pacify bpf. This
+ * is safe because bpf will only read from the mbuf
+ * (i.e., it won't try to free it or keep a pointer a
+ * to it).
+ */
+ hdr.af = af;
+ hdr.spi = sav->spi;
+ hdr.flags = flags;
+
+ m1.m_flags = 0;
+ m1.m_next = m;
+ m1.m_len = ENC_HDRLEN;
+ m1.m_data = (char *) &hdr;
+
+ bpf_mtap(encif->if_bpf, &m1);
+ }
+ mtx_unlock(&enc_mtx);
+}
Index: sys/net/if_types.h
===================================================================
RCS file: /home/ncvs/src/sys/net/if_types.h,v
retrieving revision 1.21
diff -u -p -r1.21 if_types.h
--- sys/net/if_types.h 10 Jun 2005 16:49:19 -0000 1.21
+++ sys/net/if_types.h 15 Jun 2006 21:38:18 -0000
@@ -246,6 +246,7 @@
#define IFT_GIF 0xf0
#define IFT_PVC 0xf1
#define IFT_FAITH 0xf2
+#define IFT_ENC 0xf4
#define IFT_PFLOG 0xf6
#define IFT_PFSYNC 0xf7
#define IFT_CARP 0xf8 /* Common Address Redundancy Protocol */
Index: sys/netipsec/ipsec.h
===================================================================
RCS file: /home/ncvs/src/sys/netipsec/ipsec.h,v
retrieving revision 1.11
diff -u -p -r1.11 ipsec.h
--- sys/netipsec/ipsec.h 10 Apr 2006 15:04:36 -0000 1.11
+++ sys/netipsec/ipsec.h 15 Jun 2006 21:38:18 -0000
@@ -335,6 +335,8 @@ extern int ipsec_replay;
extern int ipsec_integrity;
#endif

+extern struct ifnet *encif;
+
extern struct newipsecstat newipsecstat;
extern struct secpolicy ip4_def_policy;
extern int ip4_esp_trans_deflev;
@@ -417,6 +419,9 @@ extern void m_checkalignment(const char*
extern struct mbuf *m_makespace(struct mbuf *m0, int skip, int hlen, int *off);
extern caddr_t m_pad(struct mbuf *m, int n);
extern int m_striphdr(struct mbuf *m, int skip, int hlen);
+extern int ipsec_filter(struct mbuf **, int);
+extern void ipsec_bpf(struct mbuf *, struct secasvar *, int);
+
#endif /* _KERNEL */

#ifndef _KERNEL
Index: sys/netipsec/ipsec_input.c
===================================================================
RCS file: /home/ncvs/src/sys/netipsec/ipsec_input.c,v
retrieving revision 1.11
diff -u -p -r1.11 ipsec_input.c
--- sys/netipsec/ipsec_input.c 4 Jun 2006 19:32:32 -0000 1.11
+++ sys/netipsec/ipsec_input.c 15 Jun 2006 21:38:18 -0000
@@ -443,6 +443,18 @@ ipsec4_common_input_cb(struct mbuf *m, s
key_sa_recordxfer(sav, m); /* record data transfer */

/*
+ * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
+ * packet later after it has been decapsulated.
+ */
+ if (encif != NULL) {
+ ipsec_bpf(m, sav, AF_INET);
+
+ if (prot != IPPROTO_IPIP)
+ if ((error = ipsec_filter(&m, 1)) != 0)
+ return (error);
+ }
+
+ /*
* Re-dispatch via software interrupt.
*/
if ((error = netisr_queue(NETISR_IP, m))) {
Index: sys/netipsec/ipsec_output.c
===================================================================
RCS file: /home/ncvs/src/sys/netipsec/ipsec_output.c,v
retrieving revision 1.11
diff -u -p -r1.11 ipsec_output.c
--- sys/netipsec/ipsec_output.c 2 Nov 2005 13:46:32 -0000 1.11
+++ sys/netipsec/ipsec_output.c 15 Jun 2006 21:38:18 -0000
@@ -358,6 +358,11 @@ ipsec4_process_packet(
goto bad;

sav = isr->sav;
+
+ /* pass the mbuf to enc0 for packet filtering */
+ if (encif != NULL && (error = ipsec_filter(&m, 2)) != 0)
+ goto bad;
+
if (!tunalready) {
union sockaddr_union *dst = &sav->sah->saidx.dst;
int setdf;
@@ -455,6 +460,10 @@ ipsec4_process_packet(
}
}

+ /* pass the mbuf to enc0 for bpf processing */
+ if (encif != NULL)
+ ipsec_bpf(m, sav, AF_INET);
+
/*
* Dispatch to the appropriate IPsec transform logic. The
* packet will be returned for transmission after crypto
Index: sys/netipsec/xform_ipip.c
===================================================================
RCS file: /home/ncvs/src/sys/netipsec/xform_ipip.c,v
retrieving revision 1.12
diff -u -p -r1.12 xform_ipip.c
--- sys/netipsec/xform_ipip.c 30 Mar 2006 18:57:04 -0000 1.12
+++ sys/netipsec/xform_ipip.c 15 Jun 2006 21:38:18 -0000
@@ -345,6 +345,10 @@ _ipip_input(struct mbuf *m, int iphlen,
/* Statistics */
ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;

+ /* pass the mbuf to enc0 for packet filtering */
+ if (encif != NULL && ipsec_filter(&m, 1) != 0)
+ return;
+
/*
* Interface pointer stays the same; if no IPsec processing has
* been done (or will be done), this will point to a normal
_______________________________________________
freebsd-net@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-net
To unsubscribe, send any mail to "freebsd-net-unsubscribe@xxxxxxxxxxx"

Relevant Pages

  • enc0 patch for ipsec
    ... This is a device to expose packets going in/out of ipsec and comes ... and handoff to pfilfor packet filtering. ... the extra work is only done when the enc0 interface is created. ...
    (freebsd-arch)
  • RE: Intrusion Prevention requirements document
    ... The tools consider one interface as "client" and other ... Packet 1 is first sent out on client interface. ... > my previous company was Blade Software where I developed IDS Informer ... Up to 75% of cyber attacks are launched on shopping carts, ...
    (Pen-Test)
  • Re: Pix 515 VLAN NAT0 issues
    ... that ACL will be exempt from NAT. ... the packet at the time the PIX receives the packet. ... ACL applied to an inside interface would have the internal IPs as ... accepted as having a translation and satisfying the security policies. ...
    (comp.dcom.sys.cisco)
  • Re: best encryption + mode for network packets ?
    ... > I don't understand much about all the different encryption modes... ... The IPSEC design deals with many issues ... that the chaining modes typically require an unpredictable but non-secret ... start of the packet they've just received, ...
    (sci.crypt)
  • [NEWS] Ascends Undocumented Protocol Allows Unauthorized Modifications
    ... TAOS Operating System provides an easy to use and support interface. ... By sending a crafted UDP packet to the devices UDP discard port, ... 06/29/02 Initial Notification *Note-Initial notification by phenoelit ... In no event shall we be liable for any damages whatsoever including direct, indirect, incidental, consequential, loss of business profits or special damages. ...
    (Securiteam)