diff --git a/wireguard/config.json b/wireguard/config.json index 61c7aea..efc5f68 100755 --- a/wireguard/config.json +++ b/wireguard/config.json @@ -42,7 +42,8 @@ "addresses": [ "172.244.66.2" ], - "allowed_ips": [] + "allowed_ips": [], + "client_allowed_ips": [] } ] }, @@ -53,15 +54,18 @@ "addresses": ["str"], "dns": ["str"], "private_key": "str?", + "public_key": "str?", "post_up": "str?", "post_down": "str?" }, "peers": [ { "name": "match(^!secret [a-zA-Z0-9_\\-]+$|^[a-zA-Z0-9\\d](?:[a-zA-Z0-9\\d]|-(?=[a-zA-Z0-9\\d])){0,32}$)", + "private_key": "str?", "public_key": "str?", "addresses": ["str"], "allowed_ips": ["str"], + "client_allowed_ips": ["str"], "persistent_keep_alive": "int?", "endpoint": "str?", "pre_shared_key": "str?" diff --git a/wireguard/rootfs/etc/cont-init.d/config.sh b/wireguard/rootfs/etc/cont-init.d/config.sh index 51a46b8..948cfab 100644 --- a/wireguard/rootfs/etc/cont-init.d/config.sh +++ b/wireguard/rootfs/etc/cont-init.d/config.sh @@ -13,18 +13,21 @@ declare endpoint declare host declare keep_alive declare name +declare peer_private_key +declare peer_public_key declare port declare post_down declare post_up declare pre_shared_key -declare private_key -declare public_key +declare server_private_key +declare server_public_key if ! bashio::fs.directory_exists '/ssl/wireguard'; then mkdir -p /ssl/wireguard || bashio::exit.nok "Could create wireguard storage folder!" fi +# Start creation of configuration echo "[Interface]" > "${CONFIG}" # Check if at least 1 address is specified @@ -48,16 +51,23 @@ else echo "DNS = ${dns}" >> ${CONFIG} fi -# Add the server's private key to the configuration +# Get the server's private key if bashio::config.has_value 'server.private_key'; then - private_key=$(bashio::config 'server.private_key') + server_private_key=$(bashio::config 'server.private_key') else if ! bashio::fs.file_exists '/ssl/wireguard/private_key'; then umask 077 || bashio::exit.nok "Could not set a proper umask" wg genkey > /ssl/wireguard/private_key || bashio::exit.nok "Could not generate private key!" fi - private_key=$(> "${CONFIG}" +# Get DNS for client configurations +if bashio::config.has_value 'server.dns'; then + dns=$(bashio::config "server.dns | join(\", \")") +fi + # Fetch all the peers for peer in $(bashio::config 'peers|keys'); do @@ -114,94 +129,97 @@ for peer in $(bashio::config 'peers|keys'); do name=$(bashio::config "peers[${peer}].name") config_dir="/ssl/wireguard/${name}" + host=$(bashio::config 'server.host') + port=$(bashio::addon.port "51820/udp") + keep_alive=$(bashio::config "peers[${peer}].persistent_keep_alive") + pre_shared_key=$(bashio::config "peers[${peer}].pre_shared_key") + endpoint=$(bashio::config "peers[${peer}].endpoint") - mkdir -p "${config_dir}" || - bashio::exit.nok "Failed creating client folder for ${name}" - - # Write peer header - echo "[Peer]" >> "${CONFIG}" - - # Get the public key - if bashio::config.has_value "peers[${peer}].public_key"; then - public_key=$(bashio::config "peers[${peer}].public_key") - elif bashio::fs.file_exists "${config_dir}/public_key"; then - public_key=$(<"${config_dir}/public_key") - else - umask 077 || bashio::exit.nok "Could not set a proper umask" - wg genkey > "${config_dir}/private_key" || - bashio::exit.nok "Could not generate private key for ${name}!" - - wg pubkey < "${config_dir}/private_key" > "${config_dir}/public_key" || - bashio::exit.nok "Could not get public key for ${name}!" - - public_key=$(<"${config_dir}/public_key") + # Get the private key + peer_private_key="" + if bashio::config.has_value "peers[${peer}].private_key"; then + peer_private_key=$(bashio::config "peers[${peer}].private_key") + elif ! basio::config.has_value "peers[${peer}].public_key"; then + # If a public key is not provided, try get a private key from disk + # or generate one if needed. + if ! bashio::fs.file_exists '/ssl/wireguard/private_key'; then + umask 077 || bashio::exit.nok "Could not set a proper umask" + wg genkey > "${config_dir}/private_key" || + bashio::exit.nok "Could not generate private key for ${name}!" + fi + peer_private_key=$(<"${config_dir}/private_key") fi - echo "PublicKey = ${public_key}" >> "${CONFIG}" + # Get the public key + peer_public_key="" + if bashio::config.has_value "peers[${peer}].public_key"; then + peer_public_key=$(bashio::config "peers[${peer}].public_key") + elif bashio::var.has_value "${peer_private_key}"; then + peer_public_key=$(wg pubkey <<< "${peer_private_key}") + fi - # Addresses in peer configuration become AllowedIPS from server side. + # Get peer addresses list=() for address in $(bashio::config "peers[${peer}].addresses"); do [[ "${address}" == *"/"* ]] || address="${address}/24" list+=("${address}") done - allowed_ips=$(IFS=", "; echo "${list[*]}") - - echo "AllowedIPs = ${allowed_ips}" >> "${CONFIG}" - - if bashio::config.has_value "peers[${peer}].persistent_keep_alive"; then - keep_alive=$(bashio::config "peers[${peer}].persistent_keep_alive") - echo "PersistentKeepalive = ${keep_alive}" >> "${CONFIG}" - fi - - if bashio::config.has_value "peers[${peer}].pre_shared_key"; then - pre_shared_key=$(bashio::config "peers[${peer}].pre_shared_key") - echo "PreSharedKey = ${pre_shared_key}" >> "${CONFIG}" - fi - - if bashio::config.has_value "peers[${peer}].endpoint"; then - endpoint=$(bashio::config "peers[${peer}].endpoint") - echo "Endpoint = ${endpoint}" >> "${CONFIG}" - fi - - # End file with an empty line - echo "" >> "${CONFIG}" - - # Generate client config - echo "[Interface]" > "${config_dir}/client.conf" - - if bashio::fs.file_exists "${config_dir}/private_key"; then - private_key=$(<"${config_dir}/private_key") - echo "PrivateKey = ${private_key}" >> "${config_dir}/client.conf" - fi - - if bashio::config.has_value 'server.dns'; then - dns=$(bashio::config "server.dns | join(\", \")") - else - dns=$(bashio::dns.host) - fi + addresses=$(IFS=", "; echo "${list[*]}") + # Determine allowed IPs for server side config, by default use + # peer defined addresses. + allowed_ips="${addresses}" if bashio::config.has_value "peers[${peer}].allowed_ips"; then - allowed_ips=$(bashio::config "peers[${peer}].allowed_ips | join(\", \")") - else - allowed_ips="0.0.0.0/0" + # Use allowed IP's defined by the user. + list=() + for address in $(bashio::config "peers[${peer}].allowed_ips"); do + [[ "${address}" == *"/"* ]] || address="${address}/24" + list+=("${address}") + done + allowed_ips=$(IFS=", "; echo "${list[*]}") fi - addresses=$(bashio::config "peers[${peer}].addresses | join(\", \")") - public_key=$(wg pubkey < /ssl/wireguard/private_key) - host=$(bashio::config 'server.host') - port=$(bashio::addon.port "51820/udp") - + # Start writing peer information in server config { + echo "[Peer]" + echo "PublicKey = ${peer_public_key}" + echo "AllowedIPs = ${allowed_ips}" + bashio::config.has_value "peers[${peer}].persistent_keep_alive" \ + && echo "PersistentKeepalive = ${keep_alive}" + bashio::config.has_value "peers[${peer}].pre_shared_key" \ + && echo "PreSharedKey = ${pre_shared_key}" + bashio::config.has_value "peers[${peer}].endpoint" \ + && echo "Endpoint = ${endpoint}" + echo "" + } >> "${CONFIG}" + + # Generate client configuration + mkdir -p "${config_dir}" || + bashio::exit.nok "Failed creating client folder for ${name}" + + # Determine allowed IPs for client configuration + allowed_ips="0.0.0.0/0" + if bashio::config.has_value "peers[${peer}].client_allowed_ips"; then + allowed_ips=$( + bashio::config "peers[${peer}].client_allowed_ips | join(\", \")" + ) + fi + + # Write client configuration file + { + echo "[Interface]" + bashio::fs.file_exists "${config_dir}/private_key" \ + && echo "PrivateKey = ${peer_private_key}" echo "Address = ${addresses}" echo "DNS = ${dns}" echo "" echo "[Peer]" - echo "PublicKey = ${public_key}" + echo "PublicKey = ${server_public_key}" echo "Endpoint = ${host}:${port}" echo "AllowedIPs = ${allowed_ips}" echo "" - } >> "${config_dir}/client.conf" + } > "${config_dir}/client.conf" + # Generate QR code with client configuration qrencode -t PNG -o "${config_dir}/qrcode.png" < "${config_dir}/client.conf" done