WIP: Ship a pia-vpn skill with the VPN support toggle #29
@@ -9,8 +9,10 @@ Bring this container's traffic out through Private Internet Access over
|
|||||||
WireGuard, using the API PIA documents for headless use.
|
WireGuard, using the API PIA documents for headless use.
|
||||||
|
|
||||||
Run `sudo ~/.claude/skills/pia-vpn/pia-wg.sh` with `up`, `up --full`, `down` or
|
Run `sudo ~/.claude/skills/pia-vpn/pia-wg.sh` with `up`, `up --full`, `down` or
|
||||||
`status`. Read the rest of this page before the first `up --full` — two of the
|
`status`. Read the rest of this page before the first `up --full` — three of the
|
||||||
behaviours below are actively misleading if you meet them without warning.
|
behaviours below are actively misleading if you meet them without warning, and
|
||||||
|
each one presents as "the VPN is fine" or "Claude is broken" rather than as
|
||||||
|
what it is.
|
||||||
|
|
||||||
## Before anything else: what the toggle does not do
|
## Before anything else: what the toggle does not do
|
||||||
|
|
||||||
@@ -72,7 +74,27 @@ that way looks perfect and works for nothing.
|
|||||||
`status` resolves a real name for this reason. Trust its `DNS:` line, and if
|
`status` resolves a real name for this reason. Trust its `DNS:` line, and if
|
||||||
you check by hand, resolve a name rather than fetching an address.
|
you check by hand, resolve a name rather than fetching an address.
|
||||||
|
|
||||||
## Trap 3: no tunnel survives a restart, and it fails open
|
## Trap 3: in test mode, the obvious probe is the one thing tunnelled
|
||||||
|
|
||||||
|
`up` routes `1.1.1.1` and nothing else. So checking your address by fetching
|
||||||
|
`https://1.1.1.1/cdn-cgi/trace` reports a **PIA** address — not because your
|
||||||
|
traffic is going through PIA, but because that single probe is. Everything else
|
||||||
|
still leaves directly.
|
||||||
|
|
||||||
|
This reads exactly like a working full tunnel, and it is the likeliest reason
|
||||||
|
someone concludes the VPN is on when it is not. `status` prints both exits in
|
||||||
|
test mode for this reason:
|
||||||
|
|
||||||
|
```
|
||||||
|
mode: test route only (1.1.1.1 through the tunnel, nothing else)
|
||||||
|
through the tunnel: 64.113.5.73
|
||||||
|
everything else: 172.116.197.166 <- your real address
|
||||||
|
```
|
||||||
|
|
||||||
|
Two different addresses there is correct and expected in test mode. If you want
|
||||||
|
the second line to change, you want `up --full`.
|
||||||
|
|
||||||
|
## Trap 4: no tunnel survives a restart, and it fails open
|
||||||
|
|
||||||
The network namespace is rebuilt every time the container starts, and nothing
|
The network namespace is rebuilt every time the container starts, and nothing
|
||||||
inside reconnects anything. After a stop/start, Reset or any config change that
|
inside reconnects anything. After a stop/start, Reset or any config change that
|
||||||
@@ -115,18 +137,22 @@ curl -s https://serverlist.piaservers.net/vpninfo/servers/v6 \
|
|||||||
|
|
||||||
## Verifying
|
## Verifying
|
||||||
|
|
||||||
`status` prints three things — handshake, DNS, and the public address:
|
`status` prints the handshake, DNS, and which address traffic actually leaves
|
||||||
|
from — labelled by mode, so the answer cannot be misread:
|
||||||
|
|
||||||
```
|
```
|
||||||
latest handshake: 2 seconds ago
|
latest handshake: 2 seconds ago
|
||||||
transfer: 92 B received, 180 B sent
|
transfer: 92 B received, 180 B sent
|
||||||
DNS: ok (via 10.0.0.243 10.0.0.242)
|
DNS: ok (via 10.0.0.243 10.0.0.242)
|
||||||
public IP: 64.113.5.244
|
mode: full tunnel
|
||||||
|
all traffic exits: 64.113.5.244
|
||||||
```
|
```
|
||||||
|
|
||||||
All three matter. A handshake with `DNS: BROKEN` is trap 1. A handshake with an
|
All of it matters. A handshake with `DNS: BROKEN` is trap 1. `mode: test route
|
||||||
unchanged public address means routing did not take — you are probably in `up`
|
only` with two different addresses is trap 3, and is correct — it means the
|
||||||
rather than `up --full`.
|
tunnel works and you have not asked for it to carry anything yet. Report the
|
||||||
|
mode line when telling someone the VPN is on; "the public IP is a PIA one" is
|
||||||
|
true in test mode too, and means much less than it sounds like.
|
||||||
|
|
||||||
## Tearing down
|
## Tearing down
|
||||||
|
|
||||||
|
|||||||
@@ -156,8 +156,17 @@ down() {
|
|||||||
echo "tunnel down"
|
echo "tunnel down"
|
||||||
}
|
}
|
||||||
|
|
||||||
|
# Both are Cloudflare and both answer /cdn-cgi/trace over their bare address, so
|
||||||
|
# neither needs DNS. Only 1.1.1.1 is ever routed into the tunnel, which is what
|
||||||
|
# lets status tell the two exits apart.
|
||||||
|
TRACE_TUNNELLED=https://1.1.1.1/cdn-cgi/trace
|
||||||
|
TRACE_DIRECT=https://1.0.0.1/cdn-cgi/trace
|
||||||
|
|
||||||
|
exit_ip() { curl -s -m 20 "$1" | sed -n 's/^ip=//p'; }
|
||||||
|
|
||||||
status() {
|
status() {
|
||||||
wg show "$IFACE" 2>/dev/null | grep -E "latest handshake|transfer" || echo "no tunnel up"
|
wg show "$IFACE" 2>/dev/null | grep -E "latest handshake|transfer" || echo "no tunnel up"
|
||||||
|
|
||||||
# Resolve a name, not an IP literal. A curl to 1.1.1.1 succeeds while DNS is
|
# Resolve a name, not an IP literal. A curl to 1.1.1.1 succeeds while DNS is
|
||||||
# completely broken, which is exactly how a dead resolver goes unnoticed.
|
# completely broken, which is exactly how a dead resolver goes unnoticed.
|
||||||
printf 'DNS: '
|
printf 'DNS: '
|
||||||
@@ -166,8 +175,22 @@ status() {
|
|||||||
else
|
else
|
||||||
echo "BROKEN - cannot resolve api.anthropic.com"
|
echo "BROKEN - cannot resolve api.anthropic.com"
|
||||||
fi
|
fi
|
||||||
echo -n "public IP: "
|
|
||||||
curl -s -m 20 https://1.1.1.1/cdn-cgi/trace | sed -n 's/^ip=//p'
|
# Report the exit per mode. In test mode the probe address is itself the one
|
||||||
|
# thing inside the tunnel, so a single "public IP" line would print a PIA
|
||||||
|
# address while every other packet leaves directly -- the exact reading that
|
||||||
|
# makes a test tunnel look like a full one.
|
||||||
|
if ip route show 0.0.0.0/1 2>/dev/null | grep -q "$IFACE"; then
|
||||||
|
echo "mode: full tunnel"
|
||||||
|
echo " all traffic exits: $(exit_ip "$TRACE_TUNNELLED")"
|
||||||
|
elif ip link show "$IFACE" >/dev/null 2>&1; then
|
||||||
|
echo "mode: test route only (1.1.1.1 through the tunnel, nothing else)"
|
||||||
|
echo " through the tunnel: $(exit_ip "$TRACE_TUNNELLED")"
|
||||||
|
echo " everything else: $(exit_ip "$TRACE_DIRECT") <- your real address"
|
||||||
|
else
|
||||||
|
echo "mode: no tunnel"
|
||||||
|
echo " all traffic exits: $(exit_ip "$TRACE_DIRECT")"
|
||||||
|
fi
|
||||||
}
|
}
|
||||||
|
|
||||||
case "${1:-}" in
|
case "${1:-}" in
|
||||||
|
|||||||
Reference in New Issue
Block a user