122 lines
2.9 KiB
Bash
122 lines
2.9 KiB
Bash
#!/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() {
|
|
# PIA serverlist responses include a JSON line followed by signature data.
|
|
# We only need the JSON line for region selection.
|
|
curl -fsS 'https://serverlist.piaservers.net/vpninfo/servers/v4' | sed -n '1p'
|
|
}
|
|
|
|
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"
|
|
}
|
|
|