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 }
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 }
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 }
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 }
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) } d0 := &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, } d := &helpers.Dialer{ Dialer: d0, Resolver: &helpers.Resolver{ LRUCache: lrucache.NewLRUCache(config.Transport.Dialer.DNSCacheSize), DNSExpiry: time.Duration(config.Transport.Dialer.DNSCacheExpiry) * time.Second, }, Level: 2, } for _, server := range servers { if server.Host != "" { d.Resolver.LRUCache.Set(server.URL.Hostname(), server.Host, 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 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) } switch fixedURL.Scheme { case "http", "https": tr.Proxy = http.ProxyURL(fixedURL) tr.Dial = nil tr.DialTLS = nil default: dialer, err := proxy.FromURL(fixedURL, d, nil) if err != nil { glog.Fatalf("proxy.FromURL(%#v) error: %s", fixedURL.String(), err) } tr.Dial = dialer.Dial tr.DialTLS = nil tr.Proxy = nil } } 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, }, }, nil }
func NewFilter(config *Config) (_ filters.Filter, err error) { var gfwlist GFWList gfwlist.Encoding = config.GFWList.Encoding gfwlist.Filename = config.GFWList.File gfwlist.Expiry = time.Duration(config.GFWList.Expiry) * time.Second gfwlist.Duration = time.Duration(config.GFWList.Duration) * time.Second gfwlist.URL, err = url.Parse(config.GFWList.URL) if err != nil { return nil, err } store := storage.LookupStoreByConfig(filterName) if err != nil { return nil, err } if _, err := store.Head(gfwlist.Filename); err != nil { return nil, err } transport := &http.Transport{} f := &Filter{ Config: *config, Store: store, IndexFilesEnabled: config.IndexFiles.Enabled, IndexFiles: make(map[string]struct{}), ProxyPacCache: lrucache.NewLRUCache(32), GFWListEnabled: config.GFWList.Enabled, GFWList: &gfwlist, Transport: transport, SiteFiltersEnabled: config.SiteFilters.Enabled, RegionFiltersEnabled: config.RegionFilters.Enabled, } for _, name := range config.IndexFiles.Files { f.IndexFiles[name] = struct{}{} } if f.SiteFiltersEnabled { fm := make(map[string]interface{}) for host, name := range config.SiteFilters.Rules { f, err := filters.GetFilter(name) if err != nil { glog.Fatalf("AUTOPROXY: filters.GetFilter(%#v) for %#v error: %v", name, host, err) } if _, ok := f.(filters.RoundTripFilter); !ok { glog.Fatalf("AUTOPROXY: filters.GetFilter(%#v) return %T, not a RoundTripFilter", name, f) } fm[host] = f } f.SiteFiltersRules = helpers.NewHostMatcherWithValue(fm) } if f.RegionFiltersEnabled { resp, err := store.Get(f.Config.RegionFilters.DataFile, -1, -1) if err != nil { glog.Fatalf("AUTOPROXY: store.Get(%#v) error: %v", f.Config.RegionFilters.DataFile, err) } defer resp.Body.Close() data, err := ioutil.ReadAll(resp.Body) if err != nil { glog.Fatalf("AUTOPROXY: ioutil.ReadAll(%#v) error: %v", resp.Body, err) } f.RegionLocator = ip17mon.NewLocatorWithData(data) fm := make(map[string]filters.RoundTripFilter) for region, name := range config.RegionFilters.Rules { if name == "" { continue } f, err := filters.GetFilter(name) if err != nil { glog.Fatalf("AUTOPROXY: filters.GetFilter(%#v) for %#v error: %v", name, region, err) } f1, ok := f.(filters.RoundTripFilter) if !ok { glog.Fatalf("AUTOPROXY: filters.GetFilter(%#v) return %T, not a RoundTripFilter", name, f) } fm[strings.ToLower(region)] = f1 } f.RegionFiltersRules = fm f.RegionFilterCache = lrucache.NewLRUCache(uint(f.Config.RegionFilters.DNSCacheSize)) } if f.GFWListEnabled { go onceUpdater.Do(f.pacUpdater) } return f, nil }
func makeLRUCache(capacity uint64) lrucache.Cache { return lrucache.NewLRUCache(uint(capacity)) }
func NewFilter(config *Config) (filters.Filter, error) { d := &helpers.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, }, Resolver: &helpers.Resolver{ LRUCache: lrucache.NewLRUCache(config.Transport.Dialer.DNSCacheSize), DNSExpiry: time.Duration(config.Transport.Dialer.DNSCacheExpiry) * time.Second, BlackList: lrucache.NewLRUCache(1024), }, } if ips, err := helpers.LocalIPv4s(); err == nil { for _, ip := range ips { d.Resolver.BlackList.Set(ip.String(), struct{}{}, time.Time{}) } for _, s := range []string{"127.0.0.1", "::1"} { d.Resolver.BlackList.Set(s, struct{}{}, time.Time{}) } } 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, } 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) } switch fixedURL.Scheme { case "http", "https": tr.Proxy = http.ProxyURL(fixedURL) tr.Dial = nil tr.DialTLS = nil default: dialer, err := proxy.FromURL(fixedURL, d, nil) if err != nil { glog.Fatalf("proxy.FromURL(%#v) error: %s", fixedURL.String(), err) } tr.Dial = dialer.Dial tr.DialTLS = nil tr.Proxy = nil } } return &Filter{ Config: *config, transport: tr, }, nil }