示例#1
0
文件: ssh2.go 项目: johnsonz/goproxy
func NewFilter(config *Config) (filters.Filter, error) {
	ss := &Servers{
		servers:    make([]Server, 0),
		sshClients: lrucache.NewLRUCache(uint(len(config.Servers))),
	}

	for _, s := range config.Servers {
		server := Server{
			Address: s.Addr,
			ClientConfig: &ssh.ClientConfig{
				User: s.Username,
				Auth: []ssh.AuthMethod{
					ssh.Password(s.Password),
				},
			},
		}

		ss.servers = append(ss.servers, server)
	}

	tr := &http.Transport{
		Dial: ss.Dial,
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: false,
			ClientSessionCache: tls.NewLRUClientSessionCache(1000),
		},
		TLSHandshakeTimeout: time.Duration(config.Transport.TLSHandshakeTimeout) * time.Second,
		MaxIdleConnsPerHost: config.Transport.MaxIdleConnsPerHost,
	}

	return &Filter{
		Config:    *config,
		Transport: tr,
	}, nil
}
示例#2
0
文件: metrics.go 项目: cfibmers/bbs
func NewETCDMetrics(logger lager.Logger, etcdOptions *ETCDOptions) (*ETCDMetrics, error) {
	var tlsConfig *tls.Config
	if etcdOptions.CertFile != "" && etcdOptions.KeyFile != "" {
		var err error
		tlsConfig, err = cfhttp.NewTLSConfig(etcdOptions.CertFile, etcdOptions.KeyFile, etcdOptions.CAFile)
		if err != nil {
			return nil, err
		}
		tlsConfig.ClientSessionCache = tls.NewLRUClientSessionCache(etcdOptions.ClientSessionCacheSize)
	}

	client := cfhttp.NewClient()
	client.CheckRedirect = func(*http.Request, []*http.Request) error {
		return errRedirected
	}

	if tr, ok := client.Transport.(*http.Transport); ok {
		tr.TLSClientConfig = tlsConfig
	} else {
		return nil, errors.New("Invalid transport")
	}

	return &ETCDMetrics{
		logger: logger,

		etcdCluster: etcdOptions.ClusterUrls,

		client: client,
	}, nil
}
示例#3
0
func newSecureClient(url, caFile, certFile, keyFile string, clientSessionCacheSize, maxIdleConnsPerHost int, skipVerify bool) (InternalClient, error) {
	client := newClient(url)

	tlsConfig, err := cfhttp.NewTLSConfig(certFile, keyFile, caFile)
	if err != nil {
		return nil, err
	}
	tlsConfig.ClientSessionCache = tls.NewLRUClientSessionCache(clientSessionCacheSize)

	tlsConfig.InsecureSkipVerify = skipVerify

	if tr, ok := client.httpClient.Transport.(*http.Transport); ok {
		tr.TLSClientConfig = tlsConfig
		tr.MaxIdleConnsPerHost = maxIdleConnsPerHost
	} else {
		return nil, errors.New("Invalid transport")
	}

	if tr, ok := client.streamingHTTPClient.Transport.(*http.Transport); ok {
		tr.TLSClientConfig = tlsConfig
		tr.MaxIdleConnsPerHost = maxIdleConnsPerHost
	} else {
		return nil, errors.New("Invalid transport")
	}

	return client, nil
}
示例#4
0
// tlsConfig builds a tls.Config for dialing the upstream host. Constructed
// tls.Configs are cached on a per-masquerade basis to enable client session
// caching and reduce the amount of PEM certificate parsing.
func (serverInfo *ServerInfo) tlsConfig(masquerade *Masquerade) *tls.Config {
	serverInfo.tlsConfigsMutex.Lock()
	defer serverInfo.tlsConfigsMutex.Unlock()

	if serverInfo.tlsConfigs == nil {
		serverInfo.tlsConfigs = make(map[string]*tls.Config)
	}

	configKey := ""
	serverName := serverInfo.Host
	if masquerade != nil {
		configKey = masquerade.Domain + "|" + masquerade.RootCA
		serverName = masquerade.Domain
	}
	tlsConfig := serverInfo.tlsConfigs[configKey]
	if tlsConfig == nil {
		tlsConfig = &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(1000),
			InsecureSkipVerify: serverInfo.InsecureSkipVerify,
			ServerName:         serverName,
		}
		if masquerade != nil && masquerade.RootCA != "" {
			caCert, err := keyman.LoadCertificateFromPEMBytes([]byte(masquerade.RootCA))
			if err != nil {
				log.Fatalf("Unable to load root ca cert: %s", err)
			}
			tlsConfig.RootCAs = caCert.PoolContainingCert()
		}
		serverInfo.tlsConfigs[configKey] = tlsConfig
	}

	return tlsConfig
}
示例#5
0
// SessionResumeScan tests that host is able to resume sessions across all addresses.
func sessionResumeScan(addr, hostname string) (grade Grade, output Output, err error) {
	config := defaultTLSConfig(hostname)
	config.ClientSessionCache = tls.NewLRUClientSessionCache(1)

	conn, err := tls.DialWithDialer(Dialer, Network, addr, config)
	if err != nil {
		return
	}
	if err = conn.Close(); err != nil {
		return
	}

	return multiscan(addr, func(addrport string) (g Grade, o Output, e error) {
		var conn *tls.Conn
		if conn, e = tls.DialWithDialer(Dialer, Network, addrport, config); e != nil {
			return
		}
		conn.Close()

		if o = conn.ConnectionState().DidResume; o.(bool) {
			g = Good
		}
		return
	})
}
示例#6
0
文件: chained.go 项目: shizhh/lantern
// Dialer creates a *balancer.Dialer backed by a chained server.
func (s *ChainedServerInfo) Dialer() (*balancer.Dialer, error) {
	netd := &net.Dialer{Timeout: chainedDialTimeout}

	var dial func() (net.Conn, error)
	if s.Cert == "" {
		log.Error("No Cert configured for chained server, will dial with plain tcp")
		dial = func() (net.Conn, error) {
			return netd.Dial("tcp", s.Addr)
		}
	} else {
		log.Trace("Cert configured for chained server, will dial with tls over tcp")
		cert, err := keyman.LoadCertificateFromPEMBytes([]byte(s.Cert))
		if err != nil {
			return nil, fmt.Errorf("Unable to parse certificate: %s", err)
		}
		x509cert := cert.X509()
		sessionCache := tls.NewLRUClientSessionCache(1000)
		dial = func() (net.Conn, error) {
			conn, err := tlsdialer.DialWithDialer(netd, "tcp", s.Addr, false, &tls.Config{
				ClientSessionCache: sessionCache,
				InsecureSkipVerify: true,
			})
			if err != nil {
				return nil, err
			}
			if !conn.ConnectionState().PeerCertificates[0].Equal(x509cert) {
				conn.Close()
				return nil, fmt.Errorf("Server's certificate didn't match expected!")
			}
			return conn, err
		}
	}

	ccfg := chained.Config{
		DialServer: dial,
	}
	if s.AuthToken != "" {
		ccfg.OnRequest = func(req *http.Request) {
			req.Header.Set("X-LANTERN-AUTH-TOKEN", s.AuthToken)
		}
	}
	d := chained.NewDialer(ccfg)

	// Is this a trusted proxy that we could use for HTTP traffic?
	var trusted string
	if s.Trusted {
		trusted = "(trusted) "
	}

	return &balancer.Dialer{
		Label:   fmt.Sprintf("%schained proxy at %s", trusted, s.Addr),
		Weight:  s.Weight,
		QOS:     s.QOS,
		Trusted: s.Trusted,
		Dial: func(network, addr string) (net.Conn, error) {
			return withStats(d.Dial(network, addr))
		},
	}, nil
}
示例#7
0
func (l *TLSLog) initConfig(config *tls.Config) {
	l.log = ""
	l.logRand = newLogRand(config.Rand)
	config.Rand = l.logRand
	config.SessionTicketsDisabled = false
	if config.ClientSessionCache == nil {
		config.ClientSessionCache = tls.NewLRUClientSessionCache(1)
	}
}
示例#8
0
func runHTTPServer() {
	cryptoConfig := &CryptoConfig{
		PKFile:   "proxypk.pem",
		CertFile: "proxycert.pem",
		ServerTLSConfig: &tls.Config{
			CipherSuites: []uint16{
				tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
				tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
				tls.TLS_ECDHE_RSA_WITH_RC4_128_SHA,
				tls.TLS_ECDHE_RSA_WITH_3DES_EDE_CBC_SHA,
				tls.TLS_RSA_WITH_RC4_128_SHA,
				tls.TLS_RSA_WITH_3DES_EDE_CBC_SHA,
				tls.TLS_RSA_WITH_AES_128_CBC_SHA,
				tls.TLS_RSA_WITH_AES_256_CBC_SHA,
				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			},
			PreferServerCipherSuites: true,
		},
	}

	rp := &httputil.ReverseProxy{
		Director: func(req *http.Request) {
			log.Printf("Processing request to: %s", req.URL)
		},
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				// Use a TLS session cache to minimize TLS connection establishment
				// Requires Go 1.3+
				ClientSessionCache: tls.NewLRUClientSessionCache(SESSIONS_TO_CACHE),
			},
		},
	}

	handler, err := Wrap(rp, cryptoConfig)
	if err != nil {
		log.Fatalf("Unable to wrap reverse proxy: %s", err)
	}

	server := &http.Server{
		Addr:         HTTP_ADDR,
		Handler:      handler,
		ReadTimeout:  10 * time.Hour,
		WriteTimeout: 10 * time.Hour,
	}

	go func() {
		log.Printf("About to start HTTP proxy at %s", HTTP_ADDR)
		if err := server.ListenAndServe(); err != nil {
			log.Fatalf("Unable to start HTTP proxy: %s", err)
		}
		exampleWg.Done()
	}()

	return
}
示例#9
0
文件: server.go 项目: mengzhuo/bla
func New() {

	flag.Parse()
	LoadConfig(*configPath)

	server := &Server{
		Docs:        make(map[string]*Doc, 0),
		sortedDocs:  make([]*Doc, 0),
		DocLock:     &sync.RWMutex{},
		Tags:        make(map[string][]*Doc, 0),
		TagLock:     &sync.RWMutex{},
		StaticFiles: make([]string, 0),
		Version:     Version,
		StopWatch:   make(chan bool)}

	server.Reset()
	if err := server.LoadTempalte(); err != nil {
		log.Fatal(err)
	}
	server.LoadStaticFiles()
	server.LoadAllDocs()
	if err := server.SaveAllDocs(); err != nil {
		log.Fatal(err)
	}
	server.MakeHome()
	log.Print(server.MakeSitemap())
	log.Print(Cfg)
	server.Watch()
	server.ConfigWatch()

	admin := map[string]http.HandlerFunc{
		".add":    server.Add,
		".edit":   server.Edit,
		".quit":   server.Quit,
		".upload": server.UploadMedia,
	}

	for k, v := range admin {
		http.HandleFunc(path.Join(Cfg.BasePath, k), server.auth(v))
	}

	http.Handle("/", http.FileServer(http.Dir(Cfg.PublicPath)))

	if Cfg.TLSKeyFile != "" && Cfg.TLSCertFile != "" {

		tls_server := http.Server{Addr: Cfg.Addr, Handler: nil,
			TLSConfig: &tls.Config{ClientSessionCache: tls.NewLRUClientSessionCache(100)}}
		log.Fatal(tls_server.ListenAndServeTLS(Cfg.TLSCertFile, Cfg.TLSKeyFile))
	} else {
		log.Fatal(http.ListenAndServe(Cfg.Addr, nil))
	}
}
示例#10
0
文件: dsp.go 项目: 2722/lantern
func New(domain string, email string, apiToken string) *Util {
	client := dnsimple.NewClient(apiToken, email)
	// Set a longish timeout on the HTTP client just in case
	client.HttpClient = &http.Client{
		Timeout: 5 * time.Minute,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				ClientSessionCache: tls.NewLRUClientSessionCache(1000),
			},
		},
	}
	return &Util{client, domain}
}
示例#11
0
func NewTLSServer(logger *util.Logger, caPool *CAPool, kvStore *kvstore.KVStore, hostname string) *TLSServer {
	inst := &TLSServer{
		ServerNode:     ch.NewServerNode(hostname),
		Logger:         logger,
		ControlChannel: make(chan (int)),
		StatusChannel:  make(chan (int)),
		Connections:    map[[16]byte]*Peer{},
		SessionCache:   tls.NewLRUClientSessionCache(1024),
		KVStore:        kvStore,
		CAPool:         caPool,
	}
	return inst
}
示例#12
0
func New(domain string, username string, apiKey string) *Util {
	client := cloudflare.NewClient(username, apiKey)
	// Set a longish timeout on the HTTP client just in case
	client.Http = &http.Client{
		Timeout: 5 * time.Minute,
		Transport: &http.Transport{
			TLSClientConfig: &tls.Config{
				ClientSessionCache: tls.NewLRUClientSessionCache(1000),
			},
		},
	}
	return &Util{client, domain}
}
示例#13
0
文件: cfr.go 项目: 2722/lantern
func New(id string, key string, httpClient *http.Client) *cloudfront.CloudFront {
	creds := aws.Creds(id, key, "")
	// Set a longish timeout on the HTTP client just in case
	if httpClient == nil {
		httpClient = &http.Client{
			Timeout: 5 * time.Minute,
			Transport: &http.Transport{
				TLSClientConfig: &tls.Config{
					ClientSessionCache: tls.NewLRUClientSessionCache(1000),
				},
			},
		}
	}
	return cloudfront.New(creds, "", httpClient)
}
示例#14
0
func post(params map[string]interface{}) error {
	buffer := bytes.NewBufferString("")

	if err := tmpl.Execute(buffer, params); err != nil {
		log.Printf("Airbrake error: %s", err)
		return err
	}

	if Verbose {
		log.Printf("Airbrake payload for endpoint %s: %s", Endpoint, buffer)
	}

	var httpClient = &http.Client{
		Transport: &http.Transport{
			Proxy: http.ProxyFromEnvironment,
			Dial: (&net.Dialer{
				Timeout:   30 * time.Second,
				KeepAlive: 30 * time.Second,
			}).Dial,
			TLSHandshakeTimeout: 10 * time.Second,
			TLSClientConfig: &tls.Config{
				ClientSessionCache: tls.NewLRUClientSessionCache(1024),
			},
			MaxIdleConnsPerHost:   100,
			ResponseHeaderTimeout: 10 * time.Second,
		},
		Timeout: 10 * time.Second,
	}
	response, err := httpClient.Post(Endpoint, "text/xml", buffer)
	if err != nil {
		log.Printf("Airbrake error: %s", err)
		return err
	}

	if Verbose {
		body, _ := ioutil.ReadAll(response.Body)
		log.Printf("response: %s", body)
	}
	response.Body.Close()

	if Verbose {
		log.Printf("Airbrake post: %s status code: %d", params["Error"], response.StatusCode)
	}

	return nil
}
示例#15
0
// tlsConfig builds a tls.Config for dialing the upstream host. Constructed
// tls.Configs are cached on a per-masquerade basis to enable client session
// caching and reduce the amount of PEM certificate parsing.
func (d *direct) tlsConfig(m *Masquerade) *tls.Config {
	d.tlsConfigsMutex.Lock()
	defer d.tlsConfigsMutex.Unlock()

	tlsConfig := d.tlsConfigs[m.Domain]
	if tlsConfig == nil {
		tlsConfig = &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(1000),
			InsecureSkipVerify: false,
			ServerName:         m.Domain,
			RootCAs:            d.certPool,
		}
		d.tlsConfigs[m.Domain] = tlsConfig
	}

	return tlsConfig
}
示例#16
0
文件: host.go 项目: 2722/lantern
// resetProxiedClient reconfigures the host so attempts to proxy through it,
// for the sake of checking whether it's up and serving, will use the given
// port.  Valid port values are "443", in which case we'll access the proxy
// through HTTPS, or "80", for an unencrypted connection.
//
// This is necessary because when peerscanner starts up and gets the list of
// hosts from the various DNS/CDN services, it has no way to know what port
// these servers are listening at.  So we want to try both until one works, or
// until the server first registers with peerscanner, advertising which port
// it uses.
func (h *host) resetProxiedClient(port string) {

	var dial func(addr string) (net.Conn, error)
	if port == "80" {
		dial = func(addr string) (net.Conn, error) {
			dialer := net.Dialer{Timeout: dialTimeout}
			return dialer.Dial("tcp", h.ip+":80")
		}
	} else if port == "443" {
		dial = func(addr string) (net.Conn, error) {
			return tlsdialer.DialWithDialer(&net.Dialer{
				Timeout: dialTimeout,
			}, "tcp", h.ip+":443", true, &tls.Config{
				InsecureSkipVerify: true,
				// Cache TLS sessions
				ClientSessionCache: tls.NewLRUClientSessionCache(1000),
			})
		}
	} else {
		log.Errorf("Unsupported port: %v", port)
		return
	}

	h.proxiedClient = &http.Client{
		Transport: &http.Transport{
			Dial: func(network, addr string) (net.Conn, error) {
				return enproxy.Dial(addr, &enproxy.Config{
					DialProxy: dial,
					NewRequest: func(upstreamHost string, method string, body io.Reader) (req *http.Request, err error) {
						return http.NewRequest(method, "http://"+h.ip+"/", body)
					},
					OnFirstResponse: func(resp *http.Response) {
						h.reportedHostMutex.Lock()
						h.reportedHost = resp.Header.Get(enproxy.X_ENPROXY_PROXY_HOST)
						h.reportedHostMutex.Unlock()
					},
				})
			},
			DisableKeepAlives: true,
		},
		Timeout: requestTimeout,
	}
}
示例#17
0
func NewDB(URL, CertPool, ClientCert string, HPKP []string) (*HTTPDB, error) {
	remote, err := url.Parse(URL)
	if err != nil {
		return nil, err
	}

	db := &HTTPDB{
		sni:        remote.Host,
		url:        URL,
		CertPool:   CertPool,
		ClientCert: ClientCert,
		client:     &http.Client{},
		tlsconfig: &tls.Config{
			ServerName:         remote.Host,
			MinVersion:         tls.VersionTLS12,
			MaxVersion:         tls.VersionTLS12,
			ClientSessionCache: tls.NewLRUClientSessionCache(MaxConn),
			CurvePreferences: []tls.CurveID{
				tls.CurveP521,
				tls.CurveP384,
				tls.CurveP256,
			},
			CipherSuites: []uint16{
				tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
				tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
				tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
				tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
			},
		},
		hpkp: make(map[string]bool),
	}

	for _, k := range HPKP {
		db.hpkp[k] = true
	}

	db.client.Transport = &http.Transport{
		MaxIdleConnsPerHost: MaxConn,
		DialTLS:             db.DialerTLS,
	}

	return db, nil
}
示例#18
0
func NewFilter(config *Config) (filters.Filter, error) {
	d := &dialer.Dialer{
		Dialer: net.Dialer{
			KeepAlive: time.Duration(config.Transport.Dialer.KeepAlive) * time.Second,
			Timeout:   time.Duration(config.Transport.Dialer.Timeout) * time.Second,
			DualStack: config.Transport.Dialer.DualStack,
		},
		RetryTimes:     config.Transport.Dialer.RetryTimes,
		RetryDelay:     time.Duration(config.Transport.Dialer.RetryDelay*1000) * time.Second,
		DNSCache:       lrucache.NewLRUCache(config.Transport.Dialer.DNSCacheSize),
		DNSCacheExpiry: time.Duration(config.Transport.Dialer.DNSCacheExpiry) * time.Second,
		LoopbackAddrs:  make(map[string]struct{}),
	}

	d.LoopbackAddrs = make(map[string]struct{})
	d.LoopbackAddrs["127.0.0.1"] = struct{}{}
	d.LoopbackAddrs["::1"] = struct{}{}
	if addrs, err := net.InterfaceAddrs(); err == nil {
		for _, addr := range addrs {
			switch addr.Network() {
			case "ip":
				d.LoopbackAddrs[addr.String()] = struct{}{}
			}
		}
	}

	tr := &http.Transport{
		Dial: d.Dial,
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: config.Transport.TLSClientConfig.InsecureSkipVerify,
			ClientSessionCache: tls.NewLRUClientSessionCache(config.Transport.TLSClientConfig.ClientSessionCacheSize),
		},
		TLSHandshakeTimeout: time.Duration(config.Transport.TLSHandshakeTimeout) * time.Second,
		MaxIdleConnsPerHost: config.Transport.MaxIdleConnsPerHost,
		DisableCompression:  config.Transport.DisableCompression,
	}

	return &Filter{
		Config:    *config,
		transport: tr,
	}, nil
}
示例#19
0
func initTransport(artDetails *config.ArtifactoryDetails) error {
	// Remove once SystemCertPool supports windows
	caCertPool, err := LoadSystemRoots()

	err = cliutils.CheckError(err)
	if err != nil {
		return err
	}
	err = loadCertificates(caCertPool)
	if err != nil {
		return err
	}
	// Setup HTTPS client
	tlsConfig := &tls.Config{
		RootCAs:            caCertPool,
		ClientSessionCache: tls.NewLRUClientSessionCache(1)}
	tlsConfig.BuildNameToCertificate()
	artDetails.Transport = &http.Transport{TLSClientConfig: tlsConfig}
	return nil
}
示例#20
0
文件: tls.go 项目: huhoo/vulcand
// NewTLSSessionCache validates parameters and creates a new TLS session cache
func NewTLSSessionCache(s *TLSSessionCache) (tls.ClientSessionCache, error) {
	cacheType := s.Type
	if cacheType == "" {
		cacheType = LRUCacheType
	}
	if cacheType != LRUCacheType {
		return nil, fmt.Errorf("unsupported session cache type: %v", s.Type)
	}
	var capacity int
	if params := s.Settings; params != nil {
		if params.Capacity < 0 {
			return nil, fmt.Errorf("bad LRU capacity: %v", params.Capacity)
		} else if params.Capacity == 0 {
			capacity = DefaultLRUCapacity
		} else {
			capacity = params.Capacity
		}
	}
	return tls.NewLRUClientSessionCache(capacity), nil
}
示例#21
0
文件: dialer.go 项目: shizhh/lantern
// tlsConfig builds a tls.Config for dialing the upstream host. Constructed
// tls.Configs are cached on a per-masquerade basis to enable client session
// caching and reduce the amount of PEM certificate parsing.
func (d *dialer) tlsConfig(masquerade *Masquerade) *tls.Config {
	d.tlsConfigsMutex.Lock()
	defer d.tlsConfigsMutex.Unlock()

	serverName := d.Host
	if masquerade != nil {
		serverName = masquerade.Domain
	}
	tlsConfig := d.tlsConfigs[serverName]
	if tlsConfig == nil {
		tlsConfig = &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(1000),
			InsecureSkipVerify: d.InsecureSkipVerify,
			ServerName:         serverName,
			RootCAs:            d.RootCAs,
		}
		d.tlsConfigs[serverName] = tlsConfig
	}

	return tlsConfig
}
示例#22
0
文件: main.go 项目: cloudfoundry/bbs
func initializeEtcdStoreClient(logger lager.Logger, etcdOptions *etcddb.ETCDOptions) etcddb.StoreClient {
	var etcdClient *etcdclient.Client
	var tr *http.Transport

	if etcdOptions.IsSSL {
		if etcdOptions.CertFile == "" || etcdOptions.KeyFile == "" {
			logger.Fatal("failed-to-construct-etcd-tls-client", errors.New("Require both cert and key path"))
		}

		var err error
		etcdClient, err = etcdclient.NewTLSClient(etcdOptions.ClusterUrls, etcdOptions.CertFile, etcdOptions.KeyFile, etcdOptions.CAFile)
		if err != nil {
			logger.Fatal("failed-to-construct-etcd-tls-client", err)
		}

		tlsCert, err := tls.LoadX509KeyPair(etcdOptions.CertFile, etcdOptions.KeyFile)
		if err != nil {
			logger.Fatal("failed-to-construct-etcd-tls-client", err)
		}

		tlsConfig := &tls.Config{
			Certificates:       []tls.Certificate{tlsCert},
			InsecureSkipVerify: true,
			ClientSessionCache: tls.NewLRUClientSessionCache(etcdOptions.ClientSessionCacheSize),
		}
		tr = &http.Transport{
			TLSClientConfig:     tlsConfig,
			Dial:                etcdClient.DefaultDial,
			MaxIdleConnsPerHost: etcdOptions.MaxIdleConnsPerHost,
		}
		etcdClient.SetTransport(tr)
		etcdClient.AddRootCA(etcdOptions.CAFile)
	} else {
		etcdClient = etcdclient.NewClient(etcdOptions.ClusterUrls)
	}
	etcdClient.SetConsistency(etcdclient.STRONG_CONSISTENCY)

	return etcddb.NewStoreClient(etcdClient)
}
示例#23
0
func initializeEtcdClient(etcdOptions *ETCDOptions) *etcd.Client {
	var etcdClient *etcd.Client
	var tr *http.Transport

	if etcdOptions.IsSSL {
		if etcdOptions.CertFile == "" || etcdOptions.KeyFile == "" {
			panic(errors.New("Require both cert and key path"))
		}

		var err error
		etcdClient, err = etcd.NewTLSClient(etcdOptions.ClusterUrls, etcdOptions.CertFile, etcdOptions.KeyFile, etcdOptions.CAFile)
		if err != nil {
			panic(err)
		}

		tlsCert, err := tls.LoadX509KeyPair(etcdOptions.CertFile, etcdOptions.KeyFile)
		if err != nil {
			panic(err)
		}

		tlsConfig := &tls.Config{
			Certificates:       []tls.Certificate{tlsCert},
			InsecureSkipVerify: true,
			ClientSessionCache: tls.NewLRUClientSessionCache(etcdOptions.ClientSessionCacheSize),
		}
		tr = &http.Transport{
			TLSClientConfig:     tlsConfig,
			Dial:                etcdClient.DefaultDial,
			MaxIdleConnsPerHost: etcdOptions.MaxIdleConnsPerHost,
		}
		etcdClient.SetTransport(tr)
	} else {
		etcdClient = etcd.NewClient(etcdOptions.ClusterUrls)
	}
	etcdClient.SetConsistency(etcd.STRONG_CONSISTENCY)

	return etcdClient
}
示例#24
0
func NewFilter(config *Config) (filters.Filter, error) {
	d := &Dailer{}
	d.Timeout = time.Duration(config.Dialer.Timeout) * time.Second
	d.KeepAlive = time.Duration(config.Dialer.KeepAlive) * time.Second
	d.DNSCache = lrucache.NewMultiLRUCache(4, uint(config.DNSCache.Size))
	d.DNSCacheExpires = time.Duration(config.DNSCache.Expires) * time.Second
	d.Blacklist = make(map[string]struct{})

	// d.Blacklist["127.0.0.1"] = struct{}{}
	d.Blacklist["::1"] = struct{}{}
	if addrs, err := net.InterfaceAddrs(); err == nil {
		for _, addr := range addrs {
			switch addr.Network() {
			case "ip":
				d.Blacklist[addr.String()] = struct{}{}
			}
		}
	}
	// glog.V(2).Infof("add blacklist=%v to direct filter", d.Blacklist)

	return &Filter{
		transport: &http.Transport{
			Dial: d.Dial,
			TLSClientConfig: &tls.Config{
				InsecureSkipVerify: false,
				ClientSessionCache: tls.NewLRUClientSessionCache(1000),
			},
			TLSHandshakeTimeout: time.Duration(config.Transport.TLSHandshakeTimeout) * time.Second,
			MaxIdleConnsPerHost: config.Transport.MaxIdleConnsPerHost,
			DisableCompression:  config.Transport.DisableCompression,
		},
		ratelimt: RateLimit{
			Threshold: int64(config.RateLimit.Threshold),
			Capacity:  int64(config.RateLimit.Capacity),
			Rate:      float64(config.RateLimit.Rate),
		},
	}, nil
}
示例#25
0
func NewFilter(config *Config) (filters.Filter, error) {
	servers := make([]Server, 0)
	for _, s := range config.Servers {
		u, err := url.Parse(s.URL)
		if err != nil {
			return nil, err
		}

		server := Server{
			URL:       u,
			Password:  s.Password,
			SSLVerify: s.SSLVerify,
			Host:      s.Host,
		}

		servers = append(servers, server)
	}

	d := &dialer.Dialer{
		Dialer: net.Dialer{
			KeepAlive: time.Duration(config.Transport.Dialer.KeepAlive) * time.Second,
			Timeout:   time.Duration(config.Transport.Dialer.Timeout) * time.Second,
			DualStack: config.Transport.Dialer.DualStack,
		},
		RetryTimes:     config.Transport.Dialer.RetryTimes,
		RetryDelay:     time.Duration(config.Transport.Dialer.RetryDelay*1000) * time.Second,
		DNSCache:       lrucache.NewLRUCache(config.Transport.Dialer.DNSCacheSize),
		DNSCacheExpiry: time.Duration(config.Transport.Dialer.DNSCacheExpiry) * time.Second,
		LoopbackAddrs:  nil,
		Level:          2,
	}

	for _, server := range servers {
		if server.Host != "" {
			host := server.URL.Host
			if _, _, err := net.SplitHostPort(host); err != nil {
				if server.URL.Scheme == "https" {
					host += ":443"
				} else {
					host += ":80"
				}
			}

			host1 := server.Host
			if _, _, err := net.SplitHostPort(host1); err != nil {
				if server.URL.Scheme == "https" {
					host1 += ":443"
				} else {
					host1 += ":80"
				}
			}

			d.DNSCache.Set(host, host1, time.Time{})
		}
	}

	tr := &http.Transport{
		Dial: d.Dial,
		TLSClientConfig: &tls.Config{
			InsecureSkipVerify: false,
			ClientSessionCache: tls.NewLRUClientSessionCache(1000),
		},
		TLSHandshakeTimeout: time.Duration(config.Transport.TLSHandshakeTimeout) * time.Second,
		MaxIdleConnsPerHost: config.Transport.MaxIdleConnsPerHost,
	}

	if tr.TLSClientConfig != nil {
		err := http2.ConfigureTransport(tr)
		if err != nil {
			glog.Warningf("PHP: Error enabling Transport HTTP/2 support: %v", err)
		}
	}

	return &Filter{
		Config: *config,
		Transport: &Transport{
			RoundTripper: tr,
			Servers:      servers,
		},
		Sites: helpers.NewHostMatcher(config.Sites),
	}, nil
}
示例#26
0
文件: gae.go 项目: ChoyesYan/goproxy
func NewFilter(config *Config) (filters.Filter, error) {
	dnsServers := make([]net.IP, 0)
	for _, s := range config.DNSServers {
		if ip := net.ParseIP(s); ip != nil {
			dnsServers = append(dnsServers, ip)
		}
	}

	GoogleG2PKP, err := base64.StdEncoding.DecodeString(config.GoogleG2PKP)
	if err != nil {
		return nil, err
	}

	googleTLSConfig := &tls.Config{
		MinVersion:         tls.VersionTLS12,
		InsecureSkipVerify: true,
		ServerName:         "www.microsoft.com",
		ClientSessionCache: tls.NewLRUClientSessionCache(config.TLSConfig.ClientSessionCacheSize),
		CipherSuites: []uint16{
			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_RSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384,
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384,
		},
	}
	switch config.TLSConfig.Version {
	case "TLSv12", "TLSv1.2":
		googleTLSConfig.MinVersion = tls.VersionTLS12
	case "TLSv11", "TLSv1.1":
		googleTLSConfig.MinVersion = tls.VersionTLS11
	default:
		googleTLSConfig.MinVersion = tls.VersionTLS10
	}
	pickupCiphers := func(names []string) []uint16 {
		ciphers := make([]uint16, 0)
		for _, name := range names {
			cipher := helpers.Cipher(name)
			if cipher == 0 {
				glog.Fatalf("GAE: cipher %#v is not supported.", name)
			}
			ciphers = append(ciphers, cipher)
		}
		helpers.ShuffleUint16s(ciphers)
		ciphers = ciphers[:1+rand.Intn(len(ciphers))]
		ciphers1 := []uint16{}
		for _, name := range []string{
			"TLS_RSA_WITH_AES_256_CBC_SHA256",
			"TLS_RSA_WITH_AES_256_GCM_SHA384",
			"TLS_ECDHE_RSA_WITH_AES_256_GCM_SHA384",
			"TLS_ECDHE_ECDSA_WITH_AES_256_GCM_SHA384",
		} {
			if !helpers.ContainsString(names, name) {
				if c := helpers.Cipher(name); c != 0 {
					ciphers1 = append(ciphers1, c)
				}
			}
		}
		helpers.ShuffleUint16s(ciphers1)
		ciphers1 = ciphers1[:rand.Intn(len(ciphers1))]
		ciphers = append(ciphers, ciphers1...)
		helpers.ShuffleUint16s(ciphers)
		return ciphers
	}
	googleTLSConfig.CipherSuites = pickupCiphers(config.TLSConfig.Ciphers)
	if len(config.TLSConfig.ServerName) > 0 {
		googleTLSConfig.ServerName = config.TLSConfig.ServerName[rand.Intn(len(config.TLSConfig.ServerName))]
	}
	if !config.DisableHTTP2 {
		googleTLSConfig.NextProtos = []string{"h2", "h2-14", "http/1.1"}
	}

	if config.Site2Alias == nil {
		config.Site2Alias = make(map[string]string)
	}
	for key, value := range config.SiteToAlias {
		config.Site2Alias[key] = value
	}
	config.SiteToAlias = config.Site2Alias

	hostmap := map[string][]string{}
	for key, value := range config.HostMap {
		hostmap[key] = helpers.UniqueStrings(value)
	}

	d := &net.Dialer{
		KeepAlive: time.Duration(config.Transport.Dialer.KeepAlive) * time.Second,
		Timeout:   time.Duration(config.Transport.Dialer.Timeout) * time.Second,
		DualStack: config.Transport.Dialer.DualStack,
	}

	md := &dialer.MultiDialer{
		Dialer:            d,
		DisableIPv6:       config.DisableIPv6,
		ForceIPv6:         config.ForceIPv6,
		SSLVerify:         config.SSLVerify,
		EnableRemoteDNS:   config.EnableRemoteDNS,
		LogToStderr:       flag.Lookup("logtostderr") != nil,
		TLSConfig:         nil,
		SiteToAlias:       helpers.NewHostMatcherWithString(config.SiteToAlias),
		IPBlackList:       lrucache.NewLRUCache(1024),
		HostMap:           hostmap,
		GoogleTLSConfig:   googleTLSConfig,
		GoogleG2PKP:       GoogleG2PKP,
		DNSServers:        dnsServers,
		DNSCache:          lrucache.NewLRUCache(config.Transport.Dialer.DNSCacheSize),
		DNSCacheExpiry:    time.Duration(config.Transport.Dialer.DNSCacheExpiry) * time.Second,
		TLSConnDuration:   lrucache.NewLRUCache(8192),
		TLSConnError:      lrucache.NewLRUCache(8192),
		TLSConnReadBuffer: config.Transport.Dialer.SocketReadBuffer,
		ConnExpiry:        5 * time.Minute,
		Level:             config.Transport.Dialer.Level,
	}

	for _, ip := range config.IPBlackList {
		md.IPBlackList.Set(ip, struct{}{}, time.Time{})
	}

	var tr http.RoundTripper

	t1 := &http.Transport{
		Dial:                  md.Dial,
		DialTLS:               md.DialTLS,
		DisableKeepAlives:     config.Transport.DisableKeepAlives,
		DisableCompression:    config.Transport.DisableCompression,
		ResponseHeaderTimeout: time.Duration(config.Transport.ResponseHeaderTimeout) * time.Second,
		IdleConnTimeout:       time.Duration(config.Transport.IdleConnTimeout) * time.Second,
		MaxIdleConnsPerHost:   config.Transport.MaxIdleConnsPerHost,
	}

	if config.Transport.Proxy.Enabled {
		fixedURL, err := url.Parse(config.Transport.Proxy.URL)
		if err != nil {
			glog.Fatalf("url.Parse(%#v) error: %s", config.Transport.Proxy.URL, err)
		}

		dialer, err := proxy.FromURL(fixedURL, d, &dialer.MultiResolver{md})
		if err != nil {
			glog.Fatalf("proxy.FromURL(%#v) error: %s", fixedURL.String(), err)
		}

		t1.Dial = dialer.Dial
		t1.DialTLS = nil
		t1.Proxy = nil
		t1.TLSClientConfig = md.GoogleTLSConfig
	}

	switch {
	case config.DisableHTTP2 && config.ForceHTTP2:
		glog.Fatalf("GAE: DisableHTTP2=%v and ForceHTTP2=%v is conflict!", config.DisableHTTP2, config.ForceHTTP2)
	case config.Transport.Proxy.Enabled && config.ForceHTTP2:
		glog.Fatalf("GAE: Proxy.Enabled=%v and ForceHTTP2=%v is conflict!", config.Transport.Proxy.Enabled, config.ForceHTTP2)
	case config.ForceHTTP2:
		tr = &http2.Transport{
			DialTLS:            md.DialTLS2,
			TLSClientConfig:    md.GoogleTLSConfig,
			DisableCompression: config.Transport.DisableCompression,
		}
	case !config.DisableHTTP2:
		err := http2.ConfigureTransport(t1)
		if err != nil {
			glog.Warningf("GAE: Error enabling Transport HTTP/2 support: %v", err)
		}
		tr = t1
	default:
		tr = t1
	}

	forceHTTPSMatcherStrings := make([]string, 0)
	for key, value := range config.SiteToAlias {
		if strings.HasPrefix(value, "google_") {
			forceHTTPSMatcherStrings = append(forceHTTPSMatcherStrings, key)
		}
	}

	forceGAEStrings := make([]string, 0)
	forceGAESuffixs := make([]string, 0)
	forceGAEMatcherStrings := make([]string, 0)
	for _, s := range config.ForceGAE {
		if strings.Contains(s, "/") {
			if strings.HasSuffix(s, "$") {
				forceGAESuffixs = append(forceGAESuffixs, strings.TrimRight(s, "$"))
			} else {
				forceGAEStrings = append(forceGAEStrings, s)
			}
		} else {
			forceGAEMatcherStrings = append(forceGAEMatcherStrings, s)
		}
	}

	if config.EnableDeadProbe && !config.Transport.Proxy.Enabled {
		go func() {
			probe := func() {
				req, _ := http.NewRequest(http.MethodGet, "https://clients3.google.com/generate_204", nil)
				ctx, cancel := context.WithTimeout(req.Context(), 3*time.Second)
				defer cancel()
				req = req.WithContext(ctx)
				resp, err := tr.RoundTrip(req)
				if resp != nil && resp.Body != nil {
					glog.V(3).Infof("GAE EnableDeadProbe \"%s %s\" %d -", req.Method, req.URL.String(), resp.StatusCode)
					resp.Body.Close()
				}
				if err != nil {
					glog.V(2).Infof("GAE EnableDeadProbe \"%s %s\" error: %v", req.Method, req.URL.String(), err)
					s := strings.ToLower(err.Error())
					if strings.HasPrefix(s, "net/http: request canceled") || strings.Contains(s, "timeout") {
						helpers.TryCloseConnections(tr)
					}
				}
			}

			for {
				time.Sleep(time.Duration(5+rand.Intn(6)) * time.Second)
				probe()
			}
		}()
	}

	helpers.ShuffleStrings(config.AppIDs)

	f := &Filter{
		Config: *config,
		GAETransport: &Transport{
			RoundTripper: tr,
			MultiDialer:  md,
			Servers: NewServers(config.AppIDs,
				config.Password,
				config.SSLVerify,
				time.Duration(config.Transport.ResponseHeaderTimeout-4)*time.Second),
			RetryDelay: time.Duration(config.Transport.RetryDelay*1000) * time.Second,
			RetryTimes: config.Transport.RetryTimes,
		},
		DirectTransport:     tr,
		ForceHTTPSMatcher:   helpers.NewHostMatcher(forceHTTPSMatcherStrings),
		ForceGAEMatcher:     helpers.NewHostMatcher(forceGAEMatcherStrings),
		ForceGAEStrings:     forceGAEStrings,
		ForceGAESuffixs:     forceGAESuffixs,
		ForceDeflateMatcher: helpers.NewHostMatcher(config.ForceDeflate),
		FakeOptionsMatcher:  helpers.NewHostMatcherWithStrings(config.FakeOptions),
		SiteMatcher:         helpers.NewHostMatcher(config.Sites),
		DirectSiteMatcher:   helpers.NewHostMatcherWithString(config.Site2Alias),
	}

	if config.Transport.Proxy.Enabled {
		f.GAETransport.MultiDialer = nil
	}

	return f, nil
}
示例#27
0
func NewFilter(config *Config) (filters.Filter, error) {
	d := &Dialer{}
	d.Timeout = time.Duration(config.Dialer.Timeout) * time.Second
	d.KeepAlive = time.Duration(config.Dialer.KeepAlive) * time.Second
	d.Blacklist = make(map[string]struct{})

	d.Window = config.Dialer.Window

	d.Blacklist["127.0.0.1"] = struct{}{}
	d.Blacklist["::1"] = struct{}{}
	if addrs, err := net.InterfaceAddrs(); err == nil {
		for _, addr := range addrs {
			switch addr.Network() {
			case "ip":
				d.Blacklist[addr.String()] = struct{}{}
			}
		}
	}

	var err error

	d.hosts = httpproxy.NewHostMatcherWithString(config.Hosts)

	d.iplist, err = NewIplist(config.Iplist, config.DNS.Servers, config.DNS.Blacklist, d.DualStack)
	if err != nil {
		return nil, err
	}

	d.TLSConfig = &tls.Config{
		InsecureSkipVerify: true,
		ClientSessionCache: tls.NewLRUClientSessionCache(1000),
	}

	d.connTCPDuration = lrucache.NewMultiLRUCache(4, 4096)
	d.connTLSDuration = lrucache.NewMultiLRUCache(4, 4096)
	d.connExpireDuration = 5 * time.Minute

	for _, name := range config.DNS.Expand {
		if _, ok := config.Iplist[name]; ok {
			go func(name string) {
				t := time.Tick(3 * time.Minute)
				for {
					select {
					case <-t:
						d.iplist.ExpandList(name)
					}
				}
			}(name)
		}
	}

	return &Filter{
		transport: &http.Transport{
			Dial:                d.Dial,
			DialTLS:             d.DialTLS,
			DisableKeepAlives:   config.Transport.DisableKeepAlives,
			DisableCompression:  config.Transport.DisableCompression,
			TLSHandshakeTimeout: time.Duration(config.Transport.TLSHandshakeTimeout) * time.Second,
			MaxIdleConnsPerHost: config.Transport.MaxIdleConnsPerHost,
		},
		dialer: d,
	}, nil
}
示例#28
0
文件: main.go 项目: carriercomm/puro
func main() {
	// Parse the flags
	flag.Parse()

	// Normalize the etcd path
	if (*etcdPath)[0] != '/' {
		*etcdPath = "/" + *etcdPath
	}
	if (*etcdPath)[len(*etcdPath)-1] == '/' {
		*etcdPath = (*etcdPath)[:len(*etcdPath)-2]
	}

	// Transform etcdAddress into addresses
	addresses := strings.Split(*etcdAddress, ",")
	etcc = etcd.NewClient(addresses)

	// Set up a new logger
	log = logrus.New()

	// Set the formatter depending on the passed flag's value
	if *logFormatterType == "text" {
		log.Formatter = &logrus.TextFormatter{
			ForceColors: *logForceColors,
		}
	} else if *logFormatterType == "json" {
		log.Formatter = &logrus.JSONFormatter{}
	}

	// Create a new TLS config
	tlsConfig = &tls.Config{
		Certificates: certs,
		MinVersion:   tls.VersionTLS10,
		MaxVersion:   tls.VersionTLS12,
		CipherSuites: []uint16{
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256,
			tls.TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA,
			tls.TLS_ECDHE_ECDSA_WITH_AES_256_CBC_SHA,
			tls.TLS_ECDHE_ECDSA_WITH_AES_128_CBC_SHA,
			tls.TLS_RSA_WITH_AES_256_CBC_SHA,
			tls.TLS_RSA_WITH_AES_128_CBC_SHA,
		},
		PreferServerCipherSuites: true,
		ClientSessionCache:       tls.NewLRUClientSessionCache(*sessionCacheSize),
	}
	tlsConfig.BuildNameToCertificate()

	// Load the settings
	loadSettings()

	// Start the HTTPS server
	go func() {
		conn, err := net.Listen("tcp", *tlsBind)
		if err != nil {
			log.WithFields(logrus.Fields{
				"error":   err.Error(),
				"address": *tlsBind,
			}).Fatal("Unable to prepare a listener for the HTTPS server")
		}

		listener := tls.NewListener(conn, tlsConfig)

		server := &http.Server{
			Handler: http.HandlerFunc(handler),
		}

		err = server.Serve(listener)
		if err != nil {
			log.WithFields(logrus.Fields{
				"error": err.Error(),
			}).Fatal("Error while serving a HTTPS listener")
		}
	}()

	// Start the HTTP server
	go func() {
		err := http.ListenAndServe(*rawBind, http.HandlerFunc(handler))
		if err != nil {
			log.WithFields(logrus.Fields{
				"error":   err.Error(),
				"address": *rawBind,
			}).Fatal("Unable to bind the HTTP server")
		}
	}()

	// Watch for changes in etcd
	receiver := make(chan *etcd.Response)
	stop := make(chan bool)

	go func() {
		for {
			// Wait for a change
			<-receiver

			// Log debug information
			log.Info("Reloading settings")

			// Reload the settings
			loadSettings()
		}
	}()

	_, err := etcc.Watch(*etcdPath, 0, true, receiver, stop)
	if err != nil {
		log.WithFields(logrus.Fields{
			"error": err.Error(),
		}).Fatal("etcd watcher errored")
	}
}
示例#29
0
		host, projectId, key,
	)
}

type filter func(*Notice) *Notice

var httpClient = &http.Client{
	Transport: &http.Transport{
		Proxy: http.ProxyFromEnvironment,
		Dial: (&net.Dialer{
			Timeout:   15 * time.Second,
			KeepAlive: 30 * time.Second,
		}).Dial,
		TLSHandshakeTimeout: 10 * time.Second,
		TLSClientConfig: &tls.Config{
			ClientSessionCache: tls.NewLRUClientSessionCache(1024),
		},
		MaxIdleConnsPerHost:   10,
		ResponseHeaderTimeout: 10 * time.Second,
	},
	Timeout: 10 * time.Second,
}

type Notifier struct {
	projectId       int64
	projectKey      string
	createNoticeURL string

	Client *http.Client

	context map[string]string
示例#30
0
			n = defaultReadBufferSize
		}
		return bufio.NewReaderSize(conn, n)
	}
	br := v.(*bufio.Reader)
	br.Reset(conn)
	return br
}

func (c *HostClient) releaseReader(br *bufio.Reader) {
	c.readerPool.Put(br)
}

var defaultTLSConfig = &tls.Config{
	InsecureSkipVerify: true,
	ClientSessionCache: tls.NewLRUClientSessionCache(0),
}

func (c *HostClient) nextAddr() string {
	c.addrsLock.Lock()
	if c.addrs == nil {
		c.addrs = strings.Split(c.Addr, ",")
	}
	addr := c.addrs[0]
	if len(c.addrs) > 1 {
		addr = c.addrs[c.addrIdx%uint32(len(c.addrs))]
		c.addrIdx++
	}
	c.addrsLock.Unlock()
	return addr
}