114 lines
3.6 KiB
Markdown
114 lines
3.6 KiB
Markdown
# VSHP Protocol Specification
|
|
|
|
VSHP is the VPN Share packet tunnel protocol. It carries IP packets from a
|
|
paired client virtual interface to an Android gateway over USB, Wi-Fi, or
|
|
hotspot-local transport.
|
|
|
|
## Goals
|
|
|
|
- Encrypted by default.
|
|
- Transport independent.
|
|
- Resumable after USB or Wi-Fi interruption.
|
|
- Small enough for battery-conscious mobile operation.
|
|
- Stable enough for third-party open-source clients.
|
|
|
|
## Version
|
|
|
|
Current version: `VSHP/1`.
|
|
|
|
## Frame Header
|
|
|
|
All multibyte integers are network byte order.
|
|
|
|
```text
|
|
0 1 2 3
|
|
0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1
|
|
+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+
|
|
| magic "VSHP" |
|
|
+---------------+---------------+-------------------------------+
|
|
| version = 1 | frame_type | flags |
|
|
+---------------+---------------+-------------------------------+
|
|
| stream_id |
|
|
+---------------------------------------------------------------+
|
|
| packet_number |
|
|
| |
|
|
+---------------------------------------------------------------+
|
|
| payload_length |
|
|
+---------------------------------------------------------------+
|
|
| payload... |
|
|
+---------------------------------------------------------------+
|
|
```
|
|
|
|
Header length: 24 bytes.
|
|
|
|
## Frame Types
|
|
|
|
- `HELLO = 1`: protocol version, platform, client public key, capabilities.
|
|
- `AUTH = 2`: Noise handshake payload or resume ticket.
|
|
- `CONFIG = 3`: virtual IP lease, DNS, MTU, routes, keepalive interval.
|
|
- `IP_PACKET = 4`: encrypted IPv4/IPv6 packet from or to the client.
|
|
- `PING = 5`: keepalive and counters.
|
|
- `RESUME = 6`: session resumption request.
|
|
- `STATS = 7`: byte, packet, loss, RTT, and battery hints.
|
|
- `CLOSE = 8`: close code and human-readable reason.
|
|
|
|
## Security Handshake
|
|
|
|
- First pairing: Noise `XXpsk2`, X25519, ChaCha20-Poly1305, BLAKE2s/HKDF.
|
|
- Known peer: Noise `IKpsk2` with stored peer static key.
|
|
- QR/USB pairing PSK is one-time and expires after 2 minutes.
|
|
- Every encrypted frame binds protocol version, peer id, transport id, and
|
|
transcript hash.
|
|
- Replay window: 256 packet numbers per direction.
|
|
- Rekey: after 1 GiB or 10 minutes, whichever comes first.
|
|
|
|
## Pairing URI
|
|
|
|
```text
|
|
vshare://pair?v=1&sid=<session>&server_pk=<base64url>&psk=<base64url>&transports=<csv>&expires=<unix>
|
|
```
|
|
|
|
Rules:
|
|
|
|
- `psk` is 128 bits minimum.
|
|
- `sid` is random and not reused.
|
|
- `expires` is enforced by the phone and client.
|
|
- QR pairing must be confirmed on the phone before a peer is trusted.
|
|
|
|
## Client Configuration Payload
|
|
|
|
```json
|
|
{
|
|
"lease_id": "base64url",
|
|
"peer_ipv4": "10.241.0.2/32",
|
|
"peer_ipv6": "fd7a:7670:7368::2/128",
|
|
"gateway_dns": "10.241.0.1",
|
|
"routes": ["0.0.0.0/0", "::/0"],
|
|
"mtu": 1280,
|
|
"keepalive_ms": 15000,
|
|
"idle_timeout_ms": 120000
|
|
}
|
|
```
|
|
|
|
IPv6 routes are omitted unless the gateway verifies upstream IPv6 through the
|
|
active VPN.
|
|
|
|
## Close Codes
|
|
|
|
- `0`: normal close.
|
|
- `1`: unsupported version.
|
|
- `2`: authentication failed.
|
|
- `3`: peer revoked.
|
|
- `4`: VPN unavailable.
|
|
- `5`: policy denied.
|
|
- `6`: protocol error.
|
|
- `7`: overload/backpressure.
|
|
|
|
## MTU Policy
|
|
|
|
- Default MTU is `1280`.
|
|
- USB may probe and raise the link MTU.
|
|
- TCP MSS is clamped to `mtu - 40` for IPv4 and `mtu - 60` for IPv6.
|
|
- Oversized packets are dropped with client-visible Packet Too Big signaling
|
|
where possible.
|