git: b6c90b909905 - main - ipfw : Enable support for EIM NAT

From: Tom Jones <thj_at_FreeBSD.org>
Date: Fri, 06 Dec 2024 09:19:32 UTC
The branch main has been updated by thj:

URL: https://cgit.FreeBSD.org/src/commit/?id=b6c90b909905a48c6f8ad027ff259e64d5d0e762

commit b6c90b909905a48c6f8ad027ff259e64d5d0e762
Author:     Damjan Jovanovic <damjan.jov@gmail.com>
AuthorDate: 2024-12-06 09:17:34 +0000
Commit:     Tom Jones <thj@FreeBSD.org>
CommitDate: 2024-12-06 09:18:09 +0000

    ipfw : Enable support for EIM NAT
    
    Enable support for endpoint-independent mapping ("full cone NAT") via
    Libalias's UDP NAT.
    
    Reviewed by:    igoro, thj
    Differential Revision:  https://reviews.freebsd.org/D46689D
---
 sbin/ipfw/ipfw.8  | 22 +++++++++++++++++++++-
 sbin/ipfw/ipfw2.h |  1 +
 sbin/ipfw/main.c  |  2 +-
 sbin/ipfw/nat.c   |  8 ++++++++
 4 files changed, 31 insertions(+), 2 deletions(-)

diff --git a/sbin/ipfw/ipfw.8 b/sbin/ipfw/ipfw.8
index 715d8580f1ce..bc78ae1c655b 100644
--- a/sbin/ipfw/ipfw.8
+++ b/sbin/ipfw/ipfw.8
@@ -1,5 +1,5 @@
 .\"
-.Dd December 17, 2023
+.Dd December 6, 2024
 .Dt IPFW 8
 .Os
 .Sh NAME
@@ -3403,6 +3403,26 @@ Skip instance in case of global state lookup (see below).
 .It Cm port_range Ar lower-upper
 Set the aliasing ports between the ranges given.
 Upper port has to be greater than lower.
+.It Cm udp_eim
+When enabled, UDP packets use endpoint-independent mapping (EIM) from RFC 4787
+("full cone" NAT of RFC 3489).
+All packets from the same internal address:port are mapped to the same NAT
+address:port, regardless of their destination address:port.
+If filtering rules allow, and if
+.Em deny_in
+is unset, any other external address:port can
+also send to the internal address:port through its mapped NAT address:port.
+This is more compatible with applications, and can reduce the need for port
+forwarding, but less scalable as each NAT address:port can only be
+concurrently used by at most one internal address:port.
+.Pp
+When disabled, UDP packets use endpoint-dependent mapping (EDM) ("symmetric"
+NAT).
+Each connection from a particular internal address:port to different
+external addresses:ports is mapped to a random and unpredictable NAT
+address:port.
+Two appplications behind EDM NATs can only connect to each other
+by port forwarding on the NAT, or tunnelling through an in-between server.
 .El
 .Pp
 Some special values can be supplied instead of
diff --git a/sbin/ipfw/ipfw2.h b/sbin/ipfw/ipfw2.h
index 2137719296f9..0c0bf32e94d6 100644
--- a/sbin/ipfw/ipfw2.h
+++ b/sbin/ipfw/ipfw2.h
@@ -324,6 +324,7 @@ enum tokens {
 	TOK_SETMARK,
 
 	TOK_SKIPACTION,
+	TOK_UDP_EIM,
 };
 
 /*
diff --git a/sbin/ipfw/main.c b/sbin/ipfw/main.c
index 1e5f4fbafc1d..92c593f4f09e 100644
--- a/sbin/ipfw/main.c
+++ b/sbin/ipfw/main.c
@@ -43,7 +43,7 @@ help(void)
 "add [num] [set N] [prob x] RULE-BODY\n"
 "{pipe|queue} N config PIPE-BODY\n"
 "[pipe|queue] {zero|delete|show} [N{,N}]\n"
-"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|unreg_cgn|\n"
+"nat N config {ip IPADDR|if IFNAME|log|deny_in|same_ports|unreg_only|unreg_cgn|udp_eim|\n"
 "		reset|reverse|proxy_only|redirect_addr linkspec|\n"
 "		redirect_port linkspec|redirect_proto linkspec|\n"
 "		port_range lower-upper}\n"
diff --git a/sbin/ipfw/nat.c b/sbin/ipfw/nat.c
index a96da30c9f8b..db74abaab233 100644
--- a/sbin/ipfw/nat.c
+++ b/sbin/ipfw/nat.c
@@ -67,6 +67,7 @@ static struct _s_x nat_params[] = {
 	{ "redirect_addr",	TOK_REDIR_ADDR },
 	{ "redirect_port",	TOK_REDIR_PORT },
 	{ "redirect_proto",	TOK_REDIR_PROTO },
+	{ "udp_eim",		TOK_UDP_EIM },
  	{ NULL, 0 }	/* terminator */
 };
 
@@ -676,6 +677,9 @@ nat_show_cfg(struct nat44_cfg_nat *n, void *arg __unused)
 		} else if (n->mode & PKT_ALIAS_PROXY_ONLY) {
 			printf(" proxy_only");
 			n->mode &= ~PKT_ALIAS_PROXY_ONLY;
+		} else if (n->mode & PKT_ALIAS_UDP_EIM) {
+			printf(" udp_eim");
+			n->mode &= ~PKT_ALIAS_UDP_EIM;
 		}
 	}
 	/* Print all the redirect's data configuration. */
@@ -821,6 +825,7 @@ ipfw_config_nat(int ac, char **av)
 		case TOK_RESET_ADDR:
 		case TOK_ALIAS_REV:
 		case TOK_PROXY_ONLY:
+		case TOK_UDP_EIM:
 			break;
 		case TOK_REDIR_ADDR:
 			if (ac1 < 2)
@@ -927,6 +932,9 @@ ipfw_config_nat(int ac, char **av)
 		case TOK_PROXY_ONLY:
 			n->mode |= PKT_ALIAS_PROXY_ONLY;
 			break;
+		case TOK_UDP_EIM:
+			n->mode |= PKT_ALIAS_UDP_EIM;
+			break;
 			/*
 			 * All the setup_redir_* functions work directly in
 			 * the final buffer, see above for details.