#!/usr/bin/env bash set -euo pipefail log() { echo "[$(date -Is)] $*"; } require_env() { local name="$1" if [[ -z "${!name:-}" ]]; then >&2 echo "Missing required env var: $name" exit 2 fi } pia_get_token() { require_env PIA_USER require_env PIA_PASS local resp token resp="$(curl -fsS --location --request POST \ 'https://www.privateinternetaccess.com/api/client/v2/token' \ --form "username=${PIA_USER}" \ --form "password=${PIA_PASS}")" token="$(jq -r '.token // empty' <<<"$resp")" if [[ -z "$token" ]]; then >&2 echo "Failed to authenticate to PIA (no token). Response:" >&2 echo "$resp" | head -c 2000 exit 3 fi echo "$token" } pia_serverlist_v4() { curl -fsS 'https://serverlist.piaservers.net/vpninfo/servers/v4' } parse_regions() { # Supports: # - CSV: "nl_amsterdam,de_berlin" # - JSON: '["nl_amsterdam","de_berlin"]' local raw="${PIA_REGIONS:-}" if [[ -z "$raw" ]]; then >&2 echo "Missing required env var: PIA_REGIONS" exit 2 fi if [[ "$raw" =~ ^\[.*\]$ ]]; then jq -r '.[]' <<<"$raw" return fi tr ',' '\n' <<<"$raw" | sed -e 's/^[[:space:]]*//' -e 's/[[:space:]]*$//' | awk 'NF' } pia_pick_region_candidates() { # Input: serverlist JSON via stdin # Output: for each requested region id -> line "region_id|wg_ip|wg_cn" local requested requested="$(parse_regions | tr '\n' ' ')" jq -r --arg requested "$requested" ' def wanted($id): ($requested | split(" ") | index($id)) != null; .regions[] | select(wanted(.id)) | . as $r | ($r.servers.wg[0] // empty) as $wg | select($wg != null) | "\($r.id)|\($wg.ip)|\($wg.cn)" ' } pia_wireguard_add_key() { # Args: WG_SERVER_IP WG_HOSTNAME PIA_TOKEN PUBKEY CA_CERT_PATH local wg_ip="$1" local wg_hostname="$2" local token="$3" local pubkey="$4" local ca_cert="$5" curl -fsS -G \ --connect-to "${wg_hostname}::${wg_ip}:" \ --cacert "$ca_cert" \ --data-urlencode "pt=${token}" \ --data-urlencode "pubkey=${pubkey}" \ "https://${wg_hostname}:1337/addKey" } pia_pf_get_signature() { # Args: PF_GATEWAY PF_HOSTNAME PIA_TOKEN CA_CERT_PATH local gateway="$1" local hostname="$2" local token="$3" local ca_cert="$4" curl -fsS -m 10 \ --connect-to "${hostname}::${gateway}:" \ --cacert "$ca_cert" \ -G --data-urlencode "token=${token}" \ "https://${hostname}:19999/getSignature" } pia_pf_bind_port() { # Args: PF_GATEWAY PF_HOSTNAME PAYLOAD SIGNATURE CA_CERT_PATH local gateway="$1" local hostname="$2" local payload="$3" local signature="$4" local ca_cert="$5" curl -fsS -m 10 \ --connect-to "${hostname}::${gateway}:" \ --cacert "$ca_cert" \ -G \ --data-urlencode "payload=${payload}" \ --data-urlencode "signature=${signature}" \ "https://${hostname}:19999/bindPort" }