...
1
16
17 package proxy
18
19 import (
20 "context"
21 "crypto/tls"
22 "fmt"
23 "net"
24 "net/http"
25 "net/url"
26
27 utilnet "k8s.io/apimachinery/pkg/util/net"
28 "k8s.io/apimachinery/third_party/forked/golang/netutil"
29 "k8s.io/klog/v2"
30 )
31
32
33
34
35
36
37 func DialURL(ctx context.Context, url *url.URL, transport http.RoundTripper) (net.Conn, error) {
38 dialAddr := netutil.CanonicalAddr(url)
39
40 dialer, err := utilnet.DialerFor(transport)
41 if err != nil {
42 klog.V(5).Infof("Unable to unwrap transport %T to get dialer: %v", transport, err)
43 }
44
45 switch url.Scheme {
46 case "http":
47 if dialer != nil {
48 return dialer(ctx, "tcp", dialAddr)
49 }
50 var d net.Dialer
51 return d.DialContext(ctx, "tcp", dialAddr)
52 case "https":
53
54 tlsConfig, err := utilnet.TLSClientConfig(transport)
55 if err != nil {
56 klog.V(5).Infof("Unable to unwrap transport %T to get at TLS config: %v", transport, err)
57 }
58
59 if dialer != nil {
60
61
62 netConn, err := dialer(ctx, "tcp", dialAddr)
63 if err != nil {
64 return nil, err
65 }
66 if tlsConfig == nil {
67
68 klog.Warning("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify")
69
70 tlsConfig = &tls.Config{
71 InsecureSkipVerify: true,
72 }
73 } else if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify {
74
75
76 inferredHost := dialAddr
77 if host, _, err := net.SplitHostPort(dialAddr); err == nil {
78 inferredHost = host
79 }
80
81 tlsConfigCopy := tlsConfig.Clone()
82 tlsConfigCopy.ServerName = inferredHost
83 tlsConfig = tlsConfigCopy
84 }
85
86
87
88
89 if supportsHTTP11(tlsConfig.NextProtos) {
90 tlsConfig = tlsConfig.Clone()
91 tlsConfig.NextProtos = []string{"http/1.1"}
92 }
93
94 tlsConn := tls.Client(netConn, tlsConfig)
95 if err := tlsConn.HandshakeContext(ctx); err != nil {
96 netConn.Close()
97 return nil, err
98 }
99 return tlsConn, nil
100 } else {
101
102 tlsDialer := tls.Dialer{
103 Config: tlsConfig,
104 }
105 return tlsDialer.DialContext(ctx, "tcp", dialAddr)
106 }
107 default:
108 return nil, fmt.Errorf("unknown scheme: %s", url.Scheme)
109 }
110 }
111
112 func supportsHTTP11(nextProtos []string) bool {
113 if len(nextProtos) == 0 {
114 return true
115 }
116 for _, proto := range nextProtos {
117 if proto == "http/1.1" {
118 return true
119 }
120 }
121 return false
122 }
123
View as plain text