mirror of
https://github.com/Ysurac/openmptcprouter.git
synced 2025-03-09 15:40:20 +00:00
Add nft fullcone support
This commit is contained in:
parent
d9b6c05d1e
commit
3feeae5315
6 changed files with 921 additions and 0 deletions
76
6.1/package/libs/libnftnl/Makefile
Normal file
76
6.1/package/libs/libnftnl/Makefile
Normal file
|
@ -0,0 +1,76 @@
|
||||||
|
#
|
||||||
|
# Copyright (C) 2014 OpenWrt.org
|
||||||
|
#
|
||||||
|
# This is free software, licensed under the GNU General Public License v2.
|
||||||
|
# See /LICENSE for more information.
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=libnftnl
|
||||||
|
PKG_CPE_ID:=cpe:/a:netfilter:libnftnl
|
||||||
|
PKG_VERSION:=1.2.5
|
||||||
|
PKG_RELEASE:=2
|
||||||
|
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||||
|
PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files
|
||||||
|
PKG_HASH:=966de0a8120c8a53db859889749368bfb2cba0c4f0b4c1a30d264eccc45f1226
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=Steven Barth <steven@midlink.org>
|
||||||
|
PKG_LICENSE:=GPL-2.0-or-later
|
||||||
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
PKG_BUILD_PARALLEL:=1
|
||||||
|
PKG_BUILD_FLAGS:=lto
|
||||||
|
PKG_FIXUP:=autoreconf
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
DISABLE_NLS:=
|
||||||
|
|
||||||
|
define Package/libnftnl
|
||||||
|
SECTION:=libs
|
||||||
|
CATEGORY:=Libraries
|
||||||
|
DEPENDS:=+libmnl
|
||||||
|
TITLE:=Low-level netlink library for the nf_tables subsystem
|
||||||
|
URL:=http://www.netfilter.org/projects/libnftnl
|
||||||
|
ABI_VERSION:=11
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/libnftnl/description
|
||||||
|
libnftnl is a userspace library providing a low-level netlink
|
||||||
|
programming interface (API) to the in-kernel nf_tables subsystem.
|
||||||
|
endef
|
||||||
|
|
||||||
|
TARGET_CFLAGS += $(FPIC)
|
||||||
|
|
||||||
|
CONFIGURE_ARGS += \
|
||||||
|
--enable-static \
|
||||||
|
--enable-shared
|
||||||
|
|
||||||
|
define Build/InstallDev
|
||||||
|
$(INSTALL_DIR) $(1)/usr/include/libnftnl
|
||||||
|
$(CP) \
|
||||||
|
$(PKG_INSTALL_DIR)/usr/include/libnftnl/*.h \
|
||||||
|
$(1)/usr/include/libnftnl/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) \
|
||||||
|
$(PKG_INSTALL_DIR)/usr/lib/libnftnl.{so*,a,la} \
|
||||||
|
$(1)/usr/lib/
|
||||||
|
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
|
||||||
|
$(CP) \
|
||||||
|
$(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libnftnl.pc \
|
||||||
|
$(1)/usr/lib/pkgconfig/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/libnftnl/install
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) \
|
||||||
|
$(PKG_INSTALL_DIR)/usr/lib/libnftnl.so.* \
|
||||||
|
$(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,libnftnl))
|
|
@ -0,0 +1,267 @@
|
||||||
|
From 6c39f04febd7cfdbd474233379416babcd0fc341 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
Date: Fri, 8 Apr 2022 23:52:11 +0800
|
||||||
|
Subject: [PATCH] libnftnl: add fullcone expression support
|
||||||
|
|
||||||
|
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
---
|
||||||
|
include/libnftnl/expr.h | 6 +
|
||||||
|
include/linux/netfilter/nf_tables.h | 16 +++
|
||||||
|
src/Makefile.am | 1 +
|
||||||
|
src/expr/fullcone.c | 167 ++++++++++++++++++++++++++++
|
||||||
|
src/expr_ops.c | 2 +
|
||||||
|
5 files changed, 192 insertions(+)
|
||||||
|
create mode 100644 src/expr/fullcone.c
|
||||||
|
|
||||||
|
diff --git a/include/libnftnl/expr.h b/include/libnftnl/expr.h
|
||||||
|
index 00c63ab..7dcf403 100644
|
||||||
|
--- a/include/libnftnl/expr.h
|
||||||
|
+++ b/include/libnftnl/expr.h
|
||||||
|
@@ -244,6 +244,12 @@ enum {
|
||||||
|
NFTNL_EXPR_MASQ_REG_PROTO_MAX,
|
||||||
|
};
|
||||||
|
|
||||||
|
+enum {
|
||||||
|
+ NFTNL_EXPR_FULLCONE_FLAGS = NFTNL_EXPR_BASE,
|
||||||
|
+ NFTNL_EXPR_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ NFTNL_EXPR_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
enum {
|
||||||
|
NFTNL_EXPR_REDIR_REG_PROTO_MIN = NFTNL_EXPR_BASE,
|
||||||
|
NFTNL_EXPR_REDIR_REG_PROTO_MAX,
|
||||||
|
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
|
||||||
|
index 0ae9120..8b8ae38 100644
|
||||||
|
--- a/include/linux/netfilter/nf_tables.h
|
||||||
|
+++ b/include/linux/netfilter/nf_tables.h
|
||||||
|
@@ -1433,6 +1433,22 @@ enum nft_masq_attributes {
|
||||||
|
};
|
||||||
|
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * enum nft_fullcone_attributes - nf_tables fullcone expression attributes
|
||||||
|
+ *
|
||||||
|
+ * @NFTA_FULLCONE_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
|
||||||
|
+ */
|
||||||
|
+enum nft_fullcone_attributes {
|
||||||
|
+ NFTA_FULLCONE_UNSPEC,
|
||||||
|
+ NFTA_FULLCONE_FLAGS,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+ __NFTA_FULLCONE_MAX
|
||||||
|
+};
|
||||||
|
+#define NFTA_FULLCONE_MAX (__NFTA_FULLCONE_MAX - 1)
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* enum nft_redir_attributes - nf_tables redirect expression netlink attributes
|
||||||
|
*
|
||||||
|
diff --git a/src/Makefile.am b/src/Makefile.am
|
||||||
|
index c3b0ab9..2718218 100644
|
||||||
|
--- a/src/Makefile.am
|
||||||
|
+++ b/src/Makefile.am
|
||||||
|
@@ -54,6 +54,7 @@ libnftnl_la_SOURCES = utils.c \
|
||||||
|
expr/target.c \
|
||||||
|
expr/tunnel.c \
|
||||||
|
expr/masq.c \
|
||||||
|
+ expr/fullcone.c \
|
||||||
|
expr/redir.c \
|
||||||
|
expr/hash.c \
|
||||||
|
expr/socket.c \
|
||||||
|
diff --git a/src/expr/fullcone.c b/src/expr/fullcone.c
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..aaedd83
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/src/expr/fullcone.c
|
||||||
|
@@ -0,0 +1,167 @@
|
||||||
|
+/*
|
||||||
|
+ * (C) 2022 wongsyrone
|
||||||
|
+ *
|
||||||
|
+ * This program is free software; you can redistribute it and/or modify
|
||||||
|
+ * it under the terms of the GNU General Public License as published
|
||||||
|
+ * by the Free Software Foundation; either version 2 of the License, or
|
||||||
|
+ * (at your option) any later version.
|
||||||
|
+ */
|
||||||
|
+
|
||||||
|
+#include <stdio.h>
|
||||||
|
+#include <stdint.h>
|
||||||
|
+#include <arpa/inet.h>
|
||||||
|
+#include <errno.h>
|
||||||
|
+#include <inttypes.h>
|
||||||
|
+
|
||||||
|
+#include <linux/netfilter/nf_tables.h>
|
||||||
|
+
|
||||||
|
+#include "internal.h"
|
||||||
|
+#include <libmnl/libmnl.h>
|
||||||
|
+#include <libnftnl/expr.h>
|
||||||
|
+#include <libnftnl/rule.h>
|
||||||
|
+
|
||||||
|
+struct nftnl_expr_fullcone {
|
||||||
|
+ uint32_t flags;
|
||||||
|
+ enum nft_registers sreg_proto_min;
|
||||||
|
+ enum nft_registers sreg_proto_max;
|
||||||
|
+};
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+nftnl_expr_fullcone_set(struct nftnl_expr *e, uint16_t type,
|
||||||
|
+ const void *data, uint32_t data_len)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_FLAGS:
|
||||||
|
+ memcpy(&fullcone->flags, data, sizeof(fullcone->flags));
|
||||||
|
+ break;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MIN:
|
||||||
|
+ memcpy(&fullcone->sreg_proto_min, data, sizeof(fullcone->sreg_proto_min));
|
||||||
|
+ break;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MAX:
|
||||||
|
+ memcpy(&fullcone->sreg_proto_max, data, sizeof(fullcone->sreg_proto_max));
|
||||||
|
+ break;
|
||||||
|
+ default:
|
||||||
|
+ return -1;
|
||||||
|
+ }
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static const void *
|
||||||
|
+nftnl_expr_fullcone_get(const struct nftnl_expr *e, uint16_t type,
|
||||||
|
+ uint32_t *data_len)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_FLAGS:
|
||||||
|
+ *data_len = sizeof(fullcone->flags);
|
||||||
|
+ return &fullcone->flags;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MIN:
|
||||||
|
+ *data_len = sizeof(fullcone->sreg_proto_min);
|
||||||
|
+ return &fullcone->sreg_proto_min;
|
||||||
|
+ case NFTNL_EXPR_FULLCONE_REG_PROTO_MAX:
|
||||||
|
+ *data_len = sizeof(fullcone->sreg_proto_max);
|
||||||
|
+ return &fullcone->sreg_proto_max;
|
||||||
|
+ }
|
||||||
|
+ return NULL;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int nftnl_expr_fullcone_cb(const struct nlattr *attr, void *data)
|
||||||
|
+{
|
||||||
|
+ const struct nlattr **tb = data;
|
||||||
|
+ int type = mnl_attr_get_type(attr);
|
||||||
|
+
|
||||||
|
+ if (mnl_attr_type_valid(attr, NFTA_FULLCONE_MAX) < 0)
|
||||||
|
+ return MNL_CB_OK;
|
||||||
|
+
|
||||||
|
+ switch (type) {
|
||||||
|
+ case NFTA_FULLCONE_REG_PROTO_MIN:
|
||||||
|
+ case NFTA_FULLCONE_REG_PROTO_MAX:
|
||||||
|
+ case NFTA_FULLCONE_FLAGS:
|
||||||
|
+ if (mnl_attr_validate(attr, MNL_TYPE_U32) < 0)
|
||||||
|
+ abi_breakage();
|
||||||
|
+ break;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ tb[type] = attr;
|
||||||
|
+ return MNL_CB_OK;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static void
|
||||||
|
+nftnl_expr_fullcone_build(struct nlmsghdr *nlh, const struct nftnl_expr *e)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_FLAGS))
|
||||||
|
+ mnl_attr_put_u32(nlh, NFTA_FULLCONE_FLAGS, htobe32(fullcone->flags));
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MIN))
|
||||||
|
+ mnl_attr_put_u32(nlh, NFTA_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ htobe32(fullcone->sreg_proto_min));
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MAX))
|
||||||
|
+ mnl_attr_put_u32(nlh, NFTA_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+ htobe32(fullcone->sreg_proto_max));
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int
|
||||||
|
+nftnl_expr_fullcone_parse(struct nftnl_expr *e, struct nlattr *attr)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+ struct nlattr *tb[NFTA_FULLCONE_MAX+1] = {};
|
||||||
|
+
|
||||||
|
+ if (mnl_attr_parse_nested(attr, nftnl_expr_fullcone_cb, tb) < 0)
|
||||||
|
+ return -1;
|
||||||
|
+
|
||||||
|
+ if (tb[NFTA_FULLCONE_FLAGS]) {
|
||||||
|
+ fullcone->flags = be32toh(mnl_attr_get_u32(tb[NFTA_FULLCONE_FLAGS]));
|
||||||
|
+ e->flags |= (1 << NFTNL_EXPR_FULLCONE_FLAGS);
|
||||||
|
+ }
|
||||||
|
+ if (tb[NFTA_FULLCONE_REG_PROTO_MIN]) {
|
||||||
|
+ fullcone->sreg_proto_min =
|
||||||
|
+ be32toh(mnl_attr_get_u32(tb[NFTA_FULLCONE_REG_PROTO_MIN]));
|
||||||
|
+ e->flags |= (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MIN);
|
||||||
|
+ }
|
||||||
|
+ if (tb[NFTA_FULLCONE_REG_PROTO_MAX]) {
|
||||||
|
+ fullcone->sreg_proto_max =
|
||||||
|
+ be32toh(mnl_attr_get_u32(tb[NFTA_FULLCONE_REG_PROTO_MAX]));
|
||||||
|
+ e->flags |= (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MAX);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return 0;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+static int nftnl_expr_fullcone_snprintf(char *buf, size_t remain,
|
||||||
|
+ uint32_t flags, const struct nftnl_expr *e)
|
||||||
|
+{
|
||||||
|
+ struct nftnl_expr_fullcone *fullcone = nftnl_expr_data(e);
|
||||||
|
+ int offset = 0, ret = 0;
|
||||||
|
+
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MIN)) {
|
||||||
|
+ ret = snprintf(buf + offset, remain, "proto_min reg %u ",
|
||||||
|
+ fullcone->sreg_proto_min);
|
||||||
|
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
|
||||||
|
+ }
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_REG_PROTO_MAX)) {
|
||||||
|
+ ret = snprintf(buf + offset, remain, "proto_max reg %u ",
|
||||||
|
+ fullcone->sreg_proto_max);
|
||||||
|
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
|
||||||
|
+ }
|
||||||
|
+ if (e->flags & (1 << NFTNL_EXPR_FULLCONE_FLAGS)) {
|
||||||
|
+ ret = snprintf(buf + offset, remain, "flags 0x%x ", fullcone->flags);
|
||||||
|
+ SNPRINTF_BUFFER_SIZE(ret, remain, offset);
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ return offset;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
+struct expr_ops expr_ops_fullcone = {
|
||||||
|
+ .name = "fullcone",
|
||||||
|
+ .alloc_len = sizeof(struct nftnl_expr_fullcone),
|
||||||
|
+ .max_attr = NFTA_FULLCONE_MAX,
|
||||||
|
+ .set = nftnl_expr_fullcone_set,
|
||||||
|
+ .get = nftnl_expr_fullcone_get,
|
||||||
|
+ .parse = nftnl_expr_fullcone_parse,
|
||||||
|
+ .build = nftnl_expr_fullcone_build,
|
||||||
|
+ .output = nftnl_expr_fullcone_snprintf,
|
||||||
|
+};
|
||||||
|
diff --git a/src/expr_ops.c b/src/expr_ops.c
|
||||||
|
index 7248e4f..9dee9f8 100644
|
||||||
|
--- a/src/expr_ops.c
|
||||||
|
+++ b/src/expr_ops.c
|
||||||
|
@@ -19,6 +19,7 @@ extern struct expr_ops expr_ops_limit;
|
||||||
|
extern struct expr_ops expr_ops_log;
|
||||||
|
extern struct expr_ops expr_ops_lookup;
|
||||||
|
extern struct expr_ops expr_ops_masq;
|
||||||
|
+extern struct expr_ops expr_ops_fullcone;
|
||||||
|
extern struct expr_ops expr_ops_match;
|
||||||
|
extern struct expr_ops expr_ops_meta;
|
||||||
|
extern struct expr_ops expr_ops_ng;
|
||||||
|
@@ -63,6 +64,7 @@ static struct expr_ops *expr_ops[] = {
|
||||||
|
&expr_ops_log,
|
||||||
|
&expr_ops_lookup,
|
||||||
|
&expr_ops_masq,
|
||||||
|
+ &expr_ops_fullcone,
|
||||||
|
&expr_ops_match,
|
||||||
|
&expr_ops_meta,
|
||||||
|
&expr_ops_ng,
|
||||||
|
--
|
||||||
|
2.35.1
|
||||||
|
|
|
@ -0,0 +1,22 @@
|
||||||
|
--- a/root/usr/share/firewall4/templates/ruleset.uc 2023-07-28 18:55:05.492297782 +0200
|
||||||
|
+++ b/root/usr/share/firewall4/templates/ruleset.uc 2023-07-28 18:58:52.300598623 +0200
|
||||||
|
@@ -218,9 +218,7 @@
|
||||||
|
{% for (let rule in fw4.rules(`input_${zone.name}`)): %}
|
||||||
|
{%+ include("rule.uc", { fw4, rule }) %}
|
||||||
|
{% endfor %}
|
||||||
|
-{% if (zone.dflags.dnat): %}
|
||||||
|
ct status dnat accept comment "!fw4: Accept port redirections"
|
||||||
|
-{% endif %}
|
||||||
|
{% fw4.includes('chain-append', `input_${zone.name}`) %}
|
||||||
|
jump {{ zone.input }}_from_{{ zone.name }}
|
||||||
|
}
|
||||||
|
@@ -239,9 +237,7 @@
|
||||||
|
{% for (let rule in fw4.rules(`forward_${zone.name}`)): %}
|
||||||
|
{%+ include("rule.uc", { fw4, rule }) %}
|
||||||
|
{% endfor %}
|
||||||
|
-{% if (zone.dflags.dnat): %}
|
||||||
|
ct status dnat accept comment "!fw4: Accept port forwards"
|
||||||
|
-{% endif %}
|
||||||
|
{% fw4.includes('chain-append', `forward_${zone.name}`) %}
|
||||||
|
jump {{ zone.forward }}_to_{{ zone.name }}
|
||||||
|
{% if (fw4.forward_policy() != "accept" && (zone.log & 1)): %}
|
|
@ -0,0 +1,248 @@
|
||||||
|
From d4081c498ddca184578903fe5199d390bbc0707b Mon Sep 17 00:00:00 2001
|
||||||
|
From: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
Date: Sat, 9 Apr 2022 13:24:19 +0800
|
||||||
|
Subject: [PATCH] firewall4: add fullcone support
|
||||||
|
|
||||||
|
fullcone is drop-in replacement of masq for non-udp traffic
|
||||||
|
|
||||||
|
add runtime fullcone rule check, disable it globally if fullcone expr is
|
||||||
|
invalid
|
||||||
|
|
||||||
|
defaults.fullcone is the global switch, while zone.fullcone4 and
|
||||||
|
zone.fullcone6 are switches for IPv4 and IPv6 respectively, most
|
||||||
|
IPv6 traffic do NOT need this FullCone NAT functionality.
|
||||||
|
---
|
||||||
|
root/etc/config/firewall | 3 +
|
||||||
|
root/usr/share/firewall4/templates/ruleset.uc | 16 +++-
|
||||||
|
.../firewall4/templates/zone-fullcone.uc | 4 +
|
||||||
|
root/usr/share/ucode/fw4.uc | 76 ++++++++++++++++++-
|
||||||
|
4 files changed, 96 insertions(+), 3 deletions(-)
|
||||||
|
create mode 100644 root/usr/share/firewall4/templates/zone-fullcone.uc
|
||||||
|
|
||||||
|
diff --git a/root/etc/config/firewall b/root/etc/config/firewall
|
||||||
|
index b9a4647..7187723 100644
|
||||||
|
--- a/root/etc/config/firewall
|
||||||
|
+++ b/root/etc/config/firewall
|
||||||
|
@@ -5,6 +5,7 @@ config defaults
|
||||||
|
option forward REJECT
|
||||||
|
# Uncomment this line to disable ipv6 rules
|
||||||
|
# option disable_ipv6 1
|
||||||
|
+ option fullcone '1'
|
||||||
|
|
||||||
|
config zone
|
||||||
|
option name lan
|
||||||
|
@@ -20,6 +21,8 @@ config zone
|
||||||
|
option input REJECT
|
||||||
|
option output ACCEPT
|
||||||
|
option forward REJECT
|
||||||
|
+ option fullcone4 '1'
|
||||||
|
+ option fullcone6 '1'
|
||||||
|
option masq 1
|
||||||
|
option mtu_fix 1
|
||||||
|
|
||||||
|
diff --git a/root/usr/share/firewall4/templates/ruleset.uc b/root/usr/share/firewall4/templates/ruleset.uc
|
||||||
|
index eaa1f04..e29eae6 100644
|
||||||
|
--- a/root/usr/share/firewall4/templates/ruleset.uc
|
||||||
|
+++ b/root/usr/share/firewall4/templates/ruleset.uc
|
||||||
|
@@ -310,6 +310,12 @@ table inet fw4 {
|
||||||
|
{% for (let redirect in fw4.redirects(`dstnat_${zone.name}`)): %}
|
||||||
|
{%+ include("redirect.uc", { fw4, redirect }) %}
|
||||||
|
{% endfor %}
|
||||||
|
+{% if (zone.fullcone4): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 4, direction: "dstnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
+{% if (zone.fullcone6): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 6, direction: "dstnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
{% fw4.includes('chain-append', `dstnat_${zone.name}`) %}
|
||||||
|
}
|
||||||
|
|
||||||
|
@@ -320,20 +326,26 @@ table inet fw4 {
|
||||||
|
{% for (let redirect in fw4.redirects(`srcnat_${zone.name}`)): %}
|
||||||
|
{%+ include("redirect.uc", { fw4, redirect }) %}
|
||||||
|
{% endfor %}
|
||||||
|
-{% if (zone.masq): %}
|
||||||
|
+{% if (zone.masq && !zone.fullcone4): %}
|
||||||
|
{% for (let saddrs in zone.masq4_src_subnets): %}
|
||||||
|
{% for (let daddrs in zone.masq4_dest_subnets): %}
|
||||||
|
{%+ include("zone-masq.uc", { fw4, zone, family: 4, saddrs, daddrs }) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
-{% if (zone.masq6): %}
|
||||||
|
+{% if (zone.masq6 && !zone.fullcone6): %}
|
||||||
|
{% for (let saddrs in zone.masq6_src_subnets): %}
|
||||||
|
{% for (let daddrs in zone.masq6_dest_subnets): %}
|
||||||
|
{%+ include("zone-masq.uc", { fw4, zone, family: 6, saddrs, daddrs }) %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endfor %}
|
||||||
|
{% endif %}
|
||||||
|
+{% if (zone.fullcone4): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 4, direction: "srcnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
+{% if (zone.fullcone6): %}
|
||||||
|
+ {%+ include("zone-fullcone.uc", { fw4, zone, family: 6, direction: "srcnat" }) %}
|
||||||
|
+{% endif %}
|
||||||
|
{% fw4.includes('chain-append', `srcnat_${zone.name}`) %}
|
||||||
|
}
|
||||||
|
|
||||||
|
diff --git a/root/usr/share/firewall4/templates/zone-fullcone.uc b/root/usr/share/firewall4/templates/zone-fullcone.uc
|
||||||
|
new file mode 100644
|
||||||
|
index 0000000..77d9806
|
||||||
|
--- /dev/null
|
||||||
|
+++ b/root/usr/share/firewall4/templates/zone-fullcone.uc
|
||||||
|
@@ -0,0 +1,4 @@
|
||||||
|
+{# /usr/share/firewall4/templates/zone-fullcone.uc #}
|
||||||
|
+ meta nfproto {{ fw4.nfproto(family) }} fullcone comment "!fw4: Handle {{
|
||||||
|
+ zone.name
|
||||||
|
+}} {{ fw4.nfproto(family, true) }} fullcone NAT {{ direction }} traffic"
|
||||||
|
diff --git a/root/usr/share/ucode/fw4.uc b/root/usr/share/ucode/fw4.uc
|
||||||
|
index 1b4764c..c5716da 100644
|
||||||
|
--- a/root/usr/share/ucode/fw4.uc
|
||||||
|
+++ b/root/usr/share/ucode/fw4.uc
|
||||||
|
@@ -1,3 +1,5 @@
|
||||||
|
+// /usr/share/ucode/fw4.uc
|
||||||
|
+
|
||||||
|
const fs = require("fs");
|
||||||
|
const uci = require("uci");
|
||||||
|
const ubus = require("ubus");
|
||||||
|
@@ -428,6 +430,25 @@ function nft_try_hw_offload(devices) {
|
||||||
|
return (rc == 0);
|
||||||
|
}
|
||||||
|
|
||||||
|
+function nft_try_fullcone() {
|
||||||
|
+ let nft_test =
|
||||||
|
+ 'add table inet fw4-fullcone-test; ' +
|
||||||
|
+ 'add chain inet fw4-fullcone-test dstnat { ' +
|
||||||
|
+ 'type nat hook prerouting priority -100; policy accept; ' +
|
||||||
|
+ 'fullcone; ' +
|
||||||
|
+ '}; ' +
|
||||||
|
+ 'add chain inet fw4-fullcone-test srcnat { ' +
|
||||||
|
+ 'type nat hook postrouting priority -100; policy accept; ' +
|
||||||
|
+ 'fullcone; ' +
|
||||||
|
+ '}; ';
|
||||||
|
+ let cmd = sprintf("/usr/sbin/nft -c '%s' 2>/dev/null", replace(nft_test, "'", "'\\''"));
|
||||||
|
+ let ok = system(cmd) == 0;
|
||||||
|
+ if (!ok) {
|
||||||
|
+ warn("nft_try_fullcone: cmd "+ cmd + "\n");
|
||||||
|
+ }
|
||||||
|
+ return ok;
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
|
||||||
|
return {
|
||||||
|
read_kernel_version: function() {
|
||||||
|
@@ -765,6 +786,18 @@ return {
|
||||||
|
warn(`[!] ${msg}\n`);
|
||||||
|
},
|
||||||
|
|
||||||
|
+ myinfo: function(fmt, ...args) {
|
||||||
|
+ if (getenv("QUIET"))
|
||||||
|
+ return;
|
||||||
|
+
|
||||||
|
+ let msg = sprintf(fmt, ...args);
|
||||||
|
+
|
||||||
|
+ if (getenv("TTY"))
|
||||||
|
+ warn(`\033[32m${msg}\033[m\n`);
|
||||||
|
+ else
|
||||||
|
+ warn(`[I] ${msg}\n`);
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
get: function(sid, opt) {
|
||||||
|
return this.cursor.get("firewall", sid, opt);
|
||||||
|
},
|
||||||
|
@@ -946,6 +979,21 @@ return {
|
||||||
|
}
|
||||||
|
},
|
||||||
|
|
||||||
|
+ myinfo_section: function(s, msg) {
|
||||||
|
+ if (s[".name"]) {
|
||||||
|
+ if (s.name)
|
||||||
|
+ this.myinfo("Section %s (%s) %s", this.section_id(s[".name"]), s.name, msg);
|
||||||
|
+ else
|
||||||
|
+ this.myinfo("Section %s %s", this.section_id(s[".name"]), msg);
|
||||||
|
+ }
|
||||||
|
+ else {
|
||||||
|
+ if (s.name)
|
||||||
|
+ this.myinfo("ubus %s (%s) %s", s.type || "rule", s.name, msg);
|
||||||
|
+ else
|
||||||
|
+ this.myinfo("ubus %s %s", s.type || "rule", msg);
|
||||||
|
+ }
|
||||||
|
+ },
|
||||||
|
+
|
||||||
|
parse_policy: function(val) {
|
||||||
|
return this.parse_enum(val, [
|
||||||
|
"accept",
|
||||||
|
@@ -1385,6 +1433,7 @@ return {
|
||||||
|
"dnat",
|
||||||
|
"snat",
|
||||||
|
"masquerade",
|
||||||
|
+ "fullcone",
|
||||||
|
"accept",
|
||||||
|
"reject",
|
||||||
|
"drop"
|
||||||
|
@@ -1852,6 +1901,7 @@ return {
|
||||||
|
}
|
||||||
|
|
||||||
|
let defs = this.parse_options(data, {
|
||||||
|
+ fullcone: [ "bool", "0" ],
|
||||||
|
input: [ "policy", "drop" ],
|
||||||
|
output: [ "policy", "drop" ],
|
||||||
|
forward: [ "policy", "drop" ],
|
||||||
|
@@ -1884,6 +1934,11 @@ return {
|
||||||
|
|
||||||
|
delete defs.syn_flood;
|
||||||
|
|
||||||
|
+ if (!nft_try_fullcone()) {
|
||||||
|
+ delete defs.fullcone;
|
||||||
|
+ warn("nft_try_fullcone failed, disable fullcone globally\n");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
this.state.defaults = defs;
|
||||||
|
},
|
||||||
|
|
||||||
|
@@ -1908,6 +1963,8 @@ return {
|
||||||
|
masq_dest: [ "network", null, PARSE_LIST ],
|
||||||
|
|
||||||
|
masq6: [ "bool" ],
|
||||||
|
+ fullcone4: [ "bool", "0" ],
|
||||||
|
+ fullcone6: [ "bool", "0" ],
|
||||||
|
|
||||||
|
extra: [ "string", null, UNSUPPORTED ],
|
||||||
|
extra_src: [ "string", null, UNSUPPORTED ],
|
||||||
|
@@ -1940,6 +1997,18 @@ return {
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
+ if (this.state.defaults && !this.state.defaults.fullcone) {
|
||||||
|
+ this.warn_section(data, "fullcone in defaults not enabled, ignore zone fullcone settings");
|
||||||
|
+ zone.fullcone4 = false;
|
||||||
|
+ zone.fullcone6 = false;
|
||||||
|
+ }
|
||||||
|
+ if (zone.fullcone4) {
|
||||||
|
+ this.myinfo_section(data, "IPv4 fullcone enabled for zone '" + zone.name + "'");
|
||||||
|
+ }
|
||||||
|
+ if (zone.fullcone6) {
|
||||||
|
+ this.myinfo_section(data, "IPv6 fullcone enabled for zone '" + zone.name + "'");
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (zone.mtu_fix && this.kernel < 0x040a0000) {
|
||||||
|
this.warn_section(data, "option 'mtu_fix' requires kernel 4.10 or later");
|
||||||
|
return;
|
||||||
|
@@ -2110,10 +2179,15 @@ return {
|
||||||
|
zone.related_subnets = related_subnets;
|
||||||
|
zone.related_physdevs = related_physdevs;
|
||||||
|
|
||||||
|
+ if (zone.fullcone4 || zone.fullcone6) {
|
||||||
|
+ zone.dflags.snat = true;
|
||||||
|
+ zone.dflags.dnat = true;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
if (zone.masq || zone.masq6)
|
||||||
|
zone.dflags.snat = true;
|
||||||
|
|
||||||
|
- if ((zone.auto_helper && !(zone.masq || zone.masq6)) || length(zone.helper)) {
|
||||||
|
+ if ((zone.auto_helper && !(zone.masq || zone.masq6 || zone.fullcone4 || zone.fullcone6)) || length(zone.helper)) {
|
||||||
|
zone.dflags.helper = true;
|
||||||
|
|
||||||
|
for (let helper in (length(zone.helper) ? zone.helper : this.state.helpers)) {
|
85
6.1/package/network/utils/nftables/Makefile
Normal file
85
6.1/package/network/utils/nftables/Makefile
Normal file
|
@ -0,0 +1,85 @@
|
||||||
|
# SPDX-License-Identifier: GPL-2.0-only
|
||||||
|
#
|
||||||
|
# Copyright (C) 2015 OpenWrt.org
|
||||||
|
#
|
||||||
|
|
||||||
|
include $(TOPDIR)/rules.mk
|
||||||
|
|
||||||
|
PKG_NAME:=nftables
|
||||||
|
PKG_VERSION:=1.0.7
|
||||||
|
PKG_RELEASE:=1
|
||||||
|
|
||||||
|
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.xz
|
||||||
|
PKG_SOURCE_URL:=https://netfilter.org/projects/$(PKG_NAME)/files
|
||||||
|
PKG_HASH:=c12ac941fff9adaedf17367d5ce213789b98a0d314277bc22b3d71e10891f412
|
||||||
|
|
||||||
|
PKG_MAINTAINER:=
|
||||||
|
PKG_LICENSE:=GPL-2.0
|
||||||
|
PKG_LICENSE_FILES:=COPYING
|
||||||
|
|
||||||
|
PKG_FIXUP:=autoreconf
|
||||||
|
PKG_INSTALL:=1
|
||||||
|
|
||||||
|
PKG_BUILD_FLAGS:=lto
|
||||||
|
|
||||||
|
include $(INCLUDE_DIR)/package.mk
|
||||||
|
|
||||||
|
DISABLE_NLS:=
|
||||||
|
|
||||||
|
CONFIGURE_ARGS += \
|
||||||
|
--disable-debug \
|
||||||
|
--disable-man-doc \
|
||||||
|
--with-mini-gmp \
|
||||||
|
--without-cli \
|
||||||
|
--disable-python
|
||||||
|
|
||||||
|
define Package/nftables/Default
|
||||||
|
SECTION:=net
|
||||||
|
CATEGORY:=Network
|
||||||
|
SUBMENU:=Firewall
|
||||||
|
TITLE:=nftables userspace utility
|
||||||
|
DEPENDS:=+kmod-nft-core +libnftnl
|
||||||
|
URL:=http://netfilter.org/projects/nftables/
|
||||||
|
PROVIDES:=nftables
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/nftables-nojson
|
||||||
|
$(Package/nftables/Default)
|
||||||
|
TITLE+= no JSON support
|
||||||
|
VARIANT:=nojson
|
||||||
|
DEFAULT_VARIANT:=1
|
||||||
|
CONFLICTS:=nftables-json
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/nftables-json
|
||||||
|
$(Package/nftables/Default)
|
||||||
|
TITLE+= with JSON support
|
||||||
|
VARIANT:=json
|
||||||
|
DEPENDS+=+jansson
|
||||||
|
endef
|
||||||
|
|
||||||
|
ifeq ($(BUILD_VARIANT),json)
|
||||||
|
CONFIGURE_ARGS += --with-json
|
||||||
|
endif
|
||||||
|
|
||||||
|
define Build/InstallDev
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib $(1)/usr/include
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/include/nftables $(1)/usr/include/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib/pkgconfig
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/pkgconfig/libnftables.pc \
|
||||||
|
$(1)/usr/lib/pkgconfig/
|
||||||
|
endef
|
||||||
|
|
||||||
|
define Package/nftables/install/Default
|
||||||
|
$(INSTALL_DIR) $(1)/usr/sbin
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/sbin/nft $(1)/usr/sbin/
|
||||||
|
$(INSTALL_DIR) $(1)/usr/lib
|
||||||
|
$(CP) $(PKG_INSTALL_DIR)/usr/lib/*.so* $(1)/usr/lib/
|
||||||
|
endef
|
||||||
|
|
||||||
|
Package/nftables-nojson/install = $(Package/nftables/install/Default)
|
||||||
|
Package/nftables-json/install = $(Package/nftables/install/Default)
|
||||||
|
|
||||||
|
$(eval $(call BuildPackage,nftables-nojson))
|
||||||
|
$(eval $(call BuildPackage,nftables-json))
|
|
@ -0,0 +1,223 @@
|
||||||
|
From 58c89e8768711a959fdc6e953df3ea2254ff93c1 Mon Sep 17 00:00:00 2001
|
||||||
|
From: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
Date: Sat, 9 Apr 2022 00:38:51 +0800
|
||||||
|
Subject: [PATCH] nftables: add fullcone expression support
|
||||||
|
|
||||||
|
Signed-off-by: Syrone Wong <wong.syrone@gmail.com>
|
||||||
|
---
|
||||||
|
include/linux/netfilter/nf_tables.h | 16 ++++++++++
|
||||||
|
include/statement.h | 1 +
|
||||||
|
src/netlink_delinearize.c | 48 +++++++++++++++++++++++++++++
|
||||||
|
src/netlink_linearize.c | 7 +++++
|
||||||
|
src/parser_bison.y | 28 +++++++++++++++--
|
||||||
|
src/scanner.l | 1 +
|
||||||
|
src/statement.c | 1 +
|
||||||
|
7 files changed, 100 insertions(+), 2 deletions(-)
|
||||||
|
|
||||||
|
diff --git a/include/linux/netfilter/nf_tables.h b/include/linux/netfilter/nf_tables.h
|
||||||
|
index 75df968..beab9d8 100644
|
||||||
|
--- a/include/linux/netfilter/nf_tables.h
|
||||||
|
+++ b/include/linux/netfilter/nf_tables.h
|
||||||
|
@@ -1409,6 +1409,22 @@ enum nft_masq_attributes {
|
||||||
|
};
|
||||||
|
#define NFTA_MASQ_MAX (__NFTA_MASQ_MAX - 1)
|
||||||
|
|
||||||
|
+/**
|
||||||
|
+ * enum nft_fullcone_attributes - nf_tables fullcone expression attributes
|
||||||
|
+ *
|
||||||
|
+ * @NFTA_FULLCONE_FLAGS: NAT flags (see NF_NAT_RANGE_* in linux/netfilter/nf_nat.h) (NLA_U32)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MIN: source register of proto range start (NLA_U32: nft_registers)
|
||||||
|
+ * @NFTA_FULLCONE_REG_PROTO_MAX: source register of proto range end (NLA_U32: nft_registers)
|
||||||
|
+ */
|
||||||
|
+enum nft_fullcone_attributes {
|
||||||
|
+ NFTA_FULLCONE_UNSPEC,
|
||||||
|
+ NFTA_FULLCONE_FLAGS,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MIN,
|
||||||
|
+ NFTA_FULLCONE_REG_PROTO_MAX,
|
||||||
|
+ __NFTA_FULLCONE_MAX
|
||||||
|
+};
|
||||||
|
+#define NFTA_FULLCONE_MAX (__NFTA_FULLCONE_MAX - 1)
|
||||||
|
+
|
||||||
|
/**
|
||||||
|
* enum nft_redir_attributes - nf_tables redirect expression netlink attributes
|
||||||
|
*
|
||||||
|
diff --git a/include/statement.h b/include/statement.h
|
||||||
|
index 2a2d300..cbd48dd 100644
|
||||||
|
--- a/include/statement.h
|
||||||
|
+++ b/include/statement.h
|
||||||
|
@@ -122,6 +122,7 @@ enum nft_nat_etypes {
|
||||||
|
__NFT_NAT_SNAT = NFT_NAT_SNAT,
|
||||||
|
__NFT_NAT_DNAT = NFT_NAT_DNAT,
|
||||||
|
NFT_NAT_MASQ,
|
||||||
|
+ NFT_NAT_FULLCONE,
|
||||||
|
NFT_NAT_REDIR,
|
||||||
|
};
|
||||||
|
|
||||||
|
diff --git a/src/netlink_delinearize.c b/src/netlink_delinearize.c
|
||||||
|
index 068c3bb..8513113 100644
|
||||||
|
--- a/src/netlink_delinearize.c
|
||||||
|
+++ b/src/netlink_delinearize.c
|
||||||
|
@@ -1369,6 +1369,53 @@ static void netlink_parse_masq(struct netlink_parse_ctx *ctx,
|
||||||
|
stmt_free(stmt);
|
||||||
|
}
|
||||||
|
|
||||||
|
+static void netlink_parse_fullcone(struct netlink_parse_ctx *ctx,
|
||||||
|
+ const struct location *loc,
|
||||||
|
+ const struct nftnl_expr *nle)
|
||||||
|
+{
|
||||||
|
+ enum nft_registers reg1, reg2;
|
||||||
|
+ struct expr *proto;
|
||||||
|
+ struct stmt *stmt;
|
||||||
|
+ uint32_t flags = 0;
|
||||||
|
+
|
||||||
|
+ if (nftnl_expr_is_set(nle, NFTNL_EXPR_FULLCONE_FLAGS))
|
||||||
|
+ flags = nftnl_expr_get_u32(nle, NFTNL_EXPR_FULLCONE_FLAGS);
|
||||||
|
+
|
||||||
|
+ stmt = nat_stmt_alloc(loc, NFT_NAT_FULLCONE);
|
||||||
|
+ stmt->nat.flags = flags;
|
||||||
|
+
|
||||||
|
+ reg1 = netlink_parse_register(nle, NFTNL_EXPR_FULLCONE_REG_PROTO_MIN);
|
||||||
|
+ if (reg1) {
|
||||||
|
+ proto = netlink_get_register(ctx, loc, reg1);
|
||||||
|
+ if (proto == NULL) {
|
||||||
|
+ netlink_error(ctx, loc,
|
||||||
|
+ "fullcone statement has no proto expression");
|
||||||
|
+ goto out_err;
|
||||||
|
+ }
|
||||||
|
+ expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
|
||||||
|
+ stmt->nat.proto = proto;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ reg2 = netlink_parse_register(nle, NFTNL_EXPR_FULLCONE_REG_PROTO_MAX);
|
||||||
|
+ if (reg2 && reg2 != reg1) {
|
||||||
|
+ proto = netlink_get_register(ctx, loc, reg2);
|
||||||
|
+ if (proto == NULL) {
|
||||||
|
+ netlink_error(ctx, loc,
|
||||||
|
+ "fullcone statement has no proto expression");
|
||||||
|
+ goto out_err;
|
||||||
|
+ }
|
||||||
|
+ expr_set_type(proto, &inet_service_type, BYTEORDER_BIG_ENDIAN);
|
||||||
|
+ if (stmt->nat.proto != NULL)
|
||||||
|
+ proto = range_expr_alloc(loc, stmt->nat.proto, proto);
|
||||||
|
+ stmt->nat.proto = proto;
|
||||||
|
+ }
|
||||||
|
+
|
||||||
|
+ ctx->stmt = stmt;
|
||||||
|
+ return;
|
||||||
|
+out_err:
|
||||||
|
+ stmt_free(stmt);
|
||||||
|
+}
|
||||||
|
+
|
||||||
|
static void netlink_parse_redir(struct netlink_parse_ctx *ctx,
|
||||||
|
const struct location *loc,
|
||||||
|
const struct nftnl_expr *nle)
|
||||||
|
@@ -1787,6 +1834,7 @@ static const struct expr_handler netlink_parsers[] = {
|
||||||
|
{ .name = "tproxy", .parse = netlink_parse_tproxy },
|
||||||
|
{ .name = "notrack", .parse = netlink_parse_notrack },
|
||||||
|
{ .name = "masq", .parse = netlink_parse_masq },
|
||||||
|
+ { .name = "fullcone", .parse = netlink_parse_fullcone },
|
||||||
|
{ .name = "redir", .parse = netlink_parse_redir },
|
||||||
|
{ .name = "dup", .parse = netlink_parse_dup },
|
||||||
|
{ .name = "queue", .parse = netlink_parse_queue },
|
||||||
|
diff --git a/src/netlink_linearize.c b/src/netlink_linearize.c
|
||||||
|
index c8bbcb7..505eafa 100644
|
||||||
|
--- a/src/netlink_linearize.c
|
||||||
|
+++ b/src/netlink_linearize.c
|
||||||
|
@@ -1140,6 +1140,13 @@ static void netlink_gen_nat_stmt(struct netlink_linearize_ctx *ctx,
|
||||||
|
nftnl_reg_pmin = NFTNL_EXPR_MASQ_REG_PROTO_MIN;
|
||||||
|
nftnl_reg_pmax = NFTNL_EXPR_MASQ_REG_PROTO_MAX;
|
||||||
|
break;
|
||||||
|
+ case NFT_NAT_FULLCONE:
|
||||||
|
+ nle = alloc_nft_expr("fullcone");
|
||||||
|
+
|
||||||
|
+ nftnl_flag_attr = NFTNL_EXPR_FULLCONE_FLAGS;
|
||||||
|
+ nftnl_reg_pmin = NFTNL_EXPR_FULLCONE_REG_PROTO_MIN;
|
||||||
|
+ nftnl_reg_pmax = NFTNL_EXPR_FULLCONE_REG_PROTO_MAX;
|
||||||
|
+ break;
|
||||||
|
case NFT_NAT_REDIR:
|
||||||
|
nle = alloc_nft_expr("redir");
|
||||||
|
|
||||||
|
diff --git a/src/parser_bison.y b/src/parser_bison.y
|
||||||
|
index ca5c488..ec9fc9b 100644
|
||||||
|
--- a/src/parser_bison.y
|
||||||
|
+++ b/src/parser_bison.y
|
||||||
|
@@ -571,6 +571,7 @@ int nft_lex(void *, void *, void *);
|
||||||
|
%token SNAT "snat"
|
||||||
|
%token DNAT "dnat"
|
||||||
|
%token MASQUERADE "masquerade"
|
||||||
|
+%token FULLCONE "fullcone"
|
||||||
|
%token REDIRECT "redirect"
|
||||||
|
%token RANDOM "random"
|
||||||
|
%token FULLY_RANDOM "fully-random"
|
||||||
|
@@ -703,8 +704,8 @@ int nft_lex(void *, void *, void *);
|
||||||
|
%type <val> limit_burst_pkts limit_burst_bytes limit_mode limit_bytes time_unit quota_mode
|
||||||
|
%type <stmt> reject_stmt reject_stmt_alloc
|
||||||
|
%destructor { stmt_free($$); } reject_stmt reject_stmt_alloc
|
||||||
|
-%type <stmt> nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
-%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
+%type <stmt> nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc fullcone_stmt fullcone_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
+%destructor { stmt_free($$); } nat_stmt nat_stmt_alloc masq_stmt masq_stmt_alloc fullcone_stmt fullcone_stmt_alloc redir_stmt redir_stmt_alloc
|
||||||
|
%type <val> nf_nat_flags nf_nat_flag offset_opt
|
||||||
|
%type <stmt> tproxy_stmt
|
||||||
|
%destructor { stmt_free($$); } tproxy_stmt
|
||||||
|
@@ -2853,6 +2854,7 @@ stmt : verdict_stmt
|
||||||
|
| queue_stmt
|
||||||
|
| ct_stmt
|
||||||
|
| masq_stmt close_scope_nat
|
||||||
|
+ | fullcone_stmt close_scope_nat
|
||||||
|
| redir_stmt close_scope_nat
|
||||||
|
| dup_stmt close_scope_dup
|
||||||
|
| fwd_stmt close_scope_fwd
|
||||||
|
@@ -3753,6 +3755,28 @@ masq_stmt_args : TO COLON stmt_expr
|
||||||
|
}
|
||||||
|
;
|
||||||
|
|
||||||
|
+fullcone_stmt : fullcone_stmt_alloc fullcone_stmt_args
|
||||||
|
+ | fullcone_stmt_alloc
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+fullcone_stmt_alloc : FULLCONE { $$ = nat_stmt_alloc(&@$, NFT_NAT_FULLCONE); }
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
+fullcone_stmt_args : TO COLON stmt_expr
|
||||||
|
+ {
|
||||||
|
+ $<stmt>0->nat.proto = $3;
|
||||||
|
+ }
|
||||||
|
+ | TO COLON stmt_expr nf_nat_flags
|
||||||
|
+ {
|
||||||
|
+ $<stmt>0->nat.proto = $3;
|
||||||
|
+ $<stmt>0->nat.flags = $4;
|
||||||
|
+ }
|
||||||
|
+ | nf_nat_flags
|
||||||
|
+ {
|
||||||
|
+ $<stmt>0->nat.flags = $1;
|
||||||
|
+ }
|
||||||
|
+ ;
|
||||||
|
+
|
||||||
|
redir_stmt : redir_stmt_alloc redir_stmt_arg
|
||||||
|
| redir_stmt_alloc
|
||||||
|
;
|
||||||
|
diff --git a/src/scanner.l b/src/scanner.l
|
||||||
|
index 2154281..c389860 100644
|
||||||
|
--- a/src/scanner.l
|
||||||
|
+++ b/src/scanner.l
|
||||||
|
@@ -453,6 +453,7 @@ addrstring ({macaddr}|{ip4addr}|{ip6addr})
|
||||||
|
"snat" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return SNAT; }
|
||||||
|
"dnat" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return DNAT; }
|
||||||
|
"masquerade" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return MASQUERADE; }
|
||||||
|
+"fullcone" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return FULLCONE; }
|
||||||
|
"redirect" { scanner_push_start_cond(yyscanner, SCANSTATE_STMT_NAT); return REDIRECT; }
|
||||||
|
"random" { return RANDOM; }
|
||||||
|
<SCANSTATE_STMT_NAT>{
|
||||||
|
diff --git a/src/statement.c b/src/statement.c
|
||||||
|
index 30caf9c..f4866c2 100644
|
||||||
|
--- a/src/statement.c
|
||||||
|
+++ b/src/statement.c
|
||||||
|
@@ -650,6 +650,7 @@ const char *nat_etype2str(enum nft_nat_etypes type)
|
||||||
|
[NFT_NAT_SNAT] = "snat",
|
||||||
|
[NFT_NAT_DNAT] = "dnat",
|
||||||
|
[NFT_NAT_MASQ] = "masquerade",
|
||||||
|
+ [NFT_NAT_FULLCONE] = "fullcone",
|
||||||
|
[NFT_NAT_REDIR] = "redirect",
|
||||||
|
};
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue