mirror of
https://git.zx2c4.com/wireguard-tools
synced 2026-06-11 09:52:20 -04:00
ipc: linux: support incremental allowed ips updates
Extend the interface of `wg set` to leverage the WGALLOWEDIP_F_REMOVE_ME flag, a direct way of removing a single allowed ip from a peer, allowing for incremental updates to a peer's configuration. By default, allowed-ips fully replaces a peer's allowed ips using WGPEER_REPLACE_ALLOWEDIPS under the hood. When '+' or '-' is prepended to any ip in the list, wg clears WGPEER_F_REPLACE_ALLOWEDIPS and sets the WGALLOWEDIP_F_REMOVE_ME flag on any ip prefixed with '-'. $ wg set wg0 peer <PUBKEY> allowed-ips +192.168.88.0/24,-192.168.0.1/32 This command means "add 192.168.88.0/24 to this peer's allowed ips if not present, and remove 192.168.0.1/32 if present". Use -isystem so that headers in uapi/ take precedence over system headers; otherwise, the build will fail on systems running kernels without the WGALLOWEDIP_F_REMOVE_ME flag. Note that this patch is meant to be merged alongside the kernel patch that introduces the flag. Signed-off-by: Jordan Rife <jordan@jrife.io> [Jason: removed linux ifdefs; this will eventually come to other platforms too. minor style nits.] Signed-off-by: Jason A. Donenfeld <Jason@zx2c4.com>
This commit is contained in:
parent
13d190bc72
commit
0788f90810
7 changed files with 42 additions and 4 deletions
|
|
@ -39,7 +39,7 @@ PLATFORM ?= $(shell uname -s | tr '[:upper:]' '[:lower:]')
|
|||
|
||||
CFLAGS ?= -O3
|
||||
ifneq ($(wildcard uapi/$(PLATFORM)/.),)
|
||||
CFLAGS += -idirafter uapi/$(PLATFORM)
|
||||
CFLAGS += -isystem uapi/$(PLATFORM)
|
||||
endif
|
||||
CFLAGS += -std=gnu99 -D_GNU_SOURCE
|
||||
CFLAGS += -Wall -Wextra
|
||||
|
|
|
|||
18
src/config.c
18
src/config.c
|
|
@ -337,6 +337,20 @@ static bool validate_netmask(struct wgallowedip *allowedip)
|
|||
return true;
|
||||
}
|
||||
|
||||
static inline void parse_ip_prefix(struct wgpeer *peer, uint32_t *flags, char **mask)
|
||||
{
|
||||
/* If the IP is prefixed with either '+' or '-' consider this an
|
||||
* incremental change. Disable WGPEER_REPLACE_ALLOWEDIPS. */
|
||||
switch ((*mask)[0]) {
|
||||
case '-':
|
||||
*flags |= WGALLOWEDIP_REMOVE_ME;
|
||||
/* fall through */
|
||||
case '+':
|
||||
peer->flags &= ~WGPEER_REPLACE_ALLOWEDIPS;
|
||||
++(*mask);
|
||||
}
|
||||
}
|
||||
|
||||
static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **last_allowedip, const char *value)
|
||||
{
|
||||
struct wgallowedip *allowedip = *last_allowedip, *new_allowedip;
|
||||
|
|
@ -353,9 +367,12 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la
|
|||
}
|
||||
sep = mutable;
|
||||
while ((mask = strsep(&sep, ","))) {
|
||||
uint32_t flags = 0;
|
||||
unsigned long cidr;
|
||||
char *end, *ip;
|
||||
|
||||
parse_ip_prefix(peer, &flags, &mask);
|
||||
|
||||
saved_entry = strdup(mask);
|
||||
ip = strsep(&mask, "/");
|
||||
|
||||
|
|
@ -387,6 +404,7 @@ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **la
|
|||
else
|
||||
goto err;
|
||||
new_allowedip->cidr = cidr;
|
||||
new_allowedip->flags = flags;
|
||||
|
||||
if (!validate_netmask(new_allowedip))
|
||||
fprintf(stderr, "Warning: AllowedIP has nonzero host part: %s/%s\n", ip, mask);
|
||||
|
|
|
|||
|
|
@ -28,6 +28,10 @@ struct timespec64 {
|
|||
int64_t tv_nsec;
|
||||
};
|
||||
|
||||
enum {
|
||||
WGALLOWEDIP_REMOVE_ME = 1U << 0,
|
||||
};
|
||||
|
||||
struct wgallowedip {
|
||||
uint16_t family;
|
||||
union {
|
||||
|
|
@ -35,6 +39,7 @@ struct wgallowedip {
|
|||
struct in6_addr ip6;
|
||||
};
|
||||
uint8_t cidr;
|
||||
uint32_t flags;
|
||||
struct wgallowedip *next_allowedip;
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -228,6 +228,8 @@ again:
|
|||
}
|
||||
if (!mnl_attr_put_u8_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_CIDR_MASK, allowedip->cidr))
|
||||
goto toobig_allowedips;
|
||||
if (allowedip->flags && !mnl_attr_put_u32_check(nlh, SOCKET_BUFFER_SIZE, WGALLOWEDIP_A_FLAGS, allowedip->flags))
|
||||
goto toobig_allowedips;
|
||||
mnl_attr_nest_end(nlh, allowedip_nest);
|
||||
allowedip_nest = NULL;
|
||||
}
|
||||
|
|
|
|||
|
|
@ -55,7 +55,7 @@ transfer-rx, transfer-tx, persistent-keepalive.
|
|||
Shows the current configuration of \fI<interface>\fP in the format described
|
||||
by \fICONFIGURATION FILE FORMAT\fP below.
|
||||
.TP
|
||||
\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI<ip1>/<cidr1>\fP[,\fI<ip2>/<cidr2>\fP]...] ]...
|
||||
\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI[+|-]<ip1>/<cidr1>\fP[,\fI[+|-]<ip2>/<cidr2>\fP]...] ]...
|
||||
Sets configuration values for the specified \fI<interface>\fP. Multiple
|
||||
\fIpeer\fPs may be specified, and if the \fIremove\fP argument is given
|
||||
for a peer, that peer is removed, not configured. If \fIlisten-port\fP
|
||||
|
|
@ -72,7 +72,11 @@ the device. The use of \fIpreshared-key\fP is optional, and may be omitted;
|
|||
it adds an additional layer of symmetric-key cryptography to be mixed into
|
||||
the already existing public-key cryptography, for post-quantum resistance.
|
||||
If \fIallowed-ips\fP is specified, but the value is the empty string, all
|
||||
allowed ips are removed from the peer. The use of \fIpersistent-keepalive\fP
|
||||
allowed ips are removed from the peer. By default, \fIallowed-ips\fP replaces
|
||||
a peer's allowed ips. If + or - is prepended to any of the ips then
|
||||
the update is incremental; ips prefixed with '+' or '' are added to the peer's
|
||||
allowed ips if not present while ips prefixed with '-' are removed if present.
|
||||
The use of \fIpersistent-keepalive\fP
|
||||
is optional and is by default off; setting it to 0 or "off" disables it.
|
||||
Otherwise it represents, in seconds, between 1 and 65535 inclusive, how often
|
||||
to send an authenticated empty packet to the peer, for the purpose of keeping
|
||||
|
|
|
|||
|
|
@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[])
|
|||
int ret = 1;
|
||||
|
||||
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>]...] ]...\n", PROG_NAME, argv[0]);
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -101,6 +101,10 @@
|
|||
* WGALLOWEDIP_A_FAMILY: NLA_U16
|
||||
* WGALLOWEDIP_A_IPADDR: struct in_addr or struct in6_addr
|
||||
* WGALLOWEDIP_A_CIDR_MASK: NLA_U8
|
||||
* WGALLOWEDIP_A_FLAGS: NLA_U32, WGALLOWEDIP_F_REMOVE_ME if
|
||||
* the specified IP should be removed;
|
||||
* otherwise, this IP will be added if
|
||||
* it is not already present.
|
||||
* 0: NLA_NESTED
|
||||
* ...
|
||||
* 0: NLA_NESTED
|
||||
|
|
@ -184,11 +188,16 @@ enum wgpeer_attribute {
|
|||
};
|
||||
#define WGPEER_A_MAX (__WGPEER_A_LAST - 1)
|
||||
|
||||
enum wgallowedip_flag {
|
||||
WGALLOWEDIP_F_REMOVE_ME = 1U << 0,
|
||||
__WGALLOWEDIP_F_ALL = WGALLOWEDIP_F_REMOVE_ME
|
||||
};
|
||||
enum wgallowedip_attribute {
|
||||
WGALLOWEDIP_A_UNSPEC,
|
||||
WGALLOWEDIP_A_FAMILY,
|
||||
WGALLOWEDIP_A_IPADDR,
|
||||
WGALLOWEDIP_A_CIDR_MASK,
|
||||
WGALLOWEDIP_A_FLAGS,
|
||||
__WGALLOWEDIP_A_LAST
|
||||
};
|
||||
#define WGALLOWEDIP_A_MAX (__WGALLOWEDIP_A_LAST - 1)
|
||||
|
|
|
|||
Loading…
Reference in a new issue