feat: add per-listener SOCKS5 server authentication (RFC 1929)

Per-listener username/password auth via `auth:` config key. When set,
clients must negotiate method 0x02 and pass RFC 1929 subnegotiation;
no-auth (0x00) is rejected to prevent downgrade. Listeners without
`auth` keep current no-auth behavior.

Includes auth_failures metric, API integration (/status auth flag,
/config auth_users count without exposing passwords), config parsing
with YAML int coercion, integration tests (success, failure, method
rejection, no-auth unchanged), and documentation updates.

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
user
2026-02-21 17:03:03 +01:00
parent 76dac61eb6
commit fa3621806d
13 changed files with 505 additions and 13 deletions

View File

@@ -242,6 +242,59 @@ error at startup. Listeners without pool hops ignore the `pool:` key.
| FirstHopPool | per unique first hop | Listeners with same first hop share it |
| Chain + pool_hops | per listener | Each listener has its own chain depth |
## Listener Authentication
Per-listener SOCKS5 username/password authentication (RFC 1929). When `auth`
is configured on a listener, clients must authenticate before connecting.
Listeners without `auth` continue to accept unauthenticated connections.
```yaml
listeners:
- listen: 0.0.0.0:1080
auth:
alice: s3cret
bob: hunter2
chain:
- socks5://127.0.0.1:9050
- pool
```
### Testing with curl
```bash
curl --proxy socks5h://alice:s3cret@127.0.0.1:1080 https://example.com
```
### Behavior
| Client offers | Listener has `auth` | Result |
|---------------|---------------------|--------|
| `0x00` (no-auth) | yes | Rejected (`0xFF`) |
| `0x02` (user/pass) | yes | Subnegotiation, then accept/reject |
| `0x00` (no-auth) | no | Accepted (current behavior) |
| `0x02` (user/pass) | no | Rejected (`0xFF`) |
Authentication failures are logged and counted in the `auth_fail` metric.
The `/status` API endpoint includes `"auth": true` on authenticated listeners.
The `/config` endpoint shows `"auth_users": N` (passwords are never exposed).
### Mixed listeners
Different listeners can have different auth settings:
```yaml
listeners:
- listen: 0.0.0.0:1080 # public, no auth
chain:
- socks5://127.0.0.1:9050
- listen: 0.0.0.0:1081 # authenticated
auth:
alice: s3cret
chain:
- socks5://127.0.0.1:9050
- pool
```
## Bypass Rules
Per-listener rules to skip the chain for specific destinations. When a target