# Xray Infrastructure Configuration ## Servers | Role | IP | Domain | OS | Xray | x-ui | |------|-----|--------|-----|------|------| | Local (client) | 95.165.85.65 | — | Ubuntu, kernel 6.8.0-94 | 25.10.15 | 2.8.10 | | Remote (server) | 83.99.190.32 | share.alogins.net | Ubuntu 24.04.3 (LXD container) | 26.2.6 | 2.8.10 | --- ## Access Credentials ### Remote server SSH - Host: `83.99.190.32` - User: `juris` - LXD container access: `lxc exec xray -- ` ### Remote 3x-ui panel - URL: `https://share.alogins.net:16627/gBdsRLtVZdgZ63wmVR/` - Username: `xrayadmin` - Password: `Admin2026!` ### Local x-ui panel - URL: `http://127.0.0.1:58959/gnYCNq4EbYukS5qtOe/` - Username: `3ZHPoQdd89` - Password: `1c1QUbKhQP` ### Local server sudo - User: `alvis` --- ## Reality Keys (shared keypair) | Key | Value | |-----|-------| | Private key (server) | `KJfhenZvJV1kXwv4kDC8NPBtMUY0RR8lFrxsxfXfFmY` | | Public key (client) | `58Iqd6LuWXgvjAgo92-7KURhTp0Vj79yGF81l_iuvTw` | ### juris-xhttp (ACTIVE — XHTTP+Reality) | Field | Value | |-------|-------| | UUID | `6e422ab5-070a-43f6-8241-38cd56d23d24` | | Short ID | `6036d37d12c443c4` | | XHTTP path | `/xt-6036d37d` | ### juris-reality (FALLBACK — TCP+Reality+Vision) | Field | Value | |-------|-------| | UUID | `64522a14-54aa-4b3c-8071-8c8b17aa1f08` | | Short ID | `48b4c16249ad44ff` | --- ## SNI Test Results Reality dest on remote server: `www.delfi.lv:443` | SNI | Status | Avg Latency | Download | Upload | |-----|--------|-------------|----------|--------| | `www.delfi.lv` | **ACTIVE** | 121ms | 44.79 Mbps | 33.90 Mbps | | `www.lmt.lv` | OK | 133ms | 50.58 Mbps | 37.33 Mbps | | `www.inbox.lv` | OK | 121ms | 45.48 Mbps | 32.98 Mbps | | `e-klase.lv` | OK | 121ms | 54.84 Mbps | 29.58 Mbps | | `www.tele2.lv` | FAIL (dest mismatch) | — | — | — | | `www.lsm.lv` | FAIL (dest mismatch) | — | — | — | | `share.alogins.net` | FAIL (dest mismatch) | — | — | — | | `www.microsoft.com` | FAIL (dest mismatch) | — | — | — | Full benchmark results: `sni_test_results.md` --- ## LXD Port Forwarding (remote host → container) ``` proxy-443: tcp:0.0.0.0:443 → tcp:127.0.0.1:443 proxy-16627: tcp:0.0.0.0:16627 → tcp:127.0.0.1:16627 ``` --- ## Remote Server Config (VLESS+XHTTP+Reality inbound) — ACTIVE Server: `share.alogins.net` / LXD container `xray` (10.187.159.41) **Winner of comparative test**: lowest latency (142ms avg, 225ms P95), best upload. ```json { "listen": "0.0.0.0", "port": 443, "protocol": "vless", "tag": "inbound-443", "settings": { "clients": [ { "id": "6e422ab5-070a-43f6-8241-38cd56d23d24", "email": "juris-xhttp", "flow": "" }, { "id": "64522a14-54aa-4b3c-8071-8c8b17aa1f08", "email": "juris-reality-legacy", "flow": "" } ], "decryption": "none" }, "streamSettings": { "network": "xhttp", "security": "reality", "realitySettings": { "dest": "www.delfi.lv:443", "serverNames": ["www.delfi.lv", "www.lmt.lv", "www.inbox.lv", "e-klase.lv"], "privateKey": "KJfhenZvJV1kXwv4kDC8NPBtMUY0RR8lFrxsxfXfFmY", "shortIds": ["48b4c16249ad44ff", "6036d37d12c443c4", ""], "show": false }, "xhttpSettings": { "path": "/xt-6036d37d", "host": "", "mode": "auto", "extra": { "xPaddingBytes": "100-1000", "xmux": { "maxConcurrency": "16-32", "maxConnections": 0, "cMaxReuseTimes": "64-128", "cMaxLifetimeMs": 0, "hMaxRequestTimes": "600-900", "hMaxReusableSecs": "1800-3000" } } } } } ``` --- ## Local Server Config (full live xray configuration) Config path: `/usr/local/x-ui/bin/config.json` DB path: `/etc/x-ui/x-ui.db` (template stored in `xrayTemplateConfig` setting) ### Outbounds | Tag | Protocol | Destination | Security | Fingerprint | Status | |-----|----------|-------------|----------|-------------|--------| | `direct` | freedom | — | — | — | Default | | `blocked` | blackhole | — | — | — | Block | | `socks` | socks | 127.0.0.1:1081 | — | — | Local proxy | | `AMS-Server` | trojan | 45.32.235.202:443 | reality (SNI: www.nvidia.com) | chrome | Active | | `juris-reality` | vless | share.alogins.net:443 | TCP+reality (SNI: www.delfi.lv) | chrome | Fallback, no routing rules | | `juris-xhttp` | vless | share.alogins.net:443 | XHTTP+reality (SNI: www.delfi.lv, Host: www.delfi.lv) | chrome | **PRIMARY**, no routing rules | | `juris-xhttp-firefox` | vless | share.alogins.net:443 | XHTTP+reality (SNI: www.delfi.lv, Host: www.delfi.lv) | firefox | Alternate fingerprint, no routing rules | | `juris-xhttp-safari` | vless | share.alogins.net:443 | XHTTP+reality (SNI: www.delfi.lv, Host: www.delfi.lv) | safari | Alternate fingerprint, no routing rules | ### Inbounds | Tag | Protocol | Listen | Port | Notes | |-----|----------|--------|------|-------| | `api` | tunnel | 127.0.0.1 | 62789 | Internal API | | `inbound-127.0.0.1:8445` | vless | 127.0.0.1 | 8445 | XHTTP stream, 4 clients | | `inbound-56928` | mixed | 0.0.0.0 | 56928 | SOCKS/HTTP proxy, routes → AMS-Server | ### Routing Rules | # | Match | Outbound | |---|-------|----------| | 1 | inboundTag: `inbound-56928` | `AMS-Server` | | 2 | inboundTag: `api` | `api` | | 3 | ip: `geoip:private` | `blocked` | | 4 | protocol: `bittorrent` | `blocked` | | 5 | domain: `ext:geosite_RU.dat:ru-blocked` + inbound `8445` | `AMS-Server` | ### VLESS Clients (inbound-127.0.0.1:8445) | Email | UUID | Comment | |-------|------|---------| | 36npz8zz | 13a01d7c-9ca7-4ee6-83d8-4c59907b13d1 | ipad pro | | 4camw53nd | 108fdf6b-f8e4-4e1a-9bbe-b7c1fa9fffa0 | pixel | | y3673rul | 584cba3d-2d43-464a-9b29-67e02adc092d | iphone promax | | j5x2285y | f6781d19-cf77-4f8f-9114-0e612aa3081c | AlinaSt | ### juris-reality Outbound (full config) ```json { "tag": "juris-reality", "protocol": "vless", "settings": { "vnext": [ { "address": "share.alogins.net", "port": 443, "users": [ { "id": "64522a14-54aa-4b3c-8071-8c8b17aa1f08", "flow": "xtls-rprx-vision", "encryption": "none" } ] } ] }, "streamSettings": { "network": "tcp", "security": "reality", "realitySettings": { "fingerprint": "chrome", "serverName": "www.delfi.lv", "publicKey": "58Iqd6LuWXgvjAgo92-7KURhTp0Vj79yGF81l_iuvTw", "shortId": "48b4c16249ad44ff", "spiderX": "/" }, "tcpSettings": { "header": { "type": "none" } } } } ``` ### AMS-Server Outbound (existing) ```json { "tag": "AMS-Server", "protocol": "trojan", "settings": { "servers": [ { "address": "45.32.235.202", "port": 443, "password": "z5Y2tMeDs1" } ] }, "streamSettings": { "network": "tcp", "security": "reality", "realitySettings": { "publicKey": "J37AuaLzZYRTQZ-pxUpbIndo15EpoY1lhnAXZ1rUFnQ", "fingerprint": "chrome", "serverName": "www.nvidia.com", "shortId": "22", "spiderX": "/" } } } ``` --- ## File Paths ### Local server | Path | Purpose | |------|---------| | `/usr/local/x-ui/bin/config.json` | Live xray config (auto-generated by x-ui, do NOT edit directly) | | `/usr/local/x-ui/bin/xray-linux-amd64` | Xray binary | | `/usr/local/x-ui/x-ui` | x-ui panel binary | | `/etc/x-ui/x-ui.db` | x-ui database (settings, inbounds, users) | | `/home/alvis/ai-xray/venv/` | Python venv with paramiko for SSH | ### Remote server (inside LXD container "xray") | Path | Purpose | |------|---------| | `/usr/local/x-ui/bin/config.json` | Live xray config (auto-generated) | | `/usr/local/x-ui/bin/xray-linux-amd64` | Xray binary | | `/etc/x-ui/x-ui.db` | x-ui database | --- ## How to Route Traffic Through juris-reality Currently `juris-reality` has no routing rules. To use it, add a rule to the xray template in the DB: **Route specific domains:** ```json { "type": "field", "domain": ["example.com", "example.org"], "outboundTag": "juris-reality" } ``` **Route all SOCKS proxy traffic (replaces AMS-Server):** ```json { "type": "field", "inboundTag": ["inbound-56928"], "outboundTag": "juris-reality" } ``` **Route Russian-blocked domains through juris-reality instead of AMS-Server:** Change outboundTag in rule #5 from `AMS-Server` to `juris-reality`. --- ## Updating Xray Config via x-ui REST API (no sudo) `config.json` is auto-generated by x-ui from the DB template. **Never edit it directly.** ### Step-by-step **1. Authenticate:** ```bash curl -s -c /tmp/xui-cookie.txt -X POST \ 'http://127.0.0.1:58959/gnYCNq4EbYukS5qtOe/login' \ -H 'Content-Type: application/x-www-form-urlencoded' \ -d 'username=3ZHPoQdd89&password=1c1QUbKhQP' ``` **2. Read current xray template:** ```bash curl -s -b /tmp/xui-cookie.txt -X POST \ 'http://127.0.0.1:58959/gnYCNq4EbYukS5qtOe/panel/xray/' ``` Returns `{"success":true,"obj":"{ \"xraySetting\": {...}, \"inboundTags\": [...] }"}`. The `obj` value is a JSON string containing the full xray template under the `xraySetting` key. **3. Update xray template:** ```bash curl -s -b /tmp/xui-cookie.txt -X POST \ 'http://127.0.0.1:58959/gnYCNq4EbYukS5qtOe/panel/xray/update' \ -d 'xraySetting=' ``` The key detail: use **form-urlencoded** with a single field `xraySetting` whose value is the full xray template JSON string. This is the `xraySetting` object from step 2 (the inner JSON, not the wrapper). **4. Restart xray to apply:** ```bash curl -s -b /tmp/xui-cookie.txt -X POST \ 'http://127.0.0.1:58959/gnYCNq4EbYukS5qtOe/panel/api/server/restartXrayService' ``` ### Python example (recommended) ```python import requests, json BASE = "http://127.0.0.1:58959/gnYCNq4EbYukS5qtOe" s = requests.Session() # Login s.post(f"{BASE}/login", data={"username": "3ZHPoQdd89", "password": "1c1QUbKhQP"}) # Read current template r = s.post(f"{BASE}/panel/xray/") obj = json.loads(r.json()["obj"]) xray = obj["xraySetting"] # Modify (example: change SNI) for ob in xray["outbounds"]: if ob.get("tag") == "juris-reality": ob["streamSettings"]["realitySettings"]["serverName"] = "www.delfi.lv" # Write back (form field, NOT JSON body) s.post(f"{BASE}/panel/xray/update", data={"xraySetting": json.dumps(xray)}) # Restart xray s.post(f"{BASE}/panel/api/server/restartXrayService") ``` ### API gotchas | Endpoint | Method | Works? | Notes | |----------|--------|--------|-------| | `POST /panel/xray/update` | form-urlencoded `xraySetting=` | **Yes** | Correct way to persist template changes | | `POST /panel/xray/update` | JSON body `{"xraySetting": ...}` | No | Returns "unexpected end of JSON input" | | `POST /panel/setting/update` | any | No | Accepts request but silently ignores `xrayTemplateConfig` | | `GET /panel/setting/getDefaultJsonConfig` | — | — | Returns factory defaults, not actual config | | `GET /panel/api/server/getConfigJson` | — | Read-only | Returns live running xray config | | `xray api ado` CLI | — | Ephemeral | Adds outbound to running instance only, lost on restart | --- ## Important Notes - The `xray api ado` CLI can add outbounds to the running instance (ephemeral, lost on restart). Requires full-config JSON format: `{"outbounds": [{...}]}`.