diff options
author | Eugene Grosbein <eugen@FreeBSD.org> | 2025-08-06 01:19:55 +0700 |
---|---|---|
committer | Eugene Grosbein <eugen@FreeBSD.org> | 2025-08-06 01:23:54 +0700 |
commit | 618ae04f2c3ac2dafbd597117995137d08a1376c (patch) | |
tree | 5dd4345bab7363a2a53ceb1127e1dd950b88b8c9 | |
parent | net-mgmt/netdata: Enable essential DASHBOARD option by default (diff) |
net/amnezia-kmod, net/amnezia-tools: new ports
AmneziaWG is a version of the popular VPN protocol, WireGuard.
It offers protection against detection by Deep Packet Inspection
(DPI) systems. At the same time, it retains the simplified
architecture and high performance of the original.
PR: 288599
Approved by: core (glebius)
-rw-r--r-- | net/Makefile | 2 | ||||
-rw-r--r-- | net/amnezia-kmod/Makefile | 23 | ||||
-rw-r--r-- | net/amnezia-kmod/distinfo | 3 | ||||
-rw-r--r-- | net/amnezia-kmod/files/patch-Makefile | 9 | ||||
-rw-r--r-- | net/amnezia-kmod/files/patch-if__wg.c | 173 | ||||
-rw-r--r-- | net/amnezia-kmod/pkg-descr | 15 | ||||
-rw-r--r-- | net/amnezia-tools/Makefile | 37 | ||||
-rw-r--r-- | net/amnezia-tools/distinfo | 3 | ||||
-rw-r--r-- | net/amnezia-tools/files/amnezia.in | 79 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-config.c | 50 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-containers.h | 21 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-ipc-freebsd.h | 27 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-ipc-uapi.h | 11 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-man_wg.8 | 24 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-set.c | 11 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-version.h | 7 | ||||
-rw-r--r-- | net/amnezia-tools/files/patch-wg-quick_freebsd.bash | 316 | ||||
-rw-r--r-- | net/amnezia-tools/pkg-descr | 2 | ||||
-rw-r--r-- | net/amnezia-tools/pkg-plist | 7 |
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 |