diff --git a/config.h.meson b/config.h.meson index e59160dec5..9ae88b26bf 100644 --- a/config.h.meson +++ b/config.h.meson @@ -67,6 +67,9 @@ /* Define to path of iptables binary */ #mesondefine IPTABLES_PATH +/* Define to path of ip6tables binary */ +#mesondefine IP6TABLES_PATH + /* Define to path of nft binary */ #mesondefine NFT_PATH diff --git a/contrib/fedora/rpm/NetworkManager.spec b/contrib/fedora/rpm/NetworkManager.spec index 2af0f44602..22a1a49cf8 100644 --- a/contrib/fedora/rpm/NetworkManager.spec +++ b/contrib/fedora/rpm/NetworkManager.spec @@ -597,6 +597,7 @@ Preferably use nmcli instead. %endif -Dnft=%{_sbindir}/nft \ -Diptables=%{_sbindir}/iptables \ + -Dip6tables=%{_sbindir}/ip6tables \ %if %{with dhclient} -Ddhclient=%{_sbindir}/dhclient \ %else diff --git a/contrib/fedora/rpm/build_clean.sh b/contrib/fedora/rpm/build_clean.sh index b1944d7780..2dbca0e7d2 100755 --- a/contrib/fedora/rpm/build_clean.sh +++ b/contrib/fedora/rpm/build_clean.sh @@ -222,6 +222,7 @@ if [[ $NO_DIST != 1 ]]; then -Dconfig_dhcp_default=internal \ -Dconfig_dns_rc_manager_default=auto \ -Diptables=/usr/sbin/iptables \ + -Dip6tables=/usr/sbin/ip6tables \ -Dnft=/usr/bin/nft \ || die "Error meson setup" diff --git a/contrib/fedora/rpm/configure-for-system.sh b/contrib/fedora/rpm/configure-for-system.sh index fff426bcad..f0638591bd 100755 --- a/contrib/fedora/rpm/configure-for-system.sh +++ b/contrib/fedora/rpm/configure-for-system.sh @@ -368,6 +368,7 @@ meson setup\ $(args_enable "$P_TEST" --werror) \ -Dnft="${D_SBINDIR}/nft" \ -Diptables="${D_SBINDIR}/iptables" \ + -Dip6tables="${D_SBINDIR}/ip6tables" \ -Ddhclient="${D_SBINDIR}/dhclient" \ -Ddhcpcd=no \ -Dconfig_dhcp_default="$P_DHCP_DEFAULT" \ diff --git a/meson.build b/meson.build index 52bd072b0c..e8d1431b19 100644 --- a/meson.build +++ b/meson.build @@ -723,6 +723,7 @@ default_paths = ['/sbin', '/usr/sbin'] # 0: cmdline option, 1: paths, 2: fallback progs = [['iptables', default_paths, '/usr/sbin/iptables'], + ['ip6tables', default_paths, '/usr/sbin/ip6tables'], ['nft', default_paths, '/usr/sbin/nft'], ['dnsmasq', default_paths, ''], ['modprobe', default_paths, '/sbin/modprobe'] @@ -1125,6 +1126,7 @@ endif output += '\n' output += ' jansson: ' + jansson_msg + '\n' output += ' iptables: ' + config_h.get('IPTABLES_PATH') + '\n' +output += ' ip6tables: ' + config_h.get('IP6TABLES_PATH') + '\n' output += ' nft: ' + config_h.get('NFT_PATH') + '\n' output += ' modprobe: ' + config_h.get('MODPROBE_PATH') + '\n' output += ' modemmanager-1: ' + enable_modem_manager.to_string() + '\n' diff --git a/meson_options.txt b/meson_options.txt index 4bc11aa08b..fe696aaf16 100644 --- a/meson_options.txt +++ b/meson_options.txt @@ -6,6 +6,7 @@ option('dbus_conf_dir', type: 'string', value: '', description: 'where D-Bus sys option('kernel_firmware_dir', type: 'string', value: '/lib/firmware', description: 'where kernel firmware directory is (default is /lib/firmware)') option('runtime_dir', type: 'string', value: '', description: 'Directory for transient runtime state [default: LOCALSTATEDIR/run or /run]') option('iptables', type: 'string', value: '', description: 'path to iptables') +option('ip6tables', type: 'string', value: '', description: 'path to ip6tables') option('nft', type: 'string', value: '', description: 'path to nft') option('dnsmasq', type: 'string', value: '', description: 'path to dnsmasq') option('modprobe', type: 'string', value: '', description: 'path to modprobe') diff --git a/src/core/devices/nm-device-wireguard.c b/src/core/devices/nm-device-wireguard.c index 4a08192e03..299e3b30e8 100644 --- a/src/core/devices/nm-device-wireguard.c +++ b/src/core/devices/nm-device-wireguard.c @@ -23,6 +23,7 @@ #include "nm-active-connection.h" #include "nm-act-request.h" #include "dns/nm-dns-manager.h" +#include "nm-firewall-utils.h" #define _NMLOG_DEVICE_TYPE NMDeviceWireGuard #include "nm-device-logging.h" @@ -1207,6 +1208,40 @@ skip: *out_allowed_ips_data = g_steal_pointer(&allowed_ips); } +static void +_configure_firewall(NMDeviceWireGuard *self, NMConnection *connection, int addr_family, gboolean up) +{ + NMDeviceWireGuardPrivate *priv = NM_DEVICE_WIREGUARD_GET_PRIVATE(self); + const char *ip_iface; + NMSettingIPConfig *ip_config; + + ip_iface = nm_device_get_ip_iface(NM_DEVICE(self)); + + nm_assert(ip_iface); + + 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); +} + /*****************************************************************************/ static void @@ -1300,6 +1335,18 @@ create_and_realize(NMDevice *device, return TRUE; } +static void +deactivate(NMDevice *device) +{ + NMDeviceWireGuard *self = NM_DEVICE_WIREGUARD(device); + NMConnection *connection = nm_device_get_applied_connection(NM_DEVICE(self)); + + if (connection) { + _configure_firewall(self, connection, AF_INET, FALSE); + _configure_firewall(self, connection, AF_INET6, FALSE); + } +} + /*****************************************************************************/ static void @@ -1768,6 +1815,10 @@ act_stage3_ip_config(NMDevice *device, int addr_family) nm_auto_unref_l3cd const NML3ConfigData *l3cd = NULL; l3cd = _get_dev2_ip_config(NM_DEVICE_WIREGUARD(device), addr_family); + _configure_firewall(NM_DEVICE_WIREGUARD(device), + nm_device_get_applied_connection(device), + addr_family, + TRUE); nm_device_devip_set_state(device, addr_family, NM_DEVICE_IP_STATE_READY, l3cd); } @@ -1866,6 +1917,10 @@ reapply_connection(NMDevice *device, NMConnection *con_old, NMConnection *con_ne if (state >= NM_DEVICE_STATE_CONFIG) { priv->auto_default_route_refresh = TRUE; + + _configure_firewall(self, con_old, AF_INET, FALSE); + _configure_firewall(self, con_old, AF_INET6, FALSE); + link_config(NM_DEVICE_WIREGUARD(device), "reapply", LINK_CONFIG_MODE_REAPPLY, NULL); } @@ -2018,6 +2073,7 @@ nm_device_wireguard_class_init(NMDeviceWireGuardClass *klass) device_class->state_changed = device_state_changed; device_class->create_and_realize = create_and_realize; + device_class->deactivate = deactivate; device_class->act_stage2_config = act_stage2_config; device_class->act_stage2_config_also_for_external_or_assume = TRUE; device_class->act_stage3_ip_config = act_stage3_ip_config; diff --git a/src/core/nm-firewall-utils.c b/src/core/nm-firewall-utils.c index b496061247..60f40228db 100644 --- a/src/core/nm-firewall-utils.c +++ b/src/core/nm-firewall-utils.c @@ -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" @@ -127,7 +128,7 @@ _share_iptables_subnet_to_str(char buf[static _SHARE_IPTABLES_SUBNET_TO_STR } static char * -_share_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const char *ip_iface) +_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const char *ip_iface) { NMStrBuf strbuf = NM_STR_BUF_INIT(NM_UTILS_GET_NEXT_REALLOC_SIZE_40, FALSE); gsize ip_iface_len; @@ -179,13 +180,13 @@ _share_iptables_get_name(gboolean is_iptables_chain, const char *prefix, const c /*****************************************************************************/ static gboolean -_share_iptables_call_v(const char *const *argv) +_iptables_call_v(const char *const *argv) { gs_free_error GError *error = NULL; gs_free char *argv_str = NULL; int status; - nm_log_dbg(LOGD_SHARING, "iptables: %s", (argv_str = g_strjoinv(" ", (char **) argv))); + nm_log_dbg(LOGD_FIREWALL, "iptables: %s", (argv_str = g_strjoinv(" ", (char **) argv))); if (!g_spawn_sync("/", (char **) argv, @@ -197,7 +198,7 @@ _share_iptables_call_v(const char *const *argv) NULL, &status, &error)) { - nm_log_warn(LOGD_SHARING, + nm_log_warn(LOGD_FIREWALL, "iptables: error executing command %s: %s", argv[0], error->message); @@ -205,20 +206,24 @@ _share_iptables_call_v(const char *const *argv) } if (!g_spawn_check_exit_status(status, &error)) { - nm_log_warn(LOGD_SHARING, "iptables: command %s failed: %s", argv[0], error->message); + nm_log_warn(LOGD_FIREWALL, "iptables: command %s failed: %s", argv[0], error->message); return FALSE; } return TRUE; } -#define _share_iptables_call(...) \ - _share_iptables_call_v(NM_MAKE_STRV("" IPTABLES_PATH "", "--wait", "2", __VA_ARGS__)) +#define _ipxtables_call(family, ...) \ + _iptables_call_v( \ + NM_MAKE_STRV((family == AF_INET ? "" IPTABLES_PATH "" : "" IP6TABLES_PATH ""), \ + "--wait", \ + "2", \ + __VA_ARGS__)) static gboolean _share_iptables_chain_op(const char *table, const char *chain, const char *op) { - return _share_iptables_call("--table", table, op, chain); + return _ipxtables_call(AF_INET, "--table", table, op, chain); } static gboolean @@ -244,24 +249,25 @@ _share_iptables_set_masquerade_sync(gboolean up, const char *ip_iface, in_addr_t char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN]; gs_free char *comment_name = NULL; - comment_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface); + comment_name = _iptables_get_name(FALSE, "nm-shared", ip_iface); _share_iptables_subnet_to_str(str_subnet, addr, plen); - _share_iptables_call("--table", - "nat", - up ? "--insert" : "--delete", - "POSTROUTING", - "--source", - str_subnet, - "!", - "--destination", - str_subnet, - "--jump", - "MASQUERADE", - "-m", - "comment", - "--comment", - comment_name); + _ipxtables_call(AF_INET, + "--table", + "nat", + up ? "--insert" : "--delete", + "POSTROUTING", + "--source", + str_subnet, + "!", + "--destination", + str_subnet, + "--jump", + "MASQUERADE", + "-m", + "comment", + "--comment", + comment_name); } static void @@ -297,70 +303,76 @@ _share_iptables_set_shared_chains_add(const char *chain_input, _share_iptables_chain_add("filter", chain_input); for (i = 0; i < (int) G_N_ELEMENTS(input_params); i++) { - _share_iptables_call("--table", - "filter", - "--append", - chain_input, - "--protocol", - input_params[i][0], - "--destination-port", - input_params[i][1], - "--jump", - "ACCEPT"); + _ipxtables_call(AF_INET, + "--table", + "filter", + "--append", + chain_input, + "--protocol", + input_params[i][0], + "--destination-port", + input_params[i][1], + "--jump", + "ACCEPT"); } _share_iptables_chain_add("filter", chain_forward); - _share_iptables_call("--table", - "filter", - "--append", - chain_forward, - "--destination", - str_subnet, - "--out-interface", - ip_iface, - "--match", - "state", - "--state", - "ESTABLISHED,RELATED", - "--jump", - "ACCEPT"); - _share_iptables_call("--table", - "filter", - "--append", - chain_forward, - "--source", - str_subnet, - "--in-interface", - ip_iface, - "--jump", - "ACCEPT"); - _share_iptables_call("--table", - "filter", - "--append", - chain_forward, - "--in-interface", - ip_iface, - "--out-interface", - ip_iface, - "--jump", - "ACCEPT"); - _share_iptables_call("--table", - "filter", - "--append", - chain_forward, - "--out-interface", - ip_iface, - "--jump", - "REJECT"); - _share_iptables_call("--table", - "filter", - "--append", - chain_forward, - "--in-interface", - ip_iface, - "--jump", - "REJECT"); + _ipxtables_call(AF_INET, + "--table", + "filter", + "--append", + chain_forward, + "--destination", + str_subnet, + "--out-interface", + ip_iface, + "--match", + "state", + "--state", + "ESTABLISHED,RELATED", + "--jump", + "ACCEPT"); + _ipxtables_call(AF_INET, + "--table", + "filter", + "--append", + chain_forward, + "--source", + str_subnet, + "--in-interface", + ip_iface, + "--jump", + "ACCEPT"); + _ipxtables_call(AF_INET, + "--table", + "filter", + "--append", + chain_forward, + "--in-interface", + ip_iface, + "--out-interface", + ip_iface, + "--jump", + "ACCEPT"); + _ipxtables_call(AF_INET, + "--table", + "filter", + "--append", + chain_forward, + "--out-interface", + ip_iface, + "--jump", + "REJECT"); + _ipxtables_call(AF_INET, + "--table", + "filter", + "--append", + chain_forward, + "--in-interface", + ip_iface, + "--jump", + "REJECT"); } static void @@ -377,36 +389,38 @@ _share_iptables_set_shared_sync(gboolean up, const char *ip_iface, in_addr_t add gs_free char *chain_input = NULL; gs_free char *chain_forward = NULL; - comment_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface); - chain_input = _share_iptables_get_name(TRUE, "nm-sh-in", ip_iface); - chain_forward = _share_iptables_get_name(TRUE, "nm-sh-fw", ip_iface); + comment_name = _iptables_get_name(FALSE, "nm-shared", ip_iface); + chain_input = _iptables_get_name(TRUE, "nm-sh-in", ip_iface); + chain_forward = _iptables_get_name(TRUE, "nm-sh-fw", ip_iface); if (up) _share_iptables_set_shared_chains_add(chain_input, chain_forward, ip_iface, addr, plen); - _share_iptables_call("--table", - "filter", - up ? "--insert" : "--delete", - "INPUT", - "--in-interface", - ip_iface, - "--jump", - chain_input, - "-m", - "comment", - "--comment", - comment_name); + _ipxtables_call(AF_INET, + "--table", + "filter", + up ? "--insert" : "--delete", + "INPUT", + "--in-interface", + ip_iface, + "--jump", + chain_input, + "-m", + "comment", + "--comment", + comment_name); - _share_iptables_call("--table", - "filter", - up ? "--insert" : "--delete", - "FORWARD", - "--jump", - chain_forward, - "-m", - "comment", - "--comment", - comment_name); + _ipxtables_call(AF_INET, + "--table", + "filter", + up ? "--insert" : "--delete", + "FORWARD", + "--jump", + chain_forward, + "-m", + "comment", + "--comment", + comment_name); if (!up) _share_iptables_set_shared_chains_delete(chain_input, chain_forward); @@ -460,19 +474,19 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user /* on any error, the process might still be running. We need to abort it in * the background... */ if (!nm_utils_error_is_cancelled(error)) { - nm_log_dbg(LOGD_SHARING, + nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: communication failed: %s. Kill process", call_data->identifier, error->message); } else if (!call_data->timeout_source) { - nm_log_dbg(LOGD_SHARING, - "firewall: ntf[%s]: communication timed out. Kill process", + nm_log_dbg(LOGD_FIREWALL, + "firewall: nft[%s]: communication timed out. Kill process", call_data->identifier); nm_clear_error(&error); nm_utils_error_set(&error, NM_UTILS_ERROR_UNKNOWN, "timeout communicating with nft"); } else { - nm_log_dbg(LOGD_SHARING, - "firewall: ntf[%s]: communication cancelled. Kill process", + nm_log_dbg(LOGD_FIREWALL, + "firewall: nft[%s]: communication cancelled. Kill process", call_data->identifier); } @@ -485,7 +499,7 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user nm_g_subprocess_terminate_in_background(call_data->subprocess, 200); } } else if (g_subprocess_get_successful(call_data->subprocess)) { - nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: command successful", call_data->identifier); + nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: command successful", call_data->identifier); } else { char buf[NM_UTILS_GET_PROCESS_EXIT_STATUS_BUF_LEN]; gs_free char *ss_stdout = NULL; @@ -498,7 +512,7 @@ _fw_nft_call_communicate_cb(GObject *source, GAsyncResult *result, gpointer user nm_utils_get_process_exit_status_desc_buf(status, buf, sizeof(buf)); - nm_log_warn(LOGD_SHARING, + nm_log_warn(LOGD_FIREWALL, "firewall: nft[%s]: command %s:%s%s%s%s%s%s%s", call_data->identifier, buf, @@ -534,7 +548,7 @@ _fw_nft_call_cancelled_cb(GCancellable *cancellable, gpointer user_data) if (call_data->cancellable_id == 0) return; - nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: operation cancelled", call_data->identifier); + nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: operation cancelled", call_data->identifier); nm_clear_g_signal_handler(g_task_get_cancellable(call_data->task), &call_data->cancellable_id); nm_clear_g_cancellable(&call_data->intern_cancellable); @@ -546,7 +560,7 @@ _fw_nft_call_timeout_cb(gpointer user_data) FwNftCallData *call_data = user_data; nm_clear_g_source_inst(&call_data->timeout_source); - nm_log_dbg(LOGD_SHARING, + nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: cancel operation after timeout", call_data->identifier); @@ -573,7 +587,7 @@ nm_firewall_nft_call(GBytes *stdin_buf, .timeout_source = NULL, }; - nm_log_trace(LOGD_SHARING, + nm_log_trace(LOGD_FIREWALL, "firewall: nft: call command: [ '%s' ]", nm_utils_buf_utf8safe_escape_bytes(stdin_buf, NM_UTILS_STR_UTF8_SAFE_FLAG_ESCAPE_CTRL, @@ -585,7 +599,7 @@ nm_firewall_nft_call(GBytes *stdin_buf, call_data, NULL); if (call_data->cancellable_id == 0) { - nm_log_dbg(LOGD_SHARING, "firewall: nft: already cancelled"); + nm_log_dbg(LOGD_FIREWALL, "firewall: nft: already cancelled"); nm_utils_error_set_cancelled(&error, FALSE, NULL); _fw_nft_call_data_free(call_data, g_steal_pointer(&error)); return; @@ -602,14 +616,14 @@ nm_firewall_nft_call(GBytes *stdin_buf, &error); if (!call_data->subprocess) { - nm_log_dbg(LOGD_SHARING, "firewall: nft: spawning nft failed: %s", error->message); + nm_log_dbg(LOGD_FIREWALL, "firewall: nft: spawning nft failed: %s", error->message); _fw_nft_call_data_free(call_data, g_steal_pointer(&error)); return; } call_data->identifier = g_strdup(g_subprocess_get_identifier(call_data->subprocess)); - nm_log_dbg(LOGD_SHARING, "firewall: nft[%s]: communicate with nft", call_data->identifier); + nm_log_dbg(LOGD_FIREWALL, "firewall: nft[%s]: communicate with nft", call_data->identifier); nm_shutdown_wait_obj_register_object(call_data->task, "nft-call"); @@ -691,7 +705,7 @@ _fw_nft_set_shared_construct(gboolean up, const char *ip_iface, in_addr_t addr, gs_free char *table_name = NULL; char str_subnet[_SHARE_IPTABLES_SUBNET_TO_STR_LEN]; - table_name = _share_iptables_get_name(FALSE, "nm-shared", ip_iface); + table_name = _iptables_get_name(FALSE, "nm-shared", ip_iface); _share_iptables_subnet_to_str(str_subnet, addr, plen); @@ -756,6 +770,141 @@ _fw_nft_set_shared_construct(gboolean up, const char *ip_iface, in_addr_t addr, return nm_str_buf_finalize_to_gbytes(&strbuf); } +static GBytes * +_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; + + table_name = _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; " + " meta l4proto udp meta mark set ct mark; " + "};", + family_str, + table_name); + + _append(&strbuf, + "add chain %s %s postmangle {" + " type filter hook postrouting priority mangle; policy accept; " + " meta l4proto udp mark 0x%08x ct mark set meta mark; " + "};", + family_str, + table_name, + fwmark); + } + + return nm_str_buf_finalize_to_gbytes(&strbuf); +} + +static void +_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 = _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", + up ? "--insert" : "--delete", + "POSTROUTING", + "--match", + "mark", + "--mark", + fwmark_str, + "--protocol", + "udp", + "--jump", + "CONNMARK", + "--save-mark", + "-m", + "comment", + "--comment", + comment_name); + + _ipxtables_call(family, + "--table", + "mangle", + up ? "--insert" : "--delete", + "PREROUTING", + "--protocol", + "udp", + "--jump", + "CONNMARK", + "--restore-mark", + "-m", + "comment", + "--comment", + comment_name); +} + /*****************************************************************************/ GBytes * @@ -1046,6 +1195,31 @@ nm_firewall_config_free(NMFirewallConfig *self) } /*****************************************************************************/ +void +nm_firewall_config_set_wg_rule(const char *ifname, + NMSettingIPConfig *ip_config, + int fwmark, + gboolean up) +{ + 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, ip_config, fwmark, up); + _fw_nft_call_sync(stdin_buf, NULL); + break; + } + case NM_FIREWALL_BACKEND_IPTABLES: + _fw_iptables_wg_configure(ifname, ip_config, fwmark, up); + break; + case NM_FIREWALL_BACKEND_NONE: + break; + default: + nm_assert_not_reached(); + break; + } +} void nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up) @@ -1124,7 +1298,7 @@ again: if (!g_atomic_int_compare_and_exchange(&backend, NM_FIREWALL_BACKEND_UNKNOWN, b)) goto again; - nm_log_dbg(LOGD_SHARING, + nm_log_dbg(LOGD_FIREWALL, "firewall: use %s backend%s%s%s%s%s%s%s", FirewallBackends[b - 1].name, NM_PRINT_FMT_QUOTED(FirewallBackends[b - 1].path, diff --git a/src/core/nm-firewall-utils.h b/src/core/nm-firewall-utils.h index 9f13a5127e..4df33d11db 100644 --- a/src/core/nm-firewall-utils.h +++ b/src/core/nm-firewall-utils.h @@ -24,6 +24,11 @@ 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, + NMSettingIPConfig *ip_config, + int fwmark, + gboolean up); + void nm_firewall_config_apply_sync(NMFirewallConfig *self, gboolean up); /*****************************************************************************/ diff --git a/src/core/tests/test-core.c b/src/core/tests/test-core.c index 2ff41f0067..e08296c20f 100644 --- a/src/core/tests/test-core.c +++ b/src/core/tests/test-core.c @@ -36,6 +36,7 @@ test_config_h(void) G_STMT_END ABSOLUTE_PATH(IPTABLES_PATH); + ABSOLUTE_PATH(IP6TABLES_PATH); ABSOLUTE_PATH(NFT_PATH); }