aboutsummaryrefslogblamecommitdiffstatshomepage
path: root/action.yml
blob: 77e482785c63ca09c342577027e2da6ffec54609 (plain) (tree)































































































































































                                                                                                           
name: Set up WireGuard
description: Set up WireGuard connection

inputs:
  endpoint:
    description: Endpoint in the HOST:PORT format
    required: true
  endpoint_public_key:
    description: Public key of the endpoint
    required: true
  ips:
    description: Comma-separated list of IP addresses
    required: true
  private_key:
    description: Private key
    required: true
  preshared_key:
    description: Preshared key
    required: false
  allowed_ips:
    description: Comma-separated list of netmasks
    required: true

runs:
  using: composite
  steps:
    - run: |
        set -o errexit -o pipefail -o nounset

        readonly endpoint='${{ inputs.endpoint }}'
        readonly endpoint_public_key='${{ inputs.endpoint_public_key }}'
        readonly ips='${{ inputs.ips }}'
        readonly private_key='${{ inputs.private_key }}'
        readonly preshared_key='${{ inputs.preshared_key }}'
        readonly allowed_ips='${{ inputs.allowed_ips }}'

        readonly minport=51000
        readonly maxport=51999

        ifname="wg$( openssl rand -hex 4 )"
        readonly ifname
        port="$( shuf "--input-range=$minport-$maxport" --head-count=1 )"
        readonly port

        via_systemd() {
            local netdev_path
            netdev_path="/etc/systemd/network/$ifname.netdev"
            local network_path
            network_path="/etc/systemd/network/$ifname.network"

            local netdev_contents
            netdev_contents="
            [NetDev]
            Name=$ifname
            Kind=wireguard
            Description=WireGuard tunnel $ifname

            [WireGuard]
            ListenPort=$port
            PrivateKey=$private_key

            [WireGuardPeer]
            Endpoint=$endpoint
            PublicKey=$endpoint_public_key
            AllowedIPs = $allowed_ips"

            if [ -n "$preshared_key" ]; then
                netdev_contents="$netdev_contents
            PresharedKey=$preshared_key"
            fi

            local network_contents
            network_contents="
            [Match]
            Name=$ifname

            [Network]"

            local delim=,
            local ip
            while IFS= read -d "$delim" -r ip; do
                network_contents="$network_contents
                Address=$ip"
            done < <( printf -- "%s$delim\\0" "$ips" )

            sudo touch -- "$netdev_path"
            sudo chown -- root:systemd-network "$netdev_path"
            sudo chmod -- 0640 "$netdev_path"
            sudo touch -- "$network_path"
            echo "$netdev_contents" | sudo tee -- "$netdev_path" > /dev/null
            echo "$network_contents" | sudo tee -- "$network_path" > /dev/null

            sudo systemctl restart systemd-networkd
            sudo systemctl status systemd-networkd
        }

        install_wg_tools() {
            sudo apt-get update
            sudo DEBIAN_FRONTEND=noninteractive apt-get install -yq --no-install-recommends wireguard-tools
        }

        readonly private_key_path=/tmp/private.key
        readonly preshared_key_path=/tmp/preshared.key

        wg_tools_cleanup() {
            rm -f -- "$private_key_path"
            rm -f -- "$preshared_key_path"
        }

        via_wg_tools() {
            install_wg_tools
            trap wg_tools_cleanup EXIT

            (
                set -o errexit -o nounset -o pipefail
                umask 0077
                echo "$private_key" > "$private_key_path"
                if [ -n "$preshared_key" ]; then
                    echo "$preshared_key" > "$preshared_key_path"
                fi
            )

            sudo ip link add dev "$ifname" type wireguard

            local delim=,
            local ip
            while IFS= read -d "$delim" -r ip; do
                sudo ip addr add "$ip" dev "$ifname"
            done < <( printf -- "%s$delim\\0" "$ips" )

            sudo wg set "$ifname" \
                listen-port "$port" \
                private-key "$private_key_path"

            if [ -z "$preshared_key" ]; then
                sudo wg set "$ifname" \
                    peer "$endpoint_public_key" \
                    endpoint "$endpoint" \
                    allowed-ips "$allowed_ips"
            else
                sudo wg set "$ifname" \
                    peer "$endpoint_public_key" \
                    preshared-key "$preshared_key_path" \
                    endpoint "$endpoint" \
                    allowed-ips "$allowed_ips"
            fi

            sudo ip link set "$ifname" up
        }

        # systemd-networkd greets me with 'Temporary failure in name
        # resolution' on Bionic when using a hostname instead of an IP address
        # for endpoint. God knows why!
        #via_systemd
        via_wg_tools
      shell: bash

branding:
  icon: star
  color: green