mirror of
https://github.com/ScuroNeko/mtg.git
synced 2026-09-01 01:44:01 +03:00
REPOSITORY / ScuroNeko/mtg
Compare commits
Compare commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
83a31e0458 | ||
|
|
95db895136 | ||
|
|
1a81efcb6e | ||
|
|
2544c521ed | ||
|
|
db2e6031a3 | ||
|
|
4b8da719ae | ||
|
|
8b3c622ea6 | ||
|
|
9d43c2d759 | ||
|
|
006fba1046 | ||
|
|
7b333ed833 | ||
|
|
de89de2ad6 | ||
|
|
7fec30908a | ||
|
|
2eb0828f72 | ||
|
|
fc72de9e39 | ||
|
|
cb627f2a66 | ||
|
|
dc81f7981c | ||
|
|
9d5fd989e5 | ||
|
|
d0502e7083 | ||
|
|
30aa9d3a44 | ||
|
|
fefc479f94 | ||
|
|
9f12620dba | ||
|
|
f5244c2bfd | ||
|
|
9946cdfeb5 | ||
|
|
7d748077e9 | ||
|
|
f61a63a59b | ||
|
|
136eea551f | ||
|
|
e6fa5906c9 | ||
|
|
b854b16e1a | ||
|
|
f4b296d1e0 | ||
|
|
e7fdb02a29 | ||
|
|
7a6ba6d8c6 | ||
|
|
25bca76da5 | ||
|
|
76109f6204 |
@@ -8,5 +8,3 @@
|
|||||||
mtg
|
mtg
|
||||||
coverage.txt
|
coverage.txt
|
||||||
dist/
|
dist/
|
||||||
.idea/
|
|
||||||
.vscode/
|
|
||||||
|
|||||||
@@ -514,50 +514,6 @@ This is not very necessary. Keep in mind these rules:
|
|||||||
you can enable `drs` setting.
|
you can enable `drs` setting.
|
||||||
9. **If you are not sure, touch nothing!**
|
9. **If you are not sure, touch nothing!**
|
||||||
|
|
||||||
## Troubleshooting
|
|
||||||
|
|
||||||
### `ip was blacklisted` for clients on the same LAN
|
|
||||||
|
|
||||||
If you run mtg at home and a client on the same LAN (for example, your
|
|
||||||
phone on the home Wi-Fi) cannot connect, check the proxy logs for a
|
|
||||||
message like:
|
|
||||||
|
|
||||||
```json
|
|
||||||
{"level":"info","ip":"10.0.1.1","logger":"proxy","message":"ip was blacklisted"}
|
|
||||||
```
|
|
||||||
|
|
||||||
The reason is that the default blocklist (`firehol_level1.netset`)
|
|
||||||
includes bogon networks, which covers all RFC1918 ranges
|
|
||||||
(`10.0.0.0/8`, `172.16.0.0/12`, `192.168.0.0/16`). Any client
|
|
||||||
connecting from such an address is rejected by the blocklist —
|
|
||||||
the TCP connection is closed immediately with no response, so
|
|
||||||
from the client's point of view nothing loads at all.
|
|
||||||
|
|
||||||
There are three ways to resolve it:
|
|
||||||
|
|
||||||
1. Disable the blocklist entirely in `config.toml`:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[defense.blocklist]
|
|
||||||
enabled = false
|
|
||||||
```
|
|
||||||
|
|
||||||
Simplest option if the proxy is used only by you and people you trust.
|
|
||||||
|
|
||||||
2. Keep the blocklist but swap `firehol_level1` for a narrower list that
|
|
||||||
does not include bogons, for example `firehol_abusers_1d`:
|
|
||||||
|
|
||||||
```toml
|
|
||||||
[defense.blocklist]
|
|
||||||
enabled = true
|
|
||||||
urls = ["https://iplists.firehol.org/files/firehol_abusers_1d.netset"]
|
|
||||||
```
|
|
||||||
|
|
||||||
3. Connect to the proxy through a public IP or domain name with hairpin
|
|
||||||
NAT (`MASQUERADE`) on your router. mtg will then see the client with
|
|
||||||
its public address and the blocklist will not match. This is more
|
|
||||||
work to set up but preserves full blocklist protection.
|
|
||||||
|
|
||||||
## Metrics
|
## Metrics
|
||||||
|
|
||||||
Out of the box, mtg works with
|
Out of the box, mtg works with
|
||||||
|
|||||||
@@ -1,30 +0,0 @@
|
|||||||
{
|
|
||||||
# Caddy sits behind HAProxy which passes raw TLS through on :8443.
|
|
||||||
# ACME HTTP-01 challenges arrive on :80 via HAProxy's acl passthrough.
|
|
||||||
http_port 80
|
|
||||||
https_port 8443
|
|
||||||
|
|
||||||
# HAProxy forwards connections to :8443 with a PROXY protocol v2
|
|
||||||
# header (see haproxy.cfg `send-proxy-v2`). The proxy_protocol
|
|
||||||
# listener wrapper strips the header and exposes the real client IP
|
|
||||||
# to Caddy's access log. The `tls` wrapper must follow so that TLS
|
|
||||||
# is terminated on the unwrapped connection.
|
|
||||||
#
|
|
||||||
# `allow` lists the networks permitted to send PROXY headers. These
|
|
||||||
# ranges cover docker compose's default bridge networks; tighten
|
|
||||||
# them if you pin a specific subnet in docker-compose.yml.
|
|
||||||
servers :8443 {
|
|
||||||
listener_wrappers {
|
|
||||||
proxy_protocol {
|
|
||||||
timeout 5s
|
|
||||||
allow 10.0.0.0/8 172.16.0.0/12 192.168.0.0/16
|
|
||||||
}
|
|
||||||
tls
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
{$DOMAIN} {
|
|
||||||
root * /srv
|
|
||||||
file_server
|
|
||||||
}
|
|
||||||
@@ -1,89 +0,0 @@
|
|||||||
# SNI-routing deployment for mtg
|
|
||||||
|
|
||||||
A turnkey `docker compose` setup that puts an SNI-aware TCP router
|
|
||||||
(HAProxy) in front of mtg **and** a real web server (Caddy with
|
|
||||||
automatic HTTPS).
|
|
||||||
|
|
||||||
## Why
|
|
||||||
|
|
||||||
Modern DPI systems actively probe suspected proxies. If the server
|
|
||||||
closes the connection or returns something unexpected, the IP gets
|
|
||||||
flagged. With this setup:
|
|
||||||
|
|
||||||
- **Telegram clients** connect to port 443, HAProxy sees the configured
|
|
||||||
SNI and routes them to mtg (FakeTLS).
|
|
||||||
- **Everything else** (browsers, DPI probes, scanners) is routed to
|
|
||||||
Caddy, which responds with a real Let's Encrypt certificate and serves
|
|
||||||
genuine web content.
|
|
||||||
|
|
||||||
Because your domain's DNS points to this server, the SNI/IP match is
|
|
||||||
natural and passive DPI has nothing to flag.
|
|
||||||
|
|
||||||
## Quick start
|
|
||||||
|
|
||||||
```bash
|
|
||||||
# 1. Point your domain's DNS A/AAAA record to this server's IP.
|
|
||||||
|
|
||||||
# 2. Generate an mtg secret:
|
|
||||||
docker run --rm nineseconds/mtg:2 generate-secret --hex YOUR_DOMAIN
|
|
||||||
|
|
||||||
# 3. Edit the config files:
|
|
||||||
# - mtg-config.toml → paste the secret
|
|
||||||
# - haproxy.cfg → replace "example.com" in the SNI ACL
|
|
||||||
# - .env or export → DOMAIN=your.domain
|
|
||||||
|
|
||||||
# 4. (Optional) put your site content into www/
|
|
||||||
|
|
||||||
# 5. Start:
|
|
||||||
docker compose up -d
|
|
||||||
|
|
||||||
# 6. Verify:
|
|
||||||
# - Open https://YOUR_DOMAIN in a browser → you should see the web page
|
|
||||||
# - Configure Telegram with the proxy link from:
|
|
||||||
docker compose exec mtg mtg access /config/config.toml
|
|
||||||
```
|
|
||||||
|
|
||||||
## Real client IPs (PROXY protocol)
|
|
||||||
|
|
||||||
HAProxy forwards TCP connections to mtg and Caddy with a PROXY protocol
|
|
||||||
v2 header so both backends see the real client IP instead of HAProxy's
|
|
||||||
container address. The three pieces must stay in sync:
|
|
||||||
|
|
||||||
- `haproxy.cfg` — `send-proxy-v2` on the `mtg` and `web` backend `server` lines
|
|
||||||
- `mtg-config.toml` — `proxy-protocol-listener = true`
|
|
||||||
- `Caddyfile` — `listener_wrappers { proxy_protocol { ... } tls }` on `:8443`
|
|
||||||
|
|
||||||
If you disable one, disable all three, otherwise the backend will fail
|
|
||||||
to parse the connection.
|
|
||||||
|
|
||||||
## ACME (Let's Encrypt) notes
|
|
||||||
|
|
||||||
HAProxy passes `/.well-known/acme-challenge/` requests on `:80` to
|
|
||||||
Caddy so that HTTP-01 validation works out of the box. Make sure your
|
|
||||||
domain's DNS A/AAAA record points to this server before starting.
|
|
||||||
|
|
||||||
## Architecture
|
|
||||||
|
|
||||||
```
|
|
||||||
┌──────────────────┐
|
|
||||||
:443 ──────>│ HAProxy │
|
|
||||||
│ (TCP, SNI peek) │
|
|
||||||
└──┬───────────┬───┘
|
|
||||||
SNI match │ │ default
|
|
||||||
v v
|
|
||||||
┌─────────┐ ┌─────────┐
|
|
||||||
│ mtg │ │ Caddy │
|
|
||||||
│ :3128 │ │ :8443 │
|
|
||||||
│ FakeTLS │ │ real TLS│
|
|
||||||
└─────────┘ └─────────┘
|
|
||||||
```
|
|
||||||
|
|
||||||
## Files
|
|
||||||
|
|
||||||
| File | Purpose |
|
|
||||||
|---|---|
|
|
||||||
| `docker-compose.yml` | Service definitions |
|
|
||||||
| `haproxy.cfg` | SNI routing rules — **edit the domain** |
|
|
||||||
| `mtg-config.toml` | mtg proxy config — **paste your secret** |
|
|
||||||
| `Caddyfile` | Web server config (auto-HTTPS) |
|
|
||||||
| `www/` | Static site content served by Caddy |
|
|
||||||
@@ -1,54 +0,0 @@
|
|||||||
# SNI-routing deployment: HAProxy (443) -> mtg + real web backend
|
|
||||||
#
|
|
||||||
# This setup puts an SNI-aware TCP router in front of mtg so that:
|
|
||||||
# - Telegram clients (FakeTLS with the correct SNI) are routed to mtg
|
|
||||||
# - All other TLS traffic (including DPI probes) reaches the real web
|
|
||||||
# server, which responds with a genuine certificate
|
|
||||||
#
|
|
||||||
# The result: active probes see a real website; passive DPI sees matching
|
|
||||||
# SNI/IP because the domain resolves to this server's IP.
|
|
||||||
#
|
|
||||||
# Quick start:
|
|
||||||
# 1. Set YOUR_DOMAIN below (and in mtg-config.toml)
|
|
||||||
# 2. docker compose up -d
|
|
||||||
# 3. mtg generate-secret YOUR_DOMAIN -> put it in mtg-config.toml
|
|
||||||
# 4. docker compose restart mtg
|
|
||||||
#
|
|
||||||
# See BEST_PRACTICES.md and the project wiki for background.
|
|
||||||
|
|
||||||
services:
|
|
||||||
haproxy:
|
|
||||||
image: haproxy:lts-alpine
|
|
||||||
ports:
|
|
||||||
- "443:443"
|
|
||||||
- "80:80"
|
|
||||||
volumes:
|
|
||||||
- ./haproxy.cfg:/usr/local/etc/haproxy/haproxy.cfg:ro
|
|
||||||
depends_on:
|
|
||||||
- mtg
|
|
||||||
- web
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
mtg:
|
|
||||||
image: nineseconds/mtg:2
|
|
||||||
volumes:
|
|
||||||
- ./mtg-config.toml:/config/config.toml:ro
|
|
||||||
expose:
|
|
||||||
- "3128"
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
web:
|
|
||||||
image: caddy:alpine
|
|
||||||
volumes:
|
|
||||||
- ./Caddyfile:/etc/caddy/Caddyfile:ro
|
|
||||||
- caddy_data:/data
|
|
||||||
- ./www:/srv:ro
|
|
||||||
expose:
|
|
||||||
- "80"
|
|
||||||
- "8443"
|
|
||||||
environment:
|
|
||||||
DOMAIN: ${DOMAIN:-example.com}
|
|
||||||
restart: unless-stopped
|
|
||||||
|
|
||||||
volumes:
|
|
||||||
caddy_data:
|
|
||||||
@@ -1,62 +0,0 @@
|
|||||||
# HAProxy SNI router — Layer 4 (TCP mode)
|
|
||||||
#
|
|
||||||
# Inspects the SNI in the TLS ClientHello and routes traffic:
|
|
||||||
# - SNI matching the mtg secret domain -> mtg (FakeTLS / MTProto)
|
|
||||||
# - Everything else -> real web backend (Caddy)
|
|
||||||
#
|
|
||||||
# Because routing happens before TLS termination, each backend sees the
|
|
||||||
# raw ClientHello and handles TLS itself. The real web backend therefore
|
|
||||||
# presents a genuine certificate to any probe or browser.
|
|
||||||
|
|
||||||
global
|
|
||||||
log stdout format raw local0 info
|
|
||||||
maxconn 4096
|
|
||||||
|
|
||||||
defaults
|
|
||||||
log global
|
|
||||||
mode tcp
|
|
||||||
option tcplog
|
|
||||||
timeout connect 5s
|
|
||||||
timeout client 60s
|
|
||||||
timeout server 60s
|
|
||||||
|
|
||||||
# --- HTTP :80 — ACME challenges + redirect -----------------------------------
|
|
||||||
|
|
||||||
frontend http
|
|
||||||
bind *:80
|
|
||||||
mode http
|
|
||||||
|
|
||||||
# Let Caddy answer ACME HTTP-01 challenges for Let's Encrypt.
|
|
||||||
acl is_acme path_beg /.well-known/acme-challenge/
|
|
||||||
use_backend web_acme if is_acme
|
|
||||||
|
|
||||||
http-request redirect scheme https code 301
|
|
||||||
|
|
||||||
# --- TLS :443 — SNI-based routing -------------------------------------------
|
|
||||||
|
|
||||||
frontend tls
|
|
||||||
bind *:443
|
|
||||||
tcp-request inspect-delay 5s
|
|
||||||
tcp-request content accept if { req_ssl_hello_type 1 }
|
|
||||||
|
|
||||||
# Route Telegram clients to mtg.
|
|
||||||
# Replace "example.com" with the domain from your mtg secret.
|
|
||||||
use_backend mtg if { req_ssl_sni -i example.com }
|
|
||||||
|
|
||||||
default_backend web
|
|
||||||
|
|
||||||
backend mtg
|
|
||||||
# send-proxy-v2 prepends a PROXY protocol v2 header so mtg sees the
|
|
||||||
# real client IP instead of HAProxy's. mtg must have
|
|
||||||
# `proxy-protocol-listener = true` in its config.
|
|
||||||
server mtg mtg:3128 send-proxy-v2
|
|
||||||
|
|
||||||
backend web
|
|
||||||
# send-proxy-v2 prepends a PROXY protocol v2 header so Caddy logs the
|
|
||||||
# real client IP instead of HAProxy's. Caddy must enable the
|
|
||||||
# proxy_protocol listener wrapper on :8443 (see Caddyfile).
|
|
||||||
server web web:8443 send-proxy-v2
|
|
||||||
|
|
||||||
backend web_acme
|
|
||||||
mode http
|
|
||||||
server web web:80
|
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
# Minimal mtg configuration for the SNI-router setup.
|
|
||||||
#
|
|
||||||
# 1. Generate a secret: mtg generate-secret --hex example.com
|
|
||||||
# 2. Paste it below.
|
|
||||||
# 3. Replace example.com with your actual domain everywhere.
|
|
||||||
|
|
||||||
secret = "PASTE_YOUR_SECRET_HERE"
|
|
||||||
bind-to = "0.0.0.0:3128"
|
|
||||||
|
|
||||||
# HAProxy in front sends PROXY protocol v2 headers so mtg can see the
|
|
||||||
# real client IP. Keep this in sync with haproxy.cfg (`send-proxy-v2`).
|
|
||||||
proxy-protocol-listener = true
|
|
||||||
|
|
||||||
[defense.anti-replay]
|
|
||||||
enabled = true
|
|
||||||
max-size = "1mib"
|
|
||||||
error-rate = 0.001
|
|
||||||
@@ -1,5 +0,0 @@
|
|||||||
<!doctype html>
|
|
||||||
<html lang="en">
|
|
||||||
<head><meta charset="utf-8"><title>Welcome</title></head>
|
|
||||||
<body><h1>It works!</h1><p>Replace this with your own content.</p></body>
|
|
||||||
</html>
|
|
||||||
+1
-13
@@ -25,18 +25,6 @@ var TelegramCoreAddresses = map[int][]string{
|
|||||||
},
|
},
|
||||||
203: {
|
203: {
|
||||||
"91.105.192.100:443",
|
"91.105.192.100:443",
|
||||||
"[2a0a:f280:0203:a:5000::100]:443",
|
"[2a0a:f280:0203:000a:5000:0000:0000:0100]:443",
|
||||||
},
|
|
||||||
10001: {
|
|
||||||
"149.154.175.10:443",
|
|
||||||
"[2001:b28:f23d:f001::e]:443",
|
|
||||||
},
|
|
||||||
10002: {
|
|
||||||
"149.154.167.40:443",
|
|
||||||
"[2001:67c:4e8:f002::e]:443",
|
|
||||||
},
|
|
||||||
10003: {
|
|
||||||
"149.154.175.117:443",
|
|
||||||
"[2001:b28:f23d:f003::e]:443",
|
|
||||||
},
|
},
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -316,17 +316,6 @@ download-concurrency = 2
|
|||||||
# A list of URLs in FireHOL format (https://iplists.firehol.org/)
|
# A list of URLs in FireHOL format (https://iplists.firehol.org/)
|
||||||
# You can provider links here (starts with https:// or http://) or
|
# You can provider links here (starts with https:// or http://) or
|
||||||
# path to a local file, but in this case it should be absolute.
|
# path to a local file, but in this case it should be absolute.
|
||||||
#
|
|
||||||
# NOTE: the default list below (firehol_level1.netset) includes bogon
|
|
||||||
# networks, and therefore RFC1918 ranges as well (10.0.0.0/8,
|
|
||||||
# 172.16.0.0/12, 192.168.0.0/16). If you run mtg on a home/LAN network
|
|
||||||
# and connect from a client on the same LAN, that client will be
|
|
||||||
# rejected with "ip was blacklisted" and the connection dropped (TCP
|
|
||||||
# close, no response). If you see this, you can either disable this section
|
|
||||||
# (enabled = false), replace firehol_level1 with a narrower list that
|
|
||||||
# does not include bogons (e.g. firehol_abusers_1d), or connect via
|
|
||||||
# a public IP/domain with hairpin NAT on your router. See README for
|
|
||||||
# details.
|
|
||||||
urls = [
|
urls = [
|
||||||
"https://iplists.firehol.org/files/firehol_level1.netset",
|
"https://iplists.firehol.org/files/firehol_level1.netset",
|
||||||
# "/local.file"
|
# "/local.file"
|
||||||
@@ -378,11 +367,3 @@ bind-to = "127.0.0.1:3129"
|
|||||||
http-path = "/"
|
http-path = "/"
|
||||||
# prefix for metrics for prometheus
|
# prefix for metrics for prometheus
|
||||||
metric-prefix = "mtg"
|
metric-prefix = "mtg"
|
||||||
|
|
||||||
[dc]
|
|
||||||
dc1 = [
|
|
||||||
"149.154.175.50:443",
|
|
||||||
"149.154.175.54:443",
|
|
||||||
"149.154.175.59:443",
|
|
||||||
"[2001:b28:f23d:f001::a]:443"
|
|
||||||
]
|
|
||||||
@@ -50,12 +50,6 @@ var (
|
|||||||
tplEDCConnect = template.Must(
|
tplEDCConnect = template.Must(
|
||||||
template.New("").Parse(" ❌ DC {{ .dc }}: {{ .error }}\n"),
|
template.New("").Parse(" ❌ DC {{ .dc }}: {{ .error }}\n"),
|
||||||
)
|
)
|
||||||
tplODCIPConnect = template.Must(
|
|
||||||
template.New("").Parse(" ✅ {{ .ip }}\n"),
|
|
||||||
)
|
|
||||||
tplEDCIPConnect = template.Must(
|
|
||||||
template.New("").Parse(" ❌ {{ .ip }}: {{ .error }}\n"),
|
|
||||||
)
|
|
||||||
|
|
||||||
tplODNSSNIMatch = template.Must(
|
tplODNSSNIMatch = template.Must(
|
||||||
template.New("").Parse(" ✅ IP address {{ .ip }} matches secret hostname {{ .hostname }}\n"),
|
template.New("").Parse(" ✅ IP address {{ .ip }} matches secret hostname {{ .hostname }}\n"),
|
||||||
@@ -291,15 +285,8 @@ func (d *Doctor) checkNetworkAddresses(ntw mtglib.Network, addresses []string) e
|
|||||||
for _, addr := range checkAddresses {
|
for _, addr := range checkAddresses {
|
||||||
conn, err = ntw.DialContext(ctx, "tcp", addr)
|
conn, err = ntw.DialContext(ctx, "tcp", addr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
tplEDCIPConnect.Execute(os.Stdout, map[string]any{
|
|
||||||
"error": err,
|
|
||||||
"ip": addr,
|
|
||||||
})
|
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
tplODCIPConnect.Execute(os.Stdout, map[string]any{
|
|
||||||
"ip": addr,
|
|
||||||
})
|
|
||||||
|
|
||||||
conn.Close() //nolint: errcheck
|
conn.Close() //nolint: errcheck
|
||||||
|
|
||||||
|
|||||||
@@ -91,17 +91,6 @@ type Config struct {
|
|||||||
MetricPrefix TypeMetricPrefix `json:"metricPrefix"`
|
MetricPrefix TypeMetricPrefix `json:"metricPrefix"`
|
||||||
} `json:"prometheus"`
|
} `json:"prometheus"`
|
||||||
} `json:"stats"`
|
} `json:"stats"`
|
||||||
DCs struct{
|
|
||||||
DC1 []TypeHostPort `json:"dc1"`
|
|
||||||
DC2 []TypeHostPort `json:"dc2"`
|
|
||||||
DC3 []TypeHostPort `json:"dc3"`
|
|
||||||
DC4 []TypeHostPort `json:"dc4"`
|
|
||||||
DC5 []TypeHostPort `json:"dc5"`
|
|
||||||
DC203 []TypeHostPort `json:"dc203"`
|
|
||||||
DC10001 []TypeHostPort `json:"dc10001"`
|
|
||||||
DC10002[]TypeHostPort `json:"dc10002"`
|
|
||||||
DC10003 []TypeHostPort `json:"dc10003"`
|
|
||||||
} `json:"dc"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (c *Config) GetConcurrency(defaultValue uint) uint {
|
func (c *Config) GetConcurrency(defaultValue uint) uint {
|
||||||
|
|||||||
@@ -84,17 +84,6 @@ type tomlConfig struct {
|
|||||||
MetricPrefix string `toml:"metric-prefix" json:"metricPrefix,omitempty"`
|
MetricPrefix string `toml:"metric-prefix" json:"metricPrefix,omitempty"`
|
||||||
} `toml:"prometheus" json:"prometheus,omitempty"`
|
} `toml:"prometheus" json:"prometheus,omitempty"`
|
||||||
} `toml:"stats" json:"stats,omitempty"`
|
} `toml:"stats" json:"stats,omitempty"`
|
||||||
DCs struct{
|
|
||||||
DC1 []string `toml:"dc1" json:"dc1,omitempty"`
|
|
||||||
DC2 []string `toml:"dc2" json:"dc2,omitempty"`
|
|
||||||
DC3 []string `toml:"dc3" json:"dc3,omitempty"`
|
|
||||||
DC4 []string `toml:"dc4" json:"dc4,omitempty"`
|
|
||||||
DC5 []string `toml:"dc5" json:"dc5,omitempty"`
|
|
||||||
DC203 []string `toml:"dc203" json:"dc203,omitempty"`
|
|
||||||
DC10001 []string `toml:"dc10001" json:"dc10001,omitempty"`
|
|
||||||
DC10002 []string `toml:"dc10002" json:"dc10002,omitempty"`
|
|
||||||
DC10003 []string `toml:"dc10003" json:"dc10003,omitempty"`
|
|
||||||
} `toml:"dc" json:"dc,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func Parse(rawData []byte) (*Config, error) {
|
func Parse(rawData []byte) (*Config, error) {
|
||||||
|
|||||||
@@ -4,77 +4,9 @@ import (
|
|||||||
"fmt"
|
"fmt"
|
||||||
"os"
|
"os"
|
||||||
|
|
||||||
"github.com/9seconds/mtg/v2/essentials"
|
|
||||||
"github.com/9seconds/mtg/v2/internal/config"
|
"github.com/9seconds/mtg/v2/internal/config"
|
||||||
)
|
)
|
||||||
|
|
||||||
func readCustomDC(cfg *config.Config) {
|
|
||||||
if len(cfg.DCs.DC1) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC1 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[1] = ips
|
|
||||||
}
|
|
||||||
if len(cfg.DCs.DC2) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC2 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[2] = ips
|
|
||||||
}
|
|
||||||
if len(cfg.DCs.DC3) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC3 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[3] = ips
|
|
||||||
}
|
|
||||||
if len(cfg.DCs.DC4) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC4 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[4] = ips
|
|
||||||
}
|
|
||||||
if len(cfg.DCs.DC5) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC5 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[5] = ips
|
|
||||||
}
|
|
||||||
if len(cfg.DCs.DC203) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC203 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[203] = ips
|
|
||||||
}
|
|
||||||
|
|
||||||
if len(cfg.DCs.DC10001) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC10001 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[10001] = ips
|
|
||||||
}
|
|
||||||
if len(cfg.DCs.DC10002) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC10002 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[10002] = ips
|
|
||||||
}
|
|
||||||
if len(cfg.DCs.DC10003) > 0 {
|
|
||||||
var ips []string
|
|
||||||
for _, addr := range cfg.DCs.DC10003 {
|
|
||||||
ips = append(ips, addr.Value)
|
|
||||||
}
|
|
||||||
essentials.TelegramCoreAddresses[10003] = ips
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func ReadConfig(path string) (*config.Config, error) {
|
func ReadConfig(path string) (*config.Config, error) {
|
||||||
content, err := os.ReadFile(path)
|
content, err := os.ReadFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
@@ -90,7 +22,5 @@ func ReadConfig(path string) (*config.Config, error) {
|
|||||||
return nil, fmt.Errorf("invalid config: %w", err)
|
return nil, fmt.Errorf("invalid config: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
readCustomDC(conf)
|
|
||||||
|
|
||||||
return conf, nil
|
return conf, nil
|
||||||
}
|
}
|
||||||
|
|||||||
+1
-1
@@ -20,7 +20,7 @@ func SetServerSocketOptions(conn net.Conn, bufferSize int) error {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func setCommonSocketOptions(conn *net.TCPConn) error {
|
func setCommonSocketOptions(conn *net.TCPConn) error {
|
||||||
if err := applyKeepAlive(conn, net.KeepAliveConfig{
|
if err := conn.SetKeepAliveConfig(net.KeepAliveConfig{
|
||||||
Enable: true,
|
Enable: true,
|
||||||
Idle: DefaultKeepAliveIdle,
|
Idle: DefaultKeepAliveIdle,
|
||||||
Interval: DefaultKeepAliveInterval,
|
Interval: DefaultKeepAliveInterval,
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
//go:build !openbsd
|
|
||||||
|
|
||||||
package network
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
// applyKeepAlive enables TCP keepalive on conn and applies the per-socket
|
|
||||||
// idle/interval/count tuning from cfg.
|
|
||||||
func applyKeepAlive(conn *net.TCPConn, cfg net.KeepAliveConfig) error {
|
|
||||||
return conn.SetKeepAliveConfig(cfg) //nolint: wrapcheck
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package network
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
// applyKeepAlive enables (or disables) TCP keepalive on conn.
|
|
||||||
//
|
|
||||||
// OpenBSD has no user-settable per-socket TCP keepalive options: TCP_KEEPIDLE,
|
|
||||||
// TCP_KEEPINTVL and TCP_KEEPCNT do not exist on OpenBSD, and Go's
|
|
||||||
// (*TCPConn).SetKeepAliveConfig therefore returns ENOPROTOOPT ("protocol not
|
|
||||||
// available") for any non-negative Idle/Interval/Count value (see
|
|
||||||
// src/net/tcpsockopt_openbsd.go in the Go source tree). Calling
|
|
||||||
// SetKeepAliveConfig with mtg's defaults (zero values) breaks every accepted
|
|
||||||
// listener connection and every outbound dial on OpenBSD.
|
|
||||||
//
|
|
||||||
// On OpenBSD we only flip SO_KEEPALIVE on or off; the keepalive timing is
|
|
||||||
// controlled system-wide via the sysctl knobs net.inet.tcp.keepidle and
|
|
||||||
// net.inet.tcp.keepintvl.
|
|
||||||
func applyKeepAlive(conn *net.TCPConn, cfg net.KeepAliveConfig) error {
|
|
||||||
return conn.SetKeepAlive(cfg.Enable) //nolint: wrapcheck
|
|
||||||
}
|
|
||||||
@@ -6,7 +6,7 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func setCommonSocketOptions(conn *net.TCPConn, keepAliveConfig net.KeepAliveConfig) error {
|
func setCommonSocketOptions(conn *net.TCPConn, keepAliveConfig net.KeepAliveConfig) error {
|
||||||
if err := applyKeepAlive(conn, keepAliveConfig); err != nil {
|
if err := conn.SetKeepAliveConfig(keepAliveConfig); err != nil {
|
||||||
return fmt.Errorf("cannot configure TCP keepalive: %w", err)
|
return fmt.Errorf("cannot configure TCP keepalive: %w", err)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,11 +0,0 @@
|
|||||||
//go:build !openbsd
|
|
||||||
|
|
||||||
package network
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
// applyKeepAlive enables TCP keepalive on conn and applies the per-socket
|
|
||||||
// idle/interval/count tuning from cfg.
|
|
||||||
func applyKeepAlive(conn *net.TCPConn, cfg net.KeepAliveConfig) error {
|
|
||||||
return conn.SetKeepAliveConfig(cfg) //nolint: wrapcheck
|
|
||||||
}
|
|
||||||
@@ -1,20 +0,0 @@
|
|||||||
package network
|
|
||||||
|
|
||||||
import "net"
|
|
||||||
|
|
||||||
// applyKeepAlive enables (or disables) TCP keepalive on conn.
|
|
||||||
//
|
|
||||||
// OpenBSD has no user-settable per-socket TCP keepalive options: TCP_KEEPIDLE,
|
|
||||||
// TCP_KEEPINTVL and TCP_KEEPCNT do not exist on OpenBSD, and Go's
|
|
||||||
// (*TCPConn).SetKeepAliveConfig therefore returns ENOPROTOOPT ("protocol not
|
|
||||||
// available") for any non-negative Idle/Interval/Count value (see
|
|
||||||
// src/net/tcpsockopt_openbsd.go in the Go source tree). Calling
|
|
||||||
// SetKeepAliveConfig with mtg's defaults (zero values) breaks every accepted
|
|
||||||
// listener connection and every outbound dial on OpenBSD.
|
|
||||||
//
|
|
||||||
// On OpenBSD we only flip SO_KEEPALIVE on or off; the keepalive timing is
|
|
||||||
// controlled system-wide via the sysctl knobs net.inet.tcp.keepidle and
|
|
||||||
// net.inet.tcp.keepintvl.
|
|
||||||
func applyKeepAlive(conn *net.TCPConn, cfg net.KeepAliveConfig) error {
|
|
||||||
return conn.SetKeepAlive(cfg.Enable) //nolint: wrapcheck
|
|
||||||
}
|
|
||||||
Reference in New Issue
Block a user