1 /* SPDX-License-Identifier: LGPL-2.1+ */
3 Copyright © 2015-2017 Jason A. Donenfeld <Jason@zx2c4.com>. All Rights Reserved.
9 #include "sd-resolve.h"
11 #include "alloc-util.h"
12 #include "event-util.h"
15 #include "hexdecoct.h"
16 #include "memory-util.h"
17 #include "netlink-util.h"
18 #include "networkd-link.h"
19 #include "networkd-manager.h"
20 #include "networkd-util.h"
21 #include "parse-util.h"
22 #include "path-util.h"
23 #include "resolve-private.h"
24 #include "string-util.h"
26 #include "wireguard-netlink.h"
27 #include "wireguard.h"
29 static void resolve_endpoints(NetDev
*netdev
);
31 static void wireguard_peer_free(WireguardPeer
*peer
) {
32 WireguardIPmask
*mask
;
37 if (peer
->wireguard
) {
38 LIST_REMOVE(peers
, peer
->wireguard
->peers
, peer
);
40 set_remove(peer
->wireguard
->peers_with_unresolved_endpoint
, peer
);
41 set_remove(peer
->wireguard
->peers_with_failed_endpoint
, peer
);
44 hashmap_remove(peer
->wireguard
->peers_by_section
, peer
->section
);
47 network_config_section_free(peer
->section
);
49 while ((mask
= peer
->ipmasks
)) {
50 LIST_REMOVE(ipmasks
, peer
->ipmasks
, mask
);
54 free(peer
->endpoint_host
);
55 free(peer
->endpoint_port
);
56 free(peer
->preshared_key_file
);
57 explicit_bzero_safe(peer
->preshared_key
, WG_KEY_LEN
);
62 DEFINE_NETWORK_SECTION_FUNCTIONS(WireguardPeer
, wireguard_peer_free
);
64 static int wireguard_peer_new_static(Wireguard
*w
, const char *filename
, unsigned section_line
, WireguardPeer
**ret
) {
65 _cleanup_(network_config_section_freep
) NetworkConfigSection
*n
= NULL
;
66 _cleanup_(wireguard_peer_freep
) WireguardPeer
*peer
= NULL
;
72 assert(section_line
> 0);
74 r
= network_config_section_new(filename
, section_line
, &n
);
78 peer
= hashmap_get(w
->peers_by_section
, n
);
80 *ret
= TAKE_PTR(peer
);
84 peer
= new(WireguardPeer
, 1);
88 *peer
= (WireguardPeer
) {
89 .flags
= WGPEER_F_REPLACE_ALLOWEDIPS
,
91 .section
= TAKE_PTR(n
),
94 LIST_PREPEND(peers
, w
->peers
, peer
);
96 r
= hashmap_ensure_allocated(&w
->peers_by_section
, &network_config_hash_ops
);
100 r
= hashmap_put(w
->peers_by_section
, peer
->section
, peer
);
104 *ret
= TAKE_PTR(peer
);
108 static int wireguard_set_ipmask_one(NetDev
*netdev
, sd_netlink_message
*message
, const WireguardIPmask
*mask
, uint16_t index
) {
115 /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */
117 r
= sd_netlink_message_open_array(message
, index
);
121 r
= sd_netlink_message_append_u16(message
, WGALLOWEDIP_A_FAMILY
, mask
->family
);
125 r
= netlink_message_append_in_addr_union(message
, WGALLOWEDIP_A_IPADDR
, mask
->family
, &mask
->ip
);
129 r
= sd_netlink_message_append_u8(message
, WGALLOWEDIP_A_CIDR_MASK
, mask
->cidr
);
133 r
= sd_netlink_message_close_container(message
);
135 return log_netdev_error_errno(netdev
, r
, "Could not add wireguard allowed ip: %m");
140 r
= sd_netlink_message_cancel_array(message
);
142 return log_netdev_error_errno(netdev
, r
, "Could not cancel wireguard allowed ip message attribute: %m");
147 static int wireguard_set_peer_one(NetDev
*netdev
, sd_netlink_message
*message
, const WireguardPeer
*peer
, uint16_t index
, WireguardIPmask
**mask_start
) {
148 WireguardIPmask
*mask
, *start
;
157 /* This returns 1 on success, 0 on recoverable error, and negative errno on failure. */
159 start
= *mask_start
?: peer
->ipmasks
;
161 r
= sd_netlink_message_open_array(message
, index
);
165 r
= sd_netlink_message_append_data(message
, WGPEER_A_PUBLIC_KEY
, &peer
->public_key
, sizeof(peer
->public_key
));
170 r
= sd_netlink_message_append_data(message
, WGPEER_A_PRESHARED_KEY
, &peer
->preshared_key
, WG_KEY_LEN
);
174 r
= sd_netlink_message_append_u32(message
, WGPEER_A_FLAGS
, peer
->flags
);
178 r
= sd_netlink_message_append_u16(message
, WGPEER_A_PERSISTENT_KEEPALIVE_INTERVAL
, peer
->persistent_keepalive_interval
);
182 if (IN_SET(peer
->endpoint
.sa
.sa_family
, AF_INET
, AF_INET6
)) {
183 r
= netlink_message_append_sockaddr_union(message
, WGPEER_A_ENDPOINT
, &peer
->endpoint
);
189 r
= sd_netlink_message_open_container(message
, WGPEER_A_ALLOWEDIPS
);
193 LIST_FOREACH(ipmasks
, mask
, start
) {
194 r
= wireguard_set_ipmask_one(netdev
, message
, mask
, ++j
);
201 r
= sd_netlink_message_close_container(message
);
203 return log_netdev_error_errno(netdev
, r
, "Could not add wireguard allowed ip: %m");
205 r
= sd_netlink_message_close_container(message
);
207 return log_netdev_error_errno(netdev
, r
, "Could not add wireguard peer: %m");
209 *mask_start
= mask
; /* Start next cycle from this mask. */
213 r
= sd_netlink_message_cancel_array(message
);
215 return log_netdev_error_errno(netdev
, r
, "Could not cancel wireguard peers: %m");
220 static int wireguard_set_interface(NetDev
*netdev
) {
221 _cleanup_(sd_netlink_message_unrefp
) sd_netlink_message
*message
= NULL
;
222 WireguardIPmask
*mask_start
= NULL
;
223 WireguardPeer
*peer
, *peer_start
;
229 w
= WIREGUARD(netdev
);
232 for (peer_start
= w
->peers
; peer_start
; ) {
235 message
= sd_netlink_message_unref(message
);
237 r
= sd_genl_message_new(netdev
->manager
->genl
, SD_GENL_WIREGUARD
, WG_CMD_SET_DEVICE
, &message
);
239 return log_netdev_error_errno(netdev
, r
, "Failed to allocate generic netlink message: %m");
241 r
= sd_netlink_message_append_string(message
, WGDEVICE_A_IFNAME
, netdev
->ifname
);
243 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard interface name: %m");
245 if (peer_start
== w
->peers
) {
246 r
= sd_netlink_message_append_data(message
, WGDEVICE_A_PRIVATE_KEY
, &w
->private_key
, WG_KEY_LEN
);
248 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard private key: %m");
250 r
= sd_netlink_message_append_u16(message
, WGDEVICE_A_LISTEN_PORT
, w
->port
);
252 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard port: %m");
254 r
= sd_netlink_message_append_u32(message
, WGDEVICE_A_FWMARK
, w
->fwmark
);
256 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard fwmark: %m");
258 r
= sd_netlink_message_append_u32(message
, WGDEVICE_A_FLAGS
, w
->flags
);
260 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard flags: %m");
263 r
= sd_netlink_message_open_container(message
, WGDEVICE_A_PEERS
);
265 return log_netdev_error_errno(netdev
, r
, "Could not append wireguard peer attributes: %m");
267 LIST_FOREACH(peers
, peer
, peer_start
) {
268 r
= wireguard_set_peer_one(netdev
, message
, peer
, ++i
, &mask_start
);
274 peer_start
= peer
; /* Start next cycle from this peer. */
276 r
= sd_netlink_message_close_container(message
);
278 return log_netdev_error_errno(netdev
, r
, "Could not close wireguard container: %m");
280 r
= sd_netlink_send(netdev
->manager
->genl
, message
, &serial
);
282 return log_netdev_error_errno(netdev
, r
, "Could not set wireguard device: %m");
288 static void wireguard_peer_destroy_callback(WireguardPeer
*peer
) {
292 assert(peer
->wireguard
);
294 netdev
= NETDEV(peer
->wireguard
);
296 if (section_is_invalid(peer
->section
))
297 wireguard_peer_free(peer
);
299 netdev_unref(netdev
);
302 static int on_resolve_retry(sd_event_source
*s
, usec_t usec
, void *userdata
) {
303 NetDev
*netdev
= userdata
;
307 w
= WIREGUARD(netdev
);
310 if (!netdev_is_managed(netdev
))
313 assert(set_isempty(w
->peers_with_unresolved_endpoint
));
315 SWAP_TWO(w
->peers_with_unresolved_endpoint
, w
->peers_with_failed_endpoint
);
317 resolve_endpoints(netdev
);
323 * Given the number of retries this function will return will an exponential
324 * increasing time in milliseconds to wait starting at 200ms and capped at 25 seconds.
326 static int exponential_backoff_milliseconds(unsigned n_retries
) {
327 return (2 << MIN(n_retries
, 7U)) * 100 * USEC_PER_MSEC
;
330 static int wireguard_resolve_handler(sd_resolve_query
*q
,
332 const struct addrinfo
*ai
,
333 WireguardPeer
*peer
) {
339 assert(peer
->wireguard
);
344 if (!netdev_is_managed(netdev
))
348 log_netdev_error(netdev
, "Failed to resolve host '%s:%s': %s", peer
->endpoint_host
, peer
->endpoint_port
, gai_strerror(ret
));
350 r
= set_ensure_allocated(&w
->peers_with_failed_endpoint
, NULL
);
353 peer
->section
->invalid
= true;
357 r
= set_put(w
->peers_with_failed_endpoint
, peer
);
359 log_netdev_error(netdev
, "Failed to save a peer, dropping the peer: %m");
360 peer
->section
->invalid
= true;
364 } else if ((ai
->ai_family
== AF_INET
&& ai
->ai_addrlen
== sizeof(struct sockaddr_in
)) ||
365 (ai
->ai_family
== AF_INET6
&& ai
->ai_addrlen
== sizeof(struct sockaddr_in6
)))
366 memcpy(&peer
->endpoint
, ai
->ai_addr
, ai
->ai_addrlen
);
368 log_netdev_error(netdev
, "Neither IPv4 nor IPv6 address found for peer endpoint %s:%s, ignoring the address.",
369 peer
->endpoint_host
, peer
->endpoint_port
);
372 if (!set_isempty(w
->peers_with_unresolved_endpoint
)) {
373 resolve_endpoints(netdev
);
377 (void) wireguard_set_interface(netdev
);
379 if (!set_isempty(w
->peers_with_failed_endpoint
)) {
383 usec
= usec_add(now(CLOCK_MONOTONIC
), exponential_backoff_milliseconds(w
->n_retries
));
384 r
= event_reset_time(netdev
->manager
->event
, &w
->resolve_retry_event_source
,
385 CLOCK_MONOTONIC
, usec
, 0, on_resolve_retry
, netdev
,
386 0, "wireguard-resolve-retry", true);
388 log_netdev_warning_errno(netdev
, r
, "Could not arm resolve retry handler: %m");
396 static void resolve_endpoints(NetDev
*netdev
) {
397 static const struct addrinfo hints
= {
398 .ai_family
= AF_UNSPEC
,
399 .ai_socktype
= SOCK_DGRAM
,
400 .ai_protocol
= IPPROTO_UDP
408 w
= WIREGUARD(netdev
);
411 SET_FOREACH(peer
, w
->peers_with_unresolved_endpoint
, i
) {
412 r
= resolve_getaddrinfo(netdev
->manager
->resolve
,
417 wireguard_resolve_handler
,
418 wireguard_peer_destroy_callback
,
423 log_netdev_error_errno(netdev
, r
, "Failed to create resolver: %m");
427 /* Avoid freeing netdev. It will be unrefed by the destroy callback. */
430 (void) set_remove(w
->peers_with_unresolved_endpoint
, peer
);
434 static int netdev_wireguard_post_create(NetDev
*netdev
, Link
*link
, sd_netlink_message
*m
) {
436 assert(WIREGUARD(netdev
));
438 (void) wireguard_set_interface(netdev
);
439 resolve_endpoints(netdev
);
443 int config_parse_wireguard_listen_port(
445 const char *filename
,
448 unsigned section_line
,
462 if (!streq(rvalue
, "auto")) {
463 r
= parse_ip_port(rvalue
, s
);
465 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
466 "Invalid port specification, ignoring assignment: %s", rvalue
);
475 static int wireguard_decode_key_and_warn(
477 uint8_t ret
[static WG_KEY_LEN
],
479 const char *filename
,
481 const char *lvalue
) {
483 _cleanup_free_
void *key
= NULL
;
492 if (isempty(rvalue
)) {
493 memzero(ret
, WG_KEY_LEN
);
497 if (!streq(lvalue
, "PublicKey"))
498 (void) warn_file_is_world_accessible(filename
, NULL
, unit
, line
);
500 r
= unbase64mem_full(rvalue
, strlen(rvalue
), true, &key
, &len
);
502 return log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
503 "Failed to decode wireguard key provided by %s=, ignoring assignment: %m", lvalue
);
504 if (len
!= WG_KEY_LEN
) {
505 explicit_bzero_safe(key
, len
);
506 return log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
507 "Wireguard key provided by %s= has invalid length (%zu bytes), ignoring assignment.",
511 memcpy(ret
, key
, WG_KEY_LEN
);
515 int config_parse_wireguard_private_key(
517 const char *filename
,
520 unsigned section_line
,
533 (void) wireguard_decode_key_and_warn(rvalue
, w
->private_key
, unit
, filename
, line
, lvalue
);
537 int config_parse_wireguard_private_key_file(
539 const char *filename
,
542 unsigned section_line
,
549 _cleanup_free_
char *path
= NULL
;
556 if (isempty(rvalue
)) {
557 w
->private_key_file
= mfree(w
->private_key_file
);
561 path
= strdup(rvalue
);
565 if (path_simplify_and_warn(path
, PATH_CHECK_ABSOLUTE
, unit
, filename
, line
, lvalue
) < 0)
568 return free_and_replace(w
->private_key_file
, path
);
571 int config_parse_wireguard_preshared_key(
573 const char *filename
,
576 unsigned section_line
,
583 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
591 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
595 r
= wireguard_decode_key_and_warn(rvalue
, peer
->preshared_key
, unit
, filename
, line
, lvalue
);
603 int config_parse_wireguard_preshared_key_file(
605 const char *filename
,
608 unsigned section_line
,
615 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
616 _cleanup_free_
char *path
= NULL
;
624 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
628 if (isempty(rvalue
)) {
629 peer
->preshared_key_file
= mfree(peer
->preshared_key_file
);
634 path
= strdup(rvalue
);
638 if (path_simplify_and_warn(path
, PATH_CHECK_ABSOLUTE
, unit
, filename
, line
, lvalue
) < 0)
641 free_and_replace(peer
->preshared_key_file
, path
);
646 int config_parse_wireguard_public_key(
648 const char *filename
,
651 unsigned section_line
,
658 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
666 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
670 r
= wireguard_decode_key_and_warn(rvalue
, peer
->public_key
, unit
, filename
, line
, lvalue
);
678 int config_parse_wireguard_allowed_ips(
680 const char *filename
,
683 unsigned section_line
,
690 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
691 union in_addr_union addr
;
692 unsigned char prefixlen
;
695 WireguardIPmask
*ipmask
;
703 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
708 _cleanup_free_
char *word
= NULL
;
710 r
= extract_first_word(&rvalue
, &word
, "," WHITESPACE
, 0);
716 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
717 "Failed to split allowed ips \"%s\" option: %m", rvalue
);
721 r
= in_addr_prefix_from_string_auto(word
, &family
, &addr
, &prefixlen
);
723 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
724 "Network address is invalid, ignoring assignment: %s", word
);
728 ipmask
= new(WireguardIPmask
, 1);
732 *ipmask
= (WireguardIPmask
) {
738 LIST_PREPEND(ipmasks
, peer
->ipmasks
, ipmask
);
745 int config_parse_wireguard_endpoint(
747 const char *filename
,
750 unsigned section_line
,
757 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
758 const char *begin
, *end
;
769 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
773 if (rvalue
[0] == '[') {
775 end
= strchr(rvalue
, ']');
777 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
778 "Unable to find matching brace of endpoint, ignoring assignment: %s",
784 if (*end
!= ':' || !*(end
+ 1)) {
785 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
786 "Unable to find port of endpoint, ignoring assignment: %s",
793 end
= strrchr(rvalue
, ':');
794 if (!end
|| !*(end
+ 1)) {
795 log_syntax(unit
, LOG_ERR
, filename
, line
, 0,
796 "Unable to find port of endpoint, ignoring assignment: %s",
804 r
= free_and_strndup(&peer
->endpoint_host
, begin
, len
);
808 r
= free_and_strdup(&peer
->endpoint_port
, end
);
812 r
= set_ensure_allocated(&w
->peers_with_unresolved_endpoint
, NULL
);
816 r
= set_put(w
->peers_with_unresolved_endpoint
, peer
);
824 int config_parse_wireguard_keepalive(
826 const char *filename
,
829 unsigned section_line
,
836 _cleanup_(wireguard_peer_free_or_set_invalidp
) WireguardPeer
*peer
= NULL
;
837 uint16_t keepalive
= 0;
847 r
= wireguard_peer_new_static(w
, filename
, section_line
, &peer
);
851 if (streq(rvalue
, "off"))
854 r
= safe_atou16(rvalue
, &keepalive
);
856 log_syntax(unit
, LOG_ERR
, filename
, line
, r
,
857 "The persistent keepalive interval must be 0-65535. Ignore assignment: %s",
863 peer
->persistent_keepalive_interval
= keepalive
;
869 static void wireguard_init(NetDev
*netdev
) {
873 w
= WIREGUARD(netdev
);
876 w
->flags
= WGDEVICE_F_REPLACE_PEERS
;
879 static void wireguard_done(NetDev
*netdev
) {
883 w
= WIREGUARD(netdev
);
886 sd_event_source_unref(w
->resolve_retry_event_source
);
888 explicit_bzero_safe(w
->private_key
, WG_KEY_LEN
);
889 free(w
->private_key_file
);
891 hashmap_free_with_destructor(w
->peers_by_section
, wireguard_peer_free
);
892 set_free(w
->peers_with_unresolved_endpoint
);
893 set_free(w
->peers_with_failed_endpoint
);
896 static int wireguard_read_key_file(const char *filename
, uint8_t dest
[static WG_KEY_LEN
]) {
897 _cleanup_free_
char *key
= NULL
;
904 r
= read_full_file_full(filename
, READ_FULL_FILE_SECURE
| READ_FULL_FILE_UNBASE64
, &key
, &key_len
);
908 if (key_len
!= WG_KEY_LEN
) {
913 memcpy(dest
, key
, WG_KEY_LEN
);
917 explicit_bzero_safe(key
, key_len
);
921 static int wireguard_peer_verify(WireguardPeer
*peer
) {
922 NetDev
*netdev
= NETDEV(peer
->wireguard
);
925 if (section_is_invalid(peer
->section
))
928 if (eqzero(peer
->public_key
))
929 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
930 "%s: WireGuardPeer section without PublicKey= configured. "
931 "Ignoring [WireGuardPeer] section from line %u.",
932 peer
->section
->filename
, peer
->section
->line
);
934 r
= wireguard_read_key_file(peer
->preshared_key_file
, peer
->preshared_key
);
936 return log_netdev_error_errno(netdev
, r
,
937 "%s: Failed to read preshared key from '%s'. "
938 "Ignoring [WireGuardPeer] section from line %u.",
939 peer
->section
->filename
, peer
->preshared_key_file
,
940 peer
->section
->line
);
945 static int wireguard_verify(NetDev
*netdev
, const char *filename
) {
946 WireguardPeer
*peer
, *peer_next
;
951 w
= WIREGUARD(netdev
);
954 r
= wireguard_read_key_file(w
->private_key_file
, w
->private_key
);
956 return log_netdev_error_errno(netdev
, r
,
957 "Failed to read private key from %s. Dropping network device %s.",
958 w
->private_key_file
, netdev
->ifname
);
960 if (eqzero(w
->private_key
))
961 return log_netdev_error_errno(netdev
, SYNTHETIC_ERRNO(EINVAL
),
962 "%s: Missing PrivateKey= or PrivateKeyFile=, "
963 "Dropping network device %s.",
964 filename
, netdev
->ifname
);
966 LIST_FOREACH_SAFE(peers
, peer
, peer_next
, w
->peers
)
967 if (wireguard_peer_verify(peer
) < 0)
968 wireguard_peer_free(peer
);
973 const NetDevVTable wireguard_vtable
= {
974 .object_size
= sizeof(Wireguard
),
975 .sections
= "Match\0NetDev\0WireGuard\0WireGuardPeer\0",
976 .post_create
= netdev_wireguard_post_create
,
977 .init
= wireguard_init
,
978 .done
= wireguard_done
,
979 .create_type
= NETDEV_CREATE_INDEPENDENT
,
980 .config_verify
= wireguard_verify
,