Re: iked(8): client-side DNS support via resolvd(8)
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)
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)
+ 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)
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)
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)
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;