From 73502a5310161181c6fb745fd5aadb7e4ef1b8bd Mon Sep 17 00:00:00 2001 From: Tobias Brunner Date: Tue, 19 Nov 2019 18:35:50 +0100 Subject: [PATCH] link-local-ts: Plugin that adds a VIP-based IPv6 link-local address to the remote TS Windows clients apparently rely on Neighbor Discovery (Router Advertisements) to install routes for IPv6. So this alone will not be enough to make this work. It requires a tool like `radvd` to actually send such messages to the clients. Also, if multiple pools are used, they have to differ in the last 64 bits to avoid assigning duplicate link-local addresses. #817 --- configure.ac | 4 + src/libcharon/Makefile.am | 7 ++ .../plugins/link_local_ts/Makefile.am | 18 ++++ .../link_local_ts/link_local_ts_narrow.c | 96 +++++++++++++++++ .../link_local_ts/link_local_ts_narrow.h | 50 +++++++++ .../link_local_ts/link_local_ts_plugin.c | 101 ++++++++++++++++++ .../link_local_ts/link_local_ts_plugin.h | 42 ++++++++ 7 files changed, 318 insertions(+) create mode 100644 src/libcharon/plugins/link_local_ts/Makefile.am create mode 100644 src/libcharon/plugins/link_local_ts/link_local_ts_narrow.c create mode 100644 src/libcharon/plugins/link_local_ts/link_local_ts_narrow.h create mode 100644 src/libcharon/plugins/link_local_ts/link_local_ts_plugin.c create mode 100644 src/libcharon/plugins/link_local_ts/link_local_ts_plugin.h diff --git a/configure.ac b/configure.ac index 4b0380b4de..76fbe883cc 100644 --- a/configure.ac +++ b/configure.ac @@ -271,6 +271,7 @@ ARG_ENABL_SET([error-notify], [enable error notification plugin.]) ARG_ENABL_SET([farp], [enable ARP faking plugin that responds to ARP requests to peers virtual IP]) ARG_ENABL_SET([ha], [enable high availability cluster plugin.]) ARG_ENABL_SET([led], [enable plugin to control LEDs on IKEv2 activity using the Linux kernel LED subsystem.]) +ARG_ENABL_SET([link-local-ts], [enable plugin that adds link-local traffic selectors for assigned virtual IPv6 addresses for Windows clients]) ARG_ENABL_SET([load-tester], [enable load testing plugin for IKEv2 daemon.]) ARG_ENABL_SET([lookip], [enable fast virtual IP lookup and notification plugin.]) ARG_ENABL_SET([radattr], [enable plugin to inject and process custom RADIUS attributes as IKEv2 client.]) @@ -1454,6 +1455,7 @@ ADD_PLUGIN([mysql], [s charon pool manager medsrv attest]) ADD_PLUGIN([sqlite], [s charon pool manager medsrv attest]) ADD_PLUGIN([attr], [c charon]) ADD_PLUGIN([attr-sql], [c charon]) +ADD_PLUGIN([link-local-ts], [c charon]) ADD_PLUGIN([load-tester], [c charon]) ADD_PLUGIN([kernel-libipsec], [c charon cmd]) ADD_PLUGIN([kernel-wfp], [c charon]) @@ -1632,6 +1634,7 @@ AM_CONDITIONAL(USE_DNSCERT, test x$dnscert = xtrue) AM_CONDITIONAL(USE_IPSECKEY, test x$ipseckey = xtrue) AM_CONDITIONAL(USE_UPDOWN, test x$updown = xtrue) AM_CONDITIONAL(USE_DHCP, test x$dhcp = xtrue) +AM_CONDITIONAL(USE_LINK_LOCAL_TS, test x$link_local_ts = xtrue) AM_CONDITIONAL(USE_LOAD_TESTER, test x$load_tester = xtrue) AM_CONDITIONAL(USE_HA, test x$ha = xtrue) AM_CONDITIONAL(USE_KERNEL_NETLINK, test x$kernel_netlink = xtrue) @@ -2005,6 +2008,7 @@ AC_CONFIG_FILES([ src/libcharon/plugins/vici/python/Makefile src/libcharon/plugins/updown/Makefile src/libcharon/plugins/dhcp/Makefile + src/libcharon/plugins/link_local_ts/Makefile src/libcharon/plugins/load_tester/Makefile src/libcharon/plugins/resolve/Makefile src/libcharon/plugins/attr/Makefile diff --git a/src/libcharon/Makefile.am b/src/libcharon/Makefile.am index 15ac7a6d1e..fc2dcee8db 100644 --- a/src/libcharon/Makefile.am +++ b/src/libcharon/Makefile.am @@ -201,6 +201,13 @@ else SUBDIRS = . endif +if USE_LINK_LOCAL_TS + SUBDIRS += plugins/link_local_ts +if MONOLITHIC + libcharon_la_LIBADD += plugins/link_local_ts/libstrongswan-link-local-ts.la +endif +endif + if USE_LOAD_TESTER SUBDIRS += plugins/load_tester if MONOLITHIC diff --git a/src/libcharon/plugins/link_local_ts/Makefile.am b/src/libcharon/plugins/link_local_ts/Makefile.am new file mode 100644 index 0000000000..33f165a3e9 --- /dev/null +++ b/src/libcharon/plugins/link_local_ts/Makefile.am @@ -0,0 +1,18 @@ +AM_CPPFLAGS = \ + -I$(top_srcdir)/src/libstrongswan \ + -I$(top_srcdir)/src/libcharon + +AM_CFLAGS = \ + $(PLUGIN_CFLAGS) + +if MONOLITHIC +noinst_LTLIBRARIES = libstrongswan-link-local-ts.la +else +plugin_LTLIBRARIES = libstrongswan-link-local-ts.la +endif + +libstrongswan_link_local_ts_la_SOURCES = \ + link_local_ts_plugin.h link_local_ts_plugin.c \ + link_local_ts_narrow.h link_local_ts_narrow.c + +libstrongswan_link_local_ts_la_LDFLAGS = -module -avoid-version diff --git a/src/libcharon/plugins/link_local_ts/link_local_ts_narrow.c b/src/libcharon/plugins/link_local_ts/link_local_ts_narrow.c new file mode 100644 index 0000000000..524f53ee07 --- /dev/null +++ b/src/libcharon/plugins/link_local_ts/link_local_ts_narrow.c @@ -0,0 +1,96 @@ +/* + * Copyright (C) 2019 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "link_local_ts_narrow.h" + +#include +#include + +typedef struct private_link_local_ts_narrow_t private_link_local_ts_narrow_t; + +/** + * Private data. + */ +struct private_link_local_ts_narrow_t { + + /** + * Public interface. + */ + link_local_ts_narrow_t public; +}; + +static traffic_selector_t *create_link_local_ts(host_t *vip) +{ + chunk_t link_local = chunk_from_chars( + 0xfe, 0x80, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, + 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00); + + /* copy the last 64 address bits of the virtual IP */ + memcpy(link_local.ptr + 8, vip->get_address(vip).ptr + 8, 8); + + return traffic_selector_create_from_bytes(0, TS_IPV6_ADDR_RANGE, link_local, + 0, link_local, 0xffff); +} + +METHOD(listener_t, narrow, bool, + private_link_local_ts_narrow_t *this, ike_sa_t *ike_sa, + child_sa_t *child_sa, narrow_hook_t type, linked_list_t *local, + linked_list_t *remote) +{ + enumerator_t *enumerator; + host_t *vip; + + /* only Windows clients currently rely on ND to receive routes (i.e. + * they actually ignore the remote TS assigned by the server, even if it + * is ::/0) */ + if (type == NARROW_RESPONDER && + ike_sa->supports_extension(ike_sa, EXT_MS_WINDOWS)) + { + enumerator = ike_sa->create_virtual_ip_enumerator(ike_sa, FALSE); + while (enumerator->enumerate(enumerator, &vip)) + { + if (vip->get_family(vip) == AF_INET6) + { + remote->insert_last(remote, create_link_local_ts(vip)); + break; + } + } + enumerator->destroy(enumerator); + } + return TRUE; +} + +METHOD(link_local_ts_narrow_t, destroy, void, + private_link_local_ts_narrow_t *this) +{ + free(this); +} + +/* + * Described in header + */ +link_local_ts_narrow_t *link_local_ts_narrow_create() +{ + private_link_local_ts_narrow_t *this; + + INIT(this, + .public = { + .listener.narrow = _narrow, + .destroy = _destroy, + }, + ); + + return &this->public; +} diff --git a/src/libcharon/plugins/link_local_ts/link_local_ts_narrow.h b/src/libcharon/plugins/link_local_ts/link_local_ts_narrow.h new file mode 100644 index 0000000000..e620ff1973 --- /dev/null +++ b/src/libcharon/plugins/link_local_ts/link_local_ts_narrow.h @@ -0,0 +1,50 @@ +/* + * Copyright (C) 2019 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup link_local_ts_narrow link_local_ts_narrow + * @{ @ingroup link_local_ts + */ + +#ifndef LINK_LOCAL_TS_NARROW_H_ +#define LINK_LOCAL_TS_NARROW_H_ + +#include + +typedef struct link_local_ts_narrow_t link_local_ts_narrow_t; + +/** + * Listener that includes a link-local IPv6 address based on a client's assigned + * virtual IPv6 address. + */ +struct link_local_ts_narrow_t { + + /** + * Implements listener_t. + */ + listener_t listener; + + /** + * Destroy this instance. + */ + void (*destroy)(link_local_ts_narrow_t *this); +}; + +/** + * Create a new instance. + */ +link_local_ts_narrow_t *link_local_ts_narrow_create(); + +#endif /** LINK_LOCAL_TS_NARROW_H_ @}*/ diff --git a/src/libcharon/plugins/link_local_ts/link_local_ts_plugin.c b/src/libcharon/plugins/link_local_ts/link_local_ts_plugin.c new file mode 100644 index 0000000000..f48e0e4ac7 --- /dev/null +++ b/src/libcharon/plugins/link_local_ts/link_local_ts_plugin.c @@ -0,0 +1,101 @@ +/* + * Copyright (C) 2019 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +#include "link_local_ts_plugin.h" + +#include +#include + +#include "link_local_ts_narrow.h" + +typedef struct private_link_local_ts_plugin_t private_link_local_ts_plugin_t; + +/** + * Private plugin data + */ +struct private_link_local_ts_plugin_t { + + /** + * Public interface. + */ + link_local_ts_plugin_t public; + + /** + * Listener to narrow traffic selectors. + */ + link_local_ts_narrow_t *narrower; +}; + +METHOD(plugin_t, get_name, char*, + private_link_local_ts_plugin_t *this) +{ + return "link-local-ts"; +} + +/** + * Register listener + */ +static bool plugin_cb(private_link_local_ts_plugin_t *this, + plugin_feature_t *feature, bool reg, void *cb_data) +{ + if (reg) + { + charon->bus->add_listener(charon->bus, &this->narrower->listener); + } + else + { + charon->bus->remove_listener(charon->bus, &this->narrower->listener); + } + return TRUE; +} + +METHOD(plugin_t, get_features, int, + private_link_local_ts_plugin_t *this, plugin_feature_t *features[]) +{ + static plugin_feature_t f[] = { + PLUGIN_CALLBACK((plugin_feature_callback_t)plugin_cb, NULL), + PLUGIN_PROVIDE(CUSTOM, "link-local-ts"), + }; + *features = f; + return countof(f); +} + +METHOD(plugin_t, destroy, void, + private_link_local_ts_plugin_t *this) +{ + this->narrower->destroy(this->narrower); + free(this); +} + +/* + * Described in header + */ +plugin_t *link_local_ts_plugin_create() +{ + private_link_local_ts_plugin_t *this; + + INIT(this, + .public = { + .plugin = { + .get_name = _get_name, + .get_features = _get_features, + .destroy = _destroy, + }, + }, + .narrower = link_local_ts_narrow_create(), + ); + + return &this->public.plugin; +} diff --git a/src/libcharon/plugins/link_local_ts/link_local_ts_plugin.h b/src/libcharon/plugins/link_local_ts/link_local_ts_plugin.h new file mode 100644 index 0000000000..5f584b87f1 --- /dev/null +++ b/src/libcharon/plugins/link_local_ts/link_local_ts_plugin.h @@ -0,0 +1,42 @@ +/* + * Copyright (C) 2019 Tobias Brunner + * HSR Hochschule fuer Technik Rapperswil + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2 of the License, or (at your + * option) any later version. See . + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY + * or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License + * for more details. + */ + +/** + * @defgroup link_local_ts link_local_ts + * @ingroup cplugins + * + * @defgroup link_local_ts_plugin link_local_ts_plugin + * @{ @ingroup link_local_ts + */ + +#ifndef LINK_LOCAL_TS_PLUGIN_H_ +#define LINK_LOCAL_TS_PLUGIN_H_ + +#include + +typedef struct link_local_ts_plugin_t link_local_ts_plugin_t; + +/** + * RFC 3779 address block checking. + */ +struct link_local_ts_plugin_t { + + /** + * Implements plugin_t interface. + */ + plugin_t plugin; +}; + +#endif /** LINK_LOCAL_TS_PLUGIN_H_ @}*/ -- 2.47.2