mirror of
https://gitlab.freedesktop.org/NetworkManager/NetworkManager.git
synced 2025-12-20 11:40:14 +01:00
firewall: set firewall rules for WireGuard
This commit is contained in:
parent
c9326fbb92
commit
b247b5b0b9
3 changed files with 169 additions and 2 deletions
|
|
@ -23,6 +23,7 @@
|
||||||
#include "nm-active-connection.h"
|
#include "nm-active-connection.h"
|
||||||
#include "nm-act-request.h"
|
#include "nm-act-request.h"
|
||||||
#include "dns/nm-dns-manager.h"
|
#include "dns/nm-dns-manager.h"
|
||||||
|
#include "nm-firewall-utils.h"
|
||||||
|
|
||||||
#define _NMLOG_DEVICE_TYPE NMDeviceWireGuard
|
#define _NMLOG_DEVICE_TYPE NMDeviceWireGuard
|
||||||
#include "nm-device-logging.h"
|
#include "nm-device-logging.h"
|
||||||
|
|
@ -120,6 +121,14 @@ typedef struct {
|
||||||
CList lst_peers_head;
|
CList lst_peers_head;
|
||||||
GHashTable *peers;
|
GHashTable *peers;
|
||||||
|
|
||||||
|
union {
|
||||||
|
struct {
|
||||||
|
NMFirewallConfig *fw_config_6;
|
||||||
|
NMFirewallConfig *fw_config_4;
|
||||||
|
};
|
||||||
|
NMFirewallConfig *fw_config_x[2];
|
||||||
|
};
|
||||||
|
|
||||||
/* counts the numbers of peers that are currently resolving. */
|
/* counts the numbers of peers that are currently resolving. */
|
||||||
guint peers_resolving_cnt;
|
guint peers_resolving_cnt;
|
||||||
|
|
||||||
|
|
@ -1423,6 +1432,7 @@ link_config(NMDeviceWireGuard *self,
|
||||||
{
|
{
|
||||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
||||||
nm_auto_bzero_secret_ptr NMSecretPtr wg_lnk_clear_private_key = NM_SECRET_PTR_INIT();
|
nm_auto_bzero_secret_ptr NMSecretPtr wg_lnk_clear_private_key = NM_SECRET_PTR_INIT();
|
||||||
|
const char *ip_iface;
|
||||||
NMSettingWireGuard *s_wg;
|
NMSettingWireGuard *s_wg;
|
||||||
NMConnection *connection;
|
NMConnection *connection;
|
||||||
NMActStageReturn ret;
|
NMActStageReturn ret;
|
||||||
|
|
@ -1436,6 +1446,7 @@ link_config(NMDeviceWireGuard *self,
|
||||||
NMPlatformWireGuardChangeFlags wg_change_flags;
|
NMPlatformWireGuardChangeFlags wg_change_flags;
|
||||||
int ifindex;
|
int ifindex;
|
||||||
int r;
|
int r;
|
||||||
|
int IS_IPv4;
|
||||||
|
|
||||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_NONE);
|
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_NONE);
|
||||||
|
|
||||||
|
|
@ -1478,8 +1489,9 @@ link_config(NMDeviceWireGuard *self,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
ifindex = nm_device_get_ip_ifindex(NM_DEVICE(self));
|
ifindex = nm_device_get_ip_ifindex(NM_DEVICE(self));
|
||||||
if (ifindex <= 0) {
|
ip_iface = nm_device_get_ip_iface(NM_DEVICE(self));
|
||||||
|
if (ifindex <= 0 || !ip_iface) {
|
||||||
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
NM_SET_OUT(out_failure_reason, NM_DEVICE_STATE_REASON_CONFIG_FAILED);
|
||||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
@ -1537,6 +1549,17 @@ link_config(NMDeviceWireGuard *self,
|
||||||
return NM_ACT_STAGE_RETURN_FAILURE;
|
return NM_ACT_STAGE_RETURN_FAILURE;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
for (IS_IPv4 = 1; IS_IPv4 >= 0; IS_IPv4--) {
|
||||||
|
//XXX
|
||||||
|
nm_firewall_config_apply(priv->fw_config_x[IS_IPv4], FALSE);
|
||||||
|
nm_clear_pointer(&priv->fw_config_x[IS_IPv4], nm_firewall_config_free);
|
||||||
|
priv->fw_config_x[IS_IPv4] = nm_firewall_config_new_wireguard(ip_iface,
|
||||||
|
IS_IPv4 ? AF_INET : AF_INET6,
|
||||||
|
wg_lnk.fwmark,
|
||||||
|
NULL,
|
||||||
|
0);
|
||||||
|
}
|
||||||
|
|
||||||
return NM_ACT_STAGE_RETURN_SUCCESS;
|
return NM_ACT_STAGE_RETURN_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -17,6 +17,7 @@
|
||||||
|
|
||||||
typedef enum _nm_packed {
|
typedef enum _nm_packed {
|
||||||
FIREWALL_TOPIC_IP4_SHARED,
|
FIREWALL_TOPIC_IP4_SHARED,
|
||||||
|
FIREWALL_TOPIC_WIREGUARD,
|
||||||
} FirewallTopic;
|
} FirewallTopic;
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
@ -689,6 +690,86 @@ _fw_nft_set_ip4_shared(gboolean up, const char *ip_iface, in_addr_t addr, guint8
|
||||||
|
|
||||||
/*****************************************************************************/
|
/*****************************************************************************/
|
||||||
|
|
||||||
|
static void
|
||||||
|
_fw_nft_set_wireguard(gboolean up,
|
||||||
|
const char *ip_iface,
|
||||||
|
int addr_family,
|
||||||
|
guint32 fwmark,
|
||||||
|
const NMIPAddr *addrs,
|
||||||
|
gsize addrs_len)
|
||||||
|
{
|
||||||
|
const int IS_IPv4 = NM_IS_IPv4(addr_family);
|
||||||
|
nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
|
||||||
|
gs_unref_bytes GBytes *stdin_buf = NULL;
|
||||||
|
gs_free char *table_name = NULL;
|
||||||
|
gs_free char *ss1 = NULL;
|
||||||
|
const char *pf = IS_IPv4 ? "ip" : "ip6";
|
||||||
|
gsize i;
|
||||||
|
|
||||||
|
table_name = _share_iptables_get_name(FALSE, "nm-wg", ip_iface);
|
||||||
|
|
||||||
|
/* Taken from wg-quick:
|
||||||
|
* https://git.zx2c4.com/wireguard-tools/tree/src/wg-quick/linux.bash?id=1fd95708391088742c139010cc6b821add941dec#n228 */
|
||||||
|
|
||||||
|
#define _append(p_strbuf, fmt, ...) nm_str_buf_append_printf((p_strbuf), "" fmt "\n", ##__VA_ARGS__)
|
||||||
|
|
||||||
|
_append(&strbuf, "add table %s %s", pf, table_name);
|
||||||
|
_append(&strbuf, "%s table %s %s", up ? "flush" : "delete", pf, table_name);
|
||||||
|
|
||||||
|
if (up) {
|
||||||
|
_append(&strbuf,
|
||||||
|
"add chain %s %s preraw {"
|
||||||
|
" type filter hook prerouting priority -300; "
|
||||||
|
"};",
|
||||||
|
pf,
|
||||||
|
table_name);
|
||||||
|
_append(&strbuf,
|
||||||
|
"add chain %s %s premangle {"
|
||||||
|
" type filter hook prerouting priority -150; "
|
||||||
|
"};",
|
||||||
|
pf,
|
||||||
|
table_name);
|
||||||
|
_append(&strbuf,
|
||||||
|
"add chain %s %s postmangle {"
|
||||||
|
" type filter hook postrouting priority -150; "
|
||||||
|
"};",
|
||||||
|
pf,
|
||||||
|
table_name);
|
||||||
|
for (i = 0; i < addrs_len; i++) {
|
||||||
|
char addr_buf[NM_UTILS_INET_ADDRSTRLEN];
|
||||||
|
|
||||||
|
_append(
|
||||||
|
&strbuf,
|
||||||
|
"add rule %s %s preraw iifname != \"%s\" %s daddr %s fib saddr type != local drop",
|
||||||
|
pf,
|
||||||
|
table_name,
|
||||||
|
ip_iface,
|
||||||
|
pf,
|
||||||
|
nm_utils_inet_ntop(addr_family, &addrs[i], addr_buf));
|
||||||
|
}
|
||||||
|
_append(&strbuf,
|
||||||
|
"add rule %s %s postmangle meta l4proto udp mark %u ct mark set mark",
|
||||||
|
pf,
|
||||||
|
table_name,
|
||||||
|
fwmark);
|
||||||
|
_append(&strbuf,
|
||||||
|
"add rule %s %s premangle meta l4proto udp meta mark set ct mark",
|
||||||
|
pf,
|
||||||
|
table_name);
|
||||||
|
}
|
||||||
|
|
||||||
|
nm_log_trace(LOGD_SHARING,
|
||||||
|
"firewall: nft command: [ %s ]",
|
||||||
|
nm_utils_str_utf8safe_escape(nm_str_buf_get_str(&strbuf),
|
||||||
|
NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL,
|
||||||
|
&ss1));
|
||||||
|
|
||||||
|
stdin_buf = nm_str_buf_finalize_to_gbytes(&strbuf);
|
||||||
|
_fw_nft_call_sync(stdin_buf, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
|
/*****************************************************************************/
|
||||||
|
|
||||||
struct _NMFirewallConfig {
|
struct _NMFirewallConfig {
|
||||||
FirewallTopic topic;
|
FirewallTopic topic;
|
||||||
char *ip_iface;
|
char *ip_iface;
|
||||||
|
|
@ -697,6 +778,12 @@ struct _NMFirewallConfig {
|
||||||
in_addr_t addr;
|
in_addr_t addr;
|
||||||
guint8 plen;
|
guint8 plen;
|
||||||
} ip4_shared;
|
} ip4_shared;
|
||||||
|
struct {
|
||||||
|
int addr_family;
|
||||||
|
guint32 fwmark;
|
||||||
|
NMIPAddr *addrs;
|
||||||
|
gsize addrs_len;
|
||||||
|
} wireguard;
|
||||||
};
|
};
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
@ -722,6 +809,35 @@ nm_firewall_config_new_ip4_shared(const char *ip_iface, in_addr_t addr, guint8 p
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
NMFirewallConfig *
|
||||||
|
nm_firewall_config_new_wireguard(const char *ip_iface,
|
||||||
|
int addr_family,
|
||||||
|
guint32 fwmark,
|
||||||
|
const NMIPAddr *addrs,
|
||||||
|
gsize addrs_len)
|
||||||
|
{
|
||||||
|
NMFirewallConfig *self;
|
||||||
|
|
||||||
|
nm_assert(ip_iface);
|
||||||
|
nm_assert_addr_family(addr_family);
|
||||||
|
nm_assert(addrs_len > 0);
|
||||||
|
nm_assert(addrs);
|
||||||
|
|
||||||
|
self = g_slice_new(NMFirewallConfig);
|
||||||
|
*self = (NMFirewallConfig){
|
||||||
|
.topic = FIREWALL_TOPIC_WIREGUARD,
|
||||||
|
.ip_iface = g_strdup(ip_iface),
|
||||||
|
.wireguard =
|
||||||
|
{
|
||||||
|
.addr_family = addr_family,
|
||||||
|
.fwmark = fwmark,
|
||||||
|
.addrs = nm_memdup(addrs, addrs_len * sizeof(addrs[0])),
|
||||||
|
.addrs_len = addrs_len,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
void
|
void
|
||||||
nm_firewall_config_free(NMFirewallConfig *self)
|
nm_firewall_config_free(NMFirewallConfig *self)
|
||||||
{
|
{
|
||||||
|
|
@ -731,6 +847,9 @@ nm_firewall_config_free(NMFirewallConfig *self)
|
||||||
switch (self->topic) {
|
switch (self->topic) {
|
||||||
case FIREWALL_TOPIC_IP4_SHARED:
|
case FIREWALL_TOPIC_IP4_SHARED:
|
||||||
goto out;
|
goto out;
|
||||||
|
case FIREWALL_TOPIC_WIREGUARD:
|
||||||
|
g_free(self->wireguard.addrs);
|
||||||
|
goto out;
|
||||||
}
|
}
|
||||||
nm_assert_not_reached();
|
nm_assert_not_reached();
|
||||||
|
|
||||||
|
|
@ -769,6 +888,25 @@ nm_firewall_config_apply(NMFirewallConfig *self, gboolean up)
|
||||||
goto out_bug;
|
goto out_bug;
|
||||||
}
|
}
|
||||||
goto out_bug;
|
goto out_bug;
|
||||||
|
case FIREWALL_TOPIC_WIREGUARD:
|
||||||
|
switch (nm_firewall_utils_get_backend()) {
|
||||||
|
case NM_FIREWALL_BACKEND_IPTABLES:
|
||||||
|
/* XXX: Not implemented. */
|
||||||
|
return;
|
||||||
|
case NM_FIREWALL_BACKEND_NFTABLES:
|
||||||
|
_fw_nft_set_wireguard(up,
|
||||||
|
self->ip_iface,
|
||||||
|
self->wireguard.addr_family,
|
||||||
|
self->wireguard.fwmark,
|
||||||
|
self->wireguard.addrs,
|
||||||
|
self->wireguard.addrs_len);
|
||||||
|
return;
|
||||||
|
case NM_FIREWALL_BACKEND_NONE:
|
||||||
|
return;
|
||||||
|
case NM_FIREWALL_BACKEND_UNKNOWN:
|
||||||
|
goto out_bug;
|
||||||
|
}
|
||||||
|
goto out_bug;
|
||||||
}
|
}
|
||||||
out_bug:
|
out_bug:
|
||||||
nm_assert_not_reached();
|
nm_assert_not_reached();
|
||||||
|
|
|
||||||
|
|
@ -23,6 +23,12 @@ typedef struct _NMFirewallConfig NMFirewallConfig;
|
||||||
NMFirewallConfig *
|
NMFirewallConfig *
|
||||||
nm_firewall_config_new_ip4_shared(const char *ip_iface, in_addr_t addr, guint8 plen);
|
nm_firewall_config_new_ip4_shared(const char *ip_iface, in_addr_t addr, guint8 plen);
|
||||||
|
|
||||||
|
NMFirewallConfig *nm_firewall_config_new_wireguard(const char *ip_iface,
|
||||||
|
int addr_family,
|
||||||
|
guint32 fwmark,
|
||||||
|
const NMIPAddr *addrs,
|
||||||
|
gsize addrs_len);
|
||||||
|
|
||||||
void nm_firewall_config_free(NMFirewallConfig *self);
|
void nm_firewall_config_free(NMFirewallConfig *self);
|
||||||
|
|
||||||
void nm_firewall_config_apply(NMFirewallConfig *self, gboolean up);
|
void nm_firewall_config_apply(NMFirewallConfig *self, gboolean up);
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue