func getFilters(profile string) ([]filters.RequestFilter, []filters.RoundTripFilter, []filters.ResponseFilter) { config, ok := Config[profile] if !ok { panic(fmt.Errorf("profile(%#v) not exists", profile)) } fs := make(map[string]filters.Filter) for _, names := range [][]string{config.RequestFilters, config.RoundTripFilters, config.ResponseFilters} { for _, name := range names { if _, ok := fs[name]; !ok { f, err := filters.GetFilter(name) if err != nil { glog.Fatalf("filters.GetFilter(%#v) failed: %#v", name, err) } fs[name] = f } } } requestFilters := make([]filters.RequestFilter, 0) for _, name := range config.RequestFilters { f := fs[name] f1, ok := f.(filters.RequestFilter) if !ok { glog.Fatalf("%#v is not a RequestFilter", f) } requestFilters = append(requestFilters, f1) } roundtripFilters := make([]filters.RoundTripFilter, 0) for _, name := range config.RoundTripFilters { f := fs[name] f1, ok := f.(filters.RoundTripFilter) if !ok { glog.Fatalf("%#v is not a RoundTripFilter", f) } roundtripFilters = append(roundtripFilters, f1) } responseFilters := make([]filters.ResponseFilter, 0) for _, name := range config.ResponseFilters { f := fs[name] f1, ok := f.(filters.ResponseFilter) if !ok { glog.Fatalf("%#v is not a ResponseFilter", f) } responseFilters = append(responseFilters, f1) } return requestFilters, roundtripFilters, responseFilters }
func ServeProfile(profile string, branding string) error { config, ok := Config[profile] if !ok { return fmt.Errorf("profile(%#v) not exists", profile) } listenOpts := &helpers.ListenOptions{TLSConfig: nil} ln, err := helpers.ListenTCP("tcp", config.Address, listenOpts) if err != nil { glog.Fatalf("ListenTCP(%s, %#v) error: %s", config.Address, listenOpts, err) } requestFilters, roundtripFilters, responseFilters := getFilters(profile) h := Handler{ Listener: ln, RequestFilters: requestFilters, RoundTripFilters: roundtripFilters, ResponseFilters: responseFilters, Branding: branding, } s := &http.Server{ Handler: h, ReadTimeout: time.Duration(config.ReadTimeout) * time.Second, WriteTimeout: time.Duration(config.WriteTimeout) * time.Second, MaxHeaderBytes: 1 << 20, } glog.Infof("ListenAndServe(%#v) on %s\n", profile, h.Listener.Addr().String()) return s.Serve(h.Listener) }
func NewFilter(config *Config) (_ filters.Filter, err error) { onceCA.Do(func() { defaultCA, err = NewRootCA(config.RootCA.Name, time.Duration(config.RootCA.Duration)*time.Second, config.RootCA.RsaBits, config.RootCA.Dirname, config.RootCA.Portable) if err != nil { glog.Fatalf("NewRootCA(%#v) error: %v", config.RootCA.Name, err) } }) f := &Filter{ Config: *config, CA: defaultCA, CAExpiry: time.Duration(config.RootCA.Duration) * time.Second, TLSConfigCache: lrucache.NewMultiLRUCache(4, 4096), Ports: make(map[string]struct{}), Sites: helpers.NewHostMatcher(config.Sites), } for _, port := range config.Ports { f.Ports[strconv.Itoa(port)] = struct{}{} } return f, nil }
func init() { filename := filterName + ".json" config := new(Config) err := storage.ReadJsonConfig(storage.LookupConfigStoreURI(filterName), filename, config) if err != nil { glog.Fatalf("storage.ReadJsonConfig(%#v) failed: %s", filename, err) } err = filters.Register(filterName, &filters.RegisteredFilter{ New: func() (filters.Filter, error) { return NewFilter(config) }, }) if err != nil { glog.Fatalf("Register(%#v) error: %s", filterName, err) } }
func init() { filename := filterName + ".json" config := new(Config) err := storage.LookupStoreByConfig(filterName).UnmarshallJson(filename, config) if err != nil { glog.Fatalf("UnmarshallJson(%#v) failed: %s", filename, err) } err = filters.Register(filterName, &filters.RegisteredFilter{ New: func() (filters.Filter, error) { return NewFilter(config) }, }) if err != nil { glog.Fatalf("Register(%#v) error: %s", filterName, err) } }
func init() { filename := filterName + ".json" config := new(Config) err := storage.ReadJsonConfig(storage.LookupConfigStoreURI(filterName), filename, config) if err != nil { glog.Fatalf("storage.ReadJsonConfig(%#v) failed: %s", filename, err) } err = filters.Register(filterName, &filters.RegisteredFilter{ New: func() (filters.Filter, error) { return NewFilter(config) }, }) if err != nil { glog.Fatalf("Register(%#v) error: %s", filterName, err) } mime.AddExtensionType(".crt", "application/x-x509-user-cert") }
func init() { filename := filterName + ".json" config := new(Config) err := storage.LookupStoreByFilterName(filterName).UnmarshallJson(filename, config) if err != nil { glog.Fatalf("storage.ReadJsonConfig(%#v) failed: %s", filename, err) } err = filters.Register(filterName, &filters.RegisteredFilter{ New: func() (filters.Filter, error) { return NewFilter(config) }, }) if err != nil { glog.Fatalf("Register(%#v) error: %s", filterName, err) } mime.AddExtensionType(".crt", "application/x-x509-ca-cert") mime.AddExtensionType(".mobileconfig", "application/x-apple-aspen-config") }
func main() { var laddr, raddr string flag.StringVar(&laddr, "laddr", "0.0.0.0:13389", "local address") flag.StringVar(&raddr, "raddr", "192.168.1.3:3389", "remote address") flag.Parse() ln, err := net.Listen("tcp", laddr) if err != nil { glog.Fatalf("net.Listen(%+v) error: %+v", laddr, err) return } defer ln.Close() glog.Infof("Serving on %+v", ln.Addr()) for { conn, err := ln.Accept() if err != nil { glog.Fatalf("%+v Accept error: %+v", ln.Addr(), err) } go forward(conn, raddr) } }
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, err := storage.OpenURI(storage.LookupConfigStoreURI(filterName)) if err != nil { return nil, err } if _, err := store.HeadObject(gfwlist.Filename); err != nil { return nil, err } autoproxy2pac := &AutoProxy2Pac{ Sites: []string{"google.com"}, } object, err := store.GetObject(gfwlist.Filename, -1, -1) if err != nil { return nil, err } rc := object.Body() defer rc.Close() var r io.Reader br := bufio.NewReader(rc) if data, err := br.Peek(20); err == nil { if bytes.HasPrefix(data, []byte("[AutoProxy ")) { r = br } else { r = base64.NewDecoder(base64.StdEncoding, br) } } err = autoproxy2pac.Read(r) if err != nil { return nil, err } transport := &http.Transport{} f := &Filter{ Config: *config, Store: store, IndexFilesEnabled: config.IndexFiles.Enabled, IndexFiles: make(map[string]struct{}), GFWListEnabled: config.GFWList.Enabled, GFWList: &gfwlist, AutoProxy2Pac: autoproxy2pac, 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 { 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.RegionFiltersRules = helpers.NewHostMatcherWithValue(fm) } if f.GFWListEnabled { go onceUpdater.Do(f.updater) } return f, 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 NewRootCA(name string, vaildFor time.Duration, rsaBits int, certDir string, portable bool) (*RootCA, error) { keyFile := name + ".key" certFile := name + ".crt" var store storage.Store if portable { exe, err := os.Executable() if err != nil { glog.Fatalf("os.Executable() error: %+v", err) } store = &storage.FileStore{filepath.Dir(exe)} } else { store = &storage.FileStore{"."} } rootCA := &RootCA{ store: store, name: name, keyFile: keyFile, certFile: certFile, rsaBits: rsaBits, certDir: certDir, mu: new(sync.Mutex), } if storage.NotExist(store, certFile) { glog.Infof("Generating RootCA for %s/%s", keyFile, certFile) template := x509.Certificate{ IsCA: true, SerialNumber: big.NewInt(1), Subject: pkix.Name{ CommonName: name, Country: []string{"US"}, Province: []string{"California"}, Locality: []string{"Los Angeles"}, Organization: []string{name}, ExtraNames: []pkix.AttributeTypeAndValue{ { Type: []int{2, 5, 4, 42}, Value: name, }, }, }, DNSNames: []string{name}, NotBefore: time.Now().Add(-time.Duration(30 * 24 * time.Hour)), NotAfter: time.Now().Add(vaildFor), KeyUsage: x509.KeyUsageKeyEncipherment | x509.KeyUsageDigitalSignature | x509.KeyUsageCertSign, ExtKeyUsage: []x509.ExtKeyUsage{x509.ExtKeyUsageServerAuth, x509.ExtKeyUsageClientAuth}, BasicConstraintsValid: true, // AuthorityKeyId: sha1.New().Sum([]byte("phuslu")), // SubjectKeyId: sha1.New().Sum([]byte("phuslu")), } priv, err := rsa.GenerateKey(rand.Reader, rsaBits) if err != nil { return nil, err } derBytes, err := x509.CreateCertificate(rand.Reader, &template, &template, &priv.PublicKey, priv) if err != nil { return nil, err } ca, err := x509.ParseCertificate(derBytes) if err != nil { return nil, err } rootCA.ca = ca rootCA.priv = priv rootCA.derBytes = derBytes keypem := &pem.Block{Type: "PRIVATE KEY", Bytes: x509.MarshalPKCS1PrivateKey(rootCA.priv)} rc := ioutil.NopCloser(bytes.NewReader(pem.EncodeToMemory(keypem))) if _, err = store.Put(keyFile, http.Header{}, rc); err != nil { return nil, err } certpem := &pem.Block{Type: "CERTIFICATE", Bytes: rootCA.derBytes} rc = ioutil.NopCloser(bytes.NewReader(pem.EncodeToMemory(certpem))) if _, err = store.Put(certFile, http.Header{}, rc); err != nil { return nil, err } } else { for _, name := range []string{keyFile, certFile} { resp, err := store.Get(name) if err != nil { return nil, err } data, err := ioutil.ReadAll(resp.Body) resp.Body.Close() if err != nil { return nil, err } var b *pem.Block for { b, data = pem.Decode(data) if b == nil { break } switch b.Type { case "CERTIFICATE": rootCA.derBytes = b.Bytes ca, err := x509.ParseCertificate(rootCA.derBytes) if err != nil { return nil, err } rootCA.ca = ca case "PRIVATE KEY", "PRIVATE RSA KEY": priv, err := x509.ParsePKCS1PrivateKey(b.Bytes) if err != nil { return nil, err } rootCA.priv = priv } } } } switch runtime.GOOS { case "windows", "darwin": if _, err := rootCA.ca.Verify(x509.VerifyOptions{}); err != nil { glog.Warningf("Verify RootCA(%#v) error: %v, try import to system root", name, err) if err = helpers.RemoveCAFromSystemRoot(rootCA.name); err != nil { glog.Errorf("Remove Old RootCA(%#v) error: %v", name, err) } if err = helpers.ImportCAToSystemRoot(rootCA.ca); err != nil { glog.Errorf("Import RootCA(%#v) error: %v", name, err) } else { glog.Infof("Import RootCA(%s) OK", certFile) } if fs, err := store.List(certDir); err == nil { for _, f := range fs { if _, err = store.Delete(f); err != nil { glog.Errorf("%T.Delete(%#v) error: %v", store, f, err) } } } } } if fs, ok := store.(*storage.FileStore); ok { if storage.NotExist(store, certDir) { if err := os.Mkdir(filepath.Join(fs.Dirname, certDir), 0777); err != nil { return nil, err } } } return rootCA, 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 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 }