Support for legacy clients

This commit is contained in:
Iurii Egorov 2024-08-16 10:22:39 +03:00 committed by Iurii Egorov
parent e42813caac
commit dafa38e4b0
8 changed files with 91 additions and 4 deletions

View file

@ -62,7 +62,8 @@ enum wgdevice_attribute {
enum wgpeer_flag { enum wgpeer_flag {
WGPEER_F_REMOVE_ME = 1U << 0, WGPEER_F_REMOVE_ME = 1U << 0,
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1 WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3
}; };
enum wgpeer_attribute { enum wgpeer_attribute {
WGPEER_A_UNSPEC, WGPEER_A_UNSPEC,
@ -76,6 +77,7 @@ enum wgpeer_attribute {
WGPEER_A_TX_BYTES, WGPEER_A_TX_BYTES,
WGPEER_A_ALLOWEDIPS, WGPEER_A_ALLOWEDIPS,
WGPEER_A_PROTOCOL_VERSION, WGPEER_A_PROTOCOL_VERSION,
WGPEER_A_ADVANCED_SECURITY,
__WGPEER_A_LAST __WGPEER_A_LAST
}; };

View file

@ -447,6 +447,41 @@ static inline bool parse_uint32(uint32_t *device_value, const char *name, const
return true; return true;
} }
static inline bool parse_bool(bool *device_value, const char *name, const char *value) {
if (!strlen(value)) {
fprintf(stderr, "Unable to parse empty string\n");
return false;
}
if (!strcasecmp(value, "off")) {
*device_value = false;
return true;
}
if (!strcasecmp(value, "on")) {
*device_value = true;
return true;
}
if (!char_is_digit(value[0]))
goto err;
char *end;
uint32_t ret;
ret = strtoul(value, &end, 10);
if (*end) {
fprintf(stderr, "Unable to parse %s: `%s'\n", name, value);
exit(1);
}
*device_value = ret != 0;
return true;
err:
fprintf(stderr, "Boolean value is neither on/off nor 0/1: `%s'\n", value);
return false;
}
static bool process_line(struct config_ctx *ctx, const char *line) static bool process_line(struct config_ctx *ctx, const char *line)
{ {
const char *value; const char *value;
@ -540,6 +575,10 @@ static bool process_line(struct config_ctx *ctx, const char *line)
ret = parse_key(ctx->last_peer->preshared_key, value); ret = parse_key(ctx->last_peer->preshared_key, value);
if (ret) if (ret)
ctx->last_peer->flags |= WGPEER_HAS_PRESHARED_KEY; ctx->last_peer->flags |= WGPEER_HAS_PRESHARED_KEY;
} else if (key_match("AdvancedSecurity")) {
ret = parse_bool(&ctx->last_peer->advanced_security, "AdvancedSecurity", value);
if (ret)
ctx->last_peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
} else } else
goto error; goto error;
} else } else
@ -774,6 +813,12 @@ struct wgdevice *config_read_cmd(const char *argv[], int argc)
peer->flags |= WGPEER_HAS_PRESHARED_KEY; peer->flags |= WGPEER_HAS_PRESHARED_KEY;
argv += 2; argv += 2;
argc -= 2; argc -= 2;
} else if (!strcmp(argv[0], "advanced-security") && argc >= 2 && peer) {
if (!parse_bool(&peer->advanced_security, "AdvancedSecurity", argv[1]))
goto error;
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
argv += 2;
argc -= 2;
} else { } else {
fprintf(stderr, "Invalid argument: %s\n", argv[0]); fprintf(stderr, "Invalid argument: %s\n", argv[0]);
goto error; goto error;

View file

@ -7,6 +7,7 @@
#define CONTAINERS_H #define CONTAINERS_H
#include <stdint.h> #include <stdint.h>
#include <stdbool.h>
#include <stdlib.h> #include <stdlib.h>
#include <time.h> #include <time.h>
#include <sys/socket.h> #include <sys/socket.h>
@ -43,7 +44,8 @@ enum {
WGPEER_REPLACE_ALLOWEDIPS = 1U << 1, WGPEER_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_HAS_PUBLIC_KEY = 1U << 2, WGPEER_HAS_PUBLIC_KEY = 1U << 2,
WGPEER_HAS_PRESHARED_KEY = 1U << 3, WGPEER_HAS_PRESHARED_KEY = 1U << 3,
WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4 WGPEER_HAS_PERSISTENT_KEEPALIVE_INTERVAL = 1U << 4,
WGPEER_HAS_ADVANCED_SECURITY = 1U << 5
}; };
struct wgpeer { struct wgpeer {
@ -62,6 +64,8 @@ struct wgpeer {
uint64_t rx_bytes, tx_bytes; uint64_t rx_bytes, tx_bytes;
uint16_t persistent_keepalive_interval; uint16_t persistent_keepalive_interval;
bool advanced_security;
struct wgallowedip *first_allowedip, *last_allowedip; struct wgallowedip *first_allowedip, *last_allowedip;
struct wgpeer *next_peer; struct wgpeer *next_peer;
}; };
@ -96,7 +100,7 @@ struct wgdevice {
uint16_t listen_port; uint16_t listen_port;
struct wgpeer *first_peer, *last_peer; struct wgpeer *first_peer, *last_peer;
uint16_t junk_packet_count; uint16_t junk_packet_count;
uint16_t junk_packet_min_size; uint16_t junk_packet_min_size;
uint16_t junk_packet_max_size; uint16_t junk_packet_max_size;

View file

@ -221,6 +221,11 @@ again:
goto toobig_peers; goto toobig_peers;
} }
} }
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
if (peer->advanced_security)
mnl_attr_put_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_ADVANCED_SECURITY, 0, NULL);
flags |= WGPEER_F_HAS_ADVANCED_SECURITY;
}
if (flags) { if (flags) {
if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags)) if (!mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGPEER_A_FLAGS, flags))
goto toobig_peers; goto toobig_peers;
@ -389,6 +394,25 @@ static int parse_peer(const struct nlattr *attr, void *data)
if (!mnl_attr_validate(attr, MNL_TYPE_U64)) if (!mnl_attr_validate(attr, MNL_TYPE_U64))
peer->tx_bytes = mnl_attr_get_u64(attr); peer->tx_bytes = mnl_attr_get_u64(attr);
break; break;
case WGPEER_A_FLAGS:
if (!mnl_attr_validate(attr, MNL_TYPE_U32)) {
uint32_t flags = mnl_attr_get_u32(attr);
if (flags & WGPEER_F_HAS_ADVANCED_SECURITY && !(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
peer->advanced_security = false;
}
}
break;
case WGPEER_A_ADVANCED_SECURITY:
if (!mnl_attr_validate(attr, MNL_TYPE_FLAG)) {
peer->advanced_security = true;
if (!(peer->flags & WGPEER_HAS_ADVANCED_SECURITY)) {
peer->flags |= WGPEER_HAS_ADVANCED_SECURITY;
}
}
break;
case WGPEER_A_ALLOWEDIPS: case WGPEER_A_ALLOWEDIPS:
return mnl_attr_parse_nested(attr, parse_allowedips, peer); return mnl_attr_parse_nested(attr, parse_allowedips, peer);
} }

View file

@ -73,6 +73,10 @@ static int userspace_set_device(struct wgdevice *dev)
for_each_wgpeer(dev, peer) { for_each_wgpeer(dev, peer) {
key_to_hex(hex, peer->public_key); key_to_hex(hex, peer->public_key);
fprintf(f, "public_key=%s\n", hex); fprintf(f, "public_key=%s\n", hex);
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
ret = -EINVAL;
goto out;
}
if (peer->flags & WGPEER_REMOVE_ME) { if (peer->flags & WGPEER_REMOVE_ME) {
fprintf(f, "remove=true\n"); fprintf(f, "remove=true\n");
continue; continue;

View file

@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[])
int ret = 1; int ret = 1;
if (argc < 3) { if (argc < 3) {
fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>]...] ]...\n", PROG_NAME, argv[0]); fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>] [advanced-security <on|off>]...] ]...\n", PROG_NAME, argv[0]);
return 1; return 1;
} }

View file

@ -73,6 +73,9 @@ int showconf_main(int argc, const char *argv[])
key_to_base64(base64, peer->preshared_key); key_to_base64(base64, peer->preshared_key);
printf("PresharedKey = %s\n", base64); printf("PresharedKey = %s\n", base64);
} }
if (peer->flags & WGPEER_HAS_ADVANCED_SECURITY) {
printf("AdvancedSecurity = %s\n", peer->advanced_security ? "on" : "off");
}
if (peer->first_allowedip) if (peer->first_allowedip)
printf("AllowedIPs = "); printf("AllowedIPs = ");
for_each_wgallowedip(peer, allowedip) { for_each_wgallowedip(peer, allowedip) {

View file

@ -111,6 +111,9 @@
* most recent protocol will be used when * most recent protocol will be used when
* this is unset. Otherwise, must be set * this is unset. Otherwise, must be set
* to 1. * to 1.
* WGPEER_A_ADVANCED_SECURITY: flag indicating that advanced security
* techniques provided by AmneziaWG should
* be used.
* 0: NLA_NESTED * 0: NLA_NESTED
* ... * ...
* ... * ...
@ -174,6 +177,7 @@ enum wgpeer_flag {
WGPEER_F_REMOVE_ME = 1U << 0, WGPEER_F_REMOVE_ME = 1U << 0,
WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1, WGPEER_F_REPLACE_ALLOWEDIPS = 1U << 1,
WGPEER_F_UPDATE_ONLY = 1U << 2, WGPEER_F_UPDATE_ONLY = 1U << 2,
WGPEER_F_HAS_ADVANCED_SECURITY = 1U << 3,
__WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS | __WGPEER_F_ALL = WGPEER_F_REMOVE_ME | WGPEER_F_REPLACE_ALLOWEDIPS |
WGPEER_F_UPDATE_ONLY WGPEER_F_UPDATE_ONLY
}; };
@ -189,6 +193,7 @@ enum wgpeer_attribute {
WGPEER_A_TX_BYTES, WGPEER_A_TX_BYTES,
WGPEER_A_ALLOWEDIPS, WGPEER_A_ALLOWEDIPS,
WGPEER_A_PROTOCOL_VERSION, WGPEER_A_PROTOCOL_VERSION,
WGPEER_A_ADVANCED_SECURITY,
__WGPEER_A_LAST __WGPEER_A_LAST
}; };
#define WGPEER_A_MAX (__WGPEER_A_LAST - 1) #define WGPEER_A_MAX (__WGPEER_A_LAST - 1)