|
|
@@ -8,6 +8,7 @@ import (
|
|
8
|
8
|
"net"
|
|
9
|
9
|
"os"
|
|
10
|
10
|
"slices"
|
|
|
11
|
+ "strconv"
|
|
11
|
12
|
"strings"
|
|
12
|
13
|
"text/template"
|
|
13
|
14
|
"time"
|
|
|
@@ -56,6 +57,13 @@ var (
|
|
56
|
57
|
tplEDNSSNIMatch = template.Must(
|
|
57
|
58
|
template.New("").Parse(" ❌ Hostname {{ .hostname }} {{ if .resolved }}is resolved to {{ .resolved }} addresses, not {{ if .ip4 }}{{ .ip4 }}{{ else }}{{ .ip6 }}{{ end }}{{ else }}cannot be resolved to any host{{ end }}\n"),
|
|
58
|
59
|
)
|
|
|
60
|
+
|
|
|
61
|
+ tplOFrontingDomain = template.Must(
|
|
|
62
|
+ template.New("").Parse(" ✅ {{ .address }} is reachable\n"),
|
|
|
63
|
+ )
|
|
|
64
|
+ tplEFrontingDomain = template.Must(
|
|
|
65
|
+ template.New("").Parse(" ❌ {{ .address }}: {{ .error }}\n"),
|
|
|
66
|
+ )
|
|
59
|
67
|
)
|
|
60
|
68
|
|
|
61
|
69
|
type Doctor struct {
|
|
|
@@ -104,6 +112,9 @@ func (d *Doctor) Run(cli *CLI, version string) error {
|
|
104
|
112
|
everythingOK = d.checkNetwork(value) && everythingOK
|
|
105
|
113
|
}
|
|
106
|
114
|
|
|
|
115
|
+ fmt.Println("Validate fronting domain connectivity")
|
|
|
116
|
+ everythingOK = d.checkFrontingDomain(base) && everythingOK
|
|
|
117
|
+
|
|
107
|
118
|
fmt.Println("Validate SNI-DNS match")
|
|
108
|
119
|
everythingOK = d.checkSecretHost(resolver, base) && everythingOK
|
|
109
|
120
|
|
|
|
@@ -279,6 +290,38 @@ func (d *Doctor) checkNetworkAddresses(ntw mtglib.Network, addresses []string) e
|
|
279
|
290
|
return err
|
|
280
|
291
|
}
|
|
281
|
292
|
|
|
|
293
|
+func (d *Doctor) checkFrontingDomain(ntw mtglib.Network) bool {
|
|
|
294
|
+ host := d.conf.Secret.Host
|
|
|
295
|
+ if ip := d.conf.GetDomainFrontingIP(nil); ip != "" {
|
|
|
296
|
+ host = ip
|
|
|
297
|
+ }
|
|
|
298
|
+
|
|
|
299
|
+ port := d.conf.GetDomainFrontingPort(mtglib.DefaultDomainFrontingPort)
|
|
|
300
|
+ address := net.JoinHostPort(host, strconv.Itoa(int(port)))
|
|
|
301
|
+
|
|
|
302
|
+ ctx, cancel := context.WithTimeout(context.Background(), 10*time.Second)
|
|
|
303
|
+ defer cancel()
|
|
|
304
|
+
|
|
|
305
|
+ dialer := ntw.NativeDialer()
|
|
|
306
|
+
|
|
|
307
|
+ conn, err := dialer.DialContext(ctx, "tcp", address)
|
|
|
308
|
+ if err != nil {
|
|
|
309
|
+ tplEFrontingDomain.Execute(os.Stdout, map[string]any{ //nolint: errcheck
|
|
|
310
|
+ "address": address,
|
|
|
311
|
+ "error": err,
|
|
|
312
|
+ })
|
|
|
313
|
+ return false
|
|
|
314
|
+ }
|
|
|
315
|
+
|
|
|
316
|
+ conn.Close() //nolint: errcheck
|
|
|
317
|
+
|
|
|
318
|
+ tplOFrontingDomain.Execute(os.Stdout, map[string]any{ //nolint: errcheck
|
|
|
319
|
+ "address": address,
|
|
|
320
|
+ })
|
|
|
321
|
+
|
|
|
322
|
+ return true
|
|
|
323
|
+}
|
|
|
324
|
+
|
|
282
|
325
|
func (d *Doctor) checkSecretHost(resolver *net.Resolver, ntw mtglib.Network) bool {
|
|
283
|
326
|
addresses, err := resolver.LookupIPAddr(context.Background(), d.conf.Secret.Host)
|
|
284
|
327
|
if err != nil {
|