aboutsummaryrefslogblamecommitdiffstatshomepage
path: root/action.yml
blob: f276af5bfcbade6365e1108d66da4a005d260076 (plain) (tree)
1
2
3
4
5
6
7
8
9
10
11
12
13












                                                     


                                                 





                              


                                         









                                                                        
                                                        

                                                            
                                                    



































                                                                         




                                                 






























































                                                                                                           
                                 

                                            
                                                                           


                                        
                                                                         

              



                                             
                                                                   
 
                                         
 

                                                                                           











                                                                              
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
  allowed_ips:
    description: Comma-separated list of netmasks
    required: true
  private_key:
    description: Private key
    required: true
  preshared_key:
    description: Preshared key
    required: false
  keepalive:
    description: Useful for NAT traversal
    required: false

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 allowed_ips='${{ inputs.allowed_ips }}'
        readonly private_key='${{ inputs.private_key }}'
        readonly preshared_key='${{ inputs.preshared_key }}'
        readonly keepalive='${{ inputs.keepalive }}'

        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

            if [ -n "$keepalive" ]; then
                netdev_contents="$netdev_contents
            PersistentKeepalive=$keepalive"
            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"

            additional_wg_args=()

            if [ -n "$preshared_key" ]; then
                additional_wg_args+=(preshared-key "${preshared_key_path}")
            fi

            if [ -n "$keepalive" ]; then
                additional_wg_args+=(persistent-keepalive "${keepalive}")
            fi

            sudo wg set "$ifname" \
                peer "$endpoint_public_key" \
                endpoint "$endpoint" \
                allowed-ips "$allowed_ips" \
                ${additional_wg_args[@]+"${additional_wg_args[@]}"}

            sudo ip link set "$ifname" up

            # Add routes for allowed_ips
            for i in ${allowed_ips//,/ }; do sudo ip route replace "$i" dev "$ifname"; done
        }

        # 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