diff --git a/wireguard-client/Dockerfile b/wireguard-client/Dockerfile new file mode 100755 index 0000000..ddc4d9a --- /dev/null +++ b/wireguard-client/Dockerfile @@ -0,0 +1,16 @@ +ARG BUILD_FROM=ghcr.io/hassio-addons/base/amd64:11.0.0 +FROM ${BUILD_FROM} + +SHELL ["/bin/bash", "-o", "pipefail", "-c"] + +RUN \ + apk add --no-cache \ + openresolv=3.12.0-r0 \ + wireguard-tools=1.0.20210914-r0 + +COPY rootfs / + +ARG BUILD_ARCH +ARG BUILD_DATE +ARG BUILD_REF +ARG BUILD_VERSION diff --git a/wireguard-client/build.yaml b/wireguard-client/build.yaml new file mode 100644 index 0000000..ee6005d --- /dev/null +++ b/wireguard-client/build.yaml @@ -0,0 +1,7 @@ +--- +build_from: + aarch64: ghcr.io/hassio-addons/base/aarch64:11.0.0 + amd64: ghcr.io/hassio-addons/base/amd64:11.0.0 + armhf: ghcr.io/hassio-addons/base/armhf:11.0.0 + armv7: ghcr.io/hassio-addons/base/armv7:11.0.0 + i386: ghcr.io/hassio-addons/base/i386:11.0.0 \ No newline at end of file diff --git a/wireguard-client/config.yaml b/wireguard-client/config.yaml index 5048231..f51d3b3 100755 --- a/wireguard-client/config.yaml +++ b/wireguard-client/config.yaml @@ -54,4 +54,4 @@ schema: allowed_ips: - str persistent_keep_alive: int -image: "git.a09.uk/alex/{arch}-addon-wireguard-client" +#image: "git.a09.uk/alex/{arch}-addon-wireguard-client" diff --git a/wireguard-client/rootfs/etc/cont-finish.d/00-stop b/wireguard-client/rootfs/etc/cont-finish.d/00-stop new file mode 100644 index 0000000..74b4e50 --- /dev/null +++ b/wireguard-client/rootfs/etc/cont-finish.d/00-stop @@ -0,0 +1,6 @@ +#!/usr/bin/with-contenv bashio +declare interface + +interface="wg0" + +exec wg-quick down "${interface}" diff --git a/wireguard-client/rootfs/etc/cont-init.d/config.sh b/wireguard-client/rootfs/etc/cont-init.d/config.sh new file mode 100644 index 0000000..483175c --- /dev/null +++ b/wireguard-client/rootfs/etc/cont-init.d/config.sh @@ -0,0 +1,167 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Third Party Add-on: WireGuard Client +# Creates the interface configuration +# ============================================================================== +declare -a list +declare address +declare allowed_ips +declare config +declare dns +declare endpoint +declare interface +declare keep_alive +declare peer_public_key +declare post_down +declare post_up +declare mtu +declare pre_shared_key + +if ! bashio::fs.directory_exists '/ssl/wireguard'; then + mkdir -p /ssl/wireguard || + bashio::exit.nok "Could not create wireguard storage folder!" +fi + +# Get interface and config file location +interface="wg0" + +config="/etc/wireguard/${interface}.conf" + +########################### +# Interface configuration # +########################### +# Start creation of configuration +echo "[Interface]" > "${config}" + +# Check if at least 1 private key value and if true get the interface private key +if ! bashio::config.has_value 'interface.private_key'; then + bashio::exit.nok 'You need a private_key configured for the interface client' +else + interface_private_key=$(bashio::config 'interface.private_key') + echo "PrivateKey = ${interface_private_key}" >> "${config}" +fi + +# Check if at least 1 address value and if true get the interface address +if ! bashio::config.has_value 'interface.address'; then + bashio::exit.nok 'You need a address configured for the interface client' +else + address=$(bashio::config 'interface.address') + [[ "${address}" == *"/"* ]] || address="${address}/24" + echo "Address = ${address}" >> "${config}" +fi + +# Add all server DNS addresses to the configuration +if bashio::config.has_value "interface.dns"; then + listDns=() + # Use allowed IP's defined by the user. + for address in $(bashio::config "interface.dns"); do + listDns+=("${address}") + done + dns=$(IFS=", "; echo "${listDns[*]}") + echo "DNS = ${dns}" >> "${config}" +fi + +if [[ $(> "${config}" +fi + +# Check if custom post_down value +if bashio::config.has_value 'interface.post_down'; then + post_down=$(bashio::config 'interface.post_down') + echo "PostDown = ${post_down}" >> "${config}" +fi + +# Check if custom mtu value +if bashio::config.has_value 'interface.mtu'; then + mtu=$(bashio::config 'interface.mtu') + echo "MTU = ${mtu}" >> "${config}" +fi + +# Status API Storage +if ! bashio::fs.directory_exists '/var/lib/wireguard'; then + mkdir -p /var/lib/wireguard \ + || bashio::exit.nok "Could not create status API storage folder" +fi + +if ! bashio::config.has_value 'peers'; then + bashio::exit.nok 'Missing required list: peers' +fi + +###################### +# Peer configuration # +###################### +# Fetch all the peers +for peer in $(bashio::config 'peers|keys'); do + + # Check if public key value and if true get the peer public key + peer_public_key=$(bashio::config "peers[${peer}].public_key") + + # Check if pre_shared key value and if true get the peer pre_shared key + pre_shared_key="" + if bashio::config.has_value "peers[${peer}].pre_shared_key"; then + pre_shared_key=$(bashio::config "peers[${peer}].pre_shared_key") + fi + + # Check if endpoint value and if true get the peer endpoint + endpoint="" + if ! bashio::config.has_value "peers[${peer}].endpoint"; then + bashio::exit.nok 'You need a endpoint configured for the peer' + else + endpoint=$(bashio::config "peers[${peer}].endpoint") + fi + + # Check if persistent_keep_alive value and if true get the peer persistent_keep_alive + keep_alive="" + if ! bashio::config.has_value "peers[${peer}].persistent_keep_alive"; then + bashio::exit.nok 'You need a persistent_keep_alive configured for the peer' + else + keep_alive=$(bashio::config "peers[${peer}].persistent_keep_alive") + fi + + # Determine allowed IPs for server side config, by default use + # peer defined addresses. + list=() + if bashio::config.has_value "peers[${peer}].allowed_ips"; then + # Use allowed IP's defined by the user. + for address in $(bashio::config "peers[${peer}].allowed_ips"); do + [[ "${address}" == *"/"* ]] || address="${address}/32" + list+=("${address}") + done + else + bashio::exit.nok 'You need a allowed_ips configured for the peer' + fi + + allowed_ips=$(IFS=", "; echo "${list[*]}") + + # Start writing peer information in client config + { + echo "" + echo "[Peer]" + echo "PublicKey = ${peer_public_key}" + if [ ! $pre_shared_key == "" ] + then + echo "PreSharedKey = ${pre_shared_key}" + fi + echo "Endpoint = ${endpoint}" + echo "AllowedIPs = ${allowed_ips}" + echo "PersistentKeepalive = ${keep_alive}" + echo "" + } >> "${config}" +done + +bashio::log.info "Ended to write Wireguard configuration into: [${config}]" diff --git a/wireguard-client/rootfs/etc/services.d/api/run b/wireguard-client/rootfs/etc/services.d/api/run new file mode 100755 index 0000000..2b4fde5 --- /dev/null +++ b/wireguard-client/rootfs/etc/services.d/api/run @@ -0,0 +1,48 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Third Party Add-on: WireGuard Client +# Provides status of WireGuard broker. +# ============================================================================== +declare -a peers +declare endpoint +declare json +declare latest_handshake +declare line +declare peer +declare transfer_rx +declare transfer_tx + +PORT=$(bashio::addon.port "80/tcp") +if [[ $PORT -eq 0 ]]; then exit; fi + +while true; do + # Get information from wg + peers=() + declare count=1 + while IFS=$'\t' read -r -a line; do + if [[ "${#line[@]}" -gt 6 ]]; then + endpoint="${line[3]}" + latest_handshake="$(exec date -d @"${line[5]}" 2>/dev/null || date -r "${line[5]}")" + transfer_rx="${line[6]}" + transfer_tx="${line[7]}" + + peer=$(bashio::var.json \ + 'endpoint' "${endpoint}" \ + 'latest_handshake' "${latest_handshake}" \ + 'transfer_rx' "^${transfer_rx}" \ + 'transfer_tx' "^${transfer_tx}") + + peers+=("peer_${count}" "^${peer}") + (( count++ )) + fi + done <<< "$(wg show all dump)" + + # Build final json content + json="{}" + if [[ "${#peers[@]}" -ne 0 ]]; then + json=$(bashio::var.json "${peers[@]}") + fi + + echo -e "HTTP/1.1 200 OK\r\nContent-type: application/json\r\n\r\n${json}" \ + | nc -l -p $PORT > /dev/null +done diff --git a/wireguard-client/rootfs/etc/services.d/status/run b/wireguard-client/rootfs/etc/services.d/status/run new file mode 100644 index 0000000..596dfdb --- /dev/null +++ b/wireguard-client/rootfs/etc/services.d/status/run @@ -0,0 +1,10 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: WireGuard Client +# Shows current WireGuard status +# ============================================================================== +sleep 30 +bashio::log.info "Requesting current status from WireGuard Client..." +if [[ "${__BASHIO_LOG_LEVEL}" -ge "${__BASHIO_LOG_LEVEL_INFO}" ]]; then + exec wg show +fi diff --git a/wireguard-client/rootfs/etc/services.d/wireguard_client/run b/wireguard-client/rootfs/etc/services.d/wireguard_client/run new file mode 100644 index 0000000..3d4a985 --- /dev/null +++ b/wireguard-client/rootfs/etc/services.d/wireguard_client/run @@ -0,0 +1,20 @@ +#!/usr/bin/with-contenv bashio +# ============================================================================== +# Home Assistant Community Add-on: WireGuard Client +# Runs WireGuard Client +# ============================================================================== +declare interface + +s6-svc -O /var/run/s6/services/wireguard_client + +bashio::log.info "Starting WireGuard Client..." + +# This is alpha software. We need to set this to instruct +# WireGuard we are OK to go. +export WG_I_PREFER_BUGGY_USERSPACE_TO_POLISHED_KMOD=1 + +# Get the interface +interface="wg0" + +# Run the WireGuard +exec wg-quick up "${interface}"