func forward(lconn net.Conn, raddr string) { if err := exec.Command("wakeonlan", "18:66:DA:17:A2:95").Run(); err != nil { glog.Warningf("exec wakeonlan error: %+v", err) } glog.Infof("try connect to %+v for %+v forwarding", raddr, lconn.RemoteAddr()) rconn, err := net.Dial("tcp", raddr) if err != nil { glog.Errorf("net.Dial(%#v) error: %v", raddr, err) return } glog.Infof("forward %+v to %+v", lconn.RemoteAddr(), rconn.RemoteAddr()) go func() { buf := bufpool.Get().([]byte) defer bufpool.Put(buf) defer rconn.Close() defer lconn.Close() io.CopyBuffer(rconn, lconn, buf) }() go func() { buf := bufpool.Get().([]byte) defer bufpool.Put(buf) defer lconn.Close() defer rconn.Close() io.CopyBuffer(lconn, rconn, buf) }() }
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 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 (f *Filter) updater() { glog.V(2).Infof("start updater for %+v, expiry=%s, duration=%s", f.GFWList.URL.String(), f.GFWList.Expiry, f.GFWList.Duration) ticker := time.Tick(f.GFWList.Duration) for { select { case <-ticker: glog.V(2).Infof("Begin auto gfwlist(%#v) update...", f.GFWList.URL.String()) h, err := f.Store.HeadObject(f.GFWList.Filename) if err != nil { glog.Warningf("stat gfwlist(%#v) err: %v", f.GFWList.Filename, err) continue } lm := h.Get("Last-Modified") if lm == "" { glog.Warningf("gfwlist(%#v) header(%#v) does not contains last-modified", f.GFWList.Filename, h) continue } modTime, err := time.Parse(f.Store.DateFormat(), lm) if err != nil { glog.Warningf("stat gfwlist(%#v) has parse %#v error: %v", f.GFWList.Filename, lm, err) continue } if time.Now().Sub(modTime) < f.GFWList.Expiry { continue } } glog.Infof("Downloading %#v", f.GFWList.URL.String()) req, err := http.NewRequest(http.MethodGet, f.GFWList.URL.String(), nil) if err != nil { glog.Warningf("NewRequest(%#v) error: %v", f.GFWList.URL.String(), err) continue } resp, err := f.Transport.RoundTrip(req) if err != nil { glog.Warningf("%T.RoundTrip(%#v) error: %v", f.Transport, f.GFWList.URL.String(), err.Error()) continue } var r io.Reader = resp.Body switch f.GFWList.Encoding { case "base64": r = base64.NewDecoder(base64.StdEncoding, r) default: break } data, err := ioutil.ReadAll(r) if err != nil { glog.Warningf("ioutil.ReadAll(%T) error: %v", r, err) resp.Body.Close() continue } err = f.Store.DeleteObject(f.GFWList.Filename) if err != nil { glog.Warningf("%T.DeleteObject(%#v) error: %v", f.Store, f.GFWList.Filename, err) continue } err = f.Store.PutObject(f.GFWList.Filename, http.Header{}, ioutil.NopCloser(bytes.NewReader(data))) if err != nil { glog.Warningf("%T.PutObject(%#v) error: %v", f.Store, f.GFWList.Filename, err) continue } glog.Infof("Update %#v from %#v OK", f.GFWList.Filename, f.GFWList.URL.String()) resp.Body.Close() } }
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 (h Handler) ServeHTTP(rw http.ResponseWriter, req *http.Request) { var err error remoteAddr := req.RemoteAddr // Prepare filter.Context ctx := filters.NewContext(req.Context(), h, h.Listener, rw, h.Branding) req = req.WithContext(ctx) // Enable transport http proxy if req.Method != "CONNECT" && !req.URL.IsAbs() { if req.URL.Scheme == "" { if req.TLS != nil && req.ProtoMajor == 1 { req.URL.Scheme = "https" } else { req.URL.Scheme = "http" } } if req.TLS != nil { if req.Host == "" { if req.URL.Host != "" { req.Host = req.URL.Host } else { req.Host = req.TLS.ServerName } } if req.URL.Host == "" { if req.Host != "" { req.URL.Host = req.Host } else { req.URL.Host = req.TLS.ServerName } } } } // Filter Request for _, f := range h.RequestFilters { ctx, req, err = f.Request(ctx, req) if req == filters.DummyRequest { return } if err != nil { if err != io.EOF { glog.Errorf("%s Filter Request %T error: %+v", remoteAddr, f, err) } return } // Update context for request req = req.WithContext(ctx) } if req.Body != nil { defer req.Body.Close() } // Filter Request -> Response var resp *http.Response for _, f := range h.RoundTripFilters { ctx, resp, err = f.RoundTrip(ctx, req) if resp == filters.DummyResponse { return } // Unexcepted errors if err != nil { filters.SetRoundTripFilter(ctx, f) glog.Errorf("%s Filter RoundTrip %T error: %+v", remoteAddr, f, err) http.Error(rw, h.FormatError(ctx, err), http.StatusBadGateway) return } // Update context for request req = req.WithContext(ctx) // A roundtrip filter give a response if resp != nil { resp.Request = req filters.SetRoundTripFilter(ctx, f) break } } // Filter Response for _, f := range h.ResponseFilters { if resp == nil || resp == filters.DummyResponse { return } ctx, resp, err = f.Response(ctx, resp) if err != nil { glog.Errorln("%s Filter %T Response error: %+v", remoteAddr, f, err) http.Error(rw, h.FormatError(ctx, err), http.StatusBadGateway) return } // Update context for request req = req.WithContext(ctx) } if resp == nil { glog.Errorln("%s Handler %#v Response empty response", remoteAddr, h) http.Error(rw, h.FormatError(ctx, fmt.Errorf("empty response")), http.StatusBadGateway) return } if resp.Header.Get("Content-Length") == "" && resp.ContentLength >= 0 { resp.Header.Set("Content-Length", strconv.FormatInt(resp.ContentLength, 10)) } for key, values := range resp.Header { for _, value := range values { rw.Header().Add(key, value) } } rw.WriteHeader(resp.StatusCode) if resp.Body != nil { defer resp.Body.Close() n, err := helpers.IOCopy(rw, resp.Body) if err != nil { if isClosedConnError(err) { glog.Infof("IOCopy %#v return %#v %T(%v)", resp.Body, n, err, err) } else { glog.Warningf("IOCopy %#v return %#v %T(%v)", resp.Body, n, err, err) } } } }
func NewRootCA(name string, vaildFor time.Duration, rsaBits int, certDir string, portable bool) (*RootCA, error) { keyFile := name + ".key" certFile := name + ".crt" if portable { rootdir := filepath.Dir(os.Args[0]) keyFile = filepath.Join(rootdir, keyFile) certFile = filepath.Join(rootdir, certFile) certDir = filepath.Join(rootdir, certDir) } rootCA := &RootCA{ name: name, keyFile: keyFile, certFile: certFile, rsaBits: rsaBits, certDir: certDir, mu: new(sync.Mutex), } if _, err := os.Stat(certFile); os.IsNotExist(err) { glog.Infof("Generating RootCA for %s", certFile) template := x509.Certificate{ IsCA: true, SerialNumber: big.NewInt(1), Subject: pkix.Name{ CommonName: name, Organization: []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, } 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)} if err = ioutil.WriteFile(keyFile, pem.EncodeToMemory(keypem), 0755); err != nil { return nil, err } certpem := &pem.Block{Type: "CERTIFICATE", Bytes: rootCA.derBytes} if err = ioutil.WriteFile(certFile, pem.EncodeToMemory(certpem), 0755); err != nil { return nil, err } } else { data, err := ioutil.ReadFile(keyFile) if err != nil { return nil, err } var b *pem.Block for { b, data = pem.Decode(data) if b == nil { break } if b.Type == "CERTIFICATE" { rootCA.derBytes = b.Bytes ca, err := x509.ParseCertificate(rootCA.derBytes) if err != nil { return nil, err } rootCA.ca = ca } else if b.Type == "PRIVATE KEY" { priv, err := x509.ParsePKCS1PrivateKey(b.Bytes) if err != nil { return nil, err } rootCA.priv = priv } } data, err = ioutil.ReadFile(certFile) if err != nil { return nil, err } for { b, data = pem.Decode(data) if b == nil { break } if b.Type == "CERTIFICATE" { rootCA.derBytes = b.Bytes ca, err := x509.ParseCertificate(rootCA.derBytes) if err != nil { return nil, err } rootCA.ca = ca } else if b.Type == "PRIVATE 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 fis, err := ioutil.ReadDir(certDir); err == nil { for _, fi := range fis { if err = os.Remove(certDir + "/" + fi.Name()); err != nil { glog.Errorf("Remove(%#v) error: %v", fi.Name(), err) } } } } } if _, err := os.Stat(certDir); os.IsNotExist(err) { if err = os.Mkdir(certDir, 0755); err != nil { return nil, err } } return rootCA, nil }