Ensure http.Transport defaults are set correctly and resolve IPv6 issue with imctl check run

This commit is contained in:
Peter 2021-10-22 11:12:46 +02:00
parent 31e0165100
commit 01ecd7a442
Signed by: prskr
GPG key ID: C1DB5D2E8DB512F9
3 changed files with 41 additions and 22 deletions

View file

@ -94,6 +94,8 @@ tasks:
deps: deps:
- go-generate - go-generate
- protoc - protoc
cmds:
- task: format
test: test:
desc: run short running unit tests that do not need sudo desc: run short running unit tests that do not need sudo
@ -191,7 +193,6 @@ tasks:
- deps - deps
- generate - generate
cmds: cmds:
- task: format
- goreleaser release --snapshot --skip-publish --rm-dist - goreleaser release --snapshot --skip-publish --rm-dist
release: release:
@ -200,7 +201,6 @@ tasks:
- deps - deps
- generate - generate
cmds: cmds:
- task: format
- goreleaser release --rm-dist - goreleaser release --rm-dist
docs: docs:

View file

@ -105,7 +105,7 @@ func init() {
runCheckCmd.Flags().Uint16Var(&args.HTTPPort, "http-port", uint16(defaultHTTPPort), "Port to connect to for 'http://' requests") runCheckCmd.Flags().Uint16Var(&args.HTTPPort, "http-port", uint16(defaultHTTPPort), "Port to connect to for 'http://' requests")
runCheckCmd.Flags().Uint16Var(&args.HTTPSPort, "https-port", defaultHTTPSPort, "Port to connect to for 'https://' requests") runCheckCmd.Flags().Uint16Var(&args.HTTPSPort, "https-port", defaultHTTPSPort, "Port to connect to for 'https://' requests")
runCheckCmd.Flags().Uint16Var(&args.DNSPort, "dns-port", defaultDNSPort, "Port to connect to for DNS requests") runCheckCmd.Flags().Uint16Var(&args.DNSPort, "dns-port", defaultDNSPort, "Port to connect to for DNS requests")
runCheckCmd.Flags().StringVar(&args.DNSProto, "dns-proto", "tcp4", "Protocol to use for DNS requests one of [tcp, tcp4, tcp6, udp, udp4, udp6]") runCheckCmd.Flags().StringVar(&args.DNSProto, "dns-proto", "tcp", "Protocol to use for DNS requests one of [tcp, tcp4, tcp6, udp, udp4, udp6]")
runCheckCmd.Flags().Uint16Var(&args.DoTPort, "dot-port", defaultDoTPort, "Port to use for DoT requests") runCheckCmd.Flags().Uint16Var(&args.DoTPort, "dot-port", defaultDoTPort, "Port to use for DoT requests")
runCheckCmd.Flags().DurationVar(&args.Timeout, "check-timeout", defaultTimeout, "timeout to execute the check") runCheckCmd.Flags().DurationVar(&args.Timeout, "check-timeout", defaultTimeout, "timeout to execute the check")
runCheckCmd.Flags().StringVar(&args.CACertPath, "ca-cert", "", "Path to CA cert file to trust additionally to system cert pool") runCheckCmd.Flags().StringVar(&args.CACertPath, "ca-cert", "", "Path to CA cert file to trust additionally to system cert pool")
@ -178,38 +178,26 @@ func setupClients(
logger logging.Logger, logger logging.Logger,
args *runCheckArgs, args *runCheckArgs,
) (health.HTTPClientForModule, health.ResolverForModule, error) { ) (health.HTTPClientForModule, health.ResolverForModule, error) {
logger = logger.With(zap.String("target", args.Target)) target, err := resolveTargetIP(ctx, logger, args.Target)
if targetIP := net.ParseIP(args.Target); len(targetIP) == 0 { if err != nil {
logger.Debug("target is apparently not an IP - resolving IP address") return nil, nil, err
if addrs, err := net.DefaultResolver.LookupHost(ctx, args.Target); err != nil {
return nil, nil, err
} else {
logger.Debug("Resolved target addresses", zap.Strings("resolvedAddresses", addrs))
//nolint:gosec // no need for cryptographic security when picking a random IP address to contact
idx := rand.Intn(len(addrs))
logger.Debug("Picked random address", zap.String("newTargetAddress", addrs[idx]))
args.Target = addrs[idx]
}
} else {
logger.Debug("target is an IP address - will be set for clients")
} }
healthCfg := health.Config{ healthCfg := health.Config{
Client: health.ClientsConfig{ Client: health.ClientsConfig{
HTTP: health.Server{ HTTP: health.Server{
IP: args.Target, IP: target,
Port: args.HTTPPort, Port: args.HTTPPort,
}, },
HTTPS: health.Server{ HTTPS: health.Server{
IP: args.Target, IP: target,
Port: args.HTTPSPort, Port: args.HTTPSPort,
}, },
DNS: health.Server{ DNS: health.Server{
IP: args.Target, IP: target,
Port: args.DNSPort, Port: args.DNSPort,
}, },
DoT: health.Server{ DoT: health.Server{
IP: args.Target, IP: target,
Port: args.DoTPort, Port: args.DoTPort,
}, },
}, },
@ -266,3 +254,29 @@ func addCACertToPool(pool *x509.CertPool) (err error) {
pool.AppendCertsFromPEM(buffer.Bytes()) pool.AppendCertsFromPEM(buffer.Bytes())
return nil return nil
} }
func resolveTargetIP(ctx context.Context, logger logging.Logger, target string) (string, error) {
logger = logger.With(zap.String("target", target))
if targetIP := net.ParseIP(target); targetIP != nil && len(targetIP) > 0 {
logger.Debug("target is an IP address - will be set for clients")
return target, nil
}
logger.Debug("target is apparently not an IP - resolving IP address")
if addrs, err := net.DefaultResolver.LookupHost(ctx, args.Target); err != nil {
return "", err
} else {
logger.Debug("Resolved target addresses", zap.Strings("resolvedAddresses", addrs))
//nolint:gosec // no need for cryptographic security when picking a random IP address to contact
pickedAddr := addrs[rand.Intn(len(addrs))]
logger.Debug("Picked random address", zap.String("newTargetAddress", pickedAddr))
if parsed := net.ParseIP(pickedAddr); parsed == nil {
logger.Error("Could not parse resolved IP", zap.String("addr", pickedAddr))
return "", errors.New("could not parse resolved IP")
} else if parsed.To4() == nil {
pickedAddr = fmt.Sprintf("[%s]", pickedAddr)
}
args.Target = pickedAddr
}
return target, nil
}

View file

@ -6,6 +6,7 @@ import (
"fmt" "fmt"
"net" "net"
gohttp "net/http" gohttp "net/http"
"time"
"golang.org/x/net/http2" "golang.org/x/net/http2"
) )
@ -44,6 +45,10 @@ func HTTPClient(cfg Config, tlsConfig *tls.Config) *gohttp.Client {
) )
roundTripper := &gohttp.Transport{ roundTripper := &gohttp.Transport{
MaxIdleConns: 100,
IdleConnTimeout: 90 * time.Second,
TLSHandshakeTimeout: 10 * time.Second,
ExpectContinueTimeout: 1 * time.Second,
DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) { DialContext: func(ctx context.Context, _, _ string) (net.Conn, error) {
return netDialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%d", httpEndpoint.IP, httpEndpoint.Port)) return netDialer.DialContext(ctx, "tcp", fmt.Sprintf("%s:%d", httpEndpoint.IP, httpEndpoint.Port))
}, },