Re: enc0 patch for ipsec
- From: Andrew Thompson <thompsa@xxxxxxxxxxx>
- Date: Sat, 17 Jun 2006 10:22:43 +1200
On Fri, Jun 16, 2006 at 06:14:12PM +0200, Max Laier wrote:
On Friday 16 June 2006 18:09, Scott Ullrich wrote:
On 6/16/06, Max Laier <max@xxxxxxxxxxxxxx> wrote:
The issue is, if an attacker manages to get root on your box they are
automatically able to read your IPSEC traffic ending at that box. If you
don't have enc(4) compiled in, that would be more difficult to do. Same
reason you don't want SADB_FLUSH on by default.
Okay, this makes sense. But couldn't you also argue that if someone
gets access to the machine they could also use tcpdump to do the same
thing technically on the internal interface? Just playing devils
advocate.. :)
Think tunnel2tunnel or an SA for a local connection, then. Given, if you are
root you *might* have other means to obtain that information, but that is why
we have a switch to turn off bpf, kmem or the like.
While the encryption keys are just a setkey -D away, I can see the
reason for seperating it out. I have attached another patch with the
changes made.
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 16 Jun 2006 22:04:25 -0000
@@ -0,0 +1,82 @@
+.\" $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 SYNOPSIS
+.Cd "device enc"
+.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
+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 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
+.Dl # tcpdump -i enc0
+.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 16 Jun 2006 21:13:10 -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 enc
net/if_ethersubr.c optional ether
net/if_faith.c optional faith
net/if_fddisubr.c optional fddi
Index: sys/conf/options
===================================================================
RCS file: /home/ncvs/src/sys/conf/options,v
retrieving revision 1.546
diff -u -p -r1.546 options
--- sys/conf/options 13 Jun 2006 13:12:55 -0000 1.546
+++ sys/conf/options 16 Jun 2006 21:24:28 -0000
@@ -340,6 +340,7 @@ BOOTP_NFSROOT opt_bootp.h
BOOTP_NFSV3 opt_bootp.h
BOOTP_WIRED_TO opt_bootp.h
DEVICE_POLLING
+DEV_ENC opt_enc.h
DEV_PF opt_pf.h
DEV_PFLOG opt_pf.h
DEV_PFSYNC opt_pf.h
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 16 Jun 2006 21:15:45 -0000
@@ -0,0 +1,323 @@
+/*-
+ * Copyright (c) 2006 The FreeBSD Project.
+ * 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.
+ *
+ * THIS SOFTWARE IS PROVIDED BY THE AUTHOR 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 AUTHOR 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.
+ *
+ * $FreeBSD$
+ */
+
+#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, 1);
+
+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 16 Jun 2006 21:21:57 -0000
@@ -417,6 +417,8 @@ 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 16 Jun 2006 21:21:19 -0000
@@ -43,6 +43,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
+#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -442,6 +443,18 @@ ipsec4_common_input_cb(struct mbuf *m, s
key_sa_recordxfer(sav, m); /* record data transfer */
+#ifdef DEV_ENC
+ /*
+ * Pass the mbuf to enc0 for bpf and pfil. We will filter the IPIP
+ * packet later after it has been decapsulated.
+ */
+ ipsec_bpf(m, sav, AF_INET);
+
+ if (prot != IPPROTO_IPIP)
+ if ((error = ipsec_filter(&m, 1)) != 0)
+ return (error);
+#endif
+
/*
* Re-dispatch via software interrupt.
*/
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 16 Jun 2006 21:21:33 -0000
@@ -32,6 +32,7 @@
#include "opt_inet.h"
#include "opt_inet6.h"
#include "opt_ipsec.h"
+#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -358,6 +359,13 @@ ipsec4_process_packet(
goto bad;
sav = isr->sav;
+
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for packet filtering */
+ if ((error = ipsec_filter(&m, 2)) != 0)
+ goto bad;
+#endif
+
if (!tunalready) {
union sockaddr_union *dst = &sav->sah->saidx.dst;
int setdf;
@@ -455,6 +463,11 @@ ipsec4_process_packet(
}
}
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for bpf processing */
+ ipsec_bpf(m, sav, AF_INET);
+#endif
+
/*
* 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 16 Jun 2006 21:21:02 -0000
@@ -41,6 +41,7 @@
*/
#include "opt_inet.h"
#include "opt_inet6.h"
+#include "opt_enc.h"
#include <sys/param.h>
#include <sys/systm.h>
@@ -345,6 +346,12 @@ _ipip_input(struct mbuf *m, int iphlen,
/* Statistics */
ipipstat.ipips_ibytes += m->m_pkthdr.len - iphlen;
+#ifdef DEV_ENC
+ /* pass the mbuf to enc0 for packet filtering */
+ if (ipsec_filter(&m, 1) != 0)
+ return;
+#endif
+
/*
* Interface pointer stays the same; if no IPsec processing has
* been done (or will be done), this will point to a normal
_______________________________________________
freebsd-arch@xxxxxxxxxxx mailing list
http://lists.freebsd.org/mailman/listinfo/freebsd-arch
To unsubscribe, send any mail to "freebsd-arch-unsubscribe@xxxxxxxxxxx"
- Follow-Ups:
- Re: enc0 patch for ipsec
- From: gnn
- Re: enc0 patch for ipsec
- References:
- enc0 patch for ipsec
- From: Andrew Thompson
- Re: enc0 patch for ipsec
- From: Max Laier
- Re: enc0 patch for ipsec
- From: Scott Ullrich
- Re: enc0 patch for ipsec
- From: Max Laier
- enc0 patch for ipsec
- Prev by Date: Re: enc0 patch for ipsec
- Next by Date: Re: MFC of socket/protocol reference improvements
- Previous by thread: Re: enc0 patch for ipsec
- Next by thread: Re: enc0 patch for ipsec
- Index(es):
Relevant Pages
|