From 8703798ca0a09773332a1c702f6c420b29b7ec5b Mon Sep 17 00:00:00 2001 From: Dselen Date: Thu, 22 Aug 2024 13:38:29 -0500 Subject: [PATCH] Modified all files and have a working product, awaiting feedback! --- docker/Dockerfile | 40 ++++----- docker/README.md | 4 +- docker/compose.yaml | 12 +-- docker/entrypoint.sh | 208 ++++++++++++++++++++++++++----------------- 4 files changed, 153 insertions(+), 111 deletions(-) diff --git a/docker/Dockerfile b/docker/Dockerfile index 03b6775..479681e 100644 --- a/docker/Dockerfile +++ b/docker/Dockerfile @@ -3,8 +3,9 @@ FROM debian:stable-slim AS build LABEL maintainer="dselen@nerthus.nl" # Declaring environment variables, change Peernet to an address you like, standard is a 24 bit subnet. -ENV wg_net="10.0.0.1" -# wg_net is used functionally as an ARG for its environment variable nature, do not change unless you know what you are doing. +ARG Git_Url="https://github.com/donaldzou/WGDashboard.git" +ARG wg_net="10.0.0.1" +ARG wg_port="51820" # Following ENV variables are changable on container runtime because /entrypoint.sh handles that. See compose.yaml for more info. ENV tz="Europe/Amsterdam" @@ -12,6 +13,7 @@ ENV global_dns="1.1.1.1" ENV enable="none" ENV isolate="wg0" ENV public_ip="0.0.0.0" +ENV update="yes" # Doing basic system maintenance. Change the timezone to the desired timezone. RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime @@ -20,8 +22,7 @@ RUN ln -sf /usr/share/zoneinfo/${tz} /etc/localtime ENV WGDASH=/opt/wireguarddashboard # Doing package management operations, such as upgrading -RUN apt-get update && \ - apt-get install -y --no-install-recommends \ +RUN apt-get update && apt-get install -y --no-install-recommends \ curl \ git \ iproute2 \ @@ -44,13 +45,8 @@ RUN apt-get update && \ # Removing the Linux Image package to preserve space on the image, for this reason also deleting apt lists, to be able to install packages: run apt update. # Doing WireGuard Dashboard installation measures. Modify the git clone command to get the preferred version, with a specific branch for example. -RUN git clone https://github.com/donaldzou/WGDashboard.git ${WGDASH} \ - && rm ${WGDASH}/.git -rdf \ - && python3 -m venv ${WGDASH}/src/venv \ - && . ${WGDASH}/src/venv/bin/activate \ - && chmod +x ${WGDASH}/src/wgd.sh \ - && cd ${WGDASH}/src \ - && ./wgd.sh install +RUN mkdir -p /setup/conf && mkdir /setup/app && mkdir ${WGDASH} \ + && git clone ${Git_Url} /setup/app # Set the volume to be used for WireGuard configuration persistency. VOLUME /etc/wireguard @@ -60,20 +56,20 @@ VOLUME ${WGDASH} # Also setting the pipefail option, verbose: https://github.com/hadolint/hadolint/wiki/DL4006. SHELL ["/bin/bash", "-o", "pipefail", "-c"] RUN wg genkey | tee /etc/wireguard/wg0_privatekey \ - && echo "[Interface]" > /wg0.conf \ - && echo "SaveConfig = true" >> /wg0.conf \ - && echo "Address = ${wg_net}/24" >> /wg0.conf \ - && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /wg0.conf \ - && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /wg0.conf \ - && echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /wg0.conf \ - && echo "PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /wg0.conf \ - && echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /wg0.conf \ - && echo "ListenPort = 51820" >> /wg0.conf \ - #&& echo "DNS = ${global_dns}" >> /wg0.conf \ + && echo "[Interface]" > /setup/conf/wg0.conf \ + && echo "Address = ${wg_net}/24" >> /setup/conf/wg0.conf \ + && echo "PrivateKey = $(cat /etc/wireguard/wg0_privatekey)" >> /setup/conf/wg0.conf \ + && echo "PostUp = iptables -t nat -I POSTROUTING 1 -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /setup/conf/wg0.conf \ + && echo "PostUp = iptables -I FORWARD -i wg0 -o wg0 -j DROP" >> /setup/conf/wg0.conf \ + && echo "PreDown = iptables -t nat -D POSTROUTING -s ${wg_net}/24 -o $(ip -o -4 route show to default | awk '{print $NF}') -j MASQUERADE" >> /setup/conf/wg0.conf \ + && echo "PreDown = iptables -D FORWARD -i wg0 -o wg0 -j DROP" >> /setup/conf/wg0.conf \ + && echo "ListenPort = ${wg_port}" >> /setup/conf/wg0.conf \ + && echo "SaveConfig = true" >> /setup/conf/wg0.conf \ + && echo "DNS = ${global_dns}" >> /setup/conf/wg0.conf \ && rm /etc/wireguard/wg0_privatekey # Defining a way for Docker to check the health of the container. In this case: checking the login URL. -HEALTHCHECK --interval=30s --timeout=10s --start-period=5s --retries=3 \ +HEALTHCHECK --interval=2m --timeout=1m --start-period=5s --retries=3 \ CMD [ "$(curl -s -o /dev/null -w '%{http_code}' http://localhost:10086/)" -eq "200" ] || exit 1 diff --git a/docker/README.md b/docker/README.md index ced5362..8d2a315 100644 --- a/docker/README.md +++ b/docker/README.md @@ -15,7 +15,9 @@ I have tried to embed some new features such as `isolate` and interface startup ## Getting the container running: To get the container running you either pull the image from the repository, `dselen/wgdashboard:latest`.
-From there either use the environment variables describe below as parameters or use the Docker Compose file: `compose.yaml`. +From there either use the environment variables describe below as parameters or use the Docker Compose file: `compose.yaml`.
+Be careful, the default generated WireGuard configuration file uses port 51820/udp. So use this port if you want to use it out of the box.
+Otherwise edit the configuration file in `/etc/wireguard/wg0.conf`. An example of a simple command to get the container running is show below:
diff --git a/docker/compose.yaml b/docker/compose.yaml index 3d6c082..6d4f2bd 100644 --- a/docker/compose.yaml +++ b/docker/compose.yaml @@ -2,22 +2,22 @@ services: wireguard-dashboard: image: dselen/wgdashboard:latest restart: unless-stopped - container_name: wire-dash + container_name: wgdashboard environment: #- tz= # <--- Set container timezone, default: Europe/Amsterdam. #- global_dns= # <--- Set global DNS address, default: 1.1.1.1. - - enable=wg0,wg2 # <--- Set the interfaces that will be enabled on startup, default: none. The option "off" is also allowed. - - isolate=wg0,wg1 # <--- When set to true, it disallows peers to talk to eachother, setting to false, allows it, default: true. + - enable=wg0 # <--- Set the interfaces that will be enabled on startup, default: none. The option "off" is also allowed. + - isolate=wg0 # <--- When set to true, it disallows peers to talk to eachother, setting to false, allows it, default: true. #- public_ip= # <--- Set public IP to ensure the correct one is chosen, defaulting to the IP give by ifconfig.me. ports: - 10086:10086/tcp - - 51830:51820/udp + - 51820:51820/udp volumes: - - conf:/etc/wireguard - app:/opt/wireguarddashboard + - conf:/etc/wireguard cap_add: - NET_ADMIN volumes: - conf: app: + conf: diff --git a/docker/entrypoint.sh b/docker/entrypoint.sh index 84b9f7f..b3595b8 100644 --- a/docker/entrypoint.sh +++ b/docker/entrypoint.sh @@ -1,9 +1,40 @@ #!/bin/bash + +echo "------------------------- START ----------------------------" echo "Starting the WireGuard Dashboard Docker container." +ensure_installation() { + # When using a custom directory to store the files, this part moves over and makes sure the installation continues. + echo "Checking if everything is present." + + if [ -z "$(ls -A ${WGDASH})" ]; then + echo "Detected empty directory, moving over..." + + mv /setup/app/* ${WGDASH} + python3 -m venv ${WGDASH}/src/venv + . "${WGDASH}/src/venv/bin/activate" + chmod +x ${WGDASH}/src/wgd.sh + cd ${WGDASH}/src + ./wgd.sh install + + echo "Looks like the installation succesfully moved over." + else + echo "Looks like everything is present." + fi + + # This first step is to ensure the wg0.conf file exists, and if not, then its copied over from the ephemeral container storage. + if [ ! -f "/etc/wireguard/wg0.conf" ]; then + echo "Standard wg0 Configuration file not found, grabbing template." + cp "/setup/conf/wg0.conf" "/etc/wireguard/wg0.conf" + else + echo "Standard wg0 Configuration file found, using that." + fi +} + # === CLEAN UP === clean_up() { - echo "--------------------- CLEAN UP -----------------------" + printf "\n------------------------ CLEAN UP --------------------------\n" + # Cleaning out previous data such as the .pid file and starting the WireGuard Dashboard. Making sure to use the python venv. echo "Looking for remains of previous instances..." local pid_file="${WGDASH}/src/gunicorn.pid" @@ -14,6 +45,7 @@ clean_up() { echo "No pid remains found, continuing." fi + # Also check for Python caches (pycache) inspired by https://github.com/shuricksumy local pycache="${WGDASH}/src/__pycache__" if [ -d "$pycache" ]; then local pycache_filecount=$(find "$pycache" -maxdepth 1 -type f | wc -l) @@ -26,89 +58,22 @@ clean_up() { else echo "No pycaches found, continuing." fi - - echo "Setting permissions to not be world-accesible." - chmod 640 /etc/wireguard/* } -# === CORE SERVICES === -start_core() { - echo "--------------------- STARTING CORE -----------------------" - - # This first step is to ensure the wg0.conf file exists, and if not, then its copied over from the ephemeral container storage. - if [ ! -f "/etc/wireguard/wg0.conf" ]; then - cp "/wg0.conf" "/etc/wireguard/wg0.conf" - echo "Standard WG0 Configuration file not found, grabbing template." - else - echo "Standard WG0 Configuration file found, using that." - fi - - echo "Activating Python venv and executing the WireGuard Dashboard service." - . "${WGDASH}"/src/venv/bin/activate - cd "${WGDASH}"/src || return # If changing the directory fails (permission or presence error), then bash will exist this function, causing the WireGuard Dashboard to not be succesfully launched. - bash wgd.sh start - - # Isolated peers feature: - local configurations=(/etc/wireguard/*) - IFS=',' read -r -a do_isolate <<< "${isolate}" - non_isolate=() - - for config in "${configurations[@]}"; do - local config=$(echo "$config" | sed -e 's|.*/etc/wireguard/||' -e 's|\.conf$||') - found=false - for interface in "${do_isolate[@]}"; do - if [[ "$config" == "$interface" ]]; then - found=true - break - fi - done - if [ "$found" = false ]; then - non_isolate+=("$config") - fi - done - - for interface in "${do_isolate[@]}"; do - if [ -f "/etc/wireguard/${interface}.conf" ]; then - echo "Isolating:" $interface - upblocking=$(grep -c "PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf) - downblocking=$(grep -c "PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf) - - if [ "$upblocking" -lt 1 ] && [ "$downblocking" -lt 1 ]; then - sed -i "/PostUp =/a PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf - sed -i "/PreDown =/a PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf - fi - else - echo "Configuration for $interface does not seem to exist, continuing." - fi - done - - for interface in "${non_isolate[@]}"; do - if [ -f "/etc/wireguard/${interface}.conf" ]; then - echo "Removing Isolation if present for:" $interface - sed -i "/PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP/d" /etc/wireguard/${interface}.conf - sed -i "/PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP/d" /etc/wireguard/${interface}.conf - else - echo "Configuration for $interface does not seem to exist, continuing." - fi - done - - # The following section takes care of enabling wireguard interfaces on startup. - IFS=',' read -r -a enable_array <<< "${enable}" - - for interface in "${enable_array[@]}"; do - echo "Preference for $interface to be turned on found." - if [ -f "/etc/wireguard/${interface}.conf" ]; then - echo "Found corresponding configuration file, activating..." - wg-quick up $interface - else - echo "No corresponding configuration file found for $interface doing nothing." - fi - done -} +#update_checker() { + #if [ "$update" = "yes" ]; then + # echo "Activating Python venv and executing the WireGuard Dashboard service." + # . "${WGDASH}/src/venv/bin/activate" + # cd "${WGDASH}"/src || exit + # bash wgd.sh update + #else + # echo "Auto Updater disabled" + #fi +#} # === SET ENV VARS === set_envvars() { - echo "------------- SETTING ENVIRONMENT VARIABLES ----------------" + printf "\n------------- SETTING ENVIRONMENT VARIABLES ----------------\n" # If the timezone is different, for example in North-America or Asia. if [ "${tz}" != "$(cat /etc/timezone)" ]; then @@ -139,9 +104,86 @@ set_envvars() { fi } +# === CORE SERVICES === +start_core() { + printf "\n---------------------- STARTING CORE -----------------------\n" + + echo "Activating Python venv and executing the WireGuard Dashboard service." + . "${WGDASH}"/src/venv/bin/activate + cd "${WGDASH}"/src || return # If changing the directory fails (permission or presence error), then bash will exist this function, causing the WireGuard Dashboard to not be succesfully launched. + bash wgd.sh start + + # Isolated peers feature, first converting the existing configuration files and the given names to arrays. + local configurations=(/etc/wireguard/*) + IFS=',' read -r -a do_isolate <<< "${isolate}" + non_isolate=() + + # Checking if there are matches between the two arrays. + for config in "${configurations[@]}"; do + local config=$(echo "$config" | sed -e 's|.*/etc/wireguard/||' -e 's|\.conf$||') + found=false + for interface in "${do_isolate[@]}"; do + if [[ "$config" == "$interface" ]]; then + found=true + break + fi + done + if [ "$found" = false ]; then + non_isolate+=("$config") + fi + done + + # Isolating the matches. + for interface in "${do_isolate[@]}"; do + if [ -f "/etc/wireguard/${interface}.conf" ]; then + echo "Isolating interface:" $interface + upblocking=$(grep -c "PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf) + downblocking=$(grep -c "PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf) + + if [ "$upblocking" -lt 1 ] && [ "$downblocking" -lt 1 ]; then + sed -i "/PostUp =/a PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf + sed -i "/PreDown =/a PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP" /etc/wireguard/${interface}.conf + fi + else + echo "Configuration for $interface does not seem to exist, continuing." + fi + done + + # Removing isolation for the configurations that did not match. + for interface in "${non_isolate[@]}"; do + if [ -f "/etc/wireguard/${interface}.conf" ]; then + echo "Removing Isolation if present for:" $interface + sed -i "/PostUp = iptables -I FORWARD -i ${interface} -o ${interface} -j DROP/d" /etc/wireguard/${interface}.conf + sed -i "/PreDown = iptables -D FORWARD -i ${interface} -o ${interface} -j DROP/d" /etc/wireguard/${interface}.conf + else + echo "Configuration for $interface does not seem to exist, continuing." + fi + done + + # The following section takes care of enabling wireguard interfaces on startup. Using arrays and given arguments. + IFS=',' read -r -a enable_array <<< "${enable}" + + for interface in "${enable_array[@]}"; do + echo "Enabling interface:" $interface + + local fileperms=$(stat -c "%a" /etc/wireguard/${interface}.conf) + if [ $fileperms -eq 644 ]; then + echo "Configuration is world accessible, adjusting." + chmod 600 "/etc/wireguard/${interface}.conf" + fi + + if [ -f "/etc/wireguard/${interface}.conf" ]; then + wg-quick up $interface + else + echo "No corresponding configuration file found for $interface doing nothing." + fi + done +} + # === CLEAN UP === ensure_blocking() { - echo "-------------- ENSURING CONTAINER CONTINUATION -------------" + printf "\n-------------- ENSURING CONTAINER CONTINUATION -------------\n" + sleep 1s echo "Ensuring container continuation." @@ -149,6 +191,7 @@ ensure_blocking() { if find "/opt/wireguarddashboard/src/log" -mindepth 1 -maxdepth 1 -type f | read -r; then latestErrLog=$(find /opt/wireguarddashboard/src/log -name "error_*.log" | head -n 1) latestAccLog=$(find /opt/wireguarddashboard/src/log -name "access_*.log" | head -n 1) + tail -f "${latestErrLog}" "${latestAccLog}" fi @@ -157,8 +200,9 @@ ensure_blocking() { } # Execute functions for the WireGuard Dashboard services, then set the environment variables +ensure_installation clean_up -repair -start_core +#update_checker set_envvars +start_core ensure_blocking \ No newline at end of file