2026-04-08 19:17:09 +03:00
<img src="https://gist.githubusercontent.com/avbor/1f8a128e628f47249aae6e058a57610b/raw/19013276c035e91058e0a9799ab145f8e70e3ff5/scheme.svg">
## Concept
- **Server A** (_e.g., RU_):\
2026-04-09 19:51:35 +03:00
Entry point, accepts Telegram proxy user traffic via **Xray ** (port `443\tcp` )\
and sends it through the tunnel to Server **B ** .\
Public port for Telegram clients — `443\tcp`
2026-04-08 19:17:09 +03:00
- **Server B** (_e.g., NL_):\
Exit point, runs the **Xray server ** (to terminate the tunnel entry point) and **telemt ** .\
The server must have unrestricted access to Telegram Data Centers.\
Public port for VLESS/REALITY (incoming) — `443\tcp` \
Internal telemt port (where decrypted Xray traffic ends up) — `8443\tcp`
2026-04-09 19:51:35 +03:00
The tunnel works over the `VLESS-XTLS-Reality` (or `VLESS/xhttp/reality` ) protocol. The original client IP address is preserved thanks to the PROXYv2 protocol, which Xray on Server A dynamically injects via a local loopback before wrapping the traffic into Reality, transparently delivering the real IPs to telemt on Server B.
2026-04-08 19:17:09 +03:00
---
## Step 1. Setup Xray Tunnel (A <-> B)
You must install **Xray-core ** (version 1.8.4 or newer recommended) on both servers.
Official installation script (run on both servers):
``` bash
bash -c " $( curl -L https://github.com/XTLS/Xray-install/raw/main/install-release.sh) " @ install
```
### Key and Parameter Generation (Run Once)
For configuration, you need a unique UUID and Xray Reality keys. Run on any server with Xray installed:
1. **Client UUID: **
``` bash
xray uuid
# Save the output (e.g.: 12345678-abcd-1234-abcd-1234567890ab) — this is <XRAY_UUID>
```
2. **X25519 Keypair (Private & Public) for Reality: **
``` bash
xray x25519
# Save the Private key (<SERVER_B_PRIVATE_KEY>) and Public key (<SERVER_B_PUBLIC_KEY>)
```
3. **Short ID (Reality identifier): **
``` bash
openssl rand -hex 16
# Save the output (e.g.: 0123456789abcdef0123456789abcdef) — this is <SHORT_ID>
```
2026-04-09 18:48:37 +03:00
4. **Random Path (for xhttp): **
``` bash
openssl rand -hex 8
# Save the output (e.g., abc123def456) to replace <YOUR_RANDOM_PATH> in configs
```
2026-04-08 19:17:09 +03:00
---
### Configuration for Server B (_EU_):
Create or edit the file `/usr/local/etc/xray/config.json` .
This Xray instance will listen on the public `443` port and proxy valid Reality traffic, while routing "disguised" traffic (e.g., direct web browser scans) to `yahoo.com` .
``` bash
nano /usr/local/etc/xray/config.json
```
File content:
``` json
{
"log" : {
"loglevel" : "error" ,
"access" : "none"
} ,
"inbounds" : [
{
2026-04-09 18:48:37 +03:00
"tag" : "vless-in" ,
2026-04-08 19:17:09 +03:00
"port" : 443 ,
"protocol" : "vless" ,
"settings" : {
"clients" : [
{
"id" : "<XRAY_UUID>"
}
] ,
"decryption" : "none"
} ,
"streamSettings" : {
2026-04-09 18:48:37 +03:00
"network" : "xhttp" ,
2026-04-08 19:17:09 +03:00
"security" : "reality" ,
"realitySettings" : {
"dest" : "yahoo.com:443" ,
"serverNames" : [
"yahoo.com"
] ,
"privateKey" : "<SERVER_B_PRIVATE_KEY>" ,
"shortIds" : [
"<SHORT_ID>"
]
2026-04-09 18:48:37 +03:00
} ,
"xhttpSettings" : {
"path" : "/<YOUR_RANDOM_PATH>" ,
"mode" : "auto"
2026-04-08 19:17:09 +03:00
}
}
}
] ,
"outbounds" : [
{
2026-04-09 18:48:37 +03:00
"tag" : "tunnel-to-telemt" ,
2026-04-08 19:17:09 +03:00
"protocol" : "freedom" ,
2026-04-08 22:24:51 +03:00
"settings" : {
"destination" : "127.0.0.1:8443"
}
2026-04-08 19:17:09 +03:00
}
2026-04-08 22:24:51 +03:00
] ,
"routing" : {
2026-04-09 18:48:37 +03:00
"domainStrategy" : "AsIs" ,
2026-04-08 22:24:51 +03:00
"rules" : [
{
"type" : "field" ,
2026-04-09 18:48:37 +03:00
"inboundTag" : [
"vless-in"
] ,
"outboundTag" : "tunnel-to-telemt"
2026-04-08 22:24:51 +03:00
}
]
}
2026-04-08 19:17:09 +03:00
}
```
Open the firewall port (if enabled):
``` bash
sudo ufw allow 443/tcp
```
Restart and setup Xray to run at boot:
``` bash
sudo systemctl restart xray
sudo systemctl enable xray
```
---
### Configuration for Server A (_RU_):
Similarly, edit `/usr/local/etc/xray/config.json` .
2026-04-09 19:51:35 +03:00
Here Xray acts as the public entry point: it listens on `443\tcp` , uses a local loopback (via internal port `10444` ) to prepend the `PROXYv2` header, and encapsulates the payload via Reality to Server B, instructing Server B to deliver it to its * local * `127.0.0.1:8443` port (where telemt will listen).
2026-04-08 19:17:09 +03:00
``` bash
nano /usr/local/etc/xray/config.json
```
File content:
``` json
{
"log" : {
"loglevel" : "error" ,
"access" : "none"
} ,
"inbounds" : [
{
2026-04-09 19:51:35 +03:00
"tag" : "public-in" ,
"port" : 443 ,
"listen" : "0.0.0.0" ,
"protocol" : "dokodemo-door" ,
"settings" : {
"address" : "127.0.0.1" ,
"port" : 10444 ,
"network" : "tcp"
}
} ,
{
"tag" : "tunnel-in" ,
"port" : 10444 ,
2026-04-08 19:17:09 +03:00
"listen" : "127.0.0.1" ,
"protocol" : "dokodemo-door" ,
"settings" : {
"address" : "127.0.0.1" ,
"port" : 8443 ,
"network" : "tcp"
}
}
] ,
"outbounds" : [
2026-04-09 19:51:35 +03:00
{
"tag" : "local-injector" ,
"protocol" : "freedom" ,
"settings" : {
"proxyProtocol" : 2
}
} ,
2026-04-08 19:17:09 +03:00
{
2026-04-09 18:48:37 +03:00
"tag" : "vless-out" ,
2026-04-08 19:17:09 +03:00
"protocol" : "vless" ,
"settings" : {
"vnext" : [
{
"address" : "<PUBLIC_IP_SERVER_B>" ,
"port" : 443 ,
"users" : [
{
"id" : "<XRAY_UUID>" ,
"encryption" : "none"
}
]
}
]
} ,
"streamSettings" : {
2026-04-09 18:48:37 +03:00
"network" : "xhttp" ,
2026-04-08 19:17:09 +03:00
"security" : "reality" ,
"realitySettings" : {
"serverName" : "yahoo.com" ,
"publicKey" : "<SERVER_B_PUBLIC_KEY>" ,
"shortId" : "<SHORT_ID>" ,
2026-04-09 18:48:37 +03:00
"spiderX" : "/" ,
2026-04-08 19:17:09 +03:00
"fingerprint" : "chrome"
} ,
2026-04-09 18:48:37 +03:00
"xhttpSettings" : {
"path" : "/<YOUR_RANDOM_PATH>"
2026-04-08 19:17:09 +03:00
}
}
}
2026-04-09 19:51:35 +03:00
] ,
"routing" : {
"domainStrategy" : "AsIs" ,
"rules" : [
{
"type" : "field" ,
"inboundTag" : [ "public-in" ] ,
"outboundTag" : "local-injector"
} ,
{
"type" : "field" ,
"inboundTag" : [ "tunnel-in" ] ,
"outboundTag" : "vless-out"
}
]
}
2026-04-08 19:17:09 +03:00
}
```
* Replace `<PUBLIC_IP_SERVER_B>` with the public IP address of Server B. *
2026-04-09 19:51:35 +03:00
Open the firewall port for clients (if enabled):
2026-04-08 19:17:09 +03:00
``` bash
2026-04-09 19:51:35 +03:00
sudo ufw allow 443/tcp
2026-04-08 19:17:09 +03:00
```
2026-04-09 19:51:35 +03:00
Restart and setup Xray to run at boot:
2026-04-08 19:17:09 +03:00
``` bash
2026-04-09 19:51:35 +03:00
sudo systemctl restart xray
sudo systemctl enable xray
2026-04-08 19:17:09 +03:00
```
---
2026-04-09 19:51:35 +03:00
## Step 2. Install telemt on Server B (_EU_)
2026-04-08 19:17:09 +03:00
2026-04-10 13:45:53 +03:00
telemt installation is heavily covered in the [Quick Start Guide ](../Quick_start/QUICK_START_GUIDE.en.md ).
2026-04-08 19:17:09 +03:00
By contrast to standard setups, telemt must listen strictly _ locally _ (since Xray occupies the public `443` interface) and must expect `PROXYv2` packets.
Edit the configuration file (`config.toml` ) on Server B accordingly:
``` toml
[ server ]
port = 8443
listen_addr_ipv4 = "127.0.0.1"
proxy_protocol = true
[ general . links ]
show = "*"
public_host = "<FQDN_OR_IP_SERVER_A>"
public_port = 443
```
- Address `127.0.0.1` and `port = 8443` instructs the core proxy router to process connections unpacked locally via Xray-server.
2026-04-09 19:51:35 +03:00
- `proxy_protocol = true` commands telemt to parse the injected PROXY header (from Server A's Xray local loopback) and log genuine end-user IPs.
2026-04-08 19:17:09 +03:00
- Under `public_host` , place Server A's public IP address or FQDN to ensure working links are generated for Telegram users.
Restart `telemt` . Your server is now robust against DPI scanners, passing traffic optimally.