mirror of https://github.com/telemt/telemt.git
Merge branch 'flow' into flow
This commit is contained in:
commit
0475844701
|
|
@ -20,7 +20,7 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||||
| Parameter | Type | Default | Constraints / validation | Description |
|
| Parameter | Type | Default | Constraints / validation | Description |
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| data_path | `String \| null` | `null` | — | Optional runtime data directory path. |
|
| data_path | `String \| null` | `null` | — | Optional runtime data directory path. |
|
||||||
| prefer_ipv6 | `bool` | `false` | — | Prefer IPv6 where applicable in runtime logic. |
|
| prefer_ipv6 | `bool` | `false` | Deprecated. Use `network.prefer`. | Deprecated legacy IPv6 preference flag migrated to `network.prefer`. |
|
||||||
| fast_mode | `bool` | `true` | — | Enables fast-path optimizations for traffic processing. |
|
| fast_mode | `bool` | `true` | — | Enables fast-path optimizations for traffic processing. |
|
||||||
| use_middle_proxy | `bool` | `true` | none | Enables ME transport mode; if `false`, runtime falls back to direct DC routing. |
|
| use_middle_proxy | `bool` | `true` | none | Enables ME transport mode; if `false`, runtime falls back to direct DC routing. |
|
||||||
| proxy_secret_path | `String \| null` | `"proxy-secret"` | Path may be `null`. | Path to Telegram infrastructure proxy-secret file used by ME handshake logic. |
|
| proxy_secret_path | `String \| null` | `"proxy-secret"` | Path may be `null`. | Path to Telegram infrastructure proxy-secret file used by ME handshake logic. |
|
||||||
|
|
@ -44,6 +44,7 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||||
| me_writer_cmd_channel_capacity | `usize` | `4096` | Must be `> 0`. | Capacity of per-writer command channel. |
|
| me_writer_cmd_channel_capacity | `usize` | `4096` | Must be `> 0`. | Capacity of per-writer command channel. |
|
||||||
| me_route_channel_capacity | `usize` | `768` | Must be `> 0`. | Capacity of per-connection ME response route channel. |
|
| me_route_channel_capacity | `usize` | `768` | Must be `> 0`. | Capacity of per-connection ME response route channel. |
|
||||||
| me_c2me_channel_capacity | `usize` | `1024` | Must be `> 0`. | Capacity of per-client command queue (client reader -> ME sender). |
|
| me_c2me_channel_capacity | `usize` | `1024` | Must be `> 0`. | Capacity of per-client command queue (client reader -> ME sender). |
|
||||||
|
| me_c2me_send_timeout_ms | `u64` | `4000` | `0..=60000`. | Maximum wait for enqueueing client->ME commands when the per-client queue is full (`0` keeps legacy unbounded wait). |
|
||||||
| me_reader_route_data_wait_ms | `u64` | `2` | `0..=20`. | Bounded wait for routing ME DATA to per-connection queue (`0` = no wait). |
|
| me_reader_route_data_wait_ms | `u64` | `2` | `0..=20`. | Bounded wait for routing ME DATA to per-connection queue (`0` = no wait). |
|
||||||
| me_d2c_flush_batch_max_frames | `usize` | `32` | `1..=512`. | Max ME->client frames coalesced before flush. |
|
| me_d2c_flush_batch_max_frames | `usize` | `32` | `1..=512`. | Max ME->client frames coalesced before flush. |
|
||||||
| me_d2c_flush_batch_max_bytes | `usize` | `131072` | `4096..=2_097_152`. | Max ME->client payload bytes coalesced before flush. |
|
| me_d2c_flush_batch_max_bytes | `usize` | `131072` | `4096..=2_097_152`. | Max ME->client payload bytes coalesced before flush. |
|
||||||
|
|
@ -105,6 +106,8 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||||
| me_warn_rate_limit_ms | `u64` | `5000` | Must be `> 0`. | Cooldown for repetitive ME warning logs (ms). |
|
| me_warn_rate_limit_ms | `u64` | `5000` | Must be `> 0`. | Cooldown for repetitive ME warning logs (ms). |
|
||||||
| me_route_no_writer_mode | `"async_recovery_failfast" \| "inline_recovery_legacy" \| "hybrid_async_persistent"` | `"hybrid_async_persistent"` | — | Route behavior when no writer is immediately available. |
|
| me_route_no_writer_mode | `"async_recovery_failfast" \| "inline_recovery_legacy" \| "hybrid_async_persistent"` | `"hybrid_async_persistent"` | — | Route behavior when no writer is immediately available. |
|
||||||
| me_route_no_writer_wait_ms | `u64` | `250` | `10..=5000`. | Max wait in async-recovery failfast mode (ms). |
|
| me_route_no_writer_wait_ms | `u64` | `250` | `10..=5000`. | Max wait in async-recovery failfast mode (ms). |
|
||||||
|
| me_route_hybrid_max_wait_ms | `u64` | `3000` | `50..=60000`. | Maximum cumulative wait in hybrid no-writer mode before failfast fallback (ms). |
|
||||||
|
| me_route_blocking_send_timeout_ms | `u64` | `250` | `0..=5000`. | Maximum wait for blocking route-channel send fallback (`0` keeps legacy unbounded wait). |
|
||||||
| me_route_inline_recovery_attempts | `u32` | `3` | Must be `> 0`. | Inline recovery attempts in legacy mode. |
|
| me_route_inline_recovery_attempts | `u32` | `3` | Must be `> 0`. | Inline recovery attempts in legacy mode. |
|
||||||
| me_route_inline_recovery_wait_ms | `u64` | `3000` | `10..=30000`. | Max inline recovery wait in legacy mode (ms). |
|
| me_route_inline_recovery_wait_ms | `u64` | `3000` | `10..=30000`. | Max inline recovery wait in legacy mode (ms). |
|
||||||
| fast_mode_min_tls_record | `usize` | `0` | — | Minimum TLS record size when fast-mode coalescing is enabled (`0` disables). |
|
| fast_mode_min_tls_record | `usize` | `0` | — | Minimum TLS record size when fast-mode coalescing is enabled (`0` disables). |
|
||||||
|
|
@ -124,6 +127,7 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||||
| me_secret_atomic_snapshot | `bool` | `true` | — | Keeps selector and secret bytes from the same snapshot atomically. |
|
| me_secret_atomic_snapshot | `bool` | `true` | — | Keeps selector and secret bytes from the same snapshot atomically. |
|
||||||
| proxy_secret_len_max | `usize` | `256` | Must be within `[32, 4096]`. | Upper length limit for accepted proxy-secret bytes. |
|
| proxy_secret_len_max | `usize` | `256` | Must be within `[32, 4096]`. | Upper length limit for accepted proxy-secret bytes. |
|
||||||
| me_pool_drain_ttl_secs | `u64` | `90` | none | Time window where stale writers remain fallback-eligible after map change. |
|
| me_pool_drain_ttl_secs | `u64` | `90` | none | Time window where stale writers remain fallback-eligible after map change. |
|
||||||
|
| me_instadrain | `bool` | `false` | — | Forces draining stale writers to be removed on the next cleanup tick, bypassing TTL/deadline waiting. |
|
||||||
| me_pool_drain_threshold | `u64` | `128` | — | Max draining stale writers before batch force-close (`0` disables threshold cleanup). |
|
| me_pool_drain_threshold | `u64` | `128` | — | Max draining stale writers before batch force-close (`0` disables threshold cleanup). |
|
||||||
| me_pool_drain_soft_evict_enabled | `bool` | `true` | — | Enables gradual soft-eviction of stale writers during drain/reinit instead of immediate hard close. |
|
| me_pool_drain_soft_evict_enabled | `bool` | `true` | — | Enables gradual soft-eviction of stale writers during drain/reinit instead of immediate hard close. |
|
||||||
| me_pool_drain_soft_evict_grace_secs | `u64` | `30` | `0..=3600`. | Grace period before stale writers become soft-evict candidates. |
|
| me_pool_drain_soft_evict_grace_secs | `u64` | `30` | `0..=3600`. | Grace period before stale writers become soft-evict candidates. |
|
||||||
|
|
@ -203,6 +207,7 @@ This document lists all configuration keys accepted by `config.toml`.
|
||||||
| metrics_listen | `String \| null` | `null` | — | Full metrics bind address (`IP:PORT`), overrides `metrics_port`. |
|
| metrics_listen | `String \| null` | `null` | — | Full metrics bind address (`IP:PORT`), overrides `metrics_port`. |
|
||||||
| metrics_whitelist | `IpNetwork[]` | `["127.0.0.1/32", "::1/128"]` | — | CIDR whitelist for metrics endpoint access. |
|
| metrics_whitelist | `IpNetwork[]` | `["127.0.0.1/32", "::1/128"]` | — | CIDR whitelist for metrics endpoint access. |
|
||||||
| max_connections | `u32` | `10000` | — | Max concurrent client connections (`0` = unlimited). |
|
| max_connections | `u32` | `10000` | — | Max concurrent client connections (`0` = unlimited). |
|
||||||
|
| accept_permit_timeout_ms | `u64` | `250` | `0..=60000`. | Maximum wait for acquiring a connection-slot permit before the accepted connection is dropped (`0` keeps legacy unbounded wait). |
|
||||||
|
|
||||||
Note: When `server.proxy_protocol` is enabled, incoming PROXY protocol headers are parsed from the first bytes of the connection and the client source address is replaced with `src_addr` from the header. For security, the peer source IP (the direct connection address) is verified against `server.proxy_protocol_trusted_cidrs`; if this list is empty, PROXY headers are rejected and the connection is considered untrusted.
|
Note: When `server.proxy_protocol` is enabled, incoming PROXY protocol headers are parsed from the first bytes of the connection and the client source address is replaced with `src_addr` from the header. For security, the peer source IP (the direct connection address) is verified against `server.proxy_protocol_trusted_cidrs`; if this list is empty, PROXY headers are rejected and the connection is considered untrusted.
|
||||||
|
|
||||||
|
|
@ -229,7 +234,7 @@ Note: When `server.proxy_protocol` is enabled, incoming PROXY protocol headers a
|
||||||
|---|---|---|---|---|
|
|---|---|---|---|---|
|
||||||
| ip | `IpAddr` | — | — | Listener bind IP. |
|
| ip | `IpAddr` | — | — | Listener bind IP. |
|
||||||
| announce | `String \| null` | — | — | Public IP/domain announced in proxy links (priority over `announce_ip`). |
|
| announce | `String \| null` | — | — | Public IP/domain announced in proxy links (priority over `announce_ip`). |
|
||||||
| announce_ip | `IpAddr \| null` | — | — | Deprecated legacy announce IP (migrated to `announce` if needed). |
|
| announce_ip | `IpAddr \| null` | — | Deprecated. Use `announce`. | Deprecated legacy announce IP (migrated to `announce` if needed). |
|
||||||
| proxy_protocol | `bool \| null` | `null` | — | Per-listener override for PROXY protocol enable flag. |
|
| proxy_protocol | `bool \| null` | `null` | — | Per-listener override for PROXY protocol enable flag. |
|
||||||
| reuse_allow | `bool` | `false` | — | Enables `SO_REUSEPORT` for multi-instance bind sharing. |
|
| reuse_allow | `bool` | `false` | — | Enables `SO_REUSEPORT` for multi-instance bind sharing. |
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
1. Go to @MTProxybot bot.
|
1. Go to @MTProxybot bot.
|
||||||
2. Enter the command `/newproxy`
|
2. Enter the command `/newproxy`
|
||||||
3. Send the server IP and port. For example: 1.2.3.4:443
|
3. Send the server IP and port. For example: 1.2.3.4:443
|
||||||
4. Open the config `nano /etc/telemt.toml`.
|
4. Open the config `nano /etc/telemt/telemt.toml`.
|
||||||
5. Copy and send the user secret from the [access.users] section to the bot.
|
5. Copy and send the user secret from the [access.users] section to the bot.
|
||||||
6. Copy the tag received from the bot. For example 1234567890abcdef1234567890abcdef.
|
6. Copy the tag received from the bot. For example 1234567890abcdef1234567890abcdef.
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
|
|
@ -33,6 +33,9 @@ hello = "ad_tag"
|
||||||
hello2 = "ad_tag2"
|
hello2 = "ad_tag2"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Why is middle proxy (ME) needed
|
||||||
|
https://github.com/telemt/telemt/discussions/167
|
||||||
|
|
||||||
## How many people can use 1 link
|
## How many people can use 1 link
|
||||||
|
|
||||||
By default, 1 link can be used by any number of people.
|
By default, 1 link can be used by any number of people.
|
||||||
|
|
|
||||||
|
|
@ -3,7 +3,7 @@
|
||||||
1. Зайти в бота @MTProxybot.
|
1. Зайти в бота @MTProxybot.
|
||||||
2. Ввести команду `/newproxy`
|
2. Ввести команду `/newproxy`
|
||||||
3. Отправить IP и порт сервера. Например: 1.2.3.4:443
|
3. Отправить IP и порт сервера. Например: 1.2.3.4:443
|
||||||
4. Открыть конфиг `nano /etc/telemt.toml`.
|
4. Открыть конфиг `nano /etc/telemt/telemt.toml`.
|
||||||
5. Скопировать и отправить боту секрет пользователя из раздела [access.users].
|
5. Скопировать и отправить боту секрет пользователя из раздела [access.users].
|
||||||
6. Скопировать полученный tag у бота. Например 1234567890abcdef1234567890abcdef.
|
6. Скопировать полученный tag у бота. Например 1234567890abcdef1234567890abcdef.
|
||||||
> [!WARNING]
|
> [!WARNING]
|
||||||
|
|
@ -33,6 +33,10 @@ hello = "ad_tag"
|
||||||
hello2 = "ad_tag2"
|
hello2 = "ad_tag2"
|
||||||
```
|
```
|
||||||
|
|
||||||
|
## Зачем нужен middle proxy (ME)
|
||||||
|
https://github.com/telemt/telemt/discussions/167
|
||||||
|
|
||||||
|
|
||||||
## Сколько человек может пользоваться 1 ссылкой
|
## Сколько человек может пользоваться 1 ссылкой
|
||||||
|
|
||||||
По умолчанию 1 ссылкой может пользоваться сколько угодно человек.
|
По умолчанию 1 ссылкой может пользоваться сколько угодно человек.
|
||||||
|
|
|
||||||
|
|
@ -0,0 +1,283 @@
|
||||||
|
<img src="https://gist.githubusercontent.com/avbor/1f8a128e628f47249aae6e058a57610b/raw/19013276c035e91058e0a9799ab145f8e70e3ff5/scheme.svg">
|
||||||
|
|
||||||
|
## Concept
|
||||||
|
- **Server A** (__conditionally Russian Federation_):\
|
||||||
|
Entry point, receives Telegram proxy user traffic via **HAProxy** (port `443`)\
|
||||||
|
and sends it to the tunnel to Server **B**.\
|
||||||
|
Internal IP in the tunnel — `10.10.10.2`\
|
||||||
|
Port for HAProxy clients — `443\tcp`
|
||||||
|
- **Server B** (_conditionally Netherlands_):\
|
||||||
|
Exit point, runs **telemt** and accepts client connections through Server **A**.\
|
||||||
|
The server must have unrestricted access to Telegram servers.\
|
||||||
|
Internal IP in the tunnel — `10.10.10.1`\
|
||||||
|
AmneziaWG port — `8443\udp`\
|
||||||
|
Port for telemt clients — `443\tcp`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 1. Setting up the AmneziaWG tunnel (A <-> B)
|
||||||
|
[AmneziaWG](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module) must be installed on all servers.\
|
||||||
|
All following commands are given for **Ubuntu 24.04**.\
|
||||||
|
For RHEL-based distributions, installation instructions are available at the link above.
|
||||||
|
|
||||||
|
### Installing AmneziaWG (Servers A and B)
|
||||||
|
The following steps must be performed on each server:
|
||||||
|
|
||||||
|
#### 1. Adding the AmneziaWG repository and installing required packages:
|
||||||
|
```bash
|
||||||
|
sudo apt install -y software-properties-common python3-launchpadlib gnupg2 linux-headers-$(uname -r) && \
|
||||||
|
sudo add-apt-repository ppa:amnezia/ppa && \
|
||||||
|
sudo apt-get install -y amneziawg
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Generating a unique key pair:
|
||||||
|
```bash
|
||||||
|
cd /etc/amnezia/amneziawg && \
|
||||||
|
awg genkey | tee private.key | awg pubkey > public.key
|
||||||
|
```
|
||||||
|
|
||||||
|
As a result, you will get two files in the `/etc/amnezia/amneziawg` folder:\
|
||||||
|
`private.key` - private, and\
|
||||||
|
`public.key` - public server keys
|
||||||
|
|
||||||
|
#### 3. Configuring network interfaces:
|
||||||
|
Obfuscation parameters `S1`, `S2`, `H1`, `H2`, `H3`, `H4` must be strictly identical on both servers.\
|
||||||
|
Parameters `Jc`, `Jmin` and `Jmax` can differ.\
|
||||||
|
Parameters `I1-I5` ([Custom Protocol Signature](https://docs.amnezia.org/documentation/amnezia-wg/)) must be specified on the client side (Server **A**).
|
||||||
|
|
||||||
|
Recommendations for choosing values:
|
||||||
|
|
||||||
|
```text
|
||||||
|
Jc — 1 ≤ Jc ≤ 128; from 4 to 12 inclusive
|
||||||
|
Jmin — Jmax > Jmin < 1280*; recommended 8
|
||||||
|
Jmax — Jmin < Jmax ≤ 1280*; recommended 80
|
||||||
|
S1 — S1 ≤ 1132* (1280* - 148 = 1132); S1 + 56 ≠ S2;
|
||||||
|
recommended range from 15 to 150 inclusive
|
||||||
|
S2 — S2 ≤ 1188* (1280* - 92 = 1188);
|
||||||
|
recommended range from 15 to 150 inclusive
|
||||||
|
H1/H2/H3/H4 — must be unique and differ from each other;
|
||||||
|
recommended range from 5 to 2147483647 inclusive
|
||||||
|
|
||||||
|
* It is assumed that the Internet connection has an MTU of 1280.
|
||||||
|
```
|
||||||
|
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> It is recommended to use your own, unique values.\
|
||||||
|
> You can use the [generator](https://htmlpreview.github.io/?https://gist.githubusercontent.com/avbor/955782b5c37b06240b243aa375baeac5/raw/e8b269ff0089a27effd88f8d925179b78e5666c4/awg-gen.html) to select parameters.
|
||||||
|
|
||||||
|
#### Server B Configuration (Netherlands):
|
||||||
|
|
||||||
|
Create the interface configuration file (`awg0`)
|
||||||
|
```bash
|
||||||
|
nano /etc/amnezia/amneziawg/awg0.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
File content
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
Address = 10.10.10.1/24
|
||||||
|
ListenPort = 8443
|
||||||
|
PrivateKey = <PRIVATE_KEY_SERVER_B>
|
||||||
|
SaveConfig = true
|
||||||
|
Jc = 4
|
||||||
|
Jmin = 8
|
||||||
|
Jmax = 80
|
||||||
|
S1 = 29
|
||||||
|
S2 = 15
|
||||||
|
H1 = 2087563914
|
||||||
|
H2 = 188817757
|
||||||
|
H3 = 101784570
|
||||||
|
H4 = 432174303
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <PUBLIC_KEY_SERVER_A>
|
||||||
|
AllowedIPs = 10.10.10.2/32
|
||||||
|
```
|
||||||
|
`ListenPort` - the port on which the server will wait for connections, you can choose any free one.\
|
||||||
|
`<PRIVATE_KEY_SERVER_B>` - the content of the `private.key` file from Server **B**.\
|
||||||
|
`<PUBLIC_KEY_SERVER_A>` - the content of the `public.key` file from Server **A**.
|
||||||
|
|
||||||
|
Open the port on the firewall (if enabled):
|
||||||
|
```bash
|
||||||
|
sudo ufw allow from <PUBLIC_IP_SERVER_A> to any port 8443 proto udp
|
||||||
|
```
|
||||||
|
|
||||||
|
`<PUBLIC_IP_SERVER_A>` - the external IP address of Server **A**.
|
||||||
|
|
||||||
|
#### Server A Configuration (Russian Federation):
|
||||||
|
Create the interface configuration file (awg0)
|
||||||
|
|
||||||
|
```bash
|
||||||
|
nano /etc/amnezia/amneziawg/awg0.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
File content
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
Address = 10.10.10.2/24
|
||||||
|
PrivateKey = <PRIVATE_KEY_SERVER_A>
|
||||||
|
Jc = 4
|
||||||
|
Jmin = 8
|
||||||
|
Jmax = 80
|
||||||
|
S1 = 29
|
||||||
|
S2 = 15
|
||||||
|
H1 = 2087563914
|
||||||
|
H2 = 188817757
|
||||||
|
H3 = 101784570
|
||||||
|
H4 = 432174303
|
||||||
|
I1 = <b 0xc10000000108981eba846e21f74e00>
|
||||||
|
I2 = <b 0xc20000000108981eba846e21f74e00>
|
||||||
|
I3 = <b 0xc30000000108981eba846e21f74e00>
|
||||||
|
I4 = <b 0x43981eba846e21f74e>
|
||||||
|
I5 = <b 0x43981eba846e21f74e>
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <PUBLIC_KEY_SERVER_B>
|
||||||
|
Endpoint = <PUBLIC_IP_SERVER_B>:8443
|
||||||
|
AllowedIPs = 10.10.10.1/32
|
||||||
|
PersistentKeepalive = 25
|
||||||
|
```
|
||||||
|
|
||||||
|
`<PRIVATE_KEY_SERVER_A>` - the content of the `private.key` file from Server **A**.\
|
||||||
|
`<PUBLIC_KEY_SERVER_B>` - the content of the `public.key` file from Server **B**.\
|
||||||
|
`<PUBLIC_IP_SERVER_B>` - the public IP address of Server **B**.
|
||||||
|
|
||||||
|
Enable the tunnel on both servers:
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable --now awg-quick@awg0
|
||||||
|
```
|
||||||
|
|
||||||
|
Make sure Server B is accessible from Server A through the tunnel.
|
||||||
|
```bash
|
||||||
|
ping 10.10.10.1
|
||||||
|
PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data.
|
||||||
|
64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=35.1 ms
|
||||||
|
64 bytes from 10.10.10.1: icmp_seq=2 ttl=64 time=35.0 ms
|
||||||
|
64 bytes from 10.10.10.1: icmp_seq=3 ttl=64 time=35.1 ms
|
||||||
|
^C
|
||||||
|
```
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 2. Installing telemt on Server B (conditionally Netherlands)
|
||||||
|
Installation and configuration are described [here](https://github.com/telemt/telemt/blob/main/docs/QUICK_START_GUIDE.ru.md) or [here](https://gitlab.com/An0nX/telemt-docker#-quick-start-docker-compose).\
|
||||||
|
It is assumed that telemt expects connections on port `443\tcp`.
|
||||||
|
|
||||||
|
In the telemt config, you must enable the `Proxy` protocol and restrict connections to it only through the tunnel.
|
||||||
|
```toml
|
||||||
|
[server]
|
||||||
|
port = 443
|
||||||
|
listen_addr_ipv4 = "10.10.10.1"
|
||||||
|
proxy_protocol = true
|
||||||
|
```
|
||||||
|
|
||||||
|
Also, for correct link generation, specify the FQDN or IP address and port of Server `A`
|
||||||
|
```toml
|
||||||
|
[general.links]
|
||||||
|
show = "*"
|
||||||
|
public_host = "<FQDN_OR_IP_SERVER_A>"
|
||||||
|
public_port = 443
|
||||||
|
```
|
||||||
|
|
||||||
|
Open the port on the firewall (if enabled):
|
||||||
|
```bash
|
||||||
|
sudo ufw allow from 10.10.10.2 to any port 443 proto tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Step 3. Configuring HAProxy on Server A (Russian Federation)
|
||||||
|
Since the version in the standard Ubuntu repository is relatively old, it makes sense to use the official Docker image.\
|
||||||
|
[Instructions](https://docs.docker.com/engine/install/ubuntu/) for installing Docker on Ubuntu.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> By default, regular users do not have rights to use ports < 1024.
|
||||||
|
> Attempts to run HAProxy on port 443 can lead to errors:
|
||||||
|
> ```
|
||||||
|
> [ALERT] (8) : Binding [/usr/local/etc/haproxy/haproxy.cfg:17] for frontend tcp_in_443:
|
||||||
|
> protocol tcpv4: cannot bind socket (Permission denied) for [0.0.0.0:443].
|
||||||
|
> ```
|
||||||
|
> There are two simple ways to bypass this restriction, choose one:
|
||||||
|
> 1. At the OS level, change the net.ipv4.ip_unprivileged_port_start setting to allow users to use all ports:
|
||||||
|
> ```
|
||||||
|
> echo "net.ipv4.ip_unprivileged_port_start = 0" | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||||
|
> ```
|
||||||
|
> or
|
||||||
|
>
|
||||||
|
> 2. Run HAProxy as root:
|
||||||
|
> Uncomment the `user: "root"` parameter in docker-compose.yaml.
|
||||||
|
|
||||||
|
#### Create a folder for HAProxy:
|
||||||
|
```bash
|
||||||
|
mkdir -p /opt/docker-compose/haproxy && cd $_
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create the docker-compose.yaml file
|
||||||
|
`nano docker-compose.yaml`
|
||||||
|
|
||||||
|
File content
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
haproxy:
|
||||||
|
image: haproxy:latest
|
||||||
|
container_name: haproxy
|
||||||
|
restart: unless-stopped
|
||||||
|
# user: "root"
|
||||||
|
network_mode: "host"
|
||||||
|
volumes:
|
||||||
|
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "1m"
|
||||||
|
max-file: "1"
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Create the haproxy.cfg config file
|
||||||
|
Accept connections on port 443\tcp and send them through the tunnel to Server `B` 10.10.10.1:443
|
||||||
|
|
||||||
|
`nano haproxy.cfg`
|
||||||
|
|
||||||
|
File content
|
||||||
|
|
||||||
|
```haproxy
|
||||||
|
global
|
||||||
|
log stdout format raw local0
|
||||||
|
maxconn 10000
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode tcp
|
||||||
|
option tcplog
|
||||||
|
option clitcpka
|
||||||
|
option srvtcpka
|
||||||
|
timeout connect 5s
|
||||||
|
timeout client 2h
|
||||||
|
timeout server 2h
|
||||||
|
timeout check 5s
|
||||||
|
|
||||||
|
frontend tcp_in_443
|
||||||
|
bind *:443
|
||||||
|
maxconn 8000
|
||||||
|
option tcp-smart-accept
|
||||||
|
default_backend telemt_nodes
|
||||||
|
|
||||||
|
backend telemt_nodes
|
||||||
|
option tcp-smart-connect
|
||||||
|
server server_a 10.10.10.1:443 check inter 5s rise 2 fall 3 send-proxy-v2
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
> [!WARNING]
|
||||||
|
> **The file must end with an empty line, otherwise HAProxy will not start!**
|
||||||
|
|
||||||
|
#### Allow port 443\tcp in the firewall (if enabled)
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Start the HAProxy container
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
If everything is configured correctly, you can now try connecting Telegram clients using links from the telemt log\api.
|
||||||
|
|
@ -0,0 +1,287 @@
|
||||||
|
<img src="https://gist.githubusercontent.com/avbor/1f8a128e628f47249aae6e058a57610b/raw/19013276c035e91058e0a9799ab145f8e70e3ff5/scheme.svg">
|
||||||
|
|
||||||
|
## Концепция
|
||||||
|
- **Сервер A** (_РФ_):\
|
||||||
|
Точка входа, принимает трафик пользователей Telegram-прокси через **HAProxy** (порт `443`)\
|
||||||
|
и отправляет в туннель на Сервер **B**.\
|
||||||
|
Внутренний IP в туннеле — `10.10.10.2`\
|
||||||
|
Порт для клиентов HAProxy — `443\tcp`
|
||||||
|
- **Сервер B** (_условно Нидерланды_):\
|
||||||
|
Точка выхода, на нем работает **telemt** и принимает подключения клиентов через Сервер **A**.\
|
||||||
|
На сервере должен быть неограниченный доступ до серверов Telegram.\
|
||||||
|
Внутренний IP в туннеле — `10.10.10.1`\
|
||||||
|
Порт AmneziaWG — `8443\udp`\
|
||||||
|
Порт для клиентов telemt — `443\tcp`
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Шаг 1. Настройка туннеля AmneziaWG (A <-> B)
|
||||||
|
|
||||||
|
На всех серверах необходимо установить [amneziawg](https://github.com/amnezia-vpn/amneziawg-linux-kernel-module).\
|
||||||
|
Далее все команды даны для **Ununtu 24.04**.\
|
||||||
|
Для RHEL-based дистрибутивов инструкция по установке есть по ссылке выше.
|
||||||
|
|
||||||
|
### Установка AmneziaWG (Сервера A и B)
|
||||||
|
На каждом из серверов необходимо выполнить следующие шаги:
|
||||||
|
|
||||||
|
#### 1. Добавление репозитория AmneziaWG и установка необходимых пакетов:
|
||||||
|
```bash
|
||||||
|
sudo apt install -y software-properties-common python3-launchpadlib gnupg2 linux-headers-$(uname -r) && \
|
||||||
|
sudo add-apt-repository ppa:amnezia/ppa && \
|
||||||
|
sudo apt-get install -y amneziawg
|
||||||
|
```
|
||||||
|
|
||||||
|
#### 2. Генерация уникальной пары ключей:
|
||||||
|
```bash
|
||||||
|
cd /etc/amnezia/amneziawg && \
|
||||||
|
awg genkey | tee private.key | awg pubkey > public.key
|
||||||
|
```
|
||||||
|
В результате вы получите в папке `/etc/amnezia/amneziawg` два файла:\
|
||||||
|
`private.key` - приватный и\
|
||||||
|
`public.key` - публичный ключи сервера
|
||||||
|
|
||||||
|
#### 3. Настройка сетевых интерфейсов:
|
||||||
|
|
||||||
|
Параметры обфускации `S1`, `S2`, `H1`, `H2`, `H3`, `H4` должны быть строго идентичными на обоих серверах.\
|
||||||
|
Параметры `Jc`, `Jmin` и `Jmax` могут отличатся.\
|
||||||
|
Параметры `I1-I5` [(Custom Protocol Signature)](https://docs.amnezia.org/documentation/amnezia-wg/) нужно указывать на стороне _клиента_ (Сервер **А**).
|
||||||
|
|
||||||
|
Рекомендации по выбору значений:
|
||||||
|
```text
|
||||||
|
Jc — 1 ≤ Jc ≤ 128; от 4 до 12 включительно
|
||||||
|
Jmin — Jmax > Jmin < 1280*; рекомендовано 8
|
||||||
|
Jmax — Jmin < Jmax ≤ 1280*; рекомендовано 80
|
||||||
|
S1 — S1 ≤ 1132* (1280* - 148 = 1132); S1 + 56 ≠ S2;
|
||||||
|
рекомендованный диапазон от 15 до 150 включительно
|
||||||
|
S2 — S2 ≤ 1188* (1280* - 92 = 1188);
|
||||||
|
рекомендованный диапазон от 15 до 150 включительно
|
||||||
|
H1/H2/H3/H4 — должны быть уникальны и отличаться друг от друга;
|
||||||
|
рекомендованный диапазон от 5 до 2147483647 включительно
|
||||||
|
|
||||||
|
* Предполагается, что подключение к Интернету имеет MTU 1280.
|
||||||
|
```
|
||||||
|
> [!IMPORTANT]
|
||||||
|
> Рекомендуется использовать собственные, уникальные значения.\
|
||||||
|
> Для выбора параметров можете воспользоваться [генератором](https://htmlpreview.github.io/?https://gist.githubusercontent.com/avbor/955782b5c37b06240b243aa375baeac5/raw/e8b269ff0089a27effd88f8d925179b78e5666c4/awg-gen.html).
|
||||||
|
|
||||||
|
#### Конфигурация Сервера B (_Нидерланды_):
|
||||||
|
|
||||||
|
Создаем файл конфигурации интерфейса (`awg0`)
|
||||||
|
```bash
|
||||||
|
nano /etc/amnezia/amneziawg/awg0.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Содержимое файла
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
Address = 10.10.10.1/24
|
||||||
|
ListenPort = 8443
|
||||||
|
PrivateKey = <PRIVATE_KEY_SERVER_B>
|
||||||
|
SaveConfig = true
|
||||||
|
Jc = 4
|
||||||
|
Jmin = 8
|
||||||
|
Jmax = 80
|
||||||
|
S1 = 29
|
||||||
|
S2 = 15
|
||||||
|
H1 = 2087563914
|
||||||
|
H2 = 188817757
|
||||||
|
H3 = 101784570
|
||||||
|
H4 = 432174303
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <PUBLIC_KEY_SERVER_A>
|
||||||
|
AllowedIPs = 10.10.10.2/32
|
||||||
|
```
|
||||||
|
|
||||||
|
`ListenPort` - порт, на котором сервер будет ждать подключения, можете выбрать любой свободный.\
|
||||||
|
`<PRIVATE_KEY_SERVER_B>` - содержимое файла `private.key` с сервера **B**.\
|
||||||
|
`<PUBLIC_KEY_SERVER_A>` - содержимое файла `public.key` с сервера **A**.
|
||||||
|
|
||||||
|
Открываем порт на фаерволе (если включен):
|
||||||
|
```bash
|
||||||
|
sudo ufw allow from <PUBLIC_IP_SERVER_A> to any port 8443 proto udp
|
||||||
|
```
|
||||||
|
|
||||||
|
`<PUBLIC_IP_SERVER_A>` - внешний IP адрес Сервера **A**.
|
||||||
|
|
||||||
|
#### Конфигурация Сервера A (_РФ_):
|
||||||
|
|
||||||
|
Создаем файл конфигурации интерфейса (`awg0`)
|
||||||
|
```bash
|
||||||
|
nano /etc/amnezia/amneziawg/awg0.conf
|
||||||
|
```
|
||||||
|
|
||||||
|
Содержимое файла
|
||||||
|
```ini
|
||||||
|
[Interface]
|
||||||
|
Address = 10.10.10.2/24
|
||||||
|
PrivateKey = <PRIVATE_KEY_SERVER_A>
|
||||||
|
Jc = 4
|
||||||
|
Jmin = 8
|
||||||
|
Jmax = 80
|
||||||
|
S1 = 29
|
||||||
|
S2 = 15
|
||||||
|
H1 = 2087563914
|
||||||
|
H2 = 188817757
|
||||||
|
H3 = 101784570
|
||||||
|
H4 = 432174303
|
||||||
|
I1 = <b 0xc10000000108981eba846e21f74e00>
|
||||||
|
I2 = <b 0xc20000000108981eba846e21f74e00>
|
||||||
|
I3 = <b 0xc30000000108981eba846e21f74e00>
|
||||||
|
I4 = <b 0x43981eba846e21f74e>
|
||||||
|
I5 = <b 0x43981eba846e21f74e>
|
||||||
|
|
||||||
|
[Peer]
|
||||||
|
PublicKey = <PUBLIC_KEY_SERVER_B>
|
||||||
|
Endpoint = <PUBLIC_IP_SERVER_B>:8443
|
||||||
|
AllowedIPs = 10.10.10.1/32
|
||||||
|
PersistentKeepalive = 25
|
||||||
|
```
|
||||||
|
|
||||||
|
`<PRIVATE_KEY_SERVER_A>` - содержимое файла `private.key` с сервера **A**.\
|
||||||
|
`<PUBLIC_KEY_SERVER_B>` - содержимое файла `public.key` с сервера **B**.\
|
||||||
|
`<PUBLIC_IP_SERVER_B>` - публичный IP адресс сервера **B**.
|
||||||
|
|
||||||
|
#### Включаем туннель на обоих серверах:
|
||||||
|
```bash
|
||||||
|
sudo systemctl enable --now awg-quick@awg0
|
||||||
|
```
|
||||||
|
|
||||||
|
Убедитесь, что с Сервера `A` доступен Сервер `B` через туннель.
|
||||||
|
```bash
|
||||||
|
ping 10.10.10.1
|
||||||
|
PING 10.10.10.1 (10.10.10.1) 56(84) bytes of data.
|
||||||
|
64 bytes from 10.10.10.1: icmp_seq=1 ttl=64 time=35.1 ms
|
||||||
|
64 bytes from 10.10.10.1: icmp_seq=2 ttl=64 time=35.0 ms
|
||||||
|
64 bytes from 10.10.10.1: icmp_seq=3 ttl=64 time=35.1 ms
|
||||||
|
^C
|
||||||
|
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
## Шаг 2. Установка telemt на Сервере B (_условно Нидерланды_)
|
||||||
|
|
||||||
|
Установка и настройка описаны [здесь](https://github.com/telemt/telemt/blob/main/docs/QUICK_START_GUIDE.ru.md) или [здесь](https://gitlab.com/An0nX/telemt-docker#-quick-start-docker-compose).\
|
||||||
|
Подразумевается что telemt ожидает подключения на порту `443\tcp`.
|
||||||
|
|
||||||
|
В конфиге telemt необходимо включить протокол `Proxy` и ограничить подключения к нему только через туннель.
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[server]
|
||||||
|
port = 443
|
||||||
|
listen_addr_ipv4 = "10.10.10.1"
|
||||||
|
proxy_protocol = true
|
||||||
|
```
|
||||||
|
|
||||||
|
А также, для правильной генерации ссылок, указать FQDN или IP адрес и порт Сервера `A`
|
||||||
|
|
||||||
|
```toml
|
||||||
|
[general.links]
|
||||||
|
show = "*"
|
||||||
|
public_host = "<FQDN_OR_IP_SERVER_A>"
|
||||||
|
public_port = 443
|
||||||
|
```
|
||||||
|
|
||||||
|
Открываем порт на фаерволе (если включен):
|
||||||
|
```bash
|
||||||
|
sudo ufw allow from 10.10.10.2 to any port 443 proto tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
---
|
||||||
|
|
||||||
|
### Шаг 3. Настройка HAProxy на Сервере A (_РФ_)
|
||||||
|
|
||||||
|
Т.к. в стандартном репозитории Ubuntu версия относительно старая, имеет смысл воспользоваться официальным образом Docker.\
|
||||||
|
[Инструкция](https://docs.docker.com/engine/install/ubuntu/) по установке Docker на Ubuntu.
|
||||||
|
|
||||||
|
> [!WARNING]
|
||||||
|
> По умолчанию у обычных пользователей нет прав на использование портов < 1024.\
|
||||||
|
> Попытки запустить HAProxy на 443 порту могут приводить к ошибкам:
|
||||||
|
> ```
|
||||||
|
> [ALERT] (8) : Binding [/usr/local/etc/haproxy/haproxy.cfg:17] for frontend tcp_in_443:
|
||||||
|
> protocol tcpv4: cannot bind socket (Permission denied) for [0.0.0.0:443].
|
||||||
|
> ```
|
||||||
|
> Есть два простых способа обойти это ограничение, выберите что-то одно:
|
||||||
|
> 1. На уровне ОС изменить настройку net.ipv4.ip_unprivileged_port_start, разрешив пользователям использовать все порты:
|
||||||
|
> ```
|
||||||
|
> echo "net.ipv4.ip_unprivileged_port_start = 0" | sudo tee -a /etc/sysctl.conf && sudo sysctl -p
|
||||||
|
> ```
|
||||||
|
> или
|
||||||
|
>
|
||||||
|
> 2. Запустить HAProxy под root:\
|
||||||
|
> Раскомментируйте в docker-compose.yaml параметр `user: "root"`.
|
||||||
|
|
||||||
|
#### Создаем папку для HAProxy:
|
||||||
|
```bash
|
||||||
|
mkdir -p /opt/docker-compose/haproxy && cd $_
|
||||||
|
```
|
||||||
|
#### Создаем файл docker-compose.yaml
|
||||||
|
|
||||||
|
`nano docker-compose.yaml`
|
||||||
|
|
||||||
|
Содержимое файла
|
||||||
|
```yaml
|
||||||
|
services:
|
||||||
|
haproxy:
|
||||||
|
image: haproxy:latest
|
||||||
|
container_name: haproxy
|
||||||
|
restart: unless-stopped
|
||||||
|
# user: "root"
|
||||||
|
network_mode: "host"
|
||||||
|
volumes:
|
||||||
|
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
||||||
|
logging:
|
||||||
|
driver: "json-file"
|
||||||
|
options:
|
||||||
|
max-size: "1m"
|
||||||
|
max-file: "1"
|
||||||
|
```
|
||||||
|
#### Создаем файл конфига haproxy.cfg
|
||||||
|
Принимаем подключения на порту 443\tcp и отправляем их через туннель на Сервер `B` 10.10.10.1:443
|
||||||
|
|
||||||
|
`nano haproxy.cfg`
|
||||||
|
|
||||||
|
Содержимое файла
|
||||||
|
```haproxy
|
||||||
|
global
|
||||||
|
log stdout format raw local0
|
||||||
|
maxconn 10000
|
||||||
|
|
||||||
|
defaults
|
||||||
|
log global
|
||||||
|
mode tcp
|
||||||
|
option tcplog
|
||||||
|
option clitcpka
|
||||||
|
option srvtcpka
|
||||||
|
timeout connect 5s
|
||||||
|
timeout client 2h
|
||||||
|
timeout server 2h
|
||||||
|
timeout check 5s
|
||||||
|
|
||||||
|
frontend tcp_in_443
|
||||||
|
bind *:443
|
||||||
|
maxconn 8000
|
||||||
|
option tcp-smart-accept
|
||||||
|
default_backend telemt_nodes
|
||||||
|
|
||||||
|
backend telemt_nodes
|
||||||
|
option tcp-smart-connect
|
||||||
|
server server_a 10.10.10.1:443 check inter 5s rise 2 fall 3 send-proxy-v2
|
||||||
|
|
||||||
|
|
||||||
|
```
|
||||||
|
>[!WARNING]
|
||||||
|
>**Файл должен заканчиваться пустой строкой, иначе HAProxy не запуститься!**
|
||||||
|
|
||||||
|
#### Разрешаем порт 443\tcp в фаерволе (если включен)
|
||||||
|
```bash
|
||||||
|
sudo ufw allow 443/tcp
|
||||||
|
```
|
||||||
|
|
||||||
|
#### Запускаем контейнер HAProxy
|
||||||
|
```bash
|
||||||
|
docker compose up -d
|
||||||
|
```
|
||||||
|
|
||||||
|
Если все настроено верно, то теперь можно пробовать подключить клиентов Telegram с использованием ссылок из лога\api telemt.
|
||||||
|
|
@ -542,6 +542,7 @@ fn quota_exceeded_for_user(stats: &Stats, user: &str, quota_limit: Option<u64>)
|
||||||
quota_limit.is_some_and(|quota| stats.get_user_total_octets(user) >= quota)
|
quota_limit.is_some_and(|quota| stats.get_user_total_octets(user) >= quota)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
#[cfg_attr(not(test), allow(dead_code))]
|
||||||
fn quota_would_be_exceeded_for_user(
|
fn quota_would_be_exceeded_for_user(
|
||||||
stats: &Stats,
|
stats: &Stats,
|
||||||
user: &str,
|
user: &str,
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue