diff --git a/net/amnezia-tools/Makefile b/net/amnezia-tools/Makefile index 2c15bcdb024f..f017fea7b5e1 100644 --- a/net/amnezia-tools/Makefile +++ b/net/amnezia-tools/Makefile @@ -1,38 +1,42 @@ -PORTNAME= amnezia-tools -PORTVERSION= 1.0.20241018 -PORTREVISION= 1 +PORTNAME= amnezia +DISTVERSIONPREFIX= v +DISTVERSION= 1.0.20241018 +PORTREVISION= 2 CATEGORIES= net net-vpn MASTER_SITES= https://github.com/amnezia-vpn/amneziawg-tools/ +PKGNAMESUFFIX= -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 +USES= gmake shebangfix USE_GITHUB= yes GH_ACCOUNT= amnezia-vpn GH_PROJECT= amneziawg-tools -GH_TAGNAME= v${PORTVERSION} +USE_RC_SUBR= ${PORTNAME} + +SHEBANG_FILES= wg-quick/freebsd.bash -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 +WRKSRC_SUBDIR= src post-patch: - @${REINPLACE_CMD} -e 's|wg s|awg s|g' \ + @${REINPLACE_CMD} -e 's|wg s|awg s|g; \ + s|/usr/local/etc/wireguard|${ETCDIR}|' \ ${WRKSRC}/completion/wg-quick.bash-completion + @${REINPLACE_CMD} -e 's|%%ETCDIR%%|${ETCDIR}|' \ + ${WRKSRC}/wg-quick/freebsd.bash post-install: - @${RMDIR} ${STAGEDIR}${PREFIX}/etc/amnezia/amneziawg + @${RMDIR} ${STAGEDIR}${ETCDIR}/amneziawg ${STRIP_CMD} ${STAGEDIR}${PREFIX}/bin/awg .include diff --git a/net/amnezia-tools/distinfo b/net/amnezia-tools/distinfo index 3703c8bf36a2..4121ea84aa23 100644 --- a/net/amnezia-tools/distinfo +++ b/net/amnezia-tools/distinfo @@ -1,3 +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 +TIMESTAMP = 1754646104 +SHA256 (amnezia-vpn-amneziawg-tools-v1.0.20241018_GH0.tar.gz) = 60f1cec1774fb871a2d8dc24e4f731625516d90f663d6e0d2c77d9247222f2f9 +SIZE (amnezia-vpn-amneziawg-tools-v1.0.20241018_GH0.tar.gz) = 156259 diff --git a/net/amnezia-tools/files/amnezia.in b/net/amnezia-tools/files/amnezia.in index 11a5daf89861..98010c013bdb 100644 --- a/net/amnezia-tools/files/amnezia.in +++ b/net/amnezia-tools/files/amnezia.in @@ -1,81 +1,82 @@ #!/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: "amn0 amn1") # (default: "") # amnezia_env (str): Environment variables for the userspace # implementation. (eg: "LOG_LEVEL=debug") # # amnezia_kmod (str): Kernel module to load. # (default: "if_amn", "" - no module) # # amnezia_confdirs (str): Directory to store the configuration files. -# (default: "/usr/local/etc/amnezia") +# (default: "%%ETCDIR%%") . /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"} +: ${amnezia_confdirs="%%ETCDIR%%"} + +${amnezia_confdirs:+eval export AWG_QUICK_CONFIG_SEARCH_PATHS="$amnezia_confdirs"} run_rc_command "$1" diff --git a/net/amnezia-tools/files/patch-man_wg-quick.8 b/net/amnezia-tools/files/patch-man_wg-quick.8 new file mode 100644 index 000000000000..96d988cf7162 --- /dev/null +++ b/net/amnezia-tools/files/patch-man_wg-quick.8 @@ -0,0 +1,204 @@ +--- man/wg-quick.8.orig 2024-10-01 13:02:42 UTC ++++ man/wg-quick.8 +@@ -1,10 +1,10 @@ +-.TH WG-QUICK 8 "2016 January 1" ZX2C4 "WireGuard" ++.TH AWG-QUICK 8 "2025 August 8" AWG "AmneziaWG" + + .SH NAME +-wg-quick - set up a WireGuard interface simply ++awg-quick - set up a WireGuard interface simply + + .SH SYNOPSIS +-.B wg-quick ++.B awg-quick + [ + .I up + | +@@ -13,6 +13,8 @@ wg-quick - set up a WireGuard interface simply + .I save + | + .I strip ++| ++.I reload + ] [ + .I CONFIG_FILE + | +@@ -31,9 +33,9 @@ with all + runs pre/post down scripts. Running \fIsave\fP saves the configuration of an existing + interface without bringing the interface down. Use \fIstrip\fP to output a configuration file + with all +-.BR wg-quick (8)-specific ++.BR awg-quick (8)-specific + options removed, suitable for use with +-.BR wg (8). ++.BR awg (8). + + \fICONFIG_FILE\fP is a configuration file, whose filename is the interface name + followed by `.conf'. Otherwise, \fIINTERFACE\fP is an interface name, with configuration +@@ -41,24 +43,24 @@ Generally speaking, this utility is just a simple scri + search paths. + + Generally speaking, this utility is just a simple script that wraps invocations to +-.BR wg (8) ++.BR awg (8) + and +-.BR ip (8) +-in order to set up a WireGuard interface. It is designed for users with simple ++.BR ifconfig (8) ++in order to set up a AmneziaWG interface. It is designed for users with simple + needs, and users with more advanced needs are highly encouraged to use a more + specific tool, a more complete network manager, or otherwise just use +-.BR wg (8) ++.BR awg (8) + and +-.BR ip (8), ++.BR route (8), + as usual. + + .SH CONFIGURATION + + The configuration file adds a few extra configuration values to the format understood by +-.BR wg (8) ++.BR awg (8) + in order to configure additional attributes of an interface. It handles the + values that it understands, and then it passes the remaining ones directly to +-.BR wg (8) ++.BR awg (8) + for further processing. + + It infers all routes from the list of peers' allowed IPs, and automatically adds +@@ -67,7 +69,7 @@ to handle overriding of the default gateway. + .BR ip-rule (8) + to handle overriding of the default gateway. + +-The configuration file will be passed directly to \fBwg\fP(8)'s `setconf' ++The configuration file will be passed directly to \fBawg\fP(8)'s `setconf' + sub-command, with the exception of the following additions to the \fIInterface\fP section, + which are handled by this tool: + +@@ -102,9 +104,29 @@ interface is removed will therefore be overwritten. + SaveConfig \(em if set to `true', the configuration is saved from the current state of the + interface upon shutdown. Any changes made to the configuration file before the + interface is removed will therefore be overwritten. ++.IP \(bu ++Description \(em will setup interface description visible in ifconfig and SNMP. ++.IP \(bu ++UserLand \(em enforce to use amnezia-go instead of kernel driver, you can use ++\fBamnezia-wireguard-go\fP to install it. ++.IP \(bu ++Routes \(em 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. ++.IP \(bu ++Monitor default route change \(em do not run `route monitor` when there is no need to do anything on default ++change. That will help to avoid keeping two bashes and one route binaries ++per interface always. ++Default value is true. ++.IP \(bu ++Track DNS Changes \(em if peer endpoint defined as a hostname - periodically (timeout in seconds) ++check if hostname was changed, and if changed update peer endpoint according ++to new hostname. Quite useful in case of DDNS configurations. ++Default values is 0, disabled. + + .P +-Recommended \fIINTERFACE\fP names include `wg0' or `wgvpn0' or even `wgmgmtlan0'. ++Recommended \fIINTERFACE\fP names include `amn0' or `awg0'. + However, the number at the end is in fact optional, and really + any free-form string [a-zA-Z0-9_=+.-]{1,15} will work. So even interface names corresponding + to geographic locations would suffice, such as `cincinnati', `nyc', or `paris', if that's +@@ -113,9 +135,9 @@ These examples draw on the same syntax found for + .SH EXAMPLES + + These examples draw on the same syntax found for +-.BR wg (8), ++.BR awg (8), + and a more complete description may be found there. Bold lines below are for options that extend +-.BR wg (8). ++.BR awg (8). + + The following might be used for connecting as a client to a VPN gateway for tunneling all + traffic: +@@ -151,15 +173,15 @@ two lines `PostUp` and `PreDown` lines to the `[Interf + to prevent the flow of unencrypted packets through the non-WireGuard interfaces, by adding the following + two lines `PostUp` and `PreDown` lines to the `[Interface]` section: + +- \fBPostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT\fP ++ \fBPostUp = iptables -I OUTPUT ! -o %i -m mark ! --mark $(awg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT\fP + .br +- \fBPreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(wg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT\fP ++ \fBPreDown = iptables -D OUTPUT ! -o %i -m mark ! --mark $(awg show %i fwmark) -m addrtype ! --dst-type LOCAL -j REJECT\fP + .br + + The `PostUp' and `PreDown' fields have been added to specify an + .BR iptables (8) + command which, when used with interfaces that have a peer that specifies 0.0.0.0/0 as part of the +-`AllowedIPs', works together with wg-quick's fwmark usage in order to drop all packets that ++`AllowedIPs', works together with awg-quick's fwmark usage in order to drop all packets that + are either not coming out of the tunnel encrypted or not going through the tunnel itself. (Note + that this continues to allow most DHCP traffic through, since most DHCP clients make use of PF_PACKET + sockets, which bypass Netfilter.) When IPv6 is in use, additional similar lines could be added using +@@ -168,7 +190,7 @@ Or, perhaps it is desirable to store private keys in e + Or, perhaps it is desirable to store private keys in encrypted form, such as through use of + .BR pass (1): + +- \fBPreUp = wg set %i private-key <(pass WireGuard/private-keys/%i)\fP ++ \fBPreUp = awg set %i private-key <(pass WireGuard/private-keys/%i)\fP + .br + + For use on a server, the following is a more complicated example involving multiple peers: +@@ -242,36 +264,43 @@ in the filename: + These configuration files may be placed in any directory, putting the desired interface name + in the filename: + +-\fB # wg-quick up /path/to/wgnet0.conf\fP ++\fB # awg-quick up amn0\fP + ++or ++ ++\fB # awg-quick up /path/to/amn0.conf\fP ++ + For convenience, if only an interface name is supplied, it automatically chooses a path in + `/etc/wireguard/': + +-\fB # wg-quick up wgnet0\fP ++\fB # awg-quick up amn0\fP + + This will load the configuration file `/etc/wireguard/wgnet0.conf'. + + The \fIstrip\fP command is useful for reloading configuration files without disrupting active + sessions: + +-\fB # wg syncconf wgnet0 <(wg-quick strip wgnet0)\fP ++\fB # awg syncconf amn0 <(awg-quick strip amn)\fP + ++or ++ ++\fB # awg-quick reload amn0\fP ++ ++ + .SH SEE ALSO +-.BR wg (8), +-.BR ip (8), +-.BR ip-link (8), +-.BR ip-address (8), +-.BR ip-route (8), +-.BR ip-rule (8), +-.BR resolvconf (8). ++.BR awg (8), ++.BR ifconfig (8), ++.BR route (8), + + .SH AUTHOR ++.B awg-quick ++based on + .B wg-quick + was written by + .MT Jason@zx2c4.com + Jason A. Donenfeld + .ME . + For updates and more information, a project page is available on the +-.UR https://\:www.wireguard.com/ ++.UR https://\:github.com/amnezia-vpn/amneziawg-tools/ + World Wide Web + .UE . diff --git a/net/amnezia-tools/files/patch-man_wg.8 b/net/amnezia-tools/files/patch-man_wg.8 index ab226a3cc1e7..87e018ff2856 100644 --- a/net/amnezia-tools/files/patch-man_wg.8 +++ b/net/amnezia-tools/files/patch-man_wg.8 @@ -1,24 +1,158 @@ --- man/wg.8.orig 2024-10-01 13:02:42 UTC +++ man/wg.8 -@@ -55,7 +55,7 @@ by \fICONFIGURATION FILE FORMAT\fP below. +@@ -1,10 +1,10 @@ +-.TH WG 8 "2015 August 13" ZX2C4 "WireGuard" ++.TH AWG 8 "2025 August 8" AWG "AmneziaWG" + + .SH NAME +-wg - set and retrieve configuration of WireGuard interfaces ++awg - set and retrieve configuration of WireGuard interfaces + + .SH SYNOPSIS +-.B wg ++.B awg + [ + .I COMMAND + ] [ +@@ -15,17 +15,15 @@ wg - set and retrieve configuration of WireGuard inter + + .SH DESCRIPTION + +-.B wg ++.B awg + is the configuration utility for getting and setting the configuration of + WireGuard tunnel interfaces. The interfaces themselves can be added and removed + using +-.BR ip-link (8) ++.BR ifconfig (8) + and their IP addresses and routing tables can be set using +-.BR ip-address (8) +-and +-.BR ip-route (8). ++.BR route (8). + The +-.B wg ++.B awg + utility provides a series of sub-commands for changing WireGuard-specific + aspects of WireGuard interfaces. + +@@ -36,7 +34,7 @@ Sub-commands that take an INTERFACE must be passed a W + .SH COMMANDS + + .TP +-\fBshow\fP { \fI\fP | \fIall\fP | \fIinterfaces\fP } [\fIpublic-key\fP | \fIprivate-key\fP | \fIlisten-port\fP | \fIfwmark\fP | \fIpeers\fP | \fIpreshared-keys\fP | \fIendpoints\fP | \fIallowed-ips\fP | \fIlatest-handshakes\fP | \fIpersistent-keepalive\fP | \fItransfer\fP | \fIdump\fP] ++\fBshow\fP { \fI\fP | \fIall\fP | \fIinterfaces\fP } [\fIpublic-key\fP | \fIprivate-key\fP | \fIlisten-port\fP | \fIfwmark\fP | \fIpeers\fP | \fIpreshared-keys\fP | \fIendpoints\fP | \fIallowed-ips\fP | \fIlatest-handshakes\fP | \fIpersistent-keepalive\fP | \fItransfer\fP | \fIdump\fP | \fIjc\fP | \fIjmin\fP | \fIjmax\fP | \fIs1\fP | \fIs2\fP | \fIh1\fP | \fIh2\fP | \fIh3\fP | \fIh4\fP] + Shows current WireGuard configuration and runtime information of specified \fI\fP. + If no \fI\fP is specified, \fI\fP defaults to \fIall\fP. + If \fIinterfaces\fP is specified, prints a list of all WireGuard interfaces, +@@ -55,7 +53,7 @@ by \fICONFIGURATION FILE FORMAT\fP below. Shows the current configuration of \fI\fP in the format described by \fICONFIGURATION FILE FORMAT\fP below. .TP -\fBset\fP \fI\fP [\fIlisten-port\fP \fI\fP] [\fIfwmark\fP \fI\fP] [\fIprivate-key\fP \fI\fP] [\fIpeer\fP \fI\fP [\fIremove\fP] [\fIpreshared-key\fP \fI\fP] [\fIendpoint\fP \fI:\fP] [\fIpersistent-keepalive\fP \fI\fP] [\fIallowed-ips\fP \fI/\fP[,\fI/\fP]...] ]... -+\fBset\fP \fI\fP [\fIlisten-port\fP \fI\fP] [\fIfwmark\fP \fI\fP] [\fIprivate-key\fP \fI\fP] [\fIpeer\fP \fI\fP [\fIremove\fP] [\fIpreshared-key\fP \fI\fP] [\fIendpoint\fP \fI:\fP] [\fIpersistent-keepalive\fP \fI\fP] [\fIallowed-ips\fP \fI[+|-]/\fP[,\fI[+|-]/\fP]...] ]... ++\fBset\fP \fI\fP [\fIlisten-port\fP \fI\fP] [\fIfwmark\fP \fI\fP] [\fIprivate-key\fP \fI\fP] [\fIjc ]\fP [\fI]\fP [\fIjmax \fP] [\fIs1 \fP] [\fIs2 \fP] [\fIh1\fP] [\fIh2

\fP] [\fIh3

\fP] [\fIh4

\fP] [\fIpeer\fP \fI\fP [\fIremove\fP] [\fIpreshared-key\fP \fI\fP] [\fIendpoint\fP \fI:\fP] [\fIpersistent-keepalive\fP \fI\fP] [\fIallowed-ips\fP \fI[+|-]/\fP[,\fI[+|-]/\fP]...] ]... Sets configuration values for the specified \fI\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 +@@ -72,7 +70,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 +@@ -119,11 +121,52 @@ A private key and a corresponding public key may be ge + .br + $ umask 077 + .br +- $ wg genkey | tee private.key | wg pubkey > public.key ++ $ awg genkey | tee private.key | awg pubkey > public.key + .TP + \fBhelp\fP + Shows usage message. + ++.SH AMNEZIA OPTIONS ++Configuration options to be use in order to bypass DPI filters, these options appears in ++\fBshow\fP, \fBset\fP, \fBsetconf\fP, \fBaddconf\fP commands. ++ ++.TP ++\fBjc\fP ++Number of junk packets before handshake. ++.br ++1–128 (recomended 3–10) ++ ++.TP ++\fBjmin\fP ++Minimum size of junk packets. ++.br ++jmin: < jmax (recomended ~ 8) ++ ++.TP ++\fBjmax\fP ++Maximum size of junk packets. ++.br ++jmax: ≤ 1280 (recomended ~ 80) ++ ++.TP ++\fBs1\fP ++Size of handshake initiation packet prepend junk. Should be the same on both ends. ++.br ++0–1132 (recomended 15–150), s1 + 56 ≠ s2 ++ ++.TP ++\fBs2\fP ++Size of handshake response packet prepend junk. Should be the same on both ends. ++.br ++0–1188 (recomended 15–150), s1 + 56 ≠ s2 ++ ++.TP ++\fBh1-h4\fP ++Custom identifiers for initiation/response/cookie/data packets. Should be the same on both ends. ++.br ++The unique value in range of 5 - 4,294,967,295 (0x5 - 0xFFFFFFFF), h1 != h2 != h3 != h4 ++ ++ + .SH CONFIGURATION FILE FORMAT + The configuration file format is based on \fIINI\fP. There are two top level sections + -- \fIInterface\fP and \fIPeer\fP. Multiple \fIPeer\fP sections may be specified, but +@@ -224,7 +267,7 @@ on a per-interface basis by using + on a per-interface basis by using + .BR ifconfig (1): + +-\fB # ifconfig wg0 debug ++\fB # ifconfig amn0 debug\fP + + On userspace implementations, it is customary to set the \fILOG_LEVEL\fP environment variable to \fIverbose\fP. + +@@ -240,19 +283,18 @@ If set to an integer or to \fIinfinity\fP, DNS resolut + If set to an integer or to \fIinfinity\fP, DNS resolution for each peer's endpoint will be retried that many times for non-permanent errors, with an increasing delay between retries. If unset, the default is 15 retries. + + .SH SEE ALSO +-.BR wg-quick (8), +-.BR ip (8), +-.BR ip-link (8), +-.BR ip-address (8), +-.BR ip-route (8). ++.BR awg-quick (8), ++.BR ifconfig (8), ++.BR route (8). + + .SH AUTHOR ++awg based on + .B wg +-was written by ++that was written by + .MT Jason@zx2c4.com + Jason A. Donenfeld + .ME . + For updates and more information, a project page is available on the +-.UR https://\:www.wireguard.com/ ++.UR https://\:github.com/amnezia-vpn/amneziawg-tools/ + World Wide Web + .UE . diff --git a/net/amnezia-tools/files/patch-wg-quick_freebsd.bash b/net/amnezia-tools/files/patch-wg-quick_freebsd.bash index f130e5f49a6d..6d218f256182 100644 --- a/net/amnezia-tools/files/patch-wg-quick_freebsd.bash +++ b/net/amnezia-tools/files/patch-wg-quick_freebsd.bash @@ -1,316 +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=( ${AWG_QUICK_CONFIG_SEARCH_PATHS:-/usr/local/etc/amnezia} ) ++CONFIG_SEARCH_PATHS=( ${AWG_QUICK_CONFIG_SEARCH_PATHS:-%%ETCDIR%%} ) 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