init
Some checks failed
CI / Rust (push) Successful in 20s
CI / Android (push) Failing after 8m35s

This commit is contained in:
2026-05-31 15:36:07 +03:30
commit 4ffbc3bffe
61 changed files with 2760 additions and 0 deletions

113
docs/protocol.md Normal file
View File

@@ -0,0 +1,113 @@
# 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.