Re: iked(8): client-side DNS support via resolvd(8)

2021-09-01 Thread Florian Obser
On 2021-09-01 13:28 +02, Tobias Heider  wrote:
> Here's an updated diff with the following changes:
>
> - Send the ifidx of the configured 'iface' instead of ifidx 0 to prevent
>   name collisions
> - Cache the first received DNS server locally for cleanup/resending.
> - Handle RTP_PROPOSAL_SOLICIT by resending the cached server.
> - Remove the cached server from resolvd on cleanup.
>
> There is no easy way to support multiple DNS servers from different peers
> at the moment.  For now, iked will always propose the first DNS server it
> receives and simply ignore the rest.  There is room for improvement here,
> but i would rather do this in a follow-up diff.
>
> ok?

the DNS bits look correct. There seem to be unrelated fixes in here?
One comment inline.

>
> Index: config.c
> ===
> RCS file: /cvs/src/sbin/iked/config.c,v
> retrieving revision 1.79
> diff -u -p -r1.79 config.c
> --- config.c  13 May 2021 15:20:48 -  1.79
> +++ config.c  1 Sep 2021 11:26:51 -
> @@ -174,6 +174,7 @@ config_free_sa(struct iked *env, struct 
>  
>   free(sa->sa_cp_addr);
>   free(sa->sa_cp_addr6);
> + free(sa->sa_cp_dns);
>  
>   free(sa->sa_tag);
>   free(sa);
> Index: iked.c
> ===
> RCS file: /cvs/src/sbin/iked/iked.c,v
> retrieving revision 1.57
> diff -u -p -r1.57 iked.c
> --- iked.c13 May 2021 15:20:48 -  1.57
> +++ iked.c1 Sep 2021 11:26:51 -
> @@ -459,6 +459,9 @@ parent_dispatch_ikev2(int fd, struct pri
>   case IMSG_IF_ADDADDR:
>   case IMSG_IF_DELADDR:
>   return (vroute_getaddr(env, imsg));
> + case IMSG_VDNS_ADD:
> + case IMSG_VDNS_DEL:
> + return (vroute_getdns(env, imsg));
>   case IMSG_VROUTE_ADD:
>   case IMSG_VROUTE_DEL:
>   return (vroute_getroute(env, imsg));
> Index: iked.h
> ===
> RCS file: /cvs/src/sbin/iked/iked.h,v
> retrieving revision 1.192
> diff -u -p -r1.192 iked.h
> --- iked.h23 Jun 2021 12:11:40 -  1.192
> +++ iked.h1 Sep 2021 11:26:51 -
> @@ -429,6 +429,7 @@ struct iked_sa {
>   int  sa_cp; /* XXX */
>   struct iked_addr*sa_cp_addr;/* requested address */
>   struct iked_addr*sa_cp_addr6;   /* requested address */
> + struct iked_addr*sa_cp_dns; /* requested dns */
>  
>   struct iked_policy  *sa_policy;
>   struct timeval   sa_timecreated;
> @@ -611,6 +612,7 @@ struct iked_message {
>   int  msg_cp;
>   struct iked_addr*msg_cp_addr;   /* requested address */
>   struct iked_addr*msg_cp_addr6;  /* requested address */
> + struct iked_addr*msg_cp_dns;/* requested dns */
>  
>   /* MOBIKE */
>   int  msg_update_sa_addresses;
> @@ -752,6 +754,7 @@ struct iked {
>  
>   int  sc_pfkey;  /* ike process */
>   struct event sc_pfkeyev;
> + struct event sc_routeev;
>   uint8_t  sc_certreqtype;
>   struct ibuf *sc_certreq;
>   void*sc_vroute;
> @@ -975,6 +978,8 @@ void vroute_init(struct iked *);
>  int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
>  void vroute_cleanup(struct iked *);
>  int vroute_getaddr(struct iked *, struct imsg *);
> +int vroute_setdns(struct iked *, int, struct sockaddr *, unsigned int);
> +int vroute_getdns(struct iked *, struct imsg *);
>  int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
>  uint8_t, struct sockaddr *);
>  int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
> Index: ikev2.c
> ===
> RCS file: /cvs/src/sbin/iked/ikev2.c,v
> retrieving revision 1.325
> diff -u -p -r1.325 ikev2.c
> --- ikev2.c   29 Jun 2021 15:39:20 -  1.325
> +++ ikev2.c   1 Sep 2021 11:26:51 -
> @@ -998,6 +998,13 @@ ikev2_ike_auth_recv(struct iked *env, st
>   log_info("%s: obtained lease: %s", SPI_SA(sa, __func__),
>   print_host((struct sockaddr 
> *)>sa_cp_addr6->addr, NULL, 0));
>   }
> + if (msg->msg_cp_dns) {
> + sa->sa_cp_dns = msg->msg_cp_dns;
> + msg->msg_cp_dns = NULL;
> + log_debug("%s: DNS: %s", __func__,
> + print_host((struct sockaddr *)>sa_cp_dns->addr,
> + NULL, 0));
> + }
>   sa->sa_cp = msg->msg_cp;
>   }
>  
> @@ -4508,6 +4515,8 @@ ikev2_ikesa_enable(struct iked *env, str
>   sa->sa_cp_addr = NULL;
>   nsa->sa_cp_addr6 = 

Re: iked(8): client-side DNS support via resolvd(8)

2021-09-01 Thread Tobias Heider
Here's an updated diff with the following changes:

- Send the ifidx of the configured 'iface' instead of ifidx 0 to prevent
  name collisions
- Cache the first received DNS server locally for cleanup/resending.
- Handle RTP_PROPOSAL_SOLICIT by resending the cached server.
- Remove the cached server from resolvd on cleanup.

There is no easy way to support multiple DNS servers from different peers
at the moment.  For now, iked will always propose the first DNS server it
receives and simply ignore the rest.  There is room for improvement here,
but i would rather do this in a follow-up diff.

ok?

Index: config.c
===
RCS file: /cvs/src/sbin/iked/config.c,v
retrieving revision 1.79
diff -u -p -r1.79 config.c
--- config.c13 May 2021 15:20:48 -  1.79
+++ config.c1 Sep 2021 11:26:51 -
@@ -174,6 +174,7 @@ config_free_sa(struct iked *env, struct 
 
free(sa->sa_cp_addr);
free(sa->sa_cp_addr6);
+   free(sa->sa_cp_dns);
 
free(sa->sa_tag);
free(sa);
Index: iked.c
===
RCS file: /cvs/src/sbin/iked/iked.c,v
retrieving revision 1.57
diff -u -p -r1.57 iked.c
--- iked.c  13 May 2021 15:20:48 -  1.57
+++ iked.c  1 Sep 2021 11:26:51 -
@@ -459,6 +459,9 @@ parent_dispatch_ikev2(int fd, struct pri
case IMSG_IF_ADDADDR:
case IMSG_IF_DELADDR:
return (vroute_getaddr(env, imsg));
+   case IMSG_VDNS_ADD:
+   case IMSG_VDNS_DEL:
+   return (vroute_getdns(env, imsg));
case IMSG_VROUTE_ADD:
case IMSG_VROUTE_DEL:
return (vroute_getroute(env, imsg));
Index: iked.h
===
RCS file: /cvs/src/sbin/iked/iked.h,v
retrieving revision 1.192
diff -u -p -r1.192 iked.h
--- iked.h  23 Jun 2021 12:11:40 -  1.192
+++ iked.h  1 Sep 2021 11:26:51 -
@@ -429,6 +429,7 @@ struct iked_sa {
int  sa_cp; /* XXX */
struct iked_addr*sa_cp_addr;/* requested address */
struct iked_addr*sa_cp_addr6;   /* requested address */
+   struct iked_addr*sa_cp_dns; /* requested dns */
 
struct iked_policy  *sa_policy;
struct timeval   sa_timecreated;
@@ -611,6 +612,7 @@ struct iked_message {
int  msg_cp;
struct iked_addr*msg_cp_addr;   /* requested address */
struct iked_addr*msg_cp_addr6;  /* requested address */
+   struct iked_addr*msg_cp_dns;/* requested dns */
 
/* MOBIKE */
int  msg_update_sa_addresses;
@@ -752,6 +754,7 @@ struct iked {
 
int  sc_pfkey;  /* ike process */
struct event sc_pfkeyev;
+   struct event sc_routeev;
uint8_t  sc_certreqtype;
struct ibuf *sc_certreq;
void*sc_vroute;
@@ -975,6 +978,8 @@ void vroute_init(struct iked *);
 int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
 void vroute_cleanup(struct iked *);
 int vroute_getaddr(struct iked *, struct imsg *);
+int vroute_setdns(struct iked *, int, struct sockaddr *, unsigned int);
+int vroute_getdns(struct iked *, struct imsg *);
 int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
 uint8_t, struct sockaddr *);
 int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
Index: ikev2.c
===
RCS file: /cvs/src/sbin/iked/ikev2.c,v
retrieving revision 1.325
diff -u -p -r1.325 ikev2.c
--- ikev2.c 29 Jun 2021 15:39:20 -  1.325
+++ ikev2.c 1 Sep 2021 11:26:51 -
@@ -998,6 +998,13 @@ ikev2_ike_auth_recv(struct iked *env, st
log_info("%s: obtained lease: %s", SPI_SA(sa, __func__),
print_host((struct sockaddr 
*)>sa_cp_addr6->addr, NULL, 0));
}
+   if (msg->msg_cp_dns) {
+   sa->sa_cp_dns = msg->msg_cp_dns;
+   msg->msg_cp_dns = NULL;
+   log_debug("%s: DNS: %s", __func__,
+   print_host((struct sockaddr *)>sa_cp_dns->addr,
+   NULL, 0));
+   }
sa->sa_cp = msg->msg_cp;
}
 
@@ -4508,6 +4515,8 @@ ikev2_ikesa_enable(struct iked *env, str
sa->sa_cp_addr = NULL;
nsa->sa_cp_addr6 = sa->sa_cp_addr6;
sa->sa_cp_addr6 = NULL;
+   nsa->sa_cp_dns = sa->sa_cp_dns;
+   sa->sa_cp_dns = NULL;
/* Transfer other attributes */
 if (sa->sa_dstid_entry_valid) {
sa_dstid_remove(env, sa);
Index: 

Re: iked(8): client-side DNS support via resolvd(8)

2021-08-31 Thread Theo de Raadt
+   rtm.rtm_priority = RTP_PROPOSAL_STATIC;

So my gut reaction is we should have

/usr/include/net/route.h:#define RTP_PROPOSAL_TEMPORARY62

I hesitate calling this "VPN", or "road warrior", or making it specific to
certain types of proposal offering daemons...



Re: iked(8): client-side DNS support via resolvd(8)

2021-08-31 Thread Theo de Raadt
This diff doesn't set rtm_index (to identify the interface the dns
proposal is associated with)

I guess that means rtm_index is 0.

Inside resolvd, the proposal rtm_index is used to track proposals in the
learned[] array.

resolvd uses if_indextoname() to annotate the interface name on these
dynamic lines with "# resolvd: em0".  Using 0 means if_indextoname() will
fail, and it will write "# resolvd: ", I guess?

If multiple agents start offering proposals with the same rtm_index +
family, things get a little weird.

What would isakmpd or some other vpn layer do if they want to start
doing the same as this iked diff -- would they also submit rtm_index 0?
The code cannot disambiguate/sort/select from the proposals with the same
id#, so all such offers will act as a single proposal, and I think whoever
submits the latest will win the fight.  That might behave weirdly.

So, does the route message need an extension to indicate "who" is making
the offer, or should iked (ando other vpns) have unique RTP_PROPOSAL_*
identifiers, and then we can have resolvd mix that into the sort also?



Re: iked(8): client-side DNS support via resolvd(8)

2021-08-31 Thread Theo de Raadt
Very interesting.

Please be very careful that proposal withdrawal actually works, or
the experience will be poor.



iked(8): client-side DNS support via resolvd(8)

2021-08-31 Thread Tobias Heider
IKEv2 allows road warrior servers to announce internal name servers in a
configuration payload.  iked responders can be configured to send such
payloads with the 'config name-server' option.

This diff adds support for receiving DNS server configuration payloads as a
road warrior client and proposing them to resolvd(8) via route messages.
It is enabled by default for clients using the 'iface' option for automatic
address configuration.

ok?

Index: config.c
===
RCS file: /cvs/src/sbin/iked/config.c,v
retrieving revision 1.79
diff -u -p -r1.79 config.c
--- config.c13 May 2021 15:20:48 -  1.79
+++ config.c30 Aug 2021 12:15:10 -
@@ -174,6 +174,7 @@ config_free_sa(struct iked *env, struct 
 
free(sa->sa_cp_addr);
free(sa->sa_cp_addr6);
+   free(sa->sa_cp_dns);
 
free(sa->sa_tag);
free(sa);
Index: iked.c
===
RCS file: /cvs/src/sbin/iked/iked.c,v
retrieving revision 1.57
diff -u -p -r1.57 iked.c
--- iked.c  13 May 2021 15:20:48 -  1.57
+++ iked.c  30 Aug 2021 12:15:10 -
@@ -459,6 +459,9 @@ parent_dispatch_ikev2(int fd, struct pri
case IMSG_IF_ADDADDR:
case IMSG_IF_DELADDR:
return (vroute_getaddr(env, imsg));
+   case IMSG_VDNS_ADD:
+   case IMSG_VDNS_DEL:
+   return (vroute_getdns(env, imsg));
case IMSG_VROUTE_ADD:
case IMSG_VROUTE_DEL:
return (vroute_getroute(env, imsg));
Index: iked.h
===
RCS file: /cvs/src/sbin/iked/iked.h,v
retrieving revision 1.192
diff -u -p -r1.192 iked.h
--- iked.h  23 Jun 2021 12:11:40 -  1.192
+++ iked.h  30 Aug 2021 12:15:10 -
@@ -429,6 +429,7 @@ struct iked_sa {
int  sa_cp; /* XXX */
struct iked_addr*sa_cp_addr;/* requested address */
struct iked_addr*sa_cp_addr6;   /* requested address */
+   struct iked_addr*sa_cp_dns; /* requested dns */
 
struct iked_policy  *sa_policy;
struct timeval   sa_timecreated;
@@ -611,6 +612,7 @@ struct iked_message {
int  msg_cp;
struct iked_addr*msg_cp_addr;   /* requested address */
struct iked_addr*msg_cp_addr6;  /* requested address */
+   struct iked_addr*msg_cp_dns;/* requested dns */
 
/* MOBIKE */
int  msg_update_sa_addresses;
@@ -975,6 +977,8 @@ void vroute_init(struct iked *);
 int vroute_setaddr(struct iked *, int, struct sockaddr *, int, unsigned int);
 void vroute_cleanup(struct iked *);
 int vroute_getaddr(struct iked *, struct imsg *);
+int vroute_setdns(struct iked *, int, struct sockaddr *);
+int vroute_getdns(struct iked *, struct imsg *);
 int vroute_setaddroute(struct iked *, uint8_t, struct sockaddr *,
 uint8_t, struct sockaddr *);
 int vroute_setcloneroute(struct iked *, uint8_t, struct sockaddr *,
Index: ikev2.c
===
RCS file: /cvs/src/sbin/iked/ikev2.c,v
retrieving revision 1.325
diff -u -p -r1.325 ikev2.c
--- ikev2.c 29 Jun 2021 15:39:20 -  1.325
+++ ikev2.c 30 Aug 2021 12:15:10 -
@@ -998,6 +998,13 @@ ikev2_ike_auth_recv(struct iked *env, st
log_info("%s: obtained lease: %s", SPI_SA(sa, __func__),
print_host((struct sockaddr 
*)>sa_cp_addr6->addr, NULL, 0));
}
+   if (msg->msg_cp_dns) {
+   sa->sa_cp_dns = msg->msg_cp_dns;
+   msg->msg_cp_dns = NULL;
+   log_debug("%s: DNS: %s", __func__,
+   print_host((struct sockaddr *)>sa_cp_dns->addr,
+   NULL, 0));
+   }
sa->sa_cp = msg->msg_cp;
}
 
@@ -4508,6 +4515,8 @@ ikev2_ikesa_enable(struct iked *env, str
sa->sa_cp_addr = NULL;
nsa->sa_cp_addr6 = sa->sa_cp_addr6;
sa->sa_cp_addr6 = NULL;
+   nsa->sa_cp_dns = sa->sa_cp_dns;
+   sa->sa_cp_dns = NULL;
/* Transfer other attributes */
 if (sa->sa_dstid_entry_valid) {
sa_dstid_remove(env, sa);
Index: ikev2_msg.c
===
RCS file: /cvs/src/sbin/iked/ikev2_msg.c,v
retrieving revision 1.77
diff -u -p -r1.77 ikev2_msg.c
--- ikev2_msg.c 29 Oct 2020 21:49:58 -  1.77
+++ ikev2_msg.c 30 Aug 2021 12:15:10 -
@@ -197,6 +197,7 @@ ikev2_msg_cleanup(struct iked *env, stru
free(msg->msg_eap.eam_user);
free(msg->msg_cp_addr);
free(msg->msg_cp_addr6);
+   free(msg->msg_cp_dns);
 
msg->msg_nonce = NULL;