diff --git a/conf/clients.json b/conf/clients.json index f053c14..e69de29 100644 --- a/conf/clients.json +++ b/conf/clients.json @@ -1,4 +0,0 @@ -{"Cnf":{"U":"","P":"","Compress":false,"Crypt":false},"Id":4,"VerifyKey":"6h7x7tjvkocgltep","Addr":"","Remark":"","Status":true,"IsConnect":false,"RateLimit":0,"Flow":{"ExportFlow":0,"InletFlow":0,"FlowLimit":0},"Rate":{"NowRate":0},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":0,"WebUserName":"admin22","WebPassword":"123","ConfigConnAllow":false,"MaxTunnelNum":0} -*#*{"Cnf":{"U":"","P":"","Compress":false,"Crypt":false},"Id":6,"VerifyKey":"xf3nwghskyw4e7g4","Addr":"","Remark":"","Status":true,"IsConnect":false,"RateLimit":0,"Flow":{"ExportFlow":0,"InletFlow":0,"FlowLimit":0},"Rate":{"NowRate":0},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":0,"WebUserName":"admin3","WebPassword":"123","ConfigConnAllow":false,"MaxTunnelNum":0} -*#*{"Cnf":{"U":"","P":"","Compress":false,"Crypt":false},"Id":2,"VerifyKey":"06j3twjj9vjy2kdg","Addr":"","Remark":"","Status":true,"IsConnect":false,"RateLimit":0,"Flow":{"ExportFlow":2298489,"InletFlow":92324,"FlowLimit":0},"Rate":{"NowRate":0},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":0,"WebUserName":"admin55","WebPassword":"123","ConfigConnAllow":false,"MaxTunnelNum":0} -*#* \ No newline at end of file diff --git a/conf/hosts.json b/conf/hosts.json index fb2faba..e69de29 100644 --- a/conf/hosts.json +++ b/conf/hosts.json @@ -1,2 +0,0 @@ -{"Id":1,"Host":"a.o.com","HeaderChange":"","HostChange":"","Location":"/","Remark":"","Scheme":"all","CertFilePath":"","KeyFilePath":"","NoStore":false,"IsClose":false,"Flow":{"ExportFlow":2298489,"InletFlow":92303,"FlowLimit":0},"Client":{"Cnf":{"U":"","P":"","Compress":false,"Crypt":false},"Id":2,"VerifyKey":"06j3twjj9vjy2kdg","Addr":"127.0.0.1","Remark":"","Status":true,"IsConnect":true,"RateLimit":0,"Flow":{"ExportFlow":2298489,"InletFlow":92324,"FlowLimit":0},"Rate":{"NowRate":0},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":4,"WebUserName":"admin2","WebPassword":"123","ConfigConnAllow":false,"MaxTunnelNum":0},"Target":{"TargetStr":"127.0.0.1:8082","TargetArr":null,"LocalProxy":false}} -*#* \ No newline at end of file diff --git a/conf/npc.conf b/conf/npc.conf index ec6c28e..d4a31a8 100644 --- a/conf/npc.conf +++ b/conf/npc.conf @@ -1,5 +1,5 @@ [common] -server_addr=123.206.77.88:8024 +server_addr=127.0.0.1:8024 conn_type=tcp vkey=123 auto_reconnection=true diff --git a/conf/nps.conf b/conf/nps.conf index ae9c920..3d0828e 100755 --- a/conf/nps.conf +++ b/conf/nps.conf @@ -64,7 +64,7 @@ allow_multi_ip=false system_info_display=false #cache -http_cache=true +http_cache=false http_cache_length=100 diff --git a/conf/tasks.json b/conf/tasks.json index 1274ac8..e69de29 100644 --- a/conf/tasks.json +++ b/conf/tasks.json @@ -1,3 +0,0 @@ -{"Id":1,"Port":0,"ServerIp":"","Mode":"p2p","Status":true,"RunStatus":true,"Client":{"Cnf":{"U":"","P":"","Compress":false,"Crypt":false},"Id":2,"VerifyKey":"06j3twjj9vjy2kdg","Addr":"127.0.0.1","Remark":"","Status":true,"IsConnect":true,"RateLimit":0,"Flow":{"ExportFlow":0,"InletFlow":0,"FlowLimit":0},"Rate":{"NowRate":0},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":1,"WebUserName":"admin2","WebPassword":"123","ConfigConnAllow":false,"MaxTunnelNum":0},"Ports":"","Flow":{"ExportFlow":0,"InletFlow":0,"FlowLimit":0},"Password":"p2ptest","Remark":"","TargetAddr":"","NoStore":false,"LocalPath":"","StripPre":"","Target":{"TargetStr":"","TargetArr":null,"LocalProxy":false},"HealthCheckTimeout":0,"HealthMaxFail":0,"HealthCheckInterval":0,"HealthNextTime":"0001-01-01T00:00:00Z","HealthMap":null,"HttpHealthUrl":"","HealthRemoveArr":null,"HealthCheckType":"","HealthCheckTarget":""} -*#*{"Id":2,"Port":0,"ServerIp":"","Mode":"secret","Status":true,"RunStatus":true,"Client":{"Cnf":{"U":"","P":"","Compress":false,"Crypt":false},"Id":2,"VerifyKey":"06j3twjj9vjy2kdg","Addr":"127.0.0.1","Remark":"","Status":true,"IsConnect":true,"RateLimit":0,"Flow":{"ExportFlow":0,"InletFlow":0,"FlowLimit":0},"Rate":{"NowRate":0},"NoStore":false,"NoDisplay":false,"MaxConn":0,"NowConn":1,"WebUserName":"admin2","WebPassword":"123","ConfigConnAllow":false,"MaxTunnelNum":0},"Ports":"","Flow":{"ExportFlow":0,"InletFlow":21,"FlowLimit":0},"Password":"secrettest","Remark":"","TargetAddr":"","NoStore":false,"LocalPath":"","StripPre":"","Target":{"TargetStr":"118.89.159.126:22","TargetArr":null,"LocalProxy":false},"HealthCheckTimeout":0,"HealthMaxFail":0,"HealthCheckInterval":0,"HealthNextTime":"0001-01-01T00:00:00Z","HealthMap":null,"HttpHealthUrl":"","HealthRemoveArr":null,"HealthCheckType":"","HealthCheckTarget":""} -*#* \ No newline at end of file diff --git a/lib/version/version.go b/lib/version/version.go index 84c0450..aa5cdd3 100644 --- a/lib/version/version.go +++ b/lib/version/version.go @@ -1,6 +1,6 @@ package version -const VERSION = "0.21.2" +const VERSION = "0.22.0" // Compulsory minimum version, Minimum downward compatibility to this version func GetVersion() string { diff --git a/server/proxy/base.go b/server/proxy/base.go index a0d648b..ba7568f 100644 --- a/server/proxy/base.go +++ b/server/proxy/base.go @@ -17,7 +17,7 @@ type Service interface { Close() error } -//Server BaseServer struct +//BaseServer struct type BaseServer struct { id int bridge *bridge.Bridge @@ -35,6 +35,7 @@ func NewBaseServer(bridge *bridge.Bridge, task *file.Tunnel) *BaseServer { } } +//add the flow func (s *BaseServer) FlowAdd(in, out int64) { s.Lock() defer s.Unlock() @@ -42,6 +43,7 @@ func (s *BaseServer) FlowAdd(in, out int64) { s.task.Flow.InletFlow += in } +//change the flow func (s *BaseServer) FlowAddHost(host *file.Host, in, out int64) { s.Lock() defer s.Unlock() @@ -49,12 +51,13 @@ func (s *BaseServer) FlowAddHost(host *file.Host, in, out int64) { host.Flow.InletFlow += in } +//write fail bytes to the connection func (s *BaseServer) writeConnFail(c net.Conn) { c.Write([]byte(common.ConnectionFailBytes)) c.Write(s.errorContent) } -//权限认证 +//auth check func (s *BaseServer) auth(r *http.Request, c *conn.Conn, u, p string) error { if u != "" && p != "" && !common.CheckAuth(r, u, p) { c.Write([]byte(common.UnauthorizedBytes)) @@ -64,6 +67,7 @@ func (s *BaseServer) auth(r *http.Request, c *conn.Conn, u, p string) error { return nil } +//check flow limit of the client ,and decrease the allow num of client func (s *BaseServer) CheckFlowAndConnNum(client *file.Client) error { if client.Flow.FlowLimit > 0 && (client.Flow.FlowLimit<<20) < (client.Flow.ExportFlow+client.Flow.InletFlow) { return errors.New("Traffic exceeded") @@ -74,7 +78,7 @@ func (s *BaseServer) CheckFlowAndConnNum(client *file.Client) error { return nil } -//与客户端建立通道 +//create a new connection and start bytes copying func (s *BaseServer) DealClient(c *conn.Conn, client *file.Client, addr string, rb []byte, tp string, f func(), flow *file.Flow, localProxy bool) error { link := conn.NewLink(tp, addr, client.Cnf.Crypt, client.Cnf.Compress, c.Conn.RemoteAddr().String(), localProxy) if target, err := s.bridge.SendLinkInfo(client.Id, link, s.task); err != nil { diff --git a/server/proxy/http.go b/server/proxy/http.go index 83a8b7e..b7743ab 100644 --- a/server/proxy/http.go +++ b/server/proxy/http.go @@ -123,6 +123,7 @@ func (s *httpServer) httpHandle(c *conn.Conn, r *http.Request) { lk *conn.Link targetAddr string readReq bool + reqCh = make(chan *http.Request) ) if host, err = file.GetDb().GetInfoByHost(r.Host, r); err != nil { logs.Notice("the url %s %s %s can't be parsed!", r.URL.Scheme, r.Host, r.RequestURI) @@ -156,28 +157,31 @@ func (s *httpServer) httpHandle(c *conn.Conn, r *http.Request) { go func() { defer connClient.Close() defer c.Close() - if resp, err := http.ReadResponse(bufio.NewReader(connClient), r); err != nil { - return - } else { - //if the cache is start and the response is in the extension,store the response to the cache list - if s.useCache && strings.Contains(r.URL.Path, ".") { - b, err := httputil.DumpResponse(resp, true) - if err != nil { - return - } - c.Write(b) - host.Flow.Add(0, int64(len(b))) - s.cache.Add(filepath.Join(host.Host, r.URL.Path), b) + for { + r := <-reqCh + if resp, err := http.ReadResponse(bufio.NewReader(connClient), r); err != nil { + return } else { - b, err := httputil.DumpResponse(resp, false) - if err != nil { - return - } - c.Write(b) - if bodyLen, err := common.CopyBuffer(c, resp.Body); err != nil { - return + //if the cache is start and the response is in the extension,store the response to the cache list + if s.useCache && strings.Contains(r.URL.Path, ".") { + b, err := httputil.DumpResponse(resp, true) + if err != nil { + return + } + c.Write(b) + host.Flow.Add(0, int64(len(b))) + s.cache.Add(filepath.Join(host.Host, r.URL.Path), b) } else { - host.Flow.Add(0, int64(len(b))+bodyLen) + b, err := httputil.DumpResponse(resp, false) + if err != nil { + return + } + c.Write(b) + if bodyLen, err := common.CopyBuffer(c, resp.Body); err != nil { + return + } else { + host.Flow.Add(0, int64(len(b))+bodyLen) + } } } } @@ -242,6 +246,7 @@ func (s *httpServer) httpHandle(c *conn.Conn, r *http.Request) { } else { host.Flow.Add(int64(len(b))+bodyLen, 0) } + reqCh <- r } end: if isConn { diff --git a/server/proxy/https.go b/server/proxy/https.go index 0da1f89..72f42e2 100644 --- a/server/proxy/https.go +++ b/server/proxy/https.go @@ -32,6 +32,7 @@ func NewHttpsServer(l net.Listener, bridge *bridge.Bridge, useCache bool, cacheL return https } +//start https server func (https *HttpsServer) Start() error { if b, err := beego.AppConfig.Bool("https_just_proxy"); err == nil && b { conn.Accept(https.listener, func(c net.Conn) { @@ -86,16 +87,19 @@ func (https *HttpsServer) Start() error { return nil } +// close func (https *HttpsServer) Close() error { return https.listener.Close() } +// new https server by cert and key file func (https *HttpsServer) NewHttps(l net.Listener, certFile string, keyFile string) { go func() { logs.Error(https.NewServer(0, "https").ServeTLS(l, certFile, keyFile)) }() } +//handle the https which is just proxy to other client func (https *HttpsServer) handleHttps(c net.Conn) { hostName, rb := GetServerNameFromClientHello(c) var targetAddr string @@ -129,10 +133,12 @@ type HttpsListener struct { parentListener net.Listener } +// https listener func NewHttpsListener(l net.Listener) *HttpsListener { return &HttpsListener{parentListener: l, acceptConn: make(chan *conn.Conn)} } +// accept func (httpsListener *HttpsListener) Accept() (net.Conn, error) { httpsConn := <-httpsListener.acceptConn if httpsConn == nil { @@ -141,14 +147,17 @@ func (httpsListener *HttpsListener) Accept() (net.Conn, error) { return httpsConn, nil } +// close func (httpsListener *HttpsListener) Close() error { return nil } +// addr func (httpsListener *HttpsListener) Addr() net.Addr { return httpsListener.parentListener.Addr() } +// get server name from connection by read client hello bytes func GetServerNameFromClientHello(c net.Conn) (string, []byte) { buf := make([]byte, 4096) data := make([]byte, 4096) @@ -162,6 +171,7 @@ func GetServerNameFromClientHello(c net.Conn) (string, []byte) { return clientHello.GetServerName(), buf[:n] } +// build https request func buildHttpsRequest(hostName string) *http.Request { r := new(http.Request) r.RequestURI = "/"