diff options
-rw-r--r-- | .github/workflows/test.yml | 34 | ||||
-rw-r--r-- | action.yml | 160 |
2 files changed, 194 insertions, 0 deletions
diff --git a/.github/workflows/test.yml b/.github/workflows/test.yml new file mode 100644 index 0000000..7b046e9 --- /dev/null +++ b/.github/workflows/test.yml @@ -0,0 +1,34 @@ +name: Test + +on: + push: + pull_request: + schedule: + # Weekly, at 5:45 AM on Friday (somewhat randomly chosen). + - cron: '45 5 * * 5' + workflow_dispatch: + +jobs: + test: + strategy: + matrix: + os: [ubuntu-18.04, ubuntu-20.04, ubuntu-latest] + runs-on: '${{ matrix.os }}' + name: 'Test: ${{ matrix.os }}' + defaults: + run: + shell: bash + steps: + - name: Checkout + uses: actions/checkout@v2 + - name: Set up WireGuard + uses: ./ + with: + endpoint: '${{ secrets.ENDPOINT }}' + endpoint_public_key: '${{ secrets.ENDPOINT_PUBLIC }}' + ips: '${{ secrets.IPS }}' + private_key: '${{ secrets.PRIVATE }}' + preshared_key: '${{ secrets.PRESHARED }}' + allowed_ips: '${{ secrets.ALLOWED_IPS }}' + - name: Check endpoint + run: ping -W 10 -c 5 -- '${{ secrets.ENDPOINT_PRIVATE_IP }}' diff --git a/action.yml b/action.yml new file mode 100644 index 0000000..77e4827 --- /dev/null +++ b/action.yml @@ -0,0 +1,160 @@ +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 |