func (h *UpgradeAwareProxyHandler) dialURL() (net.Conn, error) { dialAddr := netutil.CanonicalAddr(h.Location) switch h.Location.Scheme { case "http": return net.Dial("tcp", dialAddr) case "https": // Get the tls config from the transport if we recognize it var tlsConfig *tls.Config if h.Transport != nil { httpTransport, ok := h.Transport.(*http.Transport) if ok { tlsConfig = httpTransport.TLSClientConfig } } // Dial tlsConn, err := tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err } // Verify host, _, _ := net.SplitHostPort(dialAddr) if err := tlsConn.VerifyHostname(host); err != nil { tlsConn.Close() return nil, err } return tlsConn, nil default: return nil, fmt.Errorf("Unknown scheme: %s", h.Location.Scheme) } }
// dial dials the host specified by req, using TLS if appropriate. func (s *SpdyRoundTripper) dial(req *http.Request) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(req.URL) if req.URL.Scheme == "http" { if s.Dialer == nil { return net.Dial("tcp", dialAddr) } else { return s.Dialer.Dial("tcp", dialAddr) } } // TODO validate the TLSClientConfig is set up? var conn *tls.Conn var err error if s.Dialer == nil { conn, err = tls.Dial("tcp", dialAddr, s.tlsConfig) } else { conn, err = tls.DialWithDialer(s.Dialer, "tcp", dialAddr, s.tlsConfig) } if err != nil { return nil, err } host, _, err := net.SplitHostPort(dialAddr) if err != nil { return nil, err } err = conn.VerifyHostname(host) if err != nil { return nil, err } return conn, nil }
func dialURL(url *url.URL, transport http.RoundTripper) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(url) switch url.Scheme { case "http": return net.Dial("tcp", dialAddr) case "https": // Get the tls config from the transport if we recognize it var tlsConfig *tls.Config if transport != nil { httpTransport, ok := transport.(*http.Transport) if ok { tlsConfig = httpTransport.TLSClientConfig } } // Dial tlsConn, err := tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err } // Verify host, _, _ := net.SplitHostPort(dialAddr) if err := tlsConn.VerifyHostname(host); err != nil { tlsConn.Close() return nil, err } return tlsConn, nil default: return nil, fmt.Errorf("Unknown scheme: %s", url.Scheme) } }
func (p *UpgradeAwareSingleHostReverseProxy) dialBackend(req *http.Request) (net.Conn, error) { dialAddr := netutil.CanonicalAddr(req.URL) switch p.backendAddr.Scheme { case "http": return net.Dial("tcp", dialAddr) case "https": tlsConfig, err := kclient.TLSConfigFor(p.clientConfig) if err != nil { return nil, err } tlsConn, err := tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err } hostToVerify, _, err := net.SplitHostPort(dialAddr) if err != nil { return nil, err } err = tlsConn.VerifyHostname(hostToVerify) return tlsConn, err default: return nil, fmt.Errorf("unknown scheme: %s", p.backendAddr.Scheme) } }
// GetClusterNicknameFromURL returns host:port of the apiServerLocation, with .'s replaced by -'s func GetClusterNicknameFromURL(apiServerLocation string) (string, error) { u, err := url.Parse(apiServerLocation) if err != nil { return "", err } hostPort := netutil.CanonicalAddr(u) // we need a character other than "." to avoid conflicts with. replace with '-' return strings.Replace(hostPort, ".", "-", -1), nil }
// tryUpgrade returns true if the request was handled. func (r *ProxyHandler) tryUpgrade(w http.ResponseWriter, req, newReq *http.Request, destURL *url.URL) bool { connectionHeader := strings.ToLower(req.Header.Get(httpstream.HeaderConnection)) if !strings.Contains(connectionHeader, strings.ToLower(httpstream.HeaderUpgrade)) || len(req.Header.Get(httpstream.HeaderUpgrade)) == 0 { return false } //TODO support TLS? Doesn't look like proxyTransport does anything special ... dialAddr := netutil.CanonicalAddr(destURL) backendConn, err := net.Dial("tcp", dialAddr) if err != nil { status := errToAPIStatus(err) writeJSON(status.Code, r.codec, status, w) return true } defer backendConn.Close() // TODO should we use _ (a bufio.ReadWriter) instead of requestHijackedConn // when copying between the client and the backend? Docker doesn't when they // hijack, just for reference... requestHijackedConn, _, err := w.(http.Hijacker).Hijack() if err != nil { status := errToAPIStatus(err) writeJSON(status.Code, r.codec, status, w) return true } defer requestHijackedConn.Close() if err = newReq.Write(backendConn); err != nil { status := errToAPIStatus(err) writeJSON(status.Code, r.codec, status, w) return true } done := make(chan struct{}, 2) go func() { _, err := io.Copy(backendConn, requestHijackedConn) if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { glog.Errorf("Error proxying data from client to backend: %v", err) } done <- struct{}{} }() go func() { _, err := io.Copy(requestHijackedConn, backendConn) if err != nil && !strings.Contains(err.Error(), "use of closed network connection") { glog.Errorf("Error proxying data from backend to client: %v", err) } done <- struct{}{} }() <-done return true }
func (h *UpgradeAwareProxyHandler) dialURL() (net.Conn, error) { dialAddr := netutil.CanonicalAddr(h.Location) var dialer func(network, addr string) (net.Conn, error) if httpTransport, ok := h.Transport.(*http.Transport); ok && httpTransport.Dial != nil { dialer = httpTransport.Dial } switch h.Location.Scheme { case "http": if dialer != nil { return dialer("tcp", dialAddr) } return net.Dial("tcp", dialAddr) case "https": // TODO: this TLS logic can probably be cleaned up; it's messy in an attempt // to preserve behavior that we don't know for sure is exercised. // Get the tls config from the transport if we recognize it var tlsConfig *tls.Config var tlsConn *tls.Conn var err error if h.Transport != nil { httpTransport, ok := h.Transport.(*http.Transport) if ok { tlsConfig = httpTransport.TLSClientConfig } } if dialer != nil { // We have a dialer; use it to open the connection, then // create a tls client using the connection. netConn, err := dialer("tcp", dialAddr) if err != nil { return nil, err } // tls.Client requires non-nil config if tlsConfig == nil { glog.Warningf("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify") tlsConfig = &tls.Config{ InsecureSkipVerify: true, } } tlsConn = tls.Client(netConn, tlsConfig) if err := tlsConn.Handshake(); err != nil { return nil, err } } else { // Dial tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err } } // Verify host, _, _ := net.SplitHostPort(dialAddr) if err := tlsConn.VerifyHostname(host); err != nil { tlsConn.Close() return nil, err } return tlsConn, nil default: return nil, fmt.Errorf("unknown scheme: %s", h.Location.Scheme) } }