Sfoglia il codice sorgente

Warn about SNI/IP mismatch at mtg run startup

The SNI-DNS validation that exists in 'mtg doctor' is now also run at
proxy startup.  If the secret hostname does not resolve to the server's
public IP, a warning is logged so that operators notice the
misconfiguration before DPI silently blocks the proxy.

The check is best-effort: if the public IP cannot be detected or the
hostname cannot be resolved, a brief warning is emitted and the proxy
starts normally.

Refs: #444, #458
pull/461/head
dolonet 3 settimane fa
parent
commit
1f8f063ec3
1 ha cambiato i file con 64 aggiunte e 1 eliminazioni
  1. 64
    1
      internal/cli/run_proxy.go

+ 64
- 1
internal/cli/run_proxy.go Vedi File

5
 	"fmt"
5
 	"fmt"
6
 	"net"
6
 	"net"
7
 	"os"
7
 	"os"
8
+	"strings"
8
 
9
 
9
 	"github.com/9seconds/mtg/v2/antireplay"
10
 	"github.com/9seconds/mtg/v2/antireplay"
10
 	"github.com/9seconds/mtg/v2/events"
11
 	"github.com/9seconds/mtg/v2/events"
207
 	return events.NewNoopStream(), nil
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
+	for _, addr := range addresses {
240
+		if (ourIP4 != nil && addr.IP.String() == ourIP4.String()) ||
241
+			(ourIP6 != nil && addr.IP.String() == ourIP6.String()) {
242
+			return
243
+		}
244
+	}
245
+
246
+	resolved := make([]string, 0, len(addresses))
247
+	for _, addr := range addresses {
248
+		resolved = append(resolved, addr.IP.String())
249
+	}
250
+
251
+	our := ""
252
+	if ourIP4 != nil {
253
+		our = ourIP4.String()
254
+	}
255
+
256
+	if ourIP6 != nil {
257
+		if our != "" {
258
+			our += "/"
259
+		}
260
+
261
+		our += ourIP6.String()
262
+	}
263
+
264
+	log.BindStr("hostname", host).
265
+		BindStr("resolved", strings.Join(resolved, ", ")).
266
+		BindStr("public_ip", our).
267
+		Warning("SNI-DNS mismatch: secret hostname does not resolve to this server's public IP. " +
268
+			"DPI may detect and block the proxy. See 'mtg doctor' for details")
269
+}
270
+
271
+func runProxy(conf *config.Config, version string) error { //nolint: funlen, cyclop
211
 	logger := makeLogger(conf)
272
 	logger := makeLogger(conf)
212
 
273
 
213
 	logger.BindJSON("configuration", conf.String()).Debug("configuration")
274
 	logger.BindJSON("configuration", conf.String()).Debug("configuration")
222
 		return fmt.Errorf("cannot build network: %w", err)
283
 		return fmt.Errorf("cannot build network: %w", err)
223
 	}
284
 	}
224
 
285
 
286
+	warnSNIMismatch(conf, ntw, logger)
287
+
225
 	blocklist, err := makeIPBlocklist(
288
 	blocklist, err := makeIPBlocklist(
226
 		conf.Defense.Blocklist,
289
 		conf.Defense.Blocklist,
227
 		logger.Named("blocklist"),
290
 		logger.Named("blocklist"),

Loading…
Annulla
Salva