summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--net/Makefile2
-rw-r--r--net/amnezia-kmod/Makefile23
-rw-r--r--net/amnezia-kmod/distinfo3
-rw-r--r--net/amnezia-kmod/files/patch-Makefile9
-rw-r--r--net/amnezia-kmod/files/patch-if__wg.c173
-rw-r--r--net/amnezia-kmod/pkg-descr15
-rw-r--r--net/amnezia-tools/Makefile37
-rw-r--r--net/amnezia-tools/distinfo3
-rw-r--r--net/amnezia-tools/files/amnezia.in79
-rw-r--r--net/amnezia-tools/files/patch-config.c50
-rw-r--r--net/amnezia-tools/files/patch-containers.h21
-rw-r--r--net/amnezia-tools/files/patch-ipc-freebsd.h27
-rw-r--r--net/amnezia-tools/files/patch-ipc-uapi.h11
-rw-r--r--net/amnezia-tools/files/patch-man_wg.824
-rw-r--r--net/amnezia-tools/files/patch-set.c11
-rw-r--r--net/amnezia-tools/files/patch-version.h7
-rw-r--r--net/amnezia-tools/files/patch-wg-quick_freebsd.bash316
-rw-r--r--net/amnezia-tools/pkg-descr2
-rw-r--r--net/amnezia-tools/pkg-plist7
19 files changed, 820 insertions, 0 deletions
diff --git a/net/Makefile b/net/Makefile
index be8657450469..7663a6f56a42 100644
--- a/net/Makefile
+++ b/net/Makefile
@@ -17,6 +17,8 @@
SUBDIR += akonadi-search
SUBDIR += alligator
SUBDIR += aluminum
+ SUBDIR += amnezia-kmod
+ SUBDIR += amnezia-tools
SUBDIR += amqpcat
SUBDIR += aoe
SUBDIR += apache-commons-net
diff --git a/net/amnezia-kmod/Makefile b/net/amnezia-kmod/Makefile
new file mode 100644
index 000000000000..8e6d734dd4ed
--- /dev/null
+++ b/net/amnezia-kmod/Makefile
@@ -0,0 +1,23 @@
+PORTNAME= amnezia
+PORTVERSION= 1.0.8
+DISTVERSIONPREFIX= v
+CATEGORIES= net net-vpn
+PKGNAMESUFFIX= -kmod
+
+MAINTAINER= vova@zote.me
+COMMENT= Amnezia VPN FreeBSD kernel module implementation
+WWW= https://docs.amnezia.org/documentation/amnezia-wg
+
+LICENSE= MIT
+LICENSE_FILE= ${WRKSRC}/COPYING
+
+BROKEN_FreeBSD_13= depends on kernel sources of recent FreeBSD 14 or newer
+
+USES= kmod uidfix
+USE_GITHUB= yes
+GH_ACCOUNT= vgrebenschikov
+GH_PROJECT= wireguard-amnezia-kmod
+
+PLIST_FILES= ${KMODDIR}/if_amn.ko
+
+.include <bsd.port.mk>
diff --git a/net/amnezia-kmod/distinfo b/net/amnezia-kmod/distinfo
new file mode 100644
index 000000000000..1e206f9cefcc
--- /dev/null
+++ b/net/amnezia-kmod/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1753648668
+SHA256 (vgrebenschikov-wireguard-amnezia-kmod-v1.0.8_GH0.tar.gz) = 5045cfe0f0f6d58c2c6f5103f2f5b4238b7f59f33ca6f0a8b516762ead7ba7eb
+SIZE (vgrebenschikov-wireguard-amnezia-kmod-v1.0.8_GH0.tar.gz) = 57959
diff --git a/net/amnezia-kmod/files/patch-Makefile b/net/amnezia-kmod/files/patch-Makefile
new file mode 100644
index 000000000000..aa9e5f9b5c09
--- /dev/null
+++ b/net/amnezia-kmod/files/patch-Makefile
@@ -0,0 +1,9 @@
+--- Makefile.orig 2025-07-22 17:42:41 UTC
++++ Makefile
+@@ -1,5 +1,5 @@
+
+-KMOD= if_wg
++KMOD= if_amn
+
+ SRCS= if_wg.c wg_cookie.c wg_crypto.c wg_noise.c
+ SRCS+= opt_inet.h opt_inet6.h device_if.h bus_if.h
diff --git a/net/amnezia-kmod/files/patch-if__wg.c b/net/amnezia-kmod/files/patch-if__wg.c
new file mode 100644
index 000000000000..9dd13ffb9054
--- /dev/null
+++ b/net/amnezia-kmod/files/patch-if__wg.c
@@ -0,0 +1,173 @@
+--- if_wg.c.orig 2025-07-22 17:38:01 UTC
++++ if_wg.c
+@@ -278,21 +278,21 @@ static volatile unsigned long peer_counter = 0;
+ static int clone_count;
+ static uma_zone_t wg_packet_zone;
+ static volatile unsigned long peer_counter = 0;
+-static const char wgname[] = "wg";
++static const char wgname[] = "amn";
+ static unsigned wg_osd_jail_slot;
+
+ static struct sx wg_sx;
+-SX_SYSINIT(wg_sx, &wg_sx, "wg_sx");
++SX_SYSINIT(wg_sx, &wg_sx, "amn_sx");
+
+ static LIST_HEAD(, wg_softc) wg_list = LIST_HEAD_INITIALIZER(wg_list);
+
+ static TASKQGROUP_DEFINE(wg_tqg, mp_ncpus, 1);
+
+-MALLOC_DEFINE(M_WG, "WG", "wireguard");
++MALLOC_DEFINE(M_WG, "amn", "amnezia");
+
+-VNET_DEFINE_STATIC(struct if_clone *, wg_cloner);
++VNET_DEFINE_STATIC(struct if_clone *, amn_cloner);
+
+-#define V_wg_cloner VNET(wg_cloner)
++#define V_amn_cloner VNET(amn_cloner)
+ #define WG_CAPS IFCAP_LINKSTATE
+
+ struct wg_timespec64 {
+@@ -386,10 +386,10 @@ static int wg_ioctl(if_t, u_long, caddr_t);
+ static void wg_reassign(if_t, struct vnet *, char *unused);
+ static void wg_init(void *);
+ static int wg_ioctl(if_t, u_long, caddr_t);
+-static void vnet_wg_init(const void *);
+-static void vnet_wg_uninit(const void *);
+-static int wg_module_init(void);
+-static void wg_module_deinit(void);
++static void vnet_amn_init(const void *);
++static void vnet_amn_uninit(const void *);
++static int amn_module_init(void);
++static void amn_module_deinit(void);
+
+ /* TODO Peer */
+ static struct wg_peer *
+@@ -408,7 +408,7 @@ wg_peer_alloc(struct wg_softc *sc, const uint8_t pub_k
+
+ cookie_maker_init(&peer->p_cookie, pub_key);
+
+- rw_init(&peer->p_endpoint_lock, "wg_peer_endpoint");
++ rw_init(&peer->p_endpoint_lock, "amn_peer_endpoint");
+
+ wg_queue_init(&peer->p_stage_queue, "stageq");
+ wg_queue_init(&peer->p_encrypt_serial, "txq");
+@@ -428,9 +428,9 @@ wg_peer_alloc(struct wg_softc *sc, const uint8_t pub_k
+ peer->p_handshake_retries = 0;
+
+ GROUPTASK_INIT(&peer->p_send, 0, (gtask_fn_t *)wg_deliver_out, peer);
+- taskqgroup_attach(qgroup_wg_tqg, &peer->p_send, peer, NULL, NULL, "wg send");
++ taskqgroup_attach(qgroup_wg_tqg, &peer->p_send, peer, NULL, NULL, "amn send");
+ GROUPTASK_INIT(&peer->p_recv, 0, (gtask_fn_t *)wg_deliver_in, peer);
+- taskqgroup_attach(qgroup_wg_tqg, &peer->p_recv, peer, NULL, NULL, "wg recv");
++ taskqgroup_attach(qgroup_wg_tqg, &peer->p_recv, peer, NULL, NULL, "amn recv");
+
+ LIST_INIT(&peer->p_aips);
+ peer->p_aips_num = 0;
+@@ -3286,26 +3286,26 @@ static void
+ }
+
+ static void
+-vnet_wg_init(const void *unused __unused)
++vnet_amn_init(const void *unused __unused)
+ {
+ struct if_clone_addreq req = {
+ .create_f = wg_clone_create,
+ .destroy_f = wg_clone_destroy,
+ .flags = IFC_F_AUTOUNIT,
+ };
+- V_wg_cloner = ifc_attach_cloner(wgname, &req);
++ V_amn_cloner = ifc_attach_cloner(wgname, &req);
+ }
+-VNET_SYSINIT(vnet_wg_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+- vnet_wg_init, NULL);
++VNET_SYSINIT(vnet_amn_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
++ vnet_amn_init, NULL);
+
+ static void
+-vnet_wg_uninit(const void *unused __unused)
++vnet_amn_uninit(const void *unused __unused)
+ {
+- if (V_wg_cloner)
+- ifc_detach_cloner(V_wg_cloner);
++ if (V_amn_cloner)
++ ifc_detach_cloner(V_amn_cloner);
+ }
+-VNET_SYSUNINIT(vnet_wg_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
+- vnet_wg_uninit, NULL);
++VNET_SYSUNINIT(vnet_amn_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY,
++ vnet_amn_uninit, NULL);
+
+ static int
+ wg_prison_remove(void *obj, void *data __unused)
+@@ -3352,14 +3352,14 @@ static int
+ #endif
+
+ static int
+-wg_module_init(void)
++amn_module_init(void)
+ {
+ int ret;
+ osd_method_t methods[PR_MAXMETHOD] = {
+ [PR_METHOD_REMOVE] = wg_prison_remove,
+ };
+
+- wg_packet_zone = uma_zcreate("wg packet", sizeof(struct wg_packet),
++ wg_packet_zone = uma_zcreate("amn packet", sizeof(struct wg_packet),
+ NULL, NULL, NULL, NULL, 0, 0);
+
+ ret = crypto_init();
+@@ -3378,15 +3378,15 @@ static void
+ }
+
+ static void
+-wg_module_deinit(void)
++amn_module_deinit(void)
+ {
+ VNET_ITERATOR_DECL(vnet_iter);
+ VNET_LIST_RLOCK();
+ VNET_FOREACH(vnet_iter) {
+- struct if_clone *clone = VNET_VNET(vnet_iter, wg_cloner);
++ struct if_clone *clone = VNET_VNET(vnet_iter, amn_cloner);
+ if (clone) {
+ ifc_detach_cloner(clone);
+- VNET_VNET(vnet_iter, wg_cloner) = NULL;
++ VNET_VNET(vnet_iter, amn_cloner) = NULL;
+ }
+ }
+ VNET_LIST_RUNLOCK();
+@@ -3401,13 +3401,13 @@ static int
+ }
+
+ static int
+-wg_module_event_handler(module_t mod, int what, void *arg)
++amn_module_event_handler(module_t mod, int what, void *arg)
+ {
+ switch (what) {
+ case MOD_LOAD:
+- return wg_module_init();
++ return amn_module_init();
+ case MOD_UNLOAD:
+- wg_module_deinit();
++ amn_module_deinit();
+ break;
+ default:
+ return (EOPNOTSUPP);
+@@ -3415,12 +3415,12 @@ wg_module_event_handler(module_t mod, int what, void *
+ return (0);
+ }
+
+-static moduledata_t wg_moduledata = {
+- "if_wg",
+- wg_module_event_handler,
++static moduledata_t amn_moduledata = {
++ "if_amn",
++ amn_module_event_handler,
+ NULL
+ };
+
+-DECLARE_MODULE(if_wg, wg_moduledata, SI_SUB_PSEUDO, SI_ORDER_ANY);
+-MODULE_VERSION(if_wg, WIREGUARD_VERSION);
+-MODULE_DEPEND(if_wg, crypto, 1, 1, 1);
++DECLARE_MODULE(if_amn, amn_moduledata, SI_SUB_PSEUDO, SI_ORDER_ANY);
++MODULE_VERSION(if_amn, WIREGUARD_VERSION);
++MODULE_DEPEND(if_amn, crypto, 1, 1, 1);
diff --git a/net/amnezia-kmod/pkg-descr b/net/amnezia-kmod/pkg-descr
new file mode 100644
index 000000000000..00d5e020f365
--- /dev/null
+++ b/net/amnezia-kmod/pkg-descr
@@ -0,0 +1,15 @@
+FreeBSD kernel module for Amnezia VPN protocol.
+
+Amnezia VPN is a VPN protocol that is backward compatible with the
+WireGuard VPN protocol. It offers protection against detection by Deep
+Packet Inspection (DPI) systems. At the same time, it retains the
+simplified architecture and high performance.
+
+The Amnezia VPN protocol has issues with detection due to distinctive
+packet signatures. Amnezia addresses this problem by employing advanced
+obfuscation methods, allowing its traffic to blend seamlessly with
+regular internet traffic.
+
+This package provides the FreeBSD kernel module (if_amn.ko)
+implementation for Amnezia VPN, enabling kernel-level support for the
+protocol.
diff --git a/net/amnezia-tools/Makefile b/net/amnezia-tools/Makefile
new file mode 100644
index 000000000000..90565fbc4de6
--- /dev/null
+++ b/net/amnezia-tools/Makefile
@@ -0,0 +1,37 @@
+PORTNAME= amnezia-tools
+PORTVERSION= 1.0.20241018
+CATEGORIES= net net-vpn
+MASTER_SITES= https://github.com/amnezia-vpn/amneziawg-tools/
+
+MAINTAINER= vova@zote.me
+COMMENT= Fast, modern and secure VPN Tunnel with AmneziaVPN anti-detection
+WWW= https://github.com/amnezia-vpn/amneziawg-tools/
+
+LICENSE= GPLv2
+
+RUN_DEPENDS= bash:shells/bash
+
+USES= gmake
+USE_GITHUB= yes
+GH_ACCOUNT= amnezia-vpn
+GH_PROJECT= amneziawg-tools
+GH_TAGNAME= v${PORTVERSION}
+
+WRKSRC_SUBDIR= src
+MAKE_ARGS+= DEBUG=no WITH_BASHCOMPLETION=yes WITH_SYSTEMDUNITS=no
+MAKE_ENV+= MANDIR="${PREFIX}/share/man" \
+ SYSCONFDIR="${PREFIX}/etc"
+
+USE_RC_SUBR= amnezia
+
+.include <bsd.port.options.mk>
+
+post-patch:
+ @${REINPLACE_CMD} -e 's|wg s|awg s|g' \
+ ${WRKSRC}/completion/wg-quick.bash-completion
+
+post-install:
+ @${RMDIR} ${STAGEDIR}${PREFIX}/etc/amnezia/amneziawg
+ ${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/awg
+
+.include <bsd.port.mk>
diff --git a/net/amnezia-tools/distinfo b/net/amnezia-tools/distinfo
new file mode 100644
index 000000000000..3703c8bf36a2
--- /dev/null
+++ b/net/amnezia-tools/distinfo
@@ -0,0 +1,3 @@
+TIMESTAMP = 1744661306
+SHA256 (amnezia-vpn-amneziawg-tools-1.0.20241018-v1.0.20241018_GH0.tar.gz) = 60f1cec1774fb871a2d8dc24e4f731625516d90f663d6e0d2c77d9247222f2f9
+SIZE (amnezia-vpn-amneziawg-tools-1.0.20241018-v1.0.20241018_GH0.tar.gz) = 156259
diff --git a/net/amnezia-tools/files/amnezia.in b/net/amnezia-tools/files/amnezia.in
new file mode 100644
index 000000000000..645f4b9c5563
--- /dev/null
+++ b/net/amnezia-tools/files/amnezia.in
@@ -0,0 +1,79 @@
+#!/bin/sh
+
+# PROVIDE: amnezia
+# REQUIRE: NETWORKING
+# KEYWORD: shutdown
+#
+# amnezia_enable (bool): Set to "YES" to enable amnezia.
+# (default: "NO")
+#
+# amnezia_interfaces (str): List of interfaces to bring up/down
+# on start/stop. (eg: "awg0 awg1")
+# (default: "")
+# amnezia_env (str): Environment variables for the userspace
+# implementation. (eg: "LOG_LEVEL=debug")
+# amnezia_kmod (str): Kernel module to load. (eg: "if_awg")
+# (default: "if_awg", "" - no module)
+# amnezia_confdirs (str): Directory to store the configuration files.
+# (default: "/usr/local/etc/amnezia/amnezia")
+
+. /etc/rc.subr
+
+name=amnezia
+rcvar=amnezia_enable
+extra_commands="reload status"
+
+start_cmd="${name}_start"
+stop_cmd="${name}_stop"
+reload_cmd="${name}_reload"
+status_cmd="${name}_status"
+
+amnezia_start()
+{
+ kmod=${amnezia_kmod:-if_amn}
+ ${amnezia_confdirs:+eval export AWG_QUICK_CONFIG_SEARCH_PATHS="$amnezia_confdirs"}
+ ${amnezia_env:+eval export $amnezia_env}
+ [ -n "${kmod}" ] && kldstat -q -n ${kmod} || kldload -n ${kmod}
+
+ for interface in ${amnezia_interfaces}; do
+ %%PREFIX%%/bin/awg-quick up ${interface}
+ done
+}
+
+amnezia_stop()
+{
+ for interface in ${amnezia_interfaces}; do
+ %%PREFIX%%/bin/awg-quick down ${interface}
+ done
+}
+
+amnezia_reload()
+{
+ ${amnezia_env:+eval export $amnezia_env}
+
+ for interface in ${amnezia_interfaces}; do
+ %%PREFIX%%/bin/awg-quick reload ${interface}
+ done
+}
+
+amnezia_status()
+{
+ ${amnezia_env:+eval export $amnezia_env}
+ amnezia_status="0"
+
+ for interface in ${amnezia_interfaces}; do
+ %%PREFIX%%/bin/awg show ${interface} || amnezia_status="1"
+ done
+
+ return ${amnezia_status}
+}
+
+load_rc_config $name
+
+: ${amnezia_enable="NO"}
+: ${amnezia_interfaces=""}
+: ${amnezia_env=""}
+: ${amnezia_kmod="if_amn"}
+: ${amnezia_confdirs="/usr/local/etc/amnezia"}
+
+run_rc_command "$1"
diff --git a/net/amnezia-tools/files/patch-config.c b/net/amnezia-tools/files/patch-config.c
new file mode 100644
index 000000000000..4e07d978251a
--- /dev/null
+++ b/net/amnezia-tools/files/patch-config.c
@@ -0,0 +1,50 @@
+--- config.c.orig 2024-10-01 13:02:42 UTC
++++ config.c
+@@ -337,6 +337,20 @@ static bool validate_netmask(struct wgallowedip *allow
+ return true;
+ }
+
++static inline void parse_ip_prefix(struct wgpeer *peer, uint32_t *flags, char **mask)
++{
++ /* If the IP is prefixed with either '+' or '-' consider this an
++ * incremental change. Disable WGPEER_REPLACE_ALLOWEDIPS. */
++ switch ((*mask)[0]) {
++ case '-':
++ *flags |= WGALLOWEDIP_REMOVE_ME;
++ /* fall through */
++ case '+':
++ peer->flags &= ~WGPEER_REPLACE_ALLOWEDIPS;
++ ++(*mask);
++ }
++}
++
+ static inline bool parse_allowedips(struct wgpeer *peer, struct wgallowedip **last_allowedip, const char *value)
+ {
+ struct wgallowedip *allowedip = *last_allowedip, *new_allowedip;
+@@ -353,10 +367,18 @@ static inline bool parse_allowedips(struct wgpeer *pee
+ }
+ sep = mutable;
+ while ((mask = strsep(&sep, ","))) {
++ uint32_t flags = 0;
+ unsigned long cidr;
+ char *end, *ip;
+
++ parse_ip_prefix(peer, &flags, &mask);
++
+ saved_entry = strdup(mask);
++ if (!saved_entry) {
++ perror("strdup");
++ free(mutable);
++ return false;
++ }
+ ip = strsep(&mask, "/");
+
+ new_allowedip = calloc(1, sizeof(*new_allowedip));
+@@ -387,6 +409,7 @@ static inline bool parse_allowedips(struct wgpeer *pee
+ else
+ goto err;
+ new_allowedip->cidr = cidr;
++ new_allowedip->flags = flags;
+
+ if (!validate_netmask(new_allowedip))
+ fprintf(stderr, "Warning: AllowedIP has nonzero host part: %s/%s\n", ip, mask);
diff --git a/net/amnezia-tools/files/patch-containers.h b/net/amnezia-tools/files/patch-containers.h
new file mode 100644
index 000000000000..88563f74058a
--- /dev/null
+++ b/net/amnezia-tools/files/patch-containers.h
@@ -0,0 +1,21 @@
+--- containers.h.orig 2024-10-01 13:02:42 UTC
++++ containers.h
+@@ -29,6 +29,10 @@ struct timespec64 {
+ int64_t tv_nsec;
+ };
+
++enum {
++ WGALLOWEDIP_REMOVE_ME = 1U << 0,
++};
++
+ struct wgallowedip {
+ uint16_t family;
+ union {
+@@ -36,6 +40,7 @@ struct wgallowedip {
+ struct in6_addr ip6;
+ };
+ uint8_t cidr;
++ uint32_t flags;
+ struct wgallowedip *next_allowedip;
+ };
+
diff --git a/net/amnezia-tools/files/patch-ipc-freebsd.h b/net/amnezia-tools/files/patch-ipc-freebsd.h
new file mode 100644
index 000000000000..22255c0bcca3
--- /dev/null
+++ b/net/amnezia-tools/files/patch-ipc-freebsd.h
@@ -0,0 +1,27 @@
+--- ipc-freebsd.h.orig 2024-10-01 13:02:42 UTC
++++ ipc-freebsd.h
+@@ -15,13 +15,13 @@ static int get_dgram_socket(void)
+ {
+ static int sock = -1;
+ if (sock < 0)
+- sock = socket(AF_INET, SOCK_DGRAM, 0);
++ sock = socket(AF_LOCAL, SOCK_DGRAM, 0);
+ return sock;
+ }
+
+ static int kernel_get_wireguard_interfaces(struct string_list *list)
+ {
+- struct ifgroupreq ifgr = { .ifgr_name = "wg" };
++ struct ifgroupreq ifgr = { .ifgr_name = "amn" };
+ struct ifg_req *ifg;
+ int s = get_dgram_socket(), ret = 0;
+
+@@ -389,6 +389,8 @@ static int kernel_set_device(struct wgdevice *dev)
+ nvl_aips[j] = nvlist_create(0);
+ if (!nvl_aips[j])
+ goto err_peer;
++ if (aip->flags)
++ nvlist_add_number(nvl_aips[j], "flags", aip->flags);
+ nvlist_add_number(nvl_aips[j], "cidr", aip->cidr);
+ if (aip->family == AF_INET)
+ nvlist_add_binary(nvl_aips[j], "ipv4", &aip->ip4, sizeof(aip->ip4));
diff --git a/net/amnezia-tools/files/patch-ipc-uapi.h b/net/amnezia-tools/files/patch-ipc-uapi.h
new file mode 100644
index 000000000000..61df9f69e784
--- /dev/null
+++ b/net/amnezia-tools/files/patch-ipc-uapi.h
@@ -0,0 +1,11 @@
+--- ipc-uapi.h.orig 2024-10-01 13:02:42 UTC
++++ ipc-uapi.h
+@@ -111,7 +111,7 @@ static int userspace_set_device(struct wgdevice *dev)
+ continue;
+ } else
+ continue;
+- fprintf(f, "allowed_ip=%s/%d\n", ip, allowedip->cidr);
++ fprintf(f, "allowed_ip=%s%s/%d\n", (allowedip->flags & WGALLOWEDIP_REMOVE_ME) ? "-" : "", ip, allowedip->cidr);
+ }
+ }
+ fprintf(f, "\n");
diff --git a/net/amnezia-tools/files/patch-man_wg.8 b/net/amnezia-tools/files/patch-man_wg.8
new file mode 100644
index 000000000000..ab226a3cc1e7
--- /dev/null
+++ b/net/amnezia-tools/files/patch-man_wg.8
@@ -0,0 +1,24 @@
+--- man/wg.8.orig 2024-10-01 13:02:42 UTC
++++ man/wg.8
+@@ -55,7 +55,7 @@ by \fICONFIGURATION FILE FORMAT\fP below.
+ Shows the current configuration of \fI<interface>\fP in the format described
+ by \fICONFIGURATION FILE FORMAT\fP below.
+ .TP
+-\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI<ip1>/<cidr1>\fP[,\fI<ip2>/<cidr2>\fP]...] ]...
++\fBset\fP \fI<interface>\fP [\fIlisten-port\fP \fI<port>\fP] [\fIfwmark\fP \fI<fwmark>\fP] [\fIprivate-key\fP \fI<file-path>\fP] [\fIpeer\fP \fI<base64-public-key>\fP [\fIremove\fP] [\fIpreshared-key\fP \fI<file-path>\fP] [\fIendpoint\fP \fI<ip>:<port>\fP] [\fIpersistent-keepalive\fP \fI<interval seconds>\fP] [\fIallowed-ips\fP \fI[+|-]<ip1>/<cidr1>\fP[,\fI[+|-]<ip2>/<cidr2>\fP]...] ]...
+ Sets configuration values for the specified \fI<interface>\fP. Multiple
+ \fIpeer\fPs may be specified, and if the \fIremove\fP argument is given
+ for a peer, that peer is removed, not configured. If \fIlisten-port\fP
+@@ -72,7 +72,11 @@ If \fIallowed-ips\fP is specified, but the value is th
+ it adds an additional layer of symmetric-key cryptography to be mixed into
+ the already existing public-key cryptography, for post-quantum resistance.
+ If \fIallowed-ips\fP is specified, but the value is the empty string, all
+-allowed ips are removed from the peer. The use of \fIpersistent-keepalive\fP
++allowed ips are removed from the peer. By default, \fIallowed-ips\fP replaces
++a peer's allowed ips. If + or - is prepended to any of the ips then
++the update is incremental; ips prefixed with '+' or '' are added to the peer's
++allowed ips if not present while ips prefixed with '-' are removed if present.
++The use of \fIpersistent-keepalive\fP
+ is optional and is by default off; setting it to 0 or "off" disables it.
+ Otherwise it represents, in seconds, between 1 and 65535 inclusive, how often
+ to send an authenticated empty packet to the peer, for the purpose of keeping
diff --git a/net/amnezia-tools/files/patch-set.c b/net/amnezia-tools/files/patch-set.c
new file mode 100644
index 000000000000..61e1ec5314d0
--- /dev/null
+++ b/net/amnezia-tools/files/patch-set.c
@@ -0,0 +1,11 @@
+--- set.c.orig 2024-10-01 13:02:42 UTC
++++ set.c
+@@ -18,7 +18,7 @@ int set_main(int argc, const char *argv[])
+ int ret = 1;
+
+ if (argc < 3) {
+- fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips <ip1>/<cidr1>[,<ip2>/<cidr2>] [advanced-security <on|off>]...] ]...\n", PROG_NAME, argv[0]);
++ fprintf(stderr, "Usage: %s %s <interface> [listen-port <port>] [fwmark <mark>] [private-key <file path>] [peer <base64 public key> [remove] [preshared-key <file path>] [endpoint <ip>:<port>] [persistent-keepalive <interval seconds>] [allowed-ips [+|-]<ip1>/<cidr1>[,[+|-]<ip2>/<cidr2>] [advanced-security <on|off>]...] ]...\n", PROG_NAME, argv[0]);
+ return 1;
+ }
+
diff --git a/net/amnezia-tools/files/patch-version.h b/net/amnezia-tools/files/patch-version.h
new file mode 100644
index 000000000000..02ae2a096e8a
--- /dev/null
+++ b/net/amnezia-tools/files/patch-version.h
@@ -0,0 +1,7 @@
+--- version.h.orig 2024-10-01 13:02:42 UTC
++++ version.h
+@@ -1,3 +1,3 @@
+ #ifndef WIREGUARD_TOOLS_VERSION
+-#define WIREGUARD_TOOLS_VERSION "1.0.20210914"
++#define WIREGUARD_TOOLS_VERSION "1.0.20250521"
+ #endif
diff --git a/net/amnezia-tools/files/patch-wg-quick_freebsd.bash b/net/amnezia-tools/files/patch-wg-quick_freebsd.bash
new file mode 100644
index 000000000000..e419ea4be7ce
--- /dev/null
+++ b/net/amnezia-tools/files/patch-wg-quick_freebsd.bash
@@ -0,0 +1,316 @@
+--- wg-quick/freebsd.bash.orig 2024-10-01 13:02:42 UTC
++++ wg-quick/freebsd.bash
+@@ -25,11 +25,20 @@ CONFIG_FILE=""
+ POST_DOWN=( )
+ SAVE_CONFIG=0
+ CONFIG_FILE=""
++DESCRIPTION=""
++USERLAND=0
++MONITOR=1
++TRACK_DNS_CHANGES=0
+ PROGRAM="${0##*/}"
+ ARGS=( "$@" )
+
+ IS_ASESCURITY_ON=0
+
++
++declare -A ROUTES
++declare -A ENDPOINTS
++
++
+ cmd() {
+ echo "[#] $*" >&3
+ "$@"
+@@ -40,7 +49,7 @@ die() {
+ exit 1
+ }
+
+-CONFIG_SEARCH_PATHS=( /etc/amnezia/amneziawg /usr/local/etc/amnezia/amneziawg )
++CONFIG_SEARCH_PATHS=( /usr/local/etc/amnezia/amneziawg /usr/local/etc/wireguard )
+
+ unset ORIGINAL_TMPDIR
+ make_temp() {
+@@ -64,7 +73,7 @@ parse_options() {
+ }
+
+ parse_options() {
+- local interface_section=0 line key value stripped path v
++ local interface_section=0 line key value stripped path v last_public_key
+ CONFIG_FILE="$1"
+ if [[ $CONFIG_FILE =~ ^[a-zA-Z0-9_=+.-]{1,15}$ ]]; then
+ for path in "${CONFIG_SEARCH_PATHS[@]}"; do
+@@ -82,7 +91,7 @@ parse_options() {
+ stripped="${line%%\#*}"
+ key="${stripped%%=*}"; key="${key##*([[:space:]])}"; key="${key%%*([[:space:]])}"
+ value="${stripped#*=}"; value="${value##*([[:space:]])}"; value="${value%%*([[:space:]])}"
+- [[ $key == "["* ]] && interface_section=0
++ [[ $key == "["* ]] && interface_section=0 && last_public_key=""
+ [[ $key == "[Interface]" ]] && interface_section=1
+ if [[ $interface_section -eq 1 ]]; then
+ case "$key" in
+@@ -96,9 +105,14 @@ parse_options() {
+ PreDown) PRE_DOWN+=( "$value" ); continue ;;
+ PostUp) POST_UP+=( "$value" ); continue ;;
+ PostDown) POST_DOWN+=( "$value" ); continue ;;
++ Description) DESCRIPTION="$value"; continue ;;
+ SaveConfig) read_bool SAVE_CONFIG "$value"; continue ;;
++ UserLand) read_bool USERLAND "$value"; continue ;;
++ Monitor) read_bool MONITOR "$value"; continue ;;
++ TrackDNSChanges) TRACK_DNS_CHANGES="$value"; continue ;;
+ esac
+ case "$key" in
++
+ Jc);&
+ Jmin);&
+ Jmax);&
+@@ -109,6 +123,17 @@ parse_options() {
+ H3);&
+ H4) IS_ASESCURITY_ON=1;;
+ esac
++ else
++ case "$key" in
++ PublicKey) last_public_key="$value" ;;
++ Routes) ROUTES["$last_public_key"]="$value"; continue ;;
++ Endpoint)
++ endpoint_host="${value%%:*}"
++ if ! [[ "$endpoint_host" =~ ^[0-9]+ ]]; then
++ ENDPOINTS["$last_public_key"]="$endpoint_host"
++ fi
++ ;;
++ esac
+ fi
+ WG_CONFIG+="$line"$'\n'
+ done < "$CONFIG_FILE"
+@@ -129,12 +154,15 @@ add_if() {
+
+ add_if() {
+ local ret rc
+- local cmd="ifconfig wg create name "$INTERFACE""
+- if [[ $IS_ASESCURITY_ON == 1 ]]; then
++ local cmd="ifconfig amn create name "$INTERFACE""
++ if [[ $USERLAND == 1 ]]; then
+ cmd="amneziawg-go "$INTERFACE"";
+ fi
+- if ret="$(cmd $cmd 2>&1 >/dev/null)"; then
+- return 0
++ if [ -n "$DESCRIPTION" ]; then
++ ret="$(cmd $cmd description "$DESCRIPTION" 2>&1 >/dev/null)" && return 0
++ else
++
++ ret="$(cmd $cmd 2>&1 >/dev/null)" && return 0
+ fi
+ rc=$?
+ if [[ $ret == *"ifconfig: ioctl SIOCSIFNAME (set name): File exists"* ]]; then
+@@ -209,7 +237,7 @@ set_mtu() {
+ [[ ${BASH_REMATCH[1]} == *:* ]] && family=inet6
+ output="$(route -n get "-$family" "${BASH_REMATCH[1]}" || true)"
+ [[ $output =~ interface:\ ([^ ]+)$'\n' && $(ifconfig "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
+- done < <(wg show "$INTERFACE" endpoints)
++ done < <(awg show "$INTERFACE" endpoints)
+ if [[ $mtu -eq 0 ]]; then
+ read -r output < <(route -n get default || true) || true
+ [[ $output =~ interface:\ ([^ ]+)$'\n' && $(ifconfig "${BASH_REMATCH[1]}") =~ mtu\ ([0-9]+) && ${BASH_REMATCH[1]} -gt $mtu ]] && mtu="${BASH_REMATCH[1]}"
+@@ -242,7 +270,7 @@ collect_endpoints() {
+ while read -r _ endpoint; do
+ [[ $endpoint =~ ^\[?([a-z0-9:.]+)\]?:[0-9]+$ ]] || continue
+ ENDPOINTS+=( "${BASH_REMATCH[1]}" )
+- done < <(wg show "$INTERFACE" endpoints)
++ done < <(awg show "$INTERFACE" endpoints)
+ }
+
+ set_endpoint_direct_route() {
+@@ -297,18 +325,18 @@ monitor_daemon() {
+ }
+
+ monitor_daemon() {
++ [[ $MONITOR -eq 0 ]] && return 0
+ echo "[+] Backgrounding route monitor" >&2
+ (make_temp
+ trap 'del_routes; clean_temp; exit 0' INT TERM EXIT
+ exec >/dev/null 2>&1
+- exec 19< <(exec route -n monitor)
++ exec 19< <(exec stdbuf -oL route -n monitor)
+ local event pid=$!
+ # TODO: this should also check to see if the endpoint actually changes
+ # in response to incoming packets, and then call set_endpoint_direct_route
+ # then too. That function should be able to gracefully cleanup if the
+ # endpoints change.
+ while read -u 19 -r event; do
+- [[ $event == RTM_* ]] || continue
+ ifconfig "$INTERFACE" >/dev/null 2>&1 || break
+ [[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route
+ # TODO: set the mtu as well, but only if up
+@@ -316,6 +344,77 @@ monitor_daemon() {
+ kill $pid) & disown
+ }
+
++wg_endpoints() {
++ awk '
++ BEGIN { RS=""; FS="\n" }
++ /Peer/ {
++ pk=""; ep=""
++ for (i = 1; i <= NF; i++) {
++ if ($i ~ /^PublicKey[ \t]*=/) {
++ pk = $i
++ sub(/^PublicKey[ \t]*=[ \t]*/, "", pk)
++ }
++ if ($i ~ /^Endpoint[ \t]*=/) {
++ ep = $i
++ sub(/^Endpoint[ \t]*=[ \t]*/, "", ep)
++ split(ep, parts, ":")
++ host = parts[1]
++ port = parts[2]
++ }
++ }
++ if (pk != "" && host != "" && port != "") {
++ print pk, host, port
++ }
++ }
++ '
++}
++
++tracker_pid_file() {
++ echo "/var/run/awg-quick.dns-tracker.${INTERFACE}.pid"
++}
++
++monitor_dns_changes() {
++ local pk peer_ip port peer_host host_ip
++ [[ $TRACK_DNS_CHANGES -eq 0 ]] && return 0
++
++ echo "[+] Backgrounding DNS tracker" >&2
++ exec >/dev/null 2>&1
++
++ pid_file="$(tracker_pid_file)"
++ [[ -f "$pid_file" ]] && kill $(cat "$pid_file") 2>/dev/null || true
++
++ (
++ trap 'rm -f "$pid_file"; exit 0' INT TERM EXIT
++
++ set -e
++ while true; do
++ sleep $TRACK_DNS_CHANGES &
++ wait $!
++
++ $cmd awg showconf "$INTERFACE" 2> /dev/null | wg_endpoints | \
++ while read -r pk peer_ip port; do
++ peer_host="${ENDPOINTS[$pk]}"
++ if [[ -n "$peer_host" ]]; then
++ host_ip=$(host "$peer_host" 2>/dev/null | awk '/has address/ { print $4; exit; }') || continue
++
++ if [[ "$host_ip" = "$peer_ip" ]]; then
++ #echo "$pk matches ${peer_ip} <=> ${host_ip}"
++ :
++ else
++ logger -t awg-quick -p local0.notice \
++ "$INTERFACE/$pk host $peer_host:" \
++ "IP missmatch: $host_ip != $peer_ip, configuring endpoint" || true
++ $cmd awg set "$INTERFACE" peer "$pk" endpoint "$peer_host:$port" || true
++ fi
++ fi
++ done
++
++ done
++ ) & disown
++ echo "$!" > "$pid_file"
++}
++
++
+ HAVE_SET_DNS=0
+ set_dns() {
+ [[ ${#DNS[@]} -gt 0 ]] || return 0
+@@ -354,7 +453,7 @@ set_config() {
+ }
+
+ set_config() {
+- echo "$WG_CONFIG" | cmd wg setconf "$INTERFACE" /dev/stdin
++ echo "$WG_CONFIG" | cmd awg setconf "$INTERFACE" /dev/stdin
+ }
+
+ save_config() {
+@@ -386,7 +485,7 @@ save_config() {
+ done
+ old_umask="$(umask)"
+ umask 077
+- current_config="$(cmd wg showconf "$INTERFACE")"
++ current_config="$(cmd awg showconf "$INTERFACE")"
+ trap 'rm -f "$CONFIG_FILE.tmp"; clean_temp; exit' INT TERM EXIT
+ echo "${current_config/\[Interface\]$'\n'/$new_config}" > "$CONFIG_FILE.tmp" || die "Could not write configuration file"
+ sync "$CONFIG_FILE.tmp"
+@@ -433,6 +532,20 @@ cmd_usage() {
+ _EOF
+ }
+
++get_routes() {
++ while read -r pub_key i; do
++ if [[ -v "ROUTES[$pub_key]" ]]; then
++ for route in ${ROUTES[$pub_key]//,/ }; do
++ echo "$route"
++ done
++ else
++ for j in $i; do
++ [[ $j =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$j"
++ done
++ fi
++ done < <(awg show "$INTERFACE" allowed-ips) | sort -nr -k 2 -t /
++}
++
+ cmd_up() {
+ local i
+ [[ -z $(ifconfig "$INTERFACE" 2>/dev/null) ]] || die "\`$INTERFACE' already exists"
+@@ -446,26 +559,31 @@ cmd_up() {
+ set_mtu
+ up_if
+ set_dns
+- for i in $(while read -r _ i; do for i in $i; do [[ $i =~ ^[0-9a-z:.]+/[0-9]+$ ]] && echo "$i"; done; done < <(wg show "$INTERFACE" allowed-ips) | sort -nr -k 2 -t /); do
++ for i in $(get_routes); do
+ add_route "$i"
+ done
+ [[ $AUTO_ROUTE4 -eq 1 || $AUTO_ROUTE6 -eq 1 ]] && set_endpoint_direct_route
+ monitor_daemon
++ monitor_dns_changes
+ execute_hooks "${POST_UP[@]}"
+ trap 'clean_temp; exit' INT TERM EXIT
+ }
+
+ cmd_down() {
+- [[ " $(wg show interfaces) " == *" $INTERFACE "* ]] || die "\`$INTERFACE' is not a WireGuard interface"
++ [[ " $(awg show interfaces) " == *" $INTERFACE "* ]] || die "\`$INTERFACE' is not a WireGuard interface"
+ execute_hooks "${PRE_DOWN[@]}"
+ [[ $SAVE_CONFIG -eq 0 ]] || save_config
+ del_if
+ unset_dns
++ if [[ -f "$(tracker_pid_file)" ]]; then
++ kill $(cat "$(tracker_pid_file)") 2>/dev/null
++ rm -f "$(tracker_pid_file)"
++ fi
+ execute_hooks "${POST_DOWN[@]}"
+ }
+
+ cmd_save() {
+- [[ " $(wg show interfaces) " == *" $INTERFACE "* ]] || die "\`$INTERFACE' is not a WireGuard interface"
++ [[ " $(awg show interfaces) " == *" $INTERFACE "* ]] || die "\`$INTERFACE' is not a WireGuard interface"
+ save_config
+ }
+
+@@ -473,6 +591,10 @@ cmd_strip() {
+ echo "$WG_CONFIG"
+ }
+
++cmd_reload() {
++ cmd awg setconf "$INTERFACE" <(cmd_strip)
++}
++
+ # ~~ function override insertion point ~~
+
+ make_temp
+@@ -496,6 +618,10 @@ elif [[ $# -eq 2 && $1 == strip ]]; then
+ auto_su
+ parse_options "$2"
+ cmd_strip
++elif [[ $# -eq 2 && $1 == reload ]]; then
++ auto_su
++ parse_options "$2"
++ cmd_reload
+ else
+ cmd_usage
+ exit 1
diff --git a/net/amnezia-tools/pkg-descr b/net/amnezia-tools/pkg-descr
new file mode 100644
index 000000000000..0b238af17b73
--- /dev/null
+++ b/net/amnezia-tools/pkg-descr
@@ -0,0 +1,2 @@
+This supplies the main userspace tooling for using and configuring
+WireGuard tunnels, including the awg(8) and awg-quick(8) utilities.
diff --git a/net/amnezia-tools/pkg-plist b/net/amnezia-tools/pkg-plist
new file mode 100644
index 000000000000..8a2c3db16065
--- /dev/null
+++ b/net/amnezia-tools/pkg-plist
@@ -0,0 +1,7 @@
+bin/awg
+bin/awg-quick
+share/bash-completion/completions/awg
+share/bash-completion/completions/awg-quick
+share/man/man8/awg.8.gz
+share/man/man8/awg-quick.8.gz
+@dir etc/amnezia