Hi,
Currently there is only one address pool which is either v4 or v6.
This means that we cannot have dual-stack VPNs via iked. Clients
then might tunnel all IPv4 traffic, but IPv6 traffic is still using
the non-encrypted default route, which might be a security issue.
To enable dual-stack IKEv2, set up a second address pool which is
specifically for v6.
Patrick
diff --git sbin/iked/config.c sbin/iked/config.c
index 1650258..4b9b3a2 100644
--- sbin/iked/config.c
+++ sbin/iked/config.c
@@ -104,6 +104,10 @@ config_free_sa(struct iked *env, struct iked_sa *sa)
(void)RB_REMOVE(iked_addrpool, >sc_addrpool, sa);
free(sa->sa_addrpool);
}
+ if (sa->sa_addrpool6) {
+ (void)RB_REMOVE(iked_addrpool6, >sc_addrpool6, sa);
+ free(sa->sa_addrpool6);
+ }
if (sa->sa_policy) {
TAILQ_REMOVE(>sa_policy->pol_sapeers, sa, sa_peer_entry);
diff --git sbin/iked/iked.h sbin/iked/iked.h
index b1c3152..3fb7c9f 100644
--- sbin/iked/iked.h
+++ sbin/iked/iked.h
@@ -449,9 +449,13 @@ struct iked_sa {
struct iked_addr*sa_addrpool; /* address from pool */
RB_ENTRY(iked_sa)sa_addrpool_entry; /* pool entries
*/
+
+ struct iked_addr*sa_addrpool6; /* address from pool */
+ RB_ENTRY(iked_sa)sa_addrpool6_entry;/* pool entries
*/
};
RB_HEAD(iked_sas, iked_sa);
RB_HEAD(iked_addrpool, iked_sa);
+RB_HEAD(iked_addrpool6, iked_sa);
struct iked_message {
struct ibuf *msg_data;
@@ -599,6 +603,7 @@ struct iked {
char*sc_ocsp_url;
struct iked_addrpool sc_addrpool;
+ struct iked_addrpool6sc_addrpool6;
};
struct iked_socket {
@@ -691,6 +696,7 @@ struct iked_user *
user_lookup(struct iked *, const char *);
RB_PROTOTYPE(iked_sas, iked_sa, sa_entry, sa_cmp);
RB_PROTOTYPE(iked_addrpool, iked_sa, sa_addrpool_entry, sa_addrpool_cmp);
+RB_PROTOTYPE(iked_addrpool6, iked_sa, sa_addrpool6_entry, sa_addrpool6_cmp);
RB_PROTOTYPE(iked_users, iked_user, user_entry, user_cmp);
RB_PROTOTYPE(iked_activesas, iked_childsa, csa_node, childsa_cmp);
RB_PROTOTYPE(iked_flows, iked_flow, flow_node, flow_cmp);
diff --git sbin/iked/ikev2.c sbin/iked/ikev2.c
index 7d36800..d4c4290 100644
--- sbin/iked/ikev2.c
+++ sbin/iked/ikev2.c
@@ -122,7 +122,7 @@ int ikev2_add_buf(struct ibuf *buf, struct ibuf *);
int ikev2_ipcomp_enable(struct iked *, struct iked_sa *);
voidikev2_ipcomp_csa_free(struct iked *, struct iked_childsa *);
-int ikev2_cp_setaddr(struct iked *, struct iked_sa *);
+int ikev2_cp_setaddr(struct iked *, struct iked_sa *, sa_family_t);
int ikev2_cp_fixaddr(struct iked_sa *, struct iked_addr *,
struct iked_addr *);
@@ -1739,9 +1739,9 @@ ikev2_add_cp(struct iked *env, struct iked_sa *sa, struct
ibuf *buf)
in6 = (ikecfg->cfg.address.addr_mask != 128 &&
(ikecfg->cfg_type ==
IKEV2_CFG_INTERNAL_IP6_ADDRESS) &&
- sa->sa_addrpool &&
- sa->sa_addrpool->addr_af == AF_INET6) ?
- (struct sockaddr_in6 *)>sa_addrpool->addr :
+ sa->sa_addrpool6 &&
+ sa->sa_addrpool6->addr_af == AF_INET6) ?
+ (struct sockaddr_in6 *)>sa_addrpool6->addr :
(struct sockaddr_in6 *)>cfg.address.addr;
cfg->cfg_length = htobe16(17);
if (ibuf_add(buf, >sin6_addr.s6_addr, 16) == -1)
@@ -2184,7 +2184,8 @@ ikev2_resp_ike_auth(struct iked *env, struct iked_sa *sa)
else if (!sa_stateok(sa, IKEV2_STATE_VALID))
return (0); /* ignore */
- if (ikev2_cp_setaddr(env, sa) < 0)
+ if (ikev2_cp_setaddr(env, sa, AF_INET) < 0 ||
+ ikev2_cp_setaddr(env, sa, AF_INET6) < 0)
return (-1);
if (ikev2_childsa_negotiate(env, sa, >sa_kex, >sa_proposals,
@@ -2943,6 +2944,12 @@ ikev2_ikesa_enable(struct iked *env, struct iked_sa *sa,
struct iked_sa *nsa)
sa->sa_addrpool = NULL;
RB_INSERT(iked_addrpool, >sc_addrpool, nsa);
}
+ if (sa->sa_addrpool6) {
+ RB_REMOVE(iked_addrpool6, >sc_addrpool6, sa);
+ nsa->sa_addrpool6 = sa->sa_addrpool6;
+ sa->sa_addrpool6 = NULL;
+ RB_INSERT(iked_addrpool6, >sc_addrpool6, nsa);
+ }
log_debug("%s: activating new IKE SA", __func__);
sa_state(env, nsa, IKEV2_STATE_ESTABLISHED);
@@ -5029,7 +5036,7 @@ ikev2_print_id(struct iked_id *id, char *idstr, size_t
idstrlen)
* and remember it in the sa_addrpool attribute.
*/
int
-ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa)
+ikev2_cp_setaddr(struct iked *env, struct iked_sa *sa,