firewall/wireguard: drop packets received to wrong interface
If we receive a packet sent to the WG interface's address, but it does not come from the WG tunnel, let's assume something is broken and drop the packet. This is also inspired by wg-quick firewall rules: https://git.zx2c4.com/wireguard-tools/tree/src/wg-quick/linux.bash?id=17c78d31c27a3c311a2ff42a881057753c6ef2a4#n221
This commit is contained in:
@@ -1213,18 +1213,33 @@ _configure_firewall(NMDeviceWireGuard *self, NMConnection *connection, int addr_
|
||||
{
|
||||
NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self);
|
||||
const char *ip_iface;
|
||||
|
||||
if (addr_family == AF_INET && !priv->auto_default_route_enabled_4)
|
||||
return;
|
||||
else if (addr_family == AF_INET6 && !priv->auto_default_route_enabled_6)
|
||||
return;
|
||||
NMSettingIPConfig *ip_config;
|
||||
|
||||
ip_iface = nm_device_get_ip_iface(NM_DEVICE(self));
|
||||
|
||||
nm_assert(priv->auto_default_route_fwmark);
|
||||
nm_assert(ip_iface);
|
||||
|
||||
nm_firewall_config_set_wg_rule(ip_iface, addr_family, priv->auto_default_route_fwmark, up);
|
||||
switch (addr_family) {
|
||||
case AF_INET:
|
||||
if (!priv->auto_default_route_enabled_4)
|
||||
return;
|
||||
|
||||
ip_config = nm_connection_get_setting_ip4_config(connection);
|
||||
break;
|
||||
case AF_INET6:
|
||||
if (!priv->auto_default_route_enabled_6)
|
||||
return;
|
||||
|
||||
ip_config = nm_connection_get_setting_ip6_config(connection);
|
||||
break;
|
||||
default:
|
||||
nm_assert_not_reached();
|
||||
}
|
||||
|
||||
nm_assert(ip_config);
|
||||
nm_assert(priv->auto_default_route_fwmark);
|
||||
|
||||
nm_firewall_config_set_wg_rule(ip_iface, ip_config, priv->auto_default_route_fwmark, up);
|
||||
}
|
||||
|
||||
/*****************************************************************************/
|
||||
|
@@ -8,6 +8,7 @@
|
||||
|
||||
#include "nm-firewall-utils.h"
|
||||
|
||||
#include "libnm-core-aux-intern/nm-libnm-core-utils.h"
|
||||
#include "libnm-glib-aux/nm-str-buf.h"
|
||||
#include "libnm-glib-aux/nm-io-utils.h"
|
||||
#include "libnm-platform/nm-platform.h"
|
||||
@@ -764,17 +765,42 @@ _fw_nft_set_shared_construct(gboolean up, const char *ip_iface, in_addr_t addr,
|
||||
}
|
||||
|
||||
static GBytes *
|
||||
_fw_nft_wg_default_construct(const char *ip_iface, int family, int fwmark, gboolean up)
|
||||
_fw_nft_wg_default_construct(const char *ip_iface,
|
||||
NMSettingIPConfig *ip_config,
|
||||
int fwmark,
|
||||
gboolean up)
|
||||
{
|
||||
nm_auto_str_buf NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_1000, FALSE);
|
||||
gs_free char *table_name = NULL;
|
||||
const char *family_str = family == AF_INET ? "ip" : "ip6";
|
||||
const char *family_str;
|
||||
|
||||
table_name = _share_iptables_get_name(FALSE, "nm-wg", ip_iface);
|
||||
family_str = nm_setting_ip_config_get_addr_family(ip_config) == AF_INET ? "ip" : "ip6";
|
||||
|
||||
_fw_nft_append_cmd_table(&strbuf, family_str, table_name, up);
|
||||
|
||||
if (up) {
|
||||
guint n_addresses = nm_setting_ip_config_get_num_addresses(ip_config);
|
||||
|
||||
if (n_addresses) {
|
||||
_append(&strbuf, "add chain %s %s preraw {", family_str, table_name);
|
||||
|
||||
for (guint i = 0; i < n_addresses; i++) {
|
||||
NMIPAddress *addr = nm_setting_ip_config_get_address(ip_config, i);
|
||||
|
||||
_append(&strbuf,
|
||||
" iifname != \"%s\" "
|
||||
" %s daddr %s "
|
||||
" fib saddr type != local "
|
||||
"drop;",
|
||||
ip_iface,
|
||||
family_str,
|
||||
nm_ip_address_get_address(addr));
|
||||
}
|
||||
|
||||
_append(&strbuf, "};");
|
||||
}
|
||||
|
||||
_append(&strbuf,
|
||||
"add chain %s %s premangle {"
|
||||
" type filter hook prerouting priority mangle; policy accept; "
|
||||
@@ -797,16 +823,47 @@ _fw_nft_wg_default_construct(const char *ip_iface, int family, int fwmark, gbool
|
||||
}
|
||||
|
||||
static void
|
||||
_fw_iptables_wg_configure(const char *ip_iface, int family, int fwmark, gboolean up)
|
||||
_fw_iptables_wg_configure(const char *ip_iface,
|
||||
NMSettingIPConfig *ip_config,
|
||||
int fwmark,
|
||||
gboolean up)
|
||||
{
|
||||
gs_free char *comment_name = NULL;
|
||||
char fwmark_str[11];
|
||||
int family = nm_setting_ip_config_get_addr_family(ip_config);
|
||||
guint n_addresses = nm_setting_ip_config_get_num_addresses(ip_config);
|
||||
|
||||
comment_name = _share_iptables_get_name(FALSE, "nm-wg", ip_iface);
|
||||
g_snprintf(fwmark_str, sizeof(fwmark_str), "%" G_GUINT32_FORMAT, fwmark);
|
||||
|
||||
nm_assert(strlen(fwmark_str) > 0);
|
||||
|
||||
for (guint i = 0; i < n_addresses; i++) {
|
||||
NMIPAddress *addr = nm_setting_ip_config_get_address(ip_config, i);
|
||||
|
||||
_ipxtables_call(family,
|
||||
"--table",
|
||||
"raw",
|
||||
up ? "--insert" : "--delete",
|
||||
"PREROUTING",
|
||||
"!",
|
||||
"--in-interface",
|
||||
ip_iface,
|
||||
"--destination",
|
||||
nm_ip_address_get_address(addr),
|
||||
"--match",
|
||||
"addrtype",
|
||||
"!",
|
||||
"--src-type",
|
||||
"LOCAL",
|
||||
"-j",
|
||||
"DROP",
|
||||
"-m",
|
||||
"comment",
|
||||
"--comment",
|
||||
comment_name);
|
||||
}
|
||||
|
||||
_ipxtables_call(family,
|
||||
"--table",
|
||||
"mangle",
|
||||
@@ -1133,21 +1190,22 @@ nm_firewall_config_free(NMFirewallConfig *self)
|
||||
|
||||
/*****************************************************************************/
|
||||
void
|
||||
nm_firewall_config_set_wg_rule(const char *ifname, int family, int fwmark, gboolean up)
|
||||
nm_firewall_config_set_wg_rule(const char *ifname,
|
||||
NMSettingIPConfig *ip_config,
|
||||
int fwmark,
|
||||
gboolean up)
|
||||
{
|
||||
nm_assert(NM_IN_SET(family, AF_INET, AF_INET6));
|
||||
|
||||
switch (nm_firewall_utils_get_backend()) {
|
||||
case NM_FIREWALL_BACKEND_NFTABLES:
|
||||
{
|
||||
gs_unref_bytes GBytes *stdin_buf = NULL;
|
||||
|
||||
stdin_buf = _fw_nft_wg_default_construct(ifname, family, fwmark, up);
|
||||
stdin_buf = _fw_nft_wg_default_construct(ifname, ip_config, fwmark, up);
|
||||
_fw_nft_call_sync(stdin_buf, NULL);
|
||||
break;
|
||||
}
|
||||
case NM_FIREWALL_BACKEND_IPTABLES:
|
||||
_fw_iptables_wg_configure(ifname, family, fwmark, up);
|
||||
_fw_iptables_wg_configure(ifname, ip_config, fwmark, up);
|
||||
break;
|
||||
case NM_FIREWALL_BACKEND_NONE:
|
||||
break;
|
||||
|
@@ -24,7 +24,10 @@ NMFirewallConfig *nm_firewall_config_new_shared(const char *ip_iface, in_addr_t
|
||||
|
||||
void nm_firewall_config_free(NMFirewallConfig *self);
|
||||
|
||||
void nm_firewall_config_set_wg_rule(const char *ifname, int family, int fwmark, gboolean up);
|
||||
void nm_firewall_config_set_wg_rule(const char *ifname,
|
||||
NMSettingIPConfig *ip_config,
|
||||
int fwmark,
|
||||
gboolean up);
|
||||
|
||||
void nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up);
|
||||
|
||||
|
Reference in New Issue
Block a user