Last active
January 15, 2025 15:09
-
-
Save kafeg/c40abad3b8987f2e3eeace2c595c8dcc to your computer and use it in GitHub Desktop.
Synology WireGuard and AmneziaWG build script: kernel module and tools
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/sh | |
set -x | |
# Place the manage.sh, awg (or wg), awg-quick (or wg-quick), amneziawg.ko (or wireguard.ko) and your wg0.conf somewhere to filesystem on Synology | |
# Use start/stop for manage as regular process or installsvc/uninstallsvc/startsvc/stopsvc to manage as systemd service | |
WG="awg" | |
WGQUICK="awg-quick" | |
KMOD="amneziawg.ko" | |
CONF="wg0.conf" | |
SVCNAME="amneziawg" | |
SCRIPT_DIR="$( cd "$( dirname "${BASH_SOURCE[0]}" )" &> /dev/null && pwd )" | |
echo "Script directory: $SCRIPT_DIR" | |
# Function to check if the script is running as root | |
require_root() { | |
if [ "$EUID" -ne 0 ]; then | |
echo "This script must be run as root. Please re-run as root or with sudo." | |
exit 1 | |
fi | |
} | |
# Function to perform common checks | |
check_environment() { | |
REQUIRED_FILES=("$CONF" "$WG" "$WGQUICK" $KMOD) | |
for FILE in "${REQUIRED_FILES[@]}"; do | |
if [ ! -f "$SCRIPT_DIR/$FILE" ]; then | |
echo "Error: Required file $FILE is missing in the script directory." | |
exit 1 | |
fi | |
done | |
for FILE in "$WG" "$WGQUICK"; do | |
if [ ! -x "$SCRIPT_DIR/$FILE" ]; then | |
echo "Error: $FILE does not have execution permissions." | |
exit 1 | |
fi | |
done | |
ARCH=$(uname -m) | |
if ! file $SCRIPT_DIR/$WG | grep -q "$ARCH" || ! file $SCRIPT_DIR/$KMOD | grep -q "$ARCH"; then | |
echo "Error: One or more binaries are not built for the current architecture ($ARCH)." | |
exit 1 | |
fi | |
if ! grep -qE "^#?DNS" $SCRIPT_DIR/$CONF && ! grep -qE "^AllowedIPs.*0\.0\.0\.0/0|::/0" $SCRIPT_DIR/$CONF; then | |
echo "Error: $CONF does not meet the required conditions. Ensure DNS lines are commented or removed and AllowedIPs does not include 0.0.0.0/0 or ::/0 (to prevent all traffic go over VPN, use something like 10.8.1.0/24 instead)." | |
exit 1 | |
fi | |
} | |
require_root | |
case $1 in | |
start) | |
check_environment | |
/sbin/insmod $SCRIPT_DIR/$KMOD | |
$SCRIPT_DIR/$WGQUICK up $SCRIPT_DIR/$CONF | |
exit 0 | |
;; | |
stop) | |
check_environment | |
$SCRIPT_DIR/$WGQUICK down $SCRIPT_DIR/$CONF | |
/sbin/rmmod $SCRIPT_DIR/$KMOD | |
exit 0 | |
;; | |
startsvc) | |
check_environment | |
systemctl start $SVCNAME.service | |
;; | |
stopsvc) | |
check_environment | |
systemctl stop $SVCNAME.service | |
;; | |
status) | |
check_environment | |
/sbin/lsmod | grep $SVCNAME | |
$SCRIPT_DIR/$WG show | |
systemctl status amneziawg.service | |
journalctl -u amneziawg.service | |
;; | |
installsvc) | |
check_environment | |
SCRIPT_PATH=$(readlink -f "$0") | |
SCRIPT_DIR=$(dirname "$SCRIPT_PATH") | |
SERVICE_FILE_CONTENT="""[Unit] | |
Description=Manage $SVCNAME | |
After=network.target | |
[Service] | |
Type=simple | |
ExecStart=$SCRIPT_DIR/manage.sh start | |
ExecStop=$SCRIPT_DIR/manage.sh stop | |
RemainAfterExit=yes | |
[Install] | |
WantedBy=multi-user.target | |
""" | |
SERVICE_PATH="/etc/systemd/system/$SVCNAME.service" | |
echo "$SERVICE_FILE_CONTENT" | sudo tee $SERVICE_PATH > /dev/null | |
systemctl daemon-reload | |
systemctl enable $SVCNAME.service | |
echo "Service installed and enabled on boot." | |
;; | |
uninstallsvc) | |
check_environment | |
SERVICE_PATH="/etc/systemd/system/$SVCNAME.service" | |
if [ -f $SERVICE_PATH ]; then | |
systemctl disable $SVCNAME.service | |
rm -f $SERVICE_PATH | |
systemctl daemon-reload | |
echo "Service uninstalled." | |
else | |
echo "Service file not found. Nothing to uninstall." | |
fi | |
;; | |
*) | |
echo "Usage: $0 {start|stop|status|installsvc|uninstallsvc}" | |
exit 1 | |
;; | |
esac |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
#!/bin/bash | |
# This script helps to cross-compile the WireGuard and AmneziaWG for Synology host (intel/arm targets) on Linux x64 host (for e.g. Ubuntu 22.04 and above). | |
# It compiles kernel module and wg/wg-quick tools. | |
# Usage: | |
# - download and save for e.g. to '/opt/syno-wg/syno-wg-build.sh' | |
# - detect your DSM version and device processor architecture. Use ssh to Synology and execute: | |
# - - awk -F '\"' '/majorversion/ {maj=$2} /minorversion/ {min=$2} END {print maj "." min}' /etc.defaults/VERSION | |
# - - awk -F '\"' '/platform_name/ {print $2}' /etc.defaults/synoinfo.conf | |
# - output can be: | |
# - - 7.2 | |
# - - r1000 or rtd1296, ... | |
# - call the script: | |
# - - cd opt/syno-wg/ | |
# - - ./syno-wg-build.sh -v 7.2 -a r1000 -t wg # build WireGuard using toolchain for Intel-based Synology and DSM 7.2 | |
# - - ./syno-wg-build.sh -v 7.2 -a r1000 -t awg # build AmneziaWG using toolchain for Intel-based Synology and DSM 7.2 | |
# - - ./syno-wg-build.sh -v 7.2 -a rtd1296 -t wg # build WireGuard using toolchain for ARM Synology and DSM 7.2 | |
# - - ./syno-wg-build.sh -v 7.2 -a rtd1296 -t awg # build AmneziaWG using toolchain for ARM Synology and DSM 7.2 | |
# - results are for example (<DSM_ARCH>-<DSM_VER> templated): | |
# - - build_env/ds.r1000-7.2/opt/wg-r1000-7.2/wg-out/ | |
# - - build_env/ds.r1000-7.2/opt/awg-r1000-7.2/awg-out/ | |
# - - build_env/ds.rtd1296-7.2/opt/wg-rtd1296-7.2/wg-out/ | |
# - - build_env/ds.rtd1296-7.2/opt/awg-rtd1296-7.2/awg-out/ | |
CURRENT=`pwd` | |
# Check for x64 Linux host | |
if [ "$(uname -m)" != "x86_64" ] || [ "$(uname -s)" != "Linux" ]; then | |
echo "This script must be run on a x64 Linux host." | |
exit 1 | |
fi | |
# Usage function | |
usage() { | |
echo "Usage: $0 -v <DSM version> -a <DSM architecture> -t <wg type>" | |
echo " -v DSM version (e.g., 7.2)" | |
echo " -a DSM architecture (e.g., avoton, broadwell, etc.)" | |
echo " -t WG type ('wg' WireGuard or 'awg' for AmneziaWG)" | |
echo | |
echo "To determine DSM version on your Synology device, run the following command:" | |
echo " awk -F '\"' '/majorversion/ {maj=\$2} /minorversion/ {min=\$2} END {print maj \".\" min}' /etc.defaults/VERSION" | |
echo | |
echo "To determine DSM architecture on your Synology device, run the following command:" | |
echo " awk -F '\"' '/platform_name/ {print \$2}' /etc.defaults/synoinfo.conf" | |
exit 1 | |
} | |
# Parse input parameters | |
while getopts "v:a:t:" opt; do | |
case $opt in | |
v) DSM_VER="$OPTARG" ;; | |
a) DSM_ARCH="$OPTARG" ;; | |
t) WG_TYPE="$OPTARG" ;; | |
*) usage ;; | |
esac | |
done | |
# Validate input parameters | |
if [ -z "$DSM_VER" ] || [ -z "$DSM_ARCH" ] || [ -z "$WG_TYPE" ]; then | |
echo "Error: Missing required parameters." | |
usage | |
fi | |
if [ "$WG_TYPE" != "wg" ] && [ "$WG_TYPE" != "awg" ]; then | |
echo "Error: WG type must be 'wg' WireGuard or 'awg' for AmneziaWG." | |
usage | |
fi | |
# Print parameters | |
echo "DSM Version: $DSM_VER" | |
echo "DSM Architecture: $DSM_ARCH" | |
echo "WG Type: $WG_TYPE" | |
# Clone Synology toolchain scripts | |
echo "Checking Synology toolchain scripts..." | |
if [ ! -d "pkgscripts-ng" ]; then | |
git clone https://github.com/SynologyOpenSource/pkgscripts-ng || { echo "Failed to clone pkgscripts-ng repository."; exit 1; } | |
else | |
echo "Synology toolchain scripts already present, skipping clone." | |
fi | |
# Prepare toolchain | |
CHROOT_DIR="$CURRENT/build_env/ds.$DSM_ARCH-$DSM_VER" | |
OPT_DIR="$CHROOT_DIR/opt/$WG_TYPE-$DSM_ARCH-$DSM_VER" | |
OPT_DIR_CHROOT="/opt/$WG_TYPE-$DSM_ARCH-$DSM_VER" | |
if [ ! -d "$CHROOT_DIR" ]; then | |
sudo $CURRENT/pkgscripts-ng/EnvDeploy -v "$DSM_VER" -p "$DSM_ARCH" --noclear || { echo "Failed to prepare toolchain for DSM version $DSM_VER and architecture $DSM_ARCH."; exit 1; } | |
sudo chown -R $(whoami):$(whoami) "$CURRENT" | |
else | |
echo "Toolchain environment already exists, skipping setup." | |
fi | |
mkdir -p "$OPT_DIR" | |
# Determine libmnl and WG versions | |
LIBMNL_URL="https://netfilter.org/projects/libmnl/files/?C=M;O=D" | |
BASE_WIREGUARD_URL="https://git.zx2c4.com" | |
WIREGUARD_REPO_NAME="wireguard-linux-compat" | |
WIREGUARD_TOOLS_REPO_NAME="wireguard-tools" | |
BASE_AWG_URL="https://github.com/amnezia-vpn" | |
AWG_REPO_NAME="amneziawg-linux-kernel-module" | |
AWG_TOOLS_REPO_NAME="amneziawg-tools" | |
# Download and extract latest libmnl if not already downloaded | |
LIBMNL_VERSION=$(wget --no-hsts -q "$LIBMNL_URL" -O - | grep -oP 'a href="libmnl-\K[0-9.]*?(?=\.tar\.bz2)' | head -n 1) | |
echo "Detected libmnl version: $LIBMNL_VERSION" | |
LIBMNL_ARCHIVE="$OPT_DIR/libmnl-$LIBMNL_VERSION.tar.bz2" | |
if [ ! -f "$LIBMNL_ARCHIVE" ]; then | |
echo "Downloading libmnl version: $LIBMNL_VERSION" | |
wget "https://netfilter.org/projects/libmnl/files/libmnl-$LIBMNL_VERSION.tar.bz2" -O "$LIBMNL_ARCHIVE" || { echo "Failed to download libmnl."; exit 1; } | |
sudo rm -rf $OPT_DIR/libmnl-$LIBMNL_VERSION | |
tar -xjf "$LIBMNL_ARCHIVE" -C "$OPT_DIR" || { echo "Failed to extract libmnl."; exit 1; } | |
else | |
echo "libmnl version $LIBMNL_VERSION already downloaded and unpacked." | |
fi | |
# Clone WG or AWG repositories into opt directory | |
if [ "$WG_TYPE" == "wg" ]; then | |
echo "Checking WireGuard repositories..." | |
[ ! -d "$OPT_DIR/$WIREGUARD_REPO_NAME" ] && git clone "$BASE_WIREGUARD_URL/$WIREGUARD_REPO_NAME" "$OPT_DIR/$WIREGUARD_REPO_NAME" || echo "WireGuard kernel module repository already present." | |
[ ! -d "$OPT_DIR/$WIREGUARD_TOOLS_REPO_NAME" ] && git clone "$BASE_WIREGUARD_URL/$WIREGUARD_TOOLS_REPO_NAME" "$OPT_DIR/$WIREGUARD_TOOLS_REPO_NAME" || echo "WireGuard tools repository already present." | |
else | |
echo "Checking AmneziaWG repositories..." | |
[ ! -d "$OPT_DIR/$AWG_REPO_NAME" ] && git clone "$BASE_AWG_URL/$AWG_REPO_NAME" "$OPT_DIR/$AWG_REPO_NAME" || echo "AmneziaWG kernel module repository already present." | |
[ ! -d "$OPT_DIR/$AWG_TOOLS_REPO_NAME" ] && git clone "$BASE_AWG_URL/$AWG_TOOLS_REPO_NAME" "$OPT_DIR/$AWG_TOOLS_REPO_NAME" || echo "AmneziaWG tools repository already present." | |
fi | |
# Print all versions | |
echo "Libmnl version: $LIBMNL_VERSION" | |
if [ "$WG_TYPE" == "wg" ]; then | |
echo "WireGuard kernel module cloned to: $OPT_DIR/$WIREGUARD_REPO_NAME" | |
echo "WireGuard tools cloned to: $OPT_DIR/$WIREGUARD_TOOLS_REPO_NAME" | |
else | |
echo "AmneziaWG kernel module cloned to: $OPT_DIR/$AWG_REPO_NAME" | |
echo "AmneziaWG tools cloned to: $OPT_DIR/$AWG_TOOLS_REPO_NAME" | |
fi | |
CROSS_COMPILE_ARGS="" | |
CROSS_COMPILE_LIBMNL_CONFIG_ARGS="" | |
CROSS_COMPILE_PATH="" | |
if [ -f $CHROOT_DIR/usr/local/aarch64-unknown-linux-gnu/bin/aarch64-unknown-linux-gnu-gcc ]; then | |
ARM64_PREFIX="/usr/local/aarch64-unknown-linux-gnu/bin/aarch64-unknown-linux-gnu-" | |
CROSS_COMPILE_ARGS="ARCH=arm64 CROSS_COMPILE=$ARM64_PREFIX CC=${ARM64_PREFIX}gcc LD=${ARM64_PREFIX}ld AR=${ARM64_PREFIX}ar RANLIB=${ARM64_PREFIX}ranlib CCLD=${ARM64_PREFIX}gcc" #"CFLAGS=\"--sysroot=/usr/local/sysroot\" LDFLAGS=\"--sysroot=/usr/local/sysroot\"" | |
CROSS_COMPILE_LIBMNL_CONFIG_ARGS="--host=aarch64-unknown-linux-gnu" | |
CROSS_COMPILE_PATH="/usr/local/aarch64-unknown-linux-gnu/bin" | |
fi | |
# Build libmnl within chroot | |
echo "Building libmnl within chroot..." | |
if [ -d "$CHROOT_DIR" ]; then | |
sudo chroot "$CHROOT_DIR" /bin/bash -c "\ | |
export PATH="$CROSS_COMPILE_PATH:$PATH" && \ | |
echo $PATH && \ | |
cd $OPT_DIR_CHROOT/libmnl-$LIBMNL_VERSION && ./configure $CROSS_COMPILE_LIBMNL_CONFIG_ARGS --prefix=/usr && make $CROSS_COMPILE_ARGS && make install" | |
if [ $? -ne 0 ]; then | |
echo "libmnl build failed." | |
exit 1 | |
else | |
echo "libmnl build completed successfully." | |
fi | |
file $OPT_DIR_CHROOT/libmnl-1.0.5/src/.libs/libmnl.so.0.2.0 | |
else | |
echo "Chroot environment not found, libmnl build cannot proceed." | |
exit 1 | |
fi | |
#exit 1 | |
# Build WireGuard or AWG kernel module within chroot | |
echo "Building $WG_TYPE kernel module within chroot..." | |
if [ -d "$CHROOT_DIR" ]; then | |
sudo chroot "$CHROOT_DIR" /bin/bash -c "\ | |
if [ \"$WG_TYPE\" == \"wg\" ]; then | |
export PATH="$CROSS_COMPILE_PATH:$PATH" && \ | |
echo $PATH && \ | |
cd $OPT_DIR_CHROOT/$WIREGUARD_REPO_NAME/src && \ | |
sed \"s#KERNELDIR ?= .*#KERNELDIR ?= /usr/local/sysroot/usr/lib/modules/DSM-$DSM_VER/build#\" -i Makefile && \ | |
make $CROSS_COMPILE_ARGS && mkdir -p $OPT_DIR_CHROOT/wg-out && cp wireguard.ko $OPT_DIR_CHROOT/wg-out/ | |
else | |
export PATH="$CROSS_COMPILE_PATH:$PATH" && \ | |
echo $PATH && \ | |
cd $OPT_DIR_CHROOT/$AWG_REPO_NAME/src && \ | |
sed \"s#KERNELDIR ?= .*#KERNELDIR ?= /usr/local/sysroot/usr/lib/modules/DSM-$DSM_VER/build#\" -i Makefile && \ | |
sed \"s#KERNELRELEASE ?= .*#KERNELRELEASE ?= 1#\" -i Makefile && \ | |
rm -f kernel && ln -s /usr/local/sysroot/usr/lib/modules/DSM-$DSM_VER/build kernel && \ | |
pwd && ls -alh ./ && ls -alh ./kernel/ && \ | |
make $CROSS_COMPILE_ARGS && mkdir -p $OPT_DIR_CHROOT/awg-out && cp amneziawg.ko $OPT_DIR_CHROOT/awg-out/ | |
fi" | |
if [ $? -ne 0 ]; then | |
echo "$WG_TYPE kernel module build failed." | |
exit 1 | |
else | |
echo "$WG_TYPE kernel module build completed successfully." | |
fi | |
else | |
echo "Chroot environment not found, $WG_TYPE kernel module build cannot proceed." | |
exit 1 | |
fi | |
# Build WireGuard or AWG tools within chroot | |
echo "Building $WG_TYPE tools within chroot..." | |
if [ -d "$CHROOT_DIR" ]; then | |
sudo chroot "$CHROOT_DIR" /bin/bash -c "\ | |
if [ \"$WG_TYPE\" == \"wg\" ]; then | |
export PATH="$CROSS_COMPILE_PATH:$PATH" && \ | |
echo $PATH && \ | |
cd $OPT_DIR_CHROOT/$WIREGUARD_TOOLS_REPO_NAME/src && \ | |
make $CROSS_COMPILE_ARGS && mkdir -p $OPT_DIR_CHROOT/wg-out && cp wg $OPT_DIR_CHROOT/wg-out/wg && cp wg-quick/linux.bash $OPT_DIR_CHROOT/wg-out/wg-quick && \ | |
chmod a+x $OPT_DIR_CHROOT/wg-out/wg* | |
else | |
export PATH="$CROSS_COMPILE_PATH:$PATH" && \ | |
echo $PATH && \ | |
cd $OPT_DIR_CHROOT/$AWG_TOOLS_REPO_NAME/src && \ | |
make $CROSS_COMPILE_ARGS && mkdir -p $OPT_DIR_CHROOT/awg-out && cp wg $OPT_DIR_CHROOT/awg-out/awg && cp wg-quick/linux.bash $OPT_DIR_CHROOT/awg-out/awg-quick && \ | |
chmod a+x $OPT_DIR_CHROOT/awg-out/awg* | |
fi" | |
if [ $? -ne 0 ]; then | |
echo "$WG_TYPE tools build failed." | |
exit 1 | |
else | |
echo "$WG_TYPE tools build completed successfully." | |
fi | |
else | |
echo "Chroot environment not found, $WG_TYPE tools build cannot proceed." | |
exit 1 | |
fi | |
sudo chown -R $(whoami):$(whoami) "$OPT_DIR" | |
if [ "$WG_TYPE" == "wg" ]; then | |
ls -alh $OPT_DIR/wg-out/ | |
file $OPT_DIR/wg-out/* | |
file $OPT_DIR/libmnl-1.0.5/src/.libs/libmnl.so.0.2.0 | |
else | |
ls -alh $OPT_DIR/awg-out/ | |
file $OPT_DIR/awg-out/* | |
file $OPT_DIR/libmnl-1.0.5/src/.libs/libmnl.so.0.2.0 | |
fi | |
exit 0 |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment