func (options *ScanOptions) SSLMatchHosts(conn *tls.Conn) []string { hosts := make([]string, 0) options.hostsMutex.Lock() for _, host := range options.inputHosts { testhost := host.Host if strings.Contains(testhost, ".appspot.com") { testhost = "appengine.google.com" } else if strings.Contains(testhost, "ggpht.com") { testhost = "googleusercontent.com" } else if strings.Contains(testhost, ".books.google.com") { testhost = "books.google.com" } else if strings.Contains(testhost, ".googleusercontent.com") { testhost = "googleusercontent.com" } if conn.VerifyHostname(testhost) == nil { hosts = append(hosts, host.Host) } } options.hostsMutex.Unlock() dest := make([]string, len(hosts)) perm := rand.Perm(len(hosts)) for i, v := range perm { dest[v] = hosts[i] } hosts = dest return hosts }
// 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 }
// NewClient establishes a new Client connection based on a set of Options. func (o Options) NewClient() (*Client, error) { host := o.Host c, err := connect(host, o.User, o.Password) if err != nil { return nil, err } if strings.LastIndex(o.Host, ":") > 0 { host = host[:strings.LastIndex(o.Host, ":")] } client := new(Client) if o.NoTLS { if o.Debug { client.conn = DebugConn{c} } else { client.conn = c } } else { var tlsconn *tls.Conn if o.TLSConfig != nil { tlsconn = tls.Client(c, o.TLSConfig) } else { DefaultConfig.ServerName = host tlsconn = tls.Client(c, &DefaultConfig) } if err = tlsconn.Handshake(); err != nil { return nil, err } insecureSkipVerify := DefaultConfig.InsecureSkipVerify if o.TLSConfig != nil { insecureSkipVerify = o.TLSConfig.InsecureSkipVerify } if !insecureSkipVerify { if err = tlsconn.VerifyHostname(host); err != nil { return nil, err } } if o.Debug { client.conn = DebugConn{tlsconn} } else { client.conn = tlsconn } } if err := client.init(&o); err != nil { client.Close() return nil, err } return client, nil }
func (p *httpProxyClient) DialTCPSAddr(network string, raddr string) (ProxyTCPConn, error) { var tlsConn *tls.Conn rawConn, err := p.upProxy.DialTCPSAddr(network, p.proxyAddr) if err != nil { return nil, fmt.Errorf("无法连接代理服务器 %v ,错误:%v", p.proxyAddr, err) } var c Conn = rawConn if p.proxyType == "https" { tlsConn = tls.Client(c, &tls.Config{ServerName: p.proxyDomain, InsecureSkipVerify: p.insecureSkipVerify}) if err := tlsConn.Handshake(); err != nil { tlsConn.Close() return nil, fmt.Errorf("TLS 协议握手错误:%v", err) } if p.insecureSkipVerify == false && tlsConn.VerifyHostname(p.proxyDomain) != nil { tlsConn.Close() return nil, fmt.Errorf("TLS 协议域名验证失败:%v", err) } c = tlsConn } req, err := http.NewRequest("CONNECT", p.proxyAddr, nil) if err != nil { c.Close() return nil, fmt.Errorf("创建请求错误:%v", err) } req.URL.Path = raddr req.URL.Host = p.proxyAddr if err := req.Write(c); err != nil { c.Close() return nil, fmt.Errorf("写请求错误:%v", err) } br := bufio.NewReader(c) res, err := http.ReadResponse(br, req) if err != nil { c.Close() return nil, fmt.Errorf("响应格式错误:%v", err) } if res.StatusCode != 200 { c.Close() return nil, fmt.Errorf("响应错误:%v", res) } return &HttpTCPConn{c, rawConn, tlsConn, net.TCPAddr{}, net.TCPAddr{}, "", "", 0, 0, p, res.Body}, nil }
// NewClient establishes a new Client connection based on a set of Options. func (o Options) NewClient() (*Client, error) { host := o.Host c, err := connect(host, o.User, o.Password) if err != nil { return nil, err } client := new(Client) if o.NoTLS { client.conn = c } else { var tlsconn *tls.Conn if o.TLSConfig != nil { tlsconn = tls.Client(c, o.TLSConfig) } else { //from https://github.com/dullgiulio/go-xmpp usrServ := strings.Split(o.User, "@") if len(usrServ) != 2 { return nil, errors.New("xmpp: invalid username (want user@domain): " + o.User) } DefaultConfig.ServerName = usrServ[1] tlsconn = tls.Client(c, &DefaultConfig) } if err = tlsconn.Handshake(); err != nil { return nil, err } if strings.LastIndex(o.Host, ":") > 0 { host = host[:strings.LastIndex(o.Host, ":")] } insecureSkipVerify := DefaultConfig.InsecureSkipVerify if o.TLSConfig != nil { insecureSkipVerify = o.TLSConfig.InsecureSkipVerify } if !insecureSkipVerify { if err = tlsconn.VerifyHostname(host); err != nil { return nil, err } } client.conn = tlsconn } if err := client.init(&o); err != nil { client.Close() return nil, err } return client, 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 { 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 } // Return if we were configured to skip validation if s.tlsConfig != nil && s.tlsConfig.InsecureSkipVerify { return conn, nil } 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) dialer, _ := utilnet.Dialer(transport) switch url.Scheme { case "http": if dialer != nil { return dialer("tcp", dialAddr) } return net.Dial("tcp", dialAddr) case "https": // Get the tls config from the transport if we recognize it var tlsConfig *tls.Config var tlsConn *tls.Conn var err error tlsConfig, _ = utilnet.TLSClientConfig(transport) 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 } if tlsConfig == nil { // tls.Client requires non-nil config glog.Warningf("using custom dialer with no TLSClientConfig. Defaulting to InsecureSkipVerify") // tls.Handshake() requires ServerName or InsecureSkipVerify tlsConfig = &tls.Config{ InsecureSkipVerify: true, } } else if len(tlsConfig.ServerName) == 0 && !tlsConfig.InsecureSkipVerify { // tls.Handshake() requires ServerName or InsecureSkipVerify // infer the ServerName from the hostname we're connecting to. inferredHost := dialAddr if host, _, err := net.SplitHostPort(dialAddr); err == nil { inferredHost = host } // Make a copy to avoid polluting the provided config tlsConfigCopy := *tlsConfig tlsConfigCopy.ServerName = inferredHost tlsConfig = &tlsConfigCopy } tlsConn = tls.Client(netConn, tlsConfig) if err := tlsConn.Handshake(); err != nil { netConn.Close() return nil, err } } else { // Dial tlsConn, err = tls.Dial("tcp", dialAddr, tlsConfig) if err != nil { return nil, err } } // Return if we were configured to skip validation if tlsConfig != nil && tlsConfig.InsecureSkipVerify { return tlsConn, nil } // 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 (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 } } // Return if we were configured to skip validation if tlsConfig != nil && tlsConfig.InsecureSkipVerify { return tlsConn, nil } // 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) } }
func (p *httpProxyClient) DialTCPSAddrTimeout(network string, raddr string, timeout time.Duration) (ProxyTCPConn, error) { var rconn ProxyTCPConn var rerr error rMutex := sync.Mutex{} // 截止时间 finalDeadline := time.Time{} if timeout != 0 { finalDeadline = time.Now().Add(timeout) } var tlsConn *tls.Conn rawConn, err := p.upProxy.DialTCPSAddrTimeout(network, p.proxyAddr, timeout) if err != nil { return nil, fmt.Errorf("无法连接代理服务器 %v ,错误:%v", p.proxyAddr, err) } c := Conn(rawConn) ch := make(chan int) // 实际执行部分 run := func() { closed := false // 当连接不被使用时,ch<-1会引发异常,这时将关闭连接。 defer func() { e := recover() if e != nil && closed == false { c.Close() } }() if p.proxyType == "https" { tlsConn = tls.Client(c, &tls.Config{ServerName: p.proxyDomain, InsecureSkipVerify: p.insecureSkipVerify}) if err := tlsConn.Handshake(); err != nil { closed = true c.Close() rMutex.Lock() rerr = fmt.Errorf("TLS 协议握手错误:%v", err) rMutex.Unlock() ch <- 0 return } if p.insecureSkipVerify == false && tlsConn.VerifyHostname(p.proxyDomain) != nil { closed = true tlsConn.Close() rMutex.Lock() rerr = fmt.Errorf("TLS 协议域名验证失败:%v", err) rMutex.Unlock() ch <- 0 return } c = tlsConn } req, err := http.NewRequest("CONNECT", raddr, nil) if err != nil { closed = true c.Close() rMutex.Lock() rerr = fmt.Errorf("创建请求错误:%v", err) rMutex.Unlock() ch <- 0 return } //req.URL.Path = raddr req.URL.Host = raddr req.Host = raddr if p.standardHeader { xpath := "/" rInt, err := rand.Int(rand.Reader, big.NewInt(20)) var rInt64 int64 if err != nil { rInt64 = srand.Int63n(20) } else { rInt64 = rInt.Int64() } for i := int64(-10); i < rInt64; i++ { xpath += "X" } req.Header.Add("Accept", "text/html, application/xhtml+xml, image/jxr, */*") req.Header.Add("Accept-Encoding", "gzip, deflate") req.Header.Add("Accept-Language", "zh-CN") req.Header.Add("XXnnection", "Keep-Alive") req.Header.Add("User-Agent", "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/000.00 (KHTML, like Gecko) Chrome/00.0.0000.0 Safari/000.00 Edge/00.00000") req.Header.Add("Cookie+path", xpath) } auth := base64.StdEncoding.EncodeToString([]byte(p.auth)) auth = fmt.Sprintf("Basic %v", auth) req.Header.Add("Proxy-Authorization", auth) if err := req.Write(c); err != nil { closed = true c.Close() rMutex.Lock() rerr = fmt.Errorf("写请求错误:%v", err) rMutex.Unlock() ch <- 0 return } br := bufio.NewReader(c) res, err := http.ReadResponse(br, req) if err != nil { closed = true c.Close() rMutex.Lock() rerr = fmt.Errorf("响应格式错误:%v", err) rMutex.Unlock() ch <- 0 return } if res.StatusCode != 200 { closed = true c.Close() rMutex.Lock() rerr = fmt.Errorf("响应错误:%v", res) rMutex.Unlock() ch <- 0 return } rMutex.Lock() rconn = &httpTCPConn{c, rawConn, tlsConn, net.TCPAddr{}, net.TCPAddr{}, "", "", 0, 0, p, res.Body} rMutex.Unlock() ch <- 1 return } if timeout == 0 { go run() select { case <-ch: rMutex.Lock() defer rMutex.Unlock() return rconn, rerr } } else { c.SetDeadline(finalDeadline) ntimeout := finalDeadline.Sub(time.Now()) if ntimeout <= 0 { return nil, fmt.Errorf("timeout") } t := time.NewTimer(ntimeout) defer t.Stop() go run() select { case <-t.C: return nil, fmt.Errorf("连接超时。") case <-ch: rMutex.Lock() defer rMutex.Unlock() if rerr == nil { c.SetDeadline(time.Time{}) } return rconn, rerr } } }
func (t *Transport) newClientConn(host, key string, tconn *tls.Conn) (*clientConn, error) { if err := tconn.Handshake(); err != nil { return nil, err } if !t.InsecureTLSDial { if err := tconn.VerifyHostname(host); err != nil { return nil, err } } state := tconn.ConnectionState() if p := state.NegotiatedProtocol; p != NextProtoTLS { return nil, fmt.Errorf("http2: unexpected ALPN protocol %q; want %q", p, NextProtoTLS) } if !state.NegotiatedProtocolIsMutual { return nil, errors.New("http2: could not negotiate protocol mutually") } if _, err := tconn.Write(clientPreface); err != nil { return nil, err } cc := &clientConn{ t: t, tconn: tconn, connKey: []string{key}, // TODO: cert's validated hostnames too tlsState: &state, readerDone: make(chan struct{}), nextStreamID: 1, maxFrameSize: 16 << 10, // spec default initialWindowSize: 65535, // spec default maxConcurrentStreams: 1000, // "infinite", per spec. 1000 seems good enough. streams: make(map[uint32]*clientStream), } cc.bw = bufio.NewWriter(stickyErrWriter{tconn, &cc.werr}) cc.br = bufio.NewReader(tconn) cc.fr = NewFramer(cc.bw, cc.br) cc.henc = hpack.NewEncoder(&cc.hbuf) cc.fr.WriteSettings() // TODO: re-send more conn-level flow control tokens when server uses all these. cc.fr.WriteWindowUpdate(0, 1<<30) // um, 0x7fffffff doesn't work to Google? it hangs? cc.bw.Flush() if cc.werr != nil { return nil, cc.werr } // Read the obligatory SETTINGS frame f, err := cc.fr.ReadFrame() if err != nil { return nil, err } sf, ok := f.(*SettingsFrame) if !ok { return nil, fmt.Errorf("expected settings frame, got: %T", f) } cc.fr.WriteSettingsAck() cc.bw.Flush() sf.ForeachSetting(func(s Setting) error { switch s.ID { case SettingMaxFrameSize: cc.maxFrameSize = s.Val case SettingMaxConcurrentStreams: cc.maxConcurrentStreams = s.Val case SettingInitialWindowSize: cc.initialWindowSize = s.Val default: // TODO(bradfitz): handle more t.vlogf("Unhandled Setting: %v", s) } return nil }) // TODO: figure out henc size cc.hdec = hpack.NewDecoder(initialHeaderTableSize, cc.onNewHeaderField) go cc.readLoop() return cc, nil }
// Dial creates a new connection to an XMPP server and authenticates as the // given user. func Dial(address, user, domain, password, resource string, config *Config) (c *Conn, err error) { c = new(Conn) c.inflights = make(map[Cookie]chan<- Stanza) var log io.Writer if config != nil && config.Log != nil { log = config.Log } var conn net.Conn if config != nil && config.Conn != nil { conn = config.Conn } else { if log != nil { io.WriteString(log, "Making TCP connection to "+address+"\n") } if conn, err = net.Dial("tcp", address); err != nil { return nil, err } } c.Conn = conn c.in, c.out = makeInOut(conn, config) features, err := c.getFeatures(domain) if err != nil { return nil, err } if features.StartTLS.XMLName.Local == "" { return nil, errors.New("xmpp: server doesn't support TLS") } fmt.Fprintf(c.out, "<starttls xmlns='%s'/>", nsTLS) proceed, err := nextStart(c.in) if err != nil { return nil, err } if proceed.Name.Space != nsTLS || proceed.Name.Local != "proceed" { return nil, errors.New("xmpp: expected <proceed> after <starttls> but got <" + proceed.Name.Local + "> in " + proceed.Name.Space) } if log != nil { io.WriteString(log, "Starting TLS handshake\n") } var tlsConn *tls.Conn if config != nil && config.SkipTLS { tlsConn = tls.Client(conn, &tls.Config{InsecureSkipVerify: true}) } else { tlsConn = tls.Client(conn, &tls.Config{ServerName: domain}) } if err := tlsConn.Handshake(); err != nil { return nil, err } tlsState := tlsConn.ConnectionState() if len(tlsState.VerifiedChains) == 0 && !config.SkipTLS { return nil, errors.New("xmpp: failed to verify TLS certificate") } if log != nil && !config.SkipTLS { for i, cert := range tlsState.VerifiedChains[0] { fmt.Fprintf(log, " certificate %d: %s\n", i, certName(cert)) } } if err := tlsConn.VerifyHostname(domain); err != nil { if config.TrustedAddress { if log != nil { fmt.Fprintf(log, "Certificate fails to verify against domain in username: %s\n", err) } host, _, err := net.SplitHostPort(address) if err != nil { return nil, errors.New("xmpp: failed to split address when checking whether TLS certificate is valid: " + err.Error()) } if err = tlsConn.VerifyHostname(host); err != nil { return nil, errors.New("xmpp: failed to match TLS certificate to address after failing to match to username: "******"Certificate matches against trusted server hostname: %s\n", host) } } else { return nil, errors.New("xmpp: failed to match TLS certificate to name: " + err.Error()) } } c.in, c.out = makeInOut(tlsConn, config) c.rawOut = tlsConn if features, err = c.getFeatures(domain); err != nil { return nil, err } if config != nil && config.Create { if log != nil { io.WriteString(log, "Attempting to create account\n") } fmt.Fprintf(c.rawOut, "<iq type='set' id='create_1'><query xmlns='jabber:iq:register'><username>%s</username><password>%s</password></query></iq>", user, password) var iq ClientIQ if err = c.in.DecodeElement(&iq, nil); err != nil { return nil, errors.New("unmarshal <iq>: " + err.Error()) } if iq.Type == "error" { return nil, errors.New("xmpp: account creation failed") } } if log != nil { io.WriteString(log, "Authenticating as "+user+"\n") } if err := c.authenticate(features, user, password); err != nil { return nil, err } if log != nil { io.WriteString(log, "Authentication successful\n") } if features, err = c.getFeatures(domain); err != nil { return nil, err } // Send IQ message asking to bind to the local user name. fmt.Fprintf(c.out, "<iq type='set' id='bind_2'><bind xmlns='%s'><resource>%s</resource></bind></iq>", nsBind, resource) var iq ClientIQ if err = c.in.DecodeElement(&iq, nil); err != nil { return nil, errors.New("unmarshal <iq>: " + err.Error()) } if &iq.Bind == nil { return nil, errors.New("<iq> result missing <bind>") } c.jid = iq.Bind.Jid // our local id if features.Session != nil { // The server needs a session to be established. See RFC 3921, // section 3. fmt.Fprintf(c.out, "<iq to='%s' type='set' id='sess_1'><session xmlns='%s'/></iq>", domain, nsSession) if err = c.in.DecodeElement(&iq, nil); err != nil { return nil, errors.New("xmpp: unmarshal <iq>: " + err.Error()) } if iq.Type != "result" { return nil, errors.New("xmpp: session establishment failed") } } return c, nil }