Просмотр исходного кода

sni-router: break domain-fronting loop

When the secret's domain resolves back to this server (the SNI-router
default), mtg's fallback fronting dial lands on HAProxy, the SNI
matches the secret, HAProxy routes the connection back to mtg -> loop.

Set [domain-fronting].host = "web" in mtg-config.toml so mtg dials
Caddy directly via compose-network DNS, bypassing HAProxy.  Requires
mtg >= 2.4 (#480 added hostname acceptance for the fronting target).

README gains a "Fronting loop" section explaining the cause.
pull/478/head
Alexey Dolotov 5 дней назад
Родитель
Сommit
0fdf6cbab7
2 измененных файлов: 45 добавлений и 0 удалений
  1. 34
    0
      contrib/sni-router/README.md
  2. 11
    0
      contrib/sni-router/mtg-config.toml

+ 34
- 0
contrib/sni-router/README.md Просмотреть файл

@@ -56,6 +56,40 @@ container address.  The three pieces must stay in sync:
56 56
 If you disable one, disable all three, otherwise the backend will fail
57 57
 to parse the connection.
58 58
 
59
+## Fronting loop (why `[domain-fronting]` is set explicitly)
60
+
61
+When mtg sees TLS that isn't valid Telegram (a probe or a browser
62
+hitting the domain on `:443`), it forwards that connection to a real
63
+web server — "domain fronting".  By default mtg uses the secret's
64
+hostname as the fronting target and resolves it via DNS, which in
65
+this setup points back to this server: the fronting dial lands on
66
+HAProxy, SNI matches the secret, HAProxy routes the connection back
67
+to mtg → loop.
68
+
69
+The trigger is DNS, not name equality: any time the secret's hostname
70
+resolves to this host, the loop reproduces.  In an SNI-router
71
+deployment the secret's hostname has to point here for clients to
72
+reach mtg in the first place, so the loop is the default state unless
73
+mtg is steered away from HAProxy.
74
+
75
+`mtg-config.toml` therefore pins the fronting target to the Caddy
76
+container directly:
77
+
78
+```toml
79
+[domain-fronting]
80
+host = "web"
81
+port = 8443
82
+proxy-protocol = true
83
+```
84
+
85
+`host = "web"` resolves through compose-network DNS to the `web`
86
+service (Caddy), bypassing HAProxy.  `proxy-protocol = true` matches
87
+Caddy's `:8443` listener wrapper so the real client IP still
88
+propagates to Caddy's logs.
89
+
90
+Requires mtg ≥ 2.4 — hostname acceptance for the fronting target was
91
+added in #480.
92
+
59 93
 ## ACME (Let's Encrypt) notes
60 94
 
61 95
 HAProxy passes `/.well-known/acme-challenge/` requests on `:80` to

+ 11
- 0
contrib/sni-router/mtg-config.toml Просмотреть файл

@@ -11,6 +11,17 @@ bind-to = "0.0.0.0:3128"
11 11
 # real client IP.  Keep this in sync with haproxy.cfg (`send-proxy-v2`).
12 12
 proxy-protocol-listener = true
13 13
 
14
+# Fronting target: point mtg at the Caddy container directly so its
15
+# fallback dial (for non-Telegram TLS) bypasses HAProxy and doesn't
16
+# loop back here.  Without this, mtg resolves the secret's hostname
17
+# via DNS, which in this setup resolves to this server -> HAProxy ->
18
+# mtg again.  See README's "Fronting loop" section for the long form.
19
+# Requires mtg >= 2.4 (#480 added hostname acceptance for the target).
20
+[domain-fronting]
21
+host = "web"
22
+port = 8443
23
+proxy-protocol = true
24
+
14 25
 [defense.anti-replay]
15 26
 enabled = true
16 27
 max-size = "1mib"

Загрузка…
Отмена
Сохранить