mirror of
https://github.com/k3s-io/kubernetes.git
synced 2025-08-20 09:05:26 +00:00
Add http proxy support for exec/port-forward
Add http proxy support for exec/port-forward in SpdyRoundTripper
This commit is contained in:
parent
26c51881ca
commit
e73652411e
@ -23,6 +23,8 @@ import (
|
|||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
"net/http/httputil"
|
||||||
|
"net/url"
|
||||||
"strings"
|
"strings"
|
||||||
|
|
||||||
"k8s.io/kubernetes/pkg/api"
|
"k8s.io/kubernetes/pkg/api"
|
||||||
@ -53,21 +55,82 @@ type SpdyRoundTripper struct {
|
|||||||
Dialer *net.Dialer
|
Dialer *net.Dialer
|
||||||
}
|
}
|
||||||
|
|
||||||
// NewSpdyRoundTripper creates a new SpdyRoundTripper that will use
|
// NewRoundTripper creates a new SpdyRoundTripper that will use
|
||||||
// the specified tlsConfig.
|
// the specified tlsConfig.
|
||||||
func NewRoundTripper(tlsConfig *tls.Config) httpstream.UpgradeRoundTripper {
|
func NewRoundTripper(tlsConfig *tls.Config) httpstream.UpgradeRoundTripper {
|
||||||
return NewSpdyRoundTripper(tlsConfig)
|
return NewSpdyRoundTripper(tlsConfig)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// NewSpdyRoundTripper creates a new SpdyRoundTripper that will use
|
||||||
|
// the specified tlsConfig. This function is mostly meant for unit tests.
|
||||||
func NewSpdyRoundTripper(tlsConfig *tls.Config) *SpdyRoundTripper {
|
func NewSpdyRoundTripper(tlsConfig *tls.Config) *SpdyRoundTripper {
|
||||||
return &SpdyRoundTripper{tlsConfig: tlsConfig}
|
return &SpdyRoundTripper{tlsConfig: tlsConfig}
|
||||||
}
|
}
|
||||||
|
|
||||||
// dial dials the host specified by req, using TLS if appropriate.
|
// dial dials the host specified by req, using TLS if appropriate, optionally
|
||||||
|
// using a proxy server if one is configured via environment variables.
|
||||||
func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) {
|
func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) {
|
||||||
dialAddr := netutil.CanonicalAddr(req.URL)
|
proxyURL, err := http.ProxyFromEnvironment(req)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
if req.URL.Scheme == "http" {
|
if proxyURL == nil {
|
||||||
|
return s.dialWithoutProxy(req.URL)
|
||||||
|
}
|
||||||
|
|
||||||
|
// proxying logic adapted from http://blog.h6t.eu/post/74098062923/golang-websocket-with-http-proxy-support
|
||||||
|
proxyReq := http.Request{
|
||||||
|
Method: "CONNECT",
|
||||||
|
URL: &url.URL{},
|
||||||
|
Host: req.URL.Host,
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyDialConn, err := s.dialWithoutProxy(proxyURL)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
proxyClientConn := httputil.NewProxyClientConn(proxyDialConn, nil)
|
||||||
|
_, err = proxyClientConn.Do(&proxyReq)
|
||||||
|
if err != nil && err != httputil.ErrPersistEOF {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
rwc, _ := proxyClientConn.Hijack()
|
||||||
|
|
||||||
|
if req.URL.Scheme != "https" {
|
||||||
|
return rwc, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
host, _, err := net.SplitHostPort(req.URL.Host)
|
||||||
|
if err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if len(s.tlsConfig.ServerName) == 0 {
|
||||||
|
s.tlsConfig.ServerName = host
|
||||||
|
}
|
||||||
|
|
||||||
|
tlsConn := tls.Client(rwc, s.tlsConfig)
|
||||||
|
|
||||||
|
// need to manually call Handshake() so we can call VerifyHostname() below
|
||||||
|
if err := tlsConn.Handshake(); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := tlsConn.VerifyHostname(host); err != nil {
|
||||||
|
return nil, err
|
||||||
|
}
|
||||||
|
|
||||||
|
return tlsConn, nil
|
||||||
|
}
|
||||||
|
|
||||||
|
// dialWithoutProxy dials the host specified by url, using TLS if appropriate.
|
||||||
|
func (s *SpdyRoundTripper) dialWithoutProxy(url *url.URL) (net.Conn, error) {
|
||||||
|
dialAddr := netutil.CanonicalAddr(url)
|
||||||
|
|
||||||
|
if url.Scheme == "http" {
|
||||||
if s.Dialer == nil {
|
if s.Dialer == nil {
|
||||||
return net.Dial("tcp", dialAddr)
|
return net.Dial("tcp", dialAddr)
|
||||||
} else {
|
} else {
|
||||||
|
Loading…
Reference in New Issue
Block a user