diff --git a/net/Makefile b/net/Makefile --- a/net/Makefile +++ b/net/Makefile @@ -17,6 +17,8 @@ SUBDIR += akonadi-search SUBDIR += alligator SUBDIR += aluminum + SUBDIR += amneziawg-kmod + SUBDIR += amneziawg-tools SUBDIR += amqpcat SUBDIR += aoe SUBDIR += apache-commons-net diff --git a/net/amneziawg-kmod/Makefile b/net/amneziawg-kmod/Makefile new file mode 100644 --- /dev/null +++ b/net/amneziawg-kmod/Makefile @@ -0,0 +1,21 @@ +PORTNAME= amneziawg +PORTVERSION= 1.0.6 +DISTVERSIONPREFIX= v +CATEGORIES= net net-vpn +PKGNAMESUFFIX= -kmod + +MAINTAINER= vova@zote.me +COMMENT= AmneziaWG FreeBSD kernel module implementation +WWW= https://github.com/vgrebenschikov/wireguard-amnezia-kmod + +LICENSE= MIT +LICENSE_FILE= ${WRKSRC}/COPYING + +USES= kmod uidfix +USE_GITHUB= yes +GH_ACCOUNT= vgrebenschikov +GH_PROJECT= wireguard-amnezia-kmod + +PLIST_FILES= ${KMODDIR}/if_awg.ko + +.include diff --git a/net/amneziawg-kmod/distinfo b/net/amneziawg-kmod/distinfo new file mode 100644 --- /dev/null +++ b/net/amneziawg-kmod/distinfo @@ -0,0 +1,3 @@ +TIMESTAMP = 1753385001 +SHA256 (vgrebenschikov-wireguard-amnezia-kmod-v1.0.6_GH0.tar.gz) = 916438447143bff815d0c6617796ff12c98c25dd5439413d67faab19c4dd65fd +SIZE (vgrebenschikov-wireguard-amnezia-kmod-v1.0.6_GH0.tar.gz) = 52053 diff --git a/net/amneziawg-kmod/files/patch-Makefile b/net/amneziawg-kmod/files/patch-Makefile new file mode 100644 --- /dev/null +++ b/net/amneziawg-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_awg + + 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/amneziawg-kmod/files/patch-if__wg.c b/net/amneziawg-kmod/files/patch-if__wg.c new file mode 100644 --- /dev/null +++ b/net/amneziawg-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[] = "awg"; + 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, "awg_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, "AWG", "amneziawg"); + +-VNET_DEFINE_STATIC(struct if_clone *, wg_cloner); ++VNET_DEFINE_STATIC(struct if_clone *, awg_cloner); + +-#define V_wg_cloner VNET(wg_cloner) ++#define V_awg_cloner VNET(awg_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_awg_init(const void *); ++static void vnet_awg_uninit(const void *); ++static int awg_module_init(void); ++static void awg_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, "awg_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, "awg 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, "awg 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_awg_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_awg_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_awg_init, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, ++ vnet_awg_init, NULL); + + static void +-vnet_wg_uninit(const void *unused __unused) ++vnet_awg_uninit(const void *unused __unused) + { +- if (V_wg_cloner) +- ifc_detach_cloner(V_wg_cloner); ++ if (V_awg_cloner) ++ ifc_detach_cloner(V_awg_cloner); + } +-VNET_SYSUNINIT(vnet_wg_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, +- vnet_wg_uninit, NULL); ++VNET_SYSUNINIT(vnet_awg_uninit, SI_SUB_PROTO_IFATTACHDOMAIN, SI_ORDER_ANY, ++ vnet_awg_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) ++awg_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("awg 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) ++awg_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, awg_cloner); + if (clone) { + ifc_detach_cloner(clone); +- VNET_VNET(vnet_iter, wg_cloner) = NULL; ++ VNET_VNET(vnet_iter, awg_cloner) = NULL; + } + } + VNET_LIST_RUNLOCK(); +@@ -3401,13 +3401,13 @@ static int + } + + static int +-wg_module_event_handler(module_t mod, int what, void *arg) ++awg_module_event_handler(module_t mod, int what, void *arg) + { + switch (what) { + case MOD_LOAD: +- return wg_module_init(); ++ return awg_module_init(); + case MOD_UNLOAD: +- wg_module_deinit(); ++ awg_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 awg_moduledata = { ++ "if_awg", ++ awg_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_awg, awg_moduledata, SI_SUB_PSEUDO, SI_ORDER_ANY); ++MODULE_VERSION(if_awg, WIREGUARD_VERSION); ++MODULE_DEPEND(if_awg, crypto, 1, 1, 1); diff --git a/net/amneziawg-kmod/pkg-descr b/net/amneziawg-kmod/pkg-descr new file mode 100644 --- /dev/null +++ b/net/amneziawg-kmod/pkg-descr @@ -0,0 +1,12 @@ +AmneziaWG is a contemporary 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. + +The progenitor of AmneziaWG, WireGuard, is known for its efficiency, but +it does have issues with detection due to distinctive packet signatures. +AmneziaWG addresses this problem by employing advanced obfuscation methods, +allowing its traffic to blend seamlessly with regular internet traffic. +As a result, AmneziaWG maintains high performance while adding an extra layer +of stealth, making it a superb choice for those seeking a fast and discreet +VPN connection. diff --git a/net/amneziawg-tools/Makefile b/net/amneziawg-tools/Makefile new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/Makefile @@ -0,0 +1,37 @@ +PORTNAME= amneziawg-tools +PORTVERSION= 1.0.20241018 +PORTREVISION= 8 +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_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= amneziawg + +.include + +post-patch: + @${REINPLACE_CMD} -e 's|wg s|awg s|g' \ + ${WRKSRC}/completion/wg-quick.bash-completion + +post-install: + @${MKDIR} ${STAGEDIR}${PREFIX}/etc/amnezia/amneziawg + ${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/awg + +.include diff --git a/net/amneziawg-tools/README.md b/net/amneziawg-tools/README.md new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/README.md @@ -0,0 +1,213 @@ +# FreeBSD port of amneziawg-tools + +## Installation + +Download and build port as: + +```shell +git clone https://github.com/vgrebenschikov/amneziawg-tools +sudo make install -C amneziawg-tools +``` + +## Using Kernel AmneziaWG module + +Install [net/amneziawg-kmod](https://github.com/vgrebenschikov/amneziawg-kmod) + +```shell +kldload -n if_awg +``` + +## Configuration with awg tool + +/usr/local/bin/awg tool can be used to configure awg device: + +```shell + +bash + +if=$(ifconfig awg create inet 192.168.1.1/24 up) +ifconfig $if + awg0: flags=10080c1 metric 0 mtu 1420 + options=80000 + inet 192.168.1.1 netmask 0xffffff00 + groups: awg + nd6 options=109 + +awg set $if jc 7 jmin 150 jmax 1000 s1 117 s2 321 h1 2008066467 h2 2351746464 h3 3053333659 h4 1789444460 +awg set $if listen-port 12345 private-key <(awg genkey) peer $(awg genkey | awg pubkey) allowed-ips 192.168.1.2/32 + +awg show $if + interface: awg0 + public key: yyAHM... + private key: (hidden) + listening port: 12345 + jc: 7 + jmin: 150 + jmax: 1000 + s1: 117 + s2: 321 + h1: 2008066467 + h2: 2351746464 + h3: 3053333659 + h4: 1789444460 + +peer: bdfTF.. + allowed ips: 192.168.1.2/32 +``` + +## Configuration with awg-quick + +Generally - similar way as you will configure with wg-quick from net/wireguard-tools: +With configuration file, like: + +```shell +# cd /usr/local/etc/amnezia/amneziawg/ +# cat > awg0.conf << EOF +[Interface] +PrivateKey = $(awg genkey) +ListenPort = 12345 +Address = 192.168.1.1/24 +Description = Test AmneziaWG + +Jc = 7 +Jmin = 150 +Jmax = 1000 +S1 = 117 +S2 = 321 +H1 = 2008066467 +H2 = 2351746464 +H3 = 3053333659 +H4 = 1789444460 + +[Peer] +PublicKey = $(awg genkey | awg pubkey) +AllowedIPs = 192.168.1.2/32 +EOF +``` + +Then start: + +```shell +awg-quick up awg0 +[#] ifconfig awg create name awg0 description Test AmneziaWG +[#] awg setconf awg0 /dev/stdin +[#] ifconfig awg0 inet 192.168.1.1/24 alias +[#] ifconfig awg0 mtu 1420 +[#] ifconfig awg0 up +[#] route -q -n add -inet 192.168.1.2/32 -interface awg0 +[+] Backgrounding route monitor + +awg show +interface: awg0 + public key: CI... + private key: (hidden) + listening port: 12345 + jc: 7 + jmin: 150 + jmax: 1000 + s1: 117 + s2: 321 + h1: 2008066467 + h2: 2351746464 + h3: 3053333659 + h4: 1789444460 + +peer: kue... + allowed ips: 192.168.1.2/32 +``` + +To setup autostart (amneziawg rc.d script will load if_awg module): + +```shell +# sysrc amneziawg_enable=YES amneziawg_interfaces="awg0" +``` + +## Amnezia Wireguard config options + +## Jc + +Number of junk packets before handshake. + +1–128 (recomended 3–10) + +## Jmin + +Minimum size of junk packets. + +Jmin: < Jmax (recomended ~ 50) + +## Jmax + +Maximum size of junk packets. + +Jmax: ≤ 1280 (recomended ~ 1000) + +## S1 + +Size of handshake initiation packet prepend junk. Should be the same on both ends. + +0–1280 (recomended 15–150), S1 != S2 + +## S2 + +Size of handshake response packet prepend junk. Should be the same on both ends. + +0–1280 (recomended 15–150), S1 != S2 + +## H1-H4 + +Custom identifiers for initiation/response/cookie/data packets. Should be the same on both ends. + +The unique value in range of 5 - 4,294,967,295 (0x5 - 0xFFFFFFFF), H1 != H2 != H3 != H4 + +## Additional config options + +### Description + +```config +[Interface] +... +Description = Some Text +``` + +Will setup interface description visible in ifconfig and SNMP. + +### UserLand + +Enforce to use amnezia-go instead of kernel driver, you can use port +[net/amnezia-wireguard-go](https://github.com/vgrebenschikov/amnezia-wireguard-go) to install it. + +```config +[Interface] +... +UserLand = true +... +``` + +### Routes + +List of routes for the peer to be installed into FIB - that option provides a way to have AllowedIPs list wider then routes installed. Empty list is allowed. + +That is useful if routing protocol will work over the link. +But remember that internal wireguard routing will happen according to AllowedIPs anyway. +Suggested use in case dynamic route - one interface -> one link. + +```config +... + +[Peer] +PublicKey = ...peer.public.key.here... +AllowedIPs = 0.0.0.0/0 +Routes = 192.168.1.2/32 +``` + +and after start - only routes limited in Routes config section: + +```shell +awg-quick up awg0 +... + +netstat -rn | fgrep awg0 +192.168.1.0/24 link#3 U awg0 +192.168.1.2 link#3 UHS awg0 +``` diff --git a/net/amneziawg-tools/distinfo b/net/amneziawg-tools/distinfo new file mode 100644 --- /dev/null +++ b/net/amneziawg-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/amneziawg-tools/files/amneziawg.in b/net/amneziawg-tools/files/amneziawg.in new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/files/amneziawg.in @@ -0,0 +1,74 @@ +#!/bin/sh + +# PROVIDE: amneziawg +# REQUIRE: NETWORKING +# KEYWORD: shutdown +# +# amneziawg_enable (bool): Set to "YES" to enable amneziawg. +# (default: "NO") +# +# amneziawg_interfaces (str): List of interfaces to bring up/down +# on start/stop. (eg: "wg0 wg1") +# (default: "") +# amneziawg_env (str): Environment variables for the userspace +# implementation. (eg: "LOG_LEVEL=debug") + +. /etc/rc.subr + +name=amneziawg +rcvar=amneziawg_enable +extra_commands="reload status" + +start_cmd="${name}_start" +stop_cmd="${name}_stop" +reload_cmd="${name}_reload" +status_cmd="${name}_status" + +amneziawg_start() +{ + ${amneziawg_env:+eval export $amneziawg_env} + kldload -n if_awg + + for interface in ${amneziawg_interfaces}; do + %%PREFIX%%/bin/awg-quick up ${interface} + done +} + +amneziawg_stop() +{ + for interface in ${amneziawg_interfaces}; do + %%PREFIX%%/bin/awg-quick down ${interface} + done +} + +amneziawg_reload() +{ + ${amneziawg_env:+eval export $amneziawg_env} + + for interface in ${amneziawg_interfaces}; do + tmpfile="`mktemp`" + %%PREFIX%%/bin/awg-quick strip ${interface} > ${tmpfile} + %%PREFIX%%/bin/awg syncconf ${interface} ${tmpfile} + rm -f ${tmpfile} + done +} + +amneziawg_status() +{ + ${amneziawg_env:+eval export $amneziawg_env} + amneziawg_status="0" + + for interface in ${amneziawg_interfaces}; do + %%PREFIX%%/bin/awg show ${interface} || amneziawg_status="1" + done + + return ${amneziawg_status} +} + +load_rc_config $name + +: ${amneziawg_enable="NO"} +: ${amneziawg_interfaces=""} +: ${amneziawg_env=""} + +run_rc_command "$1" diff --git a/net/amneziawg-tools/files/patch-config.c b/net/amneziawg-tools/files/patch-config.c new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/files/patch-config.c @@ -0,0 +1,11 @@ +--- config.c.orig 2025-06-13 09:33:11 UTC ++++ config.c +@@ -252,7 +252,7 @@ static inline bool parse_endpoint(struct sockaddr *end + * + * So this is what we do, except FreeBSD removed EAI_NODATA some time ago, so that's conditional. + */ +- if (ret == EAI_NONAME || ret == EAI_FAIL || ++ if (/* ret == EAI_NONAME || */ ret == EAI_FAIL || + #ifdef EAI_NODATA + ret == EAI_NODATA || + #endif diff --git a/net/amneziawg-tools/files/patch-ipc-freebsd.h b/net/amneziawg-tools/files/patch-ipc-freebsd.h new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/files/patch-ipc-freebsd.h @@ -0,0 +1,11 @@ +--- ipc-freebsd.h.orig 2025-07-22 19:01:39 UTC ++++ ipc-freebsd.h +@@ -21,7 +21,7 @@ static int kernel_get_wireguard_interfaces(struct stri + + static int kernel_get_wireguard_interfaces(struct string_list *list) + { +- struct ifgroupreq ifgr = { .ifgr_name = "wg" }; ++ struct ifgroupreq ifgr = { .ifgr_name = "awg" }; + struct ifg_req *ifg; + int s = get_dgram_socket(), ret = 0; + diff --git a/net/amneziawg-tools/files/patch-wg-quick_freebsd.bash b/net/amneziawg-tools/files/patch-wg-quick_freebsd.bash new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/files/patch-wg-quick_freebsd.bash @@ -0,0 +1,192 @@ +--- wg-quick/freebsd.bash.orig 2024-10-01 13:02:42 UTC ++++ wg-quick/freebsd.bash +@@ -25,11 +25,17 @@ CONFIG_FILE="" + POST_DOWN=( ) + SAVE_CONFIG=0 + CONFIG_FILE="" ++DESCRIPTION="" ++USERLAND=0 + PROGRAM="${0##*/}" + ARGS=( "$@" ) + + IS_ASESCURITY_ON=0 + ++ ++declare -A ROUTES ++ ++ + cmd() { + echo "[#] $*" >&3 + "$@" +@@ -40,7 +46,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 +70,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 +88,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 +102,12 @@ 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 ;; + esac + case "$key" in ++ + Jc);& + Jmin);& + Jmax);& +@@ -109,6 +118,12 @@ 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 ;; ++ DynamicRoutes) continue ;; ++ esac + fi + WG_CONFIG+="$line"$'\n' + done < "$CONFIG_FILE" +@@ -130,11 +145,14 @@ add_if() { + add_if() { + local ret rc +- local cmd="ifconfig wg create name "$INTERFACE"" +- if [[ $IS_ASESCURITY_ON == 1 ]]; then ++ local cmd="ifconfig awg 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 +227,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 +260,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() { +@@ -301,14 +319,13 @@ monitor_daemon() { + (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 +@@ -354,7 +371,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 +403,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 +450,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,7 +477,7 @@ 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 +@@ -456,7 +487,7 @@ cmd_down() { + } + + 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 +@@ -465,7 +496,7 @@ cmd_save() { + } + + 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 + } + diff --git a/net/amneziawg-tools/pkg-descr b/net/amneziawg-tools/pkg-descr new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/pkg-descr @@ -0,0 +1,2 @@ +This supplies the main userspace tooling for using and configuring +WireGuard tunnels, including the wg(8) and wg-quick(8) utilities. diff --git a/net/amneziawg-tools/pkg-plist b/net/amneziawg-tools/pkg-plist new file mode 100644 --- /dev/null +++ b/net/amneziawg-tools/pkg-plist @@ -0,0 +1,10 @@ +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/amneziawg