mirror of
https://gitverse.ru/kpa39l/tproxy-web-proxy.git
synced 2026-09-29 09:35:03 +00:00
Initial commit: Hermes skill tproxy-web-proxy
This commit is contained in:
@@ -0,0 +1,108 @@
|
|||||||
|
---
|
||||||
|
name: tproxy-web-proxy
|
||||||
|
description: >-
|
||||||
|
Operate tproxy-server (secrets, readyz, metrics).
|
||||||
|
tags:
|
||||||
|
- telegram
|
||||||
|
- proxy
|
||||||
|
- mtproto
|
||||||
|
- web-proxy
|
||||||
|
- systemd
|
||||||
|
- prometheus
|
||||||
|
category: devops
|
||||||
|
---
|
||||||
|
|
||||||
|
# tproxy-web-proxy — Telegram WEB Proxy (telegramdesktop/tproxy-server)
|
||||||
|
|
||||||
|
## When to Use
|
||||||
|
|
||||||
|
- Add / revoke client secrets (profiles) on a deployed tproxy-server
|
||||||
|
(«добавь ещё один секрет», «убери доступ другу»)
|
||||||
|
- Check proxy health (/readyz, /healthz) or answer what an endpoint returns
|
||||||
|
- Wire /metrics into the Prometheus stack (/opt/monitoring)
|
||||||
|
- Troubleshoot the service (Caddy → tproxy-server → MTProxy chain)
|
||||||
|
- Deploy tproxy-server on a fresh VPS
|
||||||
|
|
||||||
|
## Architecture (deployed on vps03, 2026-08)
|
||||||
|
|
||||||
|
```
|
||||||
|
Telegram Desktop (WEB Proxy) --HTTPS 443--> Caddy (vps03.nixg.ru)
|
||||||
|
--> tproxy-server :8080 (loopback) --> MTProxy :2398 (loopback)
|
||||||
|
```
|
||||||
|
|
||||||
|
Key files (Debian):
|
||||||
|
- `/etc/tproxy-server/config.json` — main config (`listen` 127.0.0.1:8080,
|
||||||
|
`admin_listen` 127.0.0.1:8081, `limits.max_profiles` default 32)
|
||||||
|
- `/etc/tproxy-server/profiles.json` — ARRAY of client profiles (secrets),
|
||||||
|
perms `600 root:tproxy`
|
||||||
|
- `/etc/systemd/system/tproxy-server.service` —
|
||||||
|
`ExecStart=/usr/local/bin/tproxy-server -config ...`,
|
||||||
|
`LoadCredential=profiles.json:/etc/tproxy-server/profiles.json`
|
||||||
|
- `/etc/tproxy-server/firewall.nft` — nft rules
|
||||||
|
|
||||||
|
## Multiple secrets (profiles)
|
||||||
|
|
||||||
|
profiles.json is an ARRAY → many secrets supported (limit `max_profiles: 32`).
|
||||||
|
Each profile points to the same MTProxy backend unless overridden — one
|
||||||
|
MTProxy, many access keys.
|
||||||
|
|
||||||
|
```json
|
||||||
|
{"profiles":[
|
||||||
|
{"name":"default","secret":"<32-hex>","backend":"127.0.0.1:2398"},
|
||||||
|
{"name":"rahuba","secret":"<32-hex>","backend":"127.0.0.1:2398"}
|
||||||
|
]}
|
||||||
|
```
|
||||||
|
|
||||||
|
Secret format: 16 bytes = 32 hex (plain) OR 17 bytes with `dd` prefix
|
||||||
|
(fake-TLS mode). `openssl rand -hex 16` → plain 32-hex.
|
||||||
|
|
||||||
|
Add a profile:
|
||||||
|
1. Edit `/etc/tproxy-server/profiles.json` (python3 json.dump for safety)
|
||||||
|
2. `chmod 600` + `chown root:tproxy` — systemd LoadCredential rejects
|
||||||
|
group/other-readable files, unit fails to start otherwise
|
||||||
|
3. `systemctl restart tproxy-server`
|
||||||
|
4. Verify: `journalctl -u tproxy-server | grep 'event=started'` shows
|
||||||
|
`profiles=N` (N = profile count); `curl :8081/readyz` → 200
|
||||||
|
|
||||||
|
Revoke: remove the profile object + restart.
|
||||||
|
|
||||||
|
## Admin endpoints (`admin_listen`, loopback only)
|
||||||
|
|
||||||
|
- `/healthz` — process alive, always 200 `ok`; does NOT check backend
|
||||||
|
- `/readyz` — TCP `net.DialTimeout` to EVERY profile's backend (5s);
|
||||||
|
all ok → 200 `ready`; any dead → 503 `backend unavailable`.
|
||||||
|
NOTE: one profile with a dead backend makes readyz fail for ALL.
|
||||||
|
- `/metrics` — Prometheus text format (13 counters; full list, scrape config
|
||||||
|
and alert ideas in `references/tproxy-monitoring.md`)
|
||||||
|
- `/debug/pprof/*` — only when `enable_pprof: true`
|
||||||
|
|
||||||
|
## Pitfalls
|
||||||
|
|
||||||
|
1. **Install: `go test ./...` fails under root** —
|
||||||
|
`TestLoadAcceptsSystemdCredentialReadPermissions` («group/other-readable
|
||||||
|
profiles file outside a credential directory was accepted»). Run the
|
||||||
|
build/tests as a non-root user, or skip that single test. Do NOT change
|
||||||
|
`loadProfiles` semantics in upstream code.
|
||||||
|
2. **profiles.json permissions** — must not be group/other readable/writable
|
||||||
|
(use `600 root:tproxy`). This is exactly what the config unit test enforces.
|
||||||
|
3. **readyz is per-backend** — a dead backend in any profile → 503 for
|
||||||
|
everyone.
|
||||||
|
4. **Admin endpoints are loopback-only** — to expose /metrics to a remote
|
||||||
|
Prometheus, open the port in nft restricted to the monitor's source IP
|
||||||
|
(e.g. bigbox public IP), never 0.0.0.0.
|
||||||
|
5. **Restart required after every profiles.json change** — profiles are
|
||||||
|
loaded once at start via LoadCredential.
|
||||||
|
6. **Keep secrets out of shell history** — pass via file `$(cat ...)`, never
|
||||||
|
inline; tproxy logs never print secrets.
|
||||||
|
|
||||||
|
## Monitoring
|
||||||
|
|
||||||
|
Full metrics table, readyz semantics, prometheus.yml job and alert ideas:
|
||||||
|
`references/tproxy-monitoring.md`. Monitoring task lives in
|
||||||
|
`/opt/monitoring/PLAN.md` («Этап 6. Метрики tproxy-server (vps03)»).
|
||||||
|
|
||||||
|
## Related Skills
|
||||||
|
|
||||||
|
- `mtproto-proxy` — classic MTProto proxy via seriyps docker image (DIFFERENT
|
||||||
|
product; tproxy-server is the official browser-based WEB proxy)
|
||||||
|
- `networking-proxy` — umbrella for the XRay/AmneziaWG/Shadowsocks stack
|
||||||
@@ -0,0 +1,85 @@
|
|||||||
|
# tproxy-server monitoring reference
|
||||||
|
|
||||||
|
Admin HTTP endpoints (bound to `127.0.0.1:8081` = `admin_listen`, loopback only):
|
||||||
|
|
||||||
|
| Endpoint | Returns |
|
||||||
|
|---|---|
|
||||||
|
| `/healthz` | always `200 ok` while the process runs; does NOT touch backends |
|
||||||
|
| `/readyz` | `200 ready` if TCP dial succeeds to EVERY profile backend; `503 backend unavailable` if any backend dial fails (timeout = `timeouts.backend_dial`, default 5s) |
|
||||||
|
| `/metrics` | Prometheus text format (`Content-Type: text/plain; version=0.0.4`), 13 counters |
|
||||||
|
| `/debug/pprof/*` | only when `config.enable_pprof: true` |
|
||||||
|
|
||||||
|
## Metrics (from serveMetrics, internal/server/server.go)
|
||||||
|
|
||||||
|
```
|
||||||
|
tproxy_sessions_live # currently active sessions
|
||||||
|
tproxy_streams_live # currently active streams
|
||||||
|
tproxy_backend_dials_in_flight # in-flight dials to MTProxy (127.0.0.1:2398)
|
||||||
|
tproxy_pending_bytes # queued payload waiting to be relayed
|
||||||
|
tproxy_pending_items # queued items
|
||||||
|
tproxy_sessions_created_total # cumulative
|
||||||
|
tproxy_sessions_closed_total # cumulative
|
||||||
|
tproxy_streams_opened_total # cumulative
|
||||||
|
tproxy_streams_rejected_total # cumulative
|
||||||
|
tproxy_backend_dial_failures_total # cumulative — growth = MTProxy down/unreachable
|
||||||
|
tproxy_bytes_up_total # cumulative, client→proxy→backend
|
||||||
|
tproxy_bytes_down_total # cumulative, backend→client
|
||||||
|
tproxy_limit_hits_total # cumulative, rate-limit / capacity hits
|
||||||
|
```
|
||||||
|
|
||||||
|
Note: live values come from `manager.Capacity()` (current), `_total` counters
|
||||||
|
from `manager.Metrics()` (cumulative). No labels/help strings emitted — plain
|
||||||
|
`name value` lines.
|
||||||
|
|
||||||
|
## Prometheus scrape config (prometheus runs network_mode: host)
|
||||||
|
|
||||||
|
```yaml
|
||||||
|
- job_name: 'tproxy'
|
||||||
|
static_configs:
|
||||||
|
- targets: ['77.67.89.154:8081'] # vps03 public IP; port must be opened
|
||||||
|
labels:
|
||||||
|
host: vps03
|
||||||
|
service: tproxy
|
||||||
|
```
|
||||||
|
|
||||||
|
## Exposing 8081 to the monitor (vps03, nft)
|
||||||
|
|
||||||
|
Endpoint listens on loopback only — open for ONE source IP, e.g. bigbox:
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nft add rule inet filter input ip saddr <BIGBOX_IP> tcp dport 8081 accept
|
||||||
|
systemctl restart tproxy-server # or nft reload
|
||||||
|
```
|
||||||
|
|
||||||
|
Never publish to 0.0.0.0; the endpoint has no auth.
|
||||||
|
|
||||||
|
## Alert ideas
|
||||||
|
|
||||||
|
- `tproxy_backend_dial_failures_total` increases → MTProxy unreachable
|
||||||
|
- `/readyz` non-200 → chain broken (but remember: ONE dead profile backend
|
||||||
|
fails readyz for everyone)
|
||||||
|
- `tproxy_limit_hits_total` increases → abuse / capacity exceeded
|
||||||
|
- `up{job="tproxy"} == 0` → exporter itself down
|
||||||
|
|
||||||
|
## Monitoring task location
|
||||||
|
|
||||||
|
`/opt/monitoring/PLAN.md` — «Этап 6. Метрики tproxy-server (vps03)» (written
|
||||||
|
2026-08-31), git repo `gitverse.ru:kpa39l/monitoring.git`, gitea mirror.
|
||||||
|
|
||||||
|
## Verified live sample (vps03, 2026-08-31, idle-ish)
|
||||||
|
|
||||||
|
```
|
||||||
|
tproxy_sessions_live 1
|
||||||
|
tproxy_streams_live 5
|
||||||
|
tproxy_backend_dials_in_flight 0
|
||||||
|
tproxy_pending_bytes 0
|
||||||
|
tproxy_pending_items 0
|
||||||
|
tproxy_sessions_created_total 1
|
||||||
|
tproxy_sessions_closed_total 0
|
||||||
|
tproxy_streams_opened_total 15
|
||||||
|
tproxy_streams_rejected_total 0
|
||||||
|
tproxy_backend_dial_failures_total 0
|
||||||
|
tproxy_bytes_up_total 166853
|
||||||
|
tproxy_bytes_down_total 5076719
|
||||||
|
tproxy_limit_hits_total 0
|
||||||
|
```
|
||||||
Reference in New Issue
Block a user