Re: iked: support MOBIKE (RFC 4555)

2017-11-27 Thread Patrick Wildt
On Tue, Nov 14, 2017 at 01:58:41PM +0100, Patrick Wildt wrote:
> On Thu, Nov 09, 2017 at 11:40:30AM +0100, Patrick Wildt wrote:
> > Hi,
> > 
> > this diff implements MOBIKE (RFC 4555) support in iked(8), with us
> > acting as responder.  In practice this support means that clients like
> > iPhones can roam in different networks (LTE, WiFi) and change their
> > external address without having to re-do the whole handshake.  It allows
> > the client to choose how and when to change the external tunnel endpoint
> > addresses on demand, depending on which network is better or even is
> > connected at all.
> > 
> > This diff already had a few iterations where race conditions were found
> > and ironed out, so this should be a rather stable version which has been
> > working really well for me now.
> > 
> > Key changes with this diff are:
> > 
> >  * MOBIKE is on by default, but can be turned off (if neccessary)
> >using a config key.
> >  * MOBIKE support is then announced to the initiator.
> >  * Peers can use different IP addresses in the IKE messages, but the
> >Tunnel is only updated when we receive IKEV2_N_UPDATE_SA_ADDRESSES.
> >  * This means we need to store two peer addresses.  The one he talked to us
> >last, so that we know where to respond to.  And the one that the kernel
> >knows, so that we know if we have to update the SAs and flows.
> >  * We need to update the SA as well as the flow.  For the SAs I added
> >a way of updating destination addresses of an existing TDB in June.
> >The flows simply need a reload after the SA changed.
> >  * COOKIE2 is used for return routability checks.  strongswan seems
> >to use it.  It's encrypted and should be sent back to the initiator.
> > 
> > When you, for instance, use your phone and turn on/off WiFi, you should
> > see that the VPN stays connected and iked should log that the address
> > has changed.  Especially `ipsecctl -sa` should show updated SAs and
> > flows.
> > 
> > OKs? Objections? Feedback?
> 
> I have heard from two more people running it and seeing it work.  Anyone
> else?

So far the response has been good.  Any OKs or should I just put it in
to give it more exposure?

Patrick

> > Patrick
> > 
> > diff --git a/sbin/iked/config.c b/sbin/iked/config.c
> > index 590e4d7f4da..da8d0745f3c 100644
> > --- a/sbin/iked/config.c
> > +++ b/sbin/iked/config.c
> > @@ -814,6 +814,29 @@ config_getcompile(struct iked *env, struct imsg *imsg)
> > return (0);
> >  }
> >  
> > +int
> > +config_setmobike(struct iked *env)
> > +{
> > +   unsigned int boolval;
> > +
> > +   boolval = env->sc_mobike;
> > +   proc_compose(>sc_ps, PROC_IKEV2, IMSG_CTL_MOBIKE,
> > +   , sizeof(boolval));
> > +   return (0);
> > +}
> > +
> > +int
> > +config_getmobike(struct iked *env, struct imsg *imsg)
> > +{
> > +   unsigned int boolval;
> > +
> > +   IMSG_SIZE_CHECK(imsg, );
> > +   memcpy(, imsg->data, sizeof(boolval));
> > +   env->sc_mobike = boolval;
> > +   log_debug("%s: %smobike", __func__, env->sc_mobike ? "" : "no ");
> > +   return (0);
> > +}
> > +
> >  int
> >  config_setocsp(struct iked *env)
> >  {
> > diff --git a/sbin/iked/iked.c b/sbin/iked/iked.c
> > index 09fef3ea877..548da77d014 100644
> > --- a/sbin/iked/iked.c
> > +++ b/sbin/iked/iked.c
> > @@ -250,6 +250,7 @@ parent_configure(struct iked *env)
> > if (pledge("stdio rpath proc dns inet route sendfd", NULL) == -1)
> > fatal("pledge");
> >  
> > +   config_setmobike(env);
> > config_setcoupled(env, env->sc_decoupled ? 0 : 1);
> > config_setmode(env, env->sc_passive ? 1 : 0);
> > config_setocsp(env);
> > @@ -280,6 +281,7 @@ parent_reload(struct iked *env, int reset, const char 
> > *filename)
> > /* Re-compile policies and skip steps */
> > config_setcompile(env, PROC_IKEV2);
> >  
> > +   config_setmobike(env);
> > config_setcoupled(env, env->sc_decoupled ? 0 : 1);
> > config_setmode(env, env->sc_passive ? 1 : 0);
> > config_setocsp(env);
> > diff --git a/sbin/iked/iked.conf.5 b/sbin/iked/iked.conf.5
> > index 8c77f24d603..be0e8ef30f6 100644
> > --- a/sbin/iked/iked.conf.5
> > +++ b/sbin/iked/iked.conf.5
> > @@ -136,6 +136,15 @@ This is the default.
> >  .It Ic set decouple
> >  Don't load the negotiated SAs and flows from the kernel.
> >  This mode is only useful for testing and debugging.
> > +.It Ic set mobike
> > +Enable MOBIKE (RFC 4555) support.
> > +This is the default.
> > +MOBIKE allows the change of the peer IP address for IKE and IPsec SAs.
> > +Currenly
> > +.Xr iked 8
> > +only supports MOBIKE when acting as a responder.
> > +.It Ic set nomobike
> > +Disables MOBIKE support.
> >  .It Ic set ocsp Ar URL
> >  Enable OCSP and set the URL of the OCSP responder.
> >  Please note that the matching responder and issuer certificates
> > diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
> > index b536d58e157..c2030ea7460 100644
> > --- a/sbin/iked/iked.h
> > +++ b/sbin/iked/iked.h

Re: iked: support MOBIKE (RFC 4555)

2017-11-14 Thread Patrick Wildt
On Thu, Nov 09, 2017 at 11:40:30AM +0100, Patrick Wildt wrote:
> Hi,
> 
> this diff implements MOBIKE (RFC 4555) support in iked(8), with us
> acting as responder.  In practice this support means that clients like
> iPhones can roam in different networks (LTE, WiFi) and change their
> external address without having to re-do the whole handshake.  It allows
> the client to choose how and when to change the external tunnel endpoint
> addresses on demand, depending on which network is better or even is
> connected at all.
> 
> This diff already had a few iterations where race conditions were found
> and ironed out, so this should be a rather stable version which has been
> working really well for me now.
> 
> Key changes with this diff are:
> 
>  * MOBIKE is on by default, but can be turned off (if neccessary)
>using a config key.
>  * MOBIKE support is then announced to the initiator.
>  * Peers can use different IP addresses in the IKE messages, but the
>Tunnel is only updated when we receive IKEV2_N_UPDATE_SA_ADDRESSES.
>  * This means we need to store two peer addresses.  The one he talked to us
>last, so that we know where to respond to.  And the one that the kernel
>knows, so that we know if we have to update the SAs and flows.
>  * We need to update the SA as well as the flow.  For the SAs I added
>a way of updating destination addresses of an existing TDB in June.
>The flows simply need a reload after the SA changed.
>  * COOKIE2 is used for return routability checks.  strongswan seems
>to use it.  It's encrypted and should be sent back to the initiator.
> 
> When you, for instance, use your phone and turn on/off WiFi, you should
> see that the VPN stays connected and iked should log that the address
> has changed.  Especially `ipsecctl -sa` should show updated SAs and
> flows.
> 
> OKs? Objections? Feedback?

I have heard from two more people running it and seeing it work.  Anyone
else?

> Patrick
> 
> diff --git a/sbin/iked/config.c b/sbin/iked/config.c
> index 590e4d7f4da..da8d0745f3c 100644
> --- a/sbin/iked/config.c
> +++ b/sbin/iked/config.c
> @@ -814,6 +814,29 @@ config_getcompile(struct iked *env, struct imsg *imsg)
>   return (0);
>  }
>  
> +int
> +config_setmobike(struct iked *env)
> +{
> + unsigned int boolval;
> +
> + boolval = env->sc_mobike;
> + proc_compose(>sc_ps, PROC_IKEV2, IMSG_CTL_MOBIKE,
> + , sizeof(boolval));
> + return (0);
> +}
> +
> +int
> +config_getmobike(struct iked *env, struct imsg *imsg)
> +{
> + unsigned int boolval;
> +
> + IMSG_SIZE_CHECK(imsg, );
> + memcpy(, imsg->data, sizeof(boolval));
> + env->sc_mobike = boolval;
> + log_debug("%s: %smobike", __func__, env->sc_mobike ? "" : "no ");
> + return (0);
> +}
> +
>  int
>  config_setocsp(struct iked *env)
>  {
> diff --git a/sbin/iked/iked.c b/sbin/iked/iked.c
> index 09fef3ea877..548da77d014 100644
> --- a/sbin/iked/iked.c
> +++ b/sbin/iked/iked.c
> @@ -250,6 +250,7 @@ parent_configure(struct iked *env)
>   if (pledge("stdio rpath proc dns inet route sendfd", NULL) == -1)
>   fatal("pledge");
>  
> + config_setmobike(env);
>   config_setcoupled(env, env->sc_decoupled ? 0 : 1);
>   config_setmode(env, env->sc_passive ? 1 : 0);
>   config_setocsp(env);
> @@ -280,6 +281,7 @@ parent_reload(struct iked *env, int reset, const char 
> *filename)
>   /* Re-compile policies and skip steps */
>   config_setcompile(env, PROC_IKEV2);
>  
> + config_setmobike(env);
>   config_setcoupled(env, env->sc_decoupled ? 0 : 1);
>   config_setmode(env, env->sc_passive ? 1 : 0);
>   config_setocsp(env);
> diff --git a/sbin/iked/iked.conf.5 b/sbin/iked/iked.conf.5
> index 8c77f24d603..be0e8ef30f6 100644
> --- a/sbin/iked/iked.conf.5
> +++ b/sbin/iked/iked.conf.5
> @@ -136,6 +136,15 @@ This is the default.
>  .It Ic set decouple
>  Don't load the negotiated SAs and flows from the kernel.
>  This mode is only useful for testing and debugging.
> +.It Ic set mobike
> +Enable MOBIKE (RFC 4555) support.
> +This is the default.
> +MOBIKE allows the change of the peer IP address for IKE and IPsec SAs.
> +Currenly
> +.Xr iked 8
> +only supports MOBIKE when acting as a responder.
> +.It Ic set nomobike
> +Disables MOBIKE support.
>  .It Ic set ocsp Ar URL
>  Enable OCSP and set the URL of the OCSP responder.
>  Please note that the matching responder and issuer certificates
> diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
> index b536d58e157..c2030ea7460 100644
> --- a/sbin/iked/iked.h
> +++ b/sbin/iked/iked.h
> @@ -157,6 +157,8 @@ struct iked_flow {
>  
>   RB_ENTRY(iked_flow)  flow_node;
>   TAILQ_ENTRY(iked_flow)   flow_entry;
> +
> + int  flow_replacing; /* cf flow_replace() */
>   int  flow_ipcomp;
>  };
>  RB_HEAD(iked_flows, iked_flow);
> @@ -371,6 +373,7 @@ struct 

iked: support MOBIKE (RFC 4555)

2017-11-09 Thread Patrick Wildt
Hi,

this diff implements MOBIKE (RFC 4555) support in iked(8), with us
acting as responder.  In practice this support means that clients like
iPhones can roam in different networks (LTE, WiFi) and change their
external address without having to re-do the whole handshake.  It allows
the client to choose how and when to change the external tunnel endpoint
addresses on demand, depending on which network is better or even is
connected at all.

This diff already had a few iterations where race conditions were found
and ironed out, so this should be a rather stable version which has been
working really well for me now.

Key changes with this diff are:

 * MOBIKE is on by default, but can be turned off (if neccessary)
   using a config key.
 * MOBIKE support is then announced to the initiator.
 * Peers can use different IP addresses in the IKE messages, but the
   Tunnel is only updated when we receive IKEV2_N_UPDATE_SA_ADDRESSES.
 * This means we need to store two peer addresses.  The one he talked to us
   last, so that we know where to respond to.  And the one that the kernel
   knows, so that we know if we have to update the SAs and flows.
 * We need to update the SA as well as the flow.  For the SAs I added
   a way of updating destination addresses of an existing TDB in June.
   The flows simply need a reload after the SA changed.
 * COOKIE2 is used for return routability checks.  strongswan seems
   to use it.  It's encrypted and should be sent back to the initiator.

When you, for instance, use your phone and turn on/off WiFi, you should
see that the VPN stays connected and iked should log that the address
has changed.  Especially `ipsecctl -sa` should show updated SAs and
flows.

OKs? Objections? Feedback?

Patrick

diff --git a/sbin/iked/config.c b/sbin/iked/config.c
index 590e4d7f4da..da8d0745f3c 100644
--- a/sbin/iked/config.c
+++ b/sbin/iked/config.c
@@ -814,6 +814,29 @@ config_getcompile(struct iked *env, struct imsg *imsg)
return (0);
 }
 
+int
+config_setmobike(struct iked *env)
+{
+   unsigned int boolval;
+
+   boolval = env->sc_mobike;
+   proc_compose(>sc_ps, PROC_IKEV2, IMSG_CTL_MOBIKE,
+   , sizeof(boolval));
+   return (0);
+}
+
+int
+config_getmobike(struct iked *env, struct imsg *imsg)
+{
+   unsigned int boolval;
+
+   IMSG_SIZE_CHECK(imsg, );
+   memcpy(, imsg->data, sizeof(boolval));
+   env->sc_mobike = boolval;
+   log_debug("%s: %smobike", __func__, env->sc_mobike ? "" : "no ");
+   return (0);
+}
+
 int
 config_setocsp(struct iked *env)
 {
diff --git a/sbin/iked/iked.c b/sbin/iked/iked.c
index 09fef3ea877..548da77d014 100644
--- a/sbin/iked/iked.c
+++ b/sbin/iked/iked.c
@@ -250,6 +250,7 @@ parent_configure(struct iked *env)
if (pledge("stdio rpath proc dns inet route sendfd", NULL) == -1)
fatal("pledge");
 
+   config_setmobike(env);
config_setcoupled(env, env->sc_decoupled ? 0 : 1);
config_setmode(env, env->sc_passive ? 1 : 0);
config_setocsp(env);
@@ -280,6 +281,7 @@ parent_reload(struct iked *env, int reset, const char 
*filename)
/* Re-compile policies and skip steps */
config_setcompile(env, PROC_IKEV2);
 
+   config_setmobike(env);
config_setcoupled(env, env->sc_decoupled ? 0 : 1);
config_setmode(env, env->sc_passive ? 1 : 0);
config_setocsp(env);
diff --git a/sbin/iked/iked.conf.5 b/sbin/iked/iked.conf.5
index 8c77f24d603..be0e8ef30f6 100644
--- a/sbin/iked/iked.conf.5
+++ b/sbin/iked/iked.conf.5
@@ -136,6 +136,15 @@ This is the default.
 .It Ic set decouple
 Don't load the negotiated SAs and flows from the kernel.
 This mode is only useful for testing and debugging.
+.It Ic set mobike
+Enable MOBIKE (RFC 4555) support.
+This is the default.
+MOBIKE allows the change of the peer IP address for IKE and IPsec SAs.
+Currenly
+.Xr iked 8
+only supports MOBIKE when acting as a responder.
+.It Ic set nomobike
+Disables MOBIKE support.
 .It Ic set ocsp Ar URL
 Enable OCSP and set the URL of the OCSP responder.
 Please note that the matching responder and issuer certificates
diff --git a/sbin/iked/iked.h b/sbin/iked/iked.h
index b536d58e157..c2030ea7460 100644
--- a/sbin/iked/iked.h
+++ b/sbin/iked/iked.h
@@ -157,6 +157,8 @@ struct iked_flow {
 
RB_ENTRY(iked_flow)  flow_node;
TAILQ_ENTRY(iked_flow)   flow_entry;
+
+   int  flow_replacing; /* cf flow_replace() */
int  flow_ipcomp;
 };
 RB_HEAD(iked_flows, iked_flow);
@@ -371,6 +373,7 @@ struct iked_sa {
 #define IKED_SATYPE_LOCAL   1  /* Local SA */
 
struct iked_addr sa_peer;
+   struct iked_addr sa_peer_loaded;/* MOBIKE */
struct iked_addr sa_local;
int  sa_fd;
 
@@ -441,6 +444,8 @@ struct iked_sa {