ソースを参照

Merge pull request #461 from dolonet/feature/sni-mismatch-warning

Warn about SNI/IP mismatch at proxy startup
pull/477/head
Sergei Arkhipov 2週間前
コミット
e5ce720a2d
コミッターのメールアドレスに関連付けられたアカウントが存在しません
1個のファイルの変更83行の追加1行の削除
  1. 83
    1
      internal/cli/run_proxy.go

+ 83
- 1
internal/cli/run_proxy.go ファイルの表示

@@ -5,6 +5,7 @@ import (
5 5
 	"fmt"
6 6
 	"net"
7 7
 	"os"
8
+	"strings"
8 9
 
9 10
 	"github.com/9seconds/mtg/v2/antireplay"
10 11
 	"github.com/9seconds/mtg/v2/events"
@@ -207,7 +208,86 @@ func makeEventStream(conf *config.Config, logger mtglib.Logger) (mtglib.EventStr
207 208
 	return events.NewNoopStream(), nil
208 209
 }
209 210
 
210
-func runProxy(conf *config.Config, version string) error { //nolint: funlen
211
+func warnSNIMismatch(conf *config.Config, ntw mtglib.Network, log mtglib.Logger) {
212
+	host := conf.Secret.Host
213
+	if host == "" {
214
+		return
215
+	}
216
+
217
+	addresses, err := net.DefaultResolver.LookupIPAddr(context.Background(), host)
218
+	if err != nil {
219
+		log.BindStr("hostname", host).
220
+			WarningError("SNI-DNS check: cannot resolve secret hostname", err)
221
+		return
222
+	}
223
+
224
+	ourIP4 := conf.PublicIPv4.Get(nil)
225
+	if ourIP4 == nil {
226
+		ourIP4 = getIP(ntw, "tcp4")
227
+	}
228
+
229
+	ourIP6 := conf.PublicIPv6.Get(nil)
230
+	if ourIP6 == nil {
231
+		ourIP6 = getIP(ntw, "tcp6")
232
+	}
233
+
234
+	if ourIP4 == nil && ourIP6 == nil {
235
+		log.Warning("SNI-DNS check: cannot detect public IP address; set public-ipv4/public-ipv6 in config or run 'mtg doctor'")
236
+		return
237
+	}
238
+
239
+	v4Match := ourIP4 == nil
240
+	v6Match := ourIP6 == nil
241
+
242
+	for _, addr := range addresses {
243
+		if ourIP4 != nil && addr.IP.String() == ourIP4.String() {
244
+			v4Match = true
245
+		}
246
+
247
+		if ourIP6 != nil && addr.IP.String() == ourIP6.String() {
248
+			v6Match = true
249
+		}
250
+	}
251
+
252
+	if v4Match && v6Match {
253
+		return
254
+	}
255
+
256
+	resolved := make([]string, 0, len(addresses))
257
+	for _, addr := range addresses {
258
+		resolved = append(resolved, addr.IP.String())
259
+	}
260
+
261
+	our := ""
262
+	if ourIP4 != nil {
263
+		our = ourIP4.String()
264
+	}
265
+
266
+	if ourIP6 != nil {
267
+		if our != "" {
268
+			our += "/"
269
+		}
270
+
271
+		our += ourIP6.String()
272
+	}
273
+
274
+	entry := log.BindStr("hostname", host).
275
+		BindStr("resolved", strings.Join(resolved, ", ")).
276
+		BindStr("public_ip", our)
277
+
278
+	if ourIP4 != nil {
279
+		entry = entry.BindStr("ipv4_match", fmt.Sprintf("%t", v4Match))
280
+	}
281
+
282
+	if ourIP6 != nil {
283
+		entry = entry.BindStr("ipv6_match", fmt.Sprintf("%t", v6Match))
284
+	}
285
+
286
+	entry.Warning("SNI-DNS mismatch: secret hostname does not resolve to this server's public IP. " +
287
+		"DPI may detect and block the proxy. See 'mtg doctor' for details")
288
+}
289
+
290
+func runProxy(conf *config.Config, version string) error { //nolint: funlen, cyclop
211 291
 	logger := makeLogger(conf)
212 292
 
213 293
 	logger.BindJSON("configuration", conf.String()).Debug("configuration")
@@ -222,6 +302,8 @@ func runProxy(conf *config.Config, version string) error { //nolint: funlen
222 302
 		return fmt.Errorf("cannot build network: %w", err)
223 303
 	}
224 304
 
305
+	warnSNIMismatch(conf, ntw, logger)
306
+
225 307
 	blocklist, err := makeIPBlocklist(
226 308
 		conf.Defense.Blocklist,
227 309
 		logger.Named("blocklist"),

読み込み中…
キャンセル
保存