This commit is contained in:
刘河 2019-02-17 19:36:48 +08:00
parent 7a8cb3d5b6
commit 9f03c2f6eb
13 changed files with 183 additions and 65 deletions

View File

@ -22,19 +22,21 @@ import (
type Client struct { type Client struct {
tunnel *conn.Conn tunnel *conn.Conn
signal *conn.Conn signal *conn.Conn
msg *conn.Conn
linkMap map[int]*conn.Link linkMap map[int]*conn.Link
linkStatusMap map[int]bool linkStatusMap map[int]bool
stop chan bool stop chan bool
sync.RWMutex sync.RWMutex
} }
func NewClient(t *conn.Conn, s *conn.Conn) *Client { func NewClient(t *conn.Conn, s *conn.Conn, m *conn.Conn) *Client {
return &Client{ return &Client{
linkMap: make(map[int]*conn.Link), linkMap: make(map[int]*conn.Link),
stop: make(chan bool), stop: make(chan bool),
linkStatusMap: make(map[int]bool), linkStatusMap: make(map[int]bool),
signal: s, signal: s,
tunnel: t, tunnel: t,
msg: m,
} }
} }
@ -150,6 +152,17 @@ func (s *Bridge) closeClient(id int) {
delete(s.Client, id) delete(s.Client, id)
} }
} }
func (s *Bridge) delClient(id int) {
s.clientLock.Lock()
defer s.clientLock.Unlock()
if v, ok := s.Client[id]; ok {
if c, err := file.GetCsvDb().GetClient(id); err == nil && c.NoStore {
s.CloseClient <- c.Id
}
v.signal.Close()
delete(s.Client, id)
}
}
//tcp连接类型区分 //tcp连接类型区分
func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) { func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
@ -166,7 +179,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
v.signal = c v.signal = c
v.Unlock() v.Unlock()
} else { } else {
s.Client[id] = NewClient(nil, c) s.Client[id] = NewClient(nil, c, nil)
s.clientLock.Unlock() s.clientLock.Unlock()
} }
lg.Printf("clientId %d connection succeeded, address:%s ", id, c.Conn.RemoteAddr()) lg.Printf("clientId %d connection succeeded, address:%s ", id, c.Conn.RemoteAddr())
@ -179,7 +192,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
v.tunnel = c v.tunnel = c
v.Unlock() v.Unlock()
} else { } else {
s.Client[id] = NewClient(c, nil) s.Client[id] = NewClient(c, nil, nil)
s.clientLock.Unlock() s.clientLock.Unlock()
} }
go s.clientCopy(id) go s.clientCopy(id)
@ -187,11 +200,44 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
go s.GetConfig(c) go s.GetConfig(c)
case common.WORK_REGISTER: case common.WORK_REGISTER:
go s.register(c) go s.register(c)
case common.WORK_SEND_STATUS:
s.clientLock.Lock()
if v, ok := s.Client[id]; ok {
s.clientLock.Unlock()
v.Lock()
v.msg = c
v.Unlock()
} else {
s.Client[id] = NewClient(nil, nil, c)
s.clientLock.Unlock()
}
go s.getMsgStatus(id)
} }
c.SetAlive(s.tunnelType) c.SetAlive(s.tunnelType)
return return
} }
func (s *Bridge) getMsgStatus(clientId int) {
s.clientLock.Lock()
client := s.Client[clientId]
s.clientLock.Unlock()
if client == nil {
return
}
for {
if id, err := client.msg.GetLen(); err != nil {
s.closeClient(clientId)
return
} else {
client.Lock()
if v, ok := client.linkMap[id]; ok {
v.StatusCh <- true
}
client.Unlock()
}
}
}
func (s *Bridge) register(c *conn.Conn) { func (s *Bridge) register(c *conn.Conn) {
var hour int32 var hour int32
if err := binary.Read(c, binary.LittleEndian, &hour); err == nil { if err := binary.Read(c, binary.LittleEndian, &hour); err == nil {
@ -251,12 +297,14 @@ func (s *Bridge) SendLinkInfo(clientId int, link *conn.Link, linkAddr string) (t
s.DelClient(clientId) s.DelClient(clientId)
return return
} }
if v.tunnel == nil { if v.tunnel == nil {
err = errors.New("get tunnel connection error") err = errors.New("get tunnel connection error")
return return
} else { } else {
tunnel = v.tunnel tunnel = v.tunnel
} }
link.MsgConn = v.msg
v.Lock() v.Lock()
v.linkMap[link.Id] = link v.linkMap[link.Id] = link
v.Unlock() v.Unlock()
@ -412,7 +460,8 @@ func (s *Bridge) clientCopy(clientId int) {
for { for {
if id, err := client.tunnel.GetLen(); err != nil { if id, err := client.tunnel.GetLen(); err != nil {
s.closeClient(clientId) lg.Println("read msg content length error close client")
s.delClient(clientId)
break break
} else { } else {
client.Lock() client.Lock()
@ -420,23 +469,11 @@ func (s *Bridge) clientCopy(clientId int) {
client.Unlock() client.Unlock()
if content, err := client.tunnel.GetMsgContent(link); err != nil { if content, err := client.tunnel.GetMsgContent(link); err != nil {
pool.PutBufPoolCopy(content) pool.PutBufPoolCopy(content)
s.closeClient(clientId) s.delClient(clientId)
lg.Println("read msg content error", err, "close client") lg.Println("read msg content error", err, "close client")
break break
} else { } else {
if len(content) == len(common.IO_EOF) && string(content) == common.IO_EOF { link.MsgCh <- content
if link.Conn != nil {
link.Conn.Close()
}
} else {
if link.UdpListener != nil && link.UdpRemoteAddr != nil {
link.UdpListener.WriteToUDP(content, link.UdpRemoteAddr)
} else {
link.Conn.Write(content)
}
link.Flow.Add(0, len(content))
}
pool.PutBufPoolCopy(content)
} }
} else { } else {
client.Unlock() client.Unlock()

View File

@ -21,6 +21,7 @@ type TRPClient struct {
svrAddr string svrAddr string
linkMap map[int]*conn.Link linkMap map[int]*conn.Link
tunnel *conn.Conn tunnel *conn.Conn
msgTunnel *conn.Conn
bridgeConnType string bridgeConnType string
stop chan bool stop chan bool
proxyUrl string proxyUrl string
@ -67,6 +68,7 @@ func (s *TRPClient) Close() {
//处理 //处理
func (s *TRPClient) processor(c *conn.Conn) { func (s *TRPClient) processor(c *conn.Conn) {
go s.dealChan() go s.dealChan()
go s.getMsgStatus()
for { for {
flags, err := c.ReadFlag() flags, err := c.ReadFlag()
if err != nil { if err != nil {
@ -83,7 +85,9 @@ func (s *TRPClient) processor(c *conn.Conn) {
s.Lock() s.Lock()
s.linkMap[link.Id] = link s.linkMap[link.Id] = link
s.Unlock() s.Unlock()
link.MsgConn = s.msgTunnel
go s.linkProcess(link, c) go s.linkProcess(link, c)
link.Run(false)
} }
case common.RES_CLOSE: case common.RES_CLOSE:
lg.Fatalln("The authentication key is connected by another client or the server closes the client.") lg.Fatalln("The authentication key is connected by another client or the server closes the client.")
@ -109,9 +113,7 @@ func (s *TRPClient) linkProcess(link *conn.Link, c *conn.Conn) {
lg.Println("connect to ", link.Host, "error:", err) lg.Println("connect to ", link.Host, "error:", err)
return return
} }
c.WriteSuccess(link.Id) c.WriteSuccess(link.Id)
link.Conn = conn.NewConn(server) link.Conn = conn.NewConn(server)
buf := pool.BufPoolCopy.Get().([]byte) buf := pool.BufPoolCopy.Get().([]byte)
for { for {
@ -123,8 +125,11 @@ func (s *TRPClient) linkProcess(link *conn.Link, c *conn.Conn) {
c.Close() c.Close()
break break
} }
lg.Println("send ok", link.Id) if link.ConnType == common.CONN_UDP {
break
}
} }
<-link.StatusCh
} }
pool.PutBufPoolCopy(buf) pool.PutBufPoolCopy(buf)
s.Lock() s.Lock()
@ -132,6 +137,31 @@ func (s *TRPClient) linkProcess(link *conn.Link, c *conn.Conn) {
s.Unlock() s.Unlock()
} }
func (s *TRPClient) getMsgStatus() {
var err error
s.msgTunnel, err = NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_SEND_STATUS, s.proxyUrl)
if err != nil {
lg.Println("connect to ", s.svrAddr, "error:", err)
return
}
go func() {
for {
if id, err := s.msgTunnel.GetLen(); err != nil {
break
} else {
s.Lock()
if v, ok := s.linkMap[id]; ok {
s.Unlock()
v.StatusCh <- true
} else {
s.Unlock()
}
}
}
}()
<-s.stop
}
//隧道模式处理 //隧道模式处理
func (s *TRPClient) dealChan() { func (s *TRPClient) dealChan() {
var err error var err error
@ -140,26 +170,20 @@ func (s *TRPClient) dealChan() {
lg.Println("connect to ", s.svrAddr, "error:", err) lg.Println("connect to ", s.svrAddr, "error:", err)
return return
} }
go func() { go func() {
for { for {
if id, err := s.tunnel.GetLen(); err != nil { if id, err := s.tunnel.GetLen(); err != nil {
lg.Println("get id error", err, id)
break break
} else { } else {
s.Lock() s.Lock()
if v, ok := s.linkMap[id]; ok { if v, ok := s.linkMap[id]; ok {
s.Unlock() s.Unlock()
if content, err := s.tunnel.GetMsgContent(v); err != nil { if content, err := s.tunnel.GetMsgContent(v); err != nil {
lg.Println("get msg content error:", err, id)
pool.PutBufPoolCopy(content) pool.PutBufPoolCopy(content)
break break
} else { } else {
if len(content) == len(common.IO_EOF) && string(content) == common.IO_EOF { v.MsgCh <- content
v.Conn.Close()
} else if v.Conn != nil {
v.Conn.Write(content)
}
pool.PutBufPoolCopy(content)
} }
} else { } else {
s.Unlock() s.Unlock()

View File

@ -12,6 +12,8 @@ import (
"github.com/cnlh/nps/vender/github.com/astaxie/beego" "github.com/cnlh/nps/vender/github.com/astaxie/beego"
_ "github.com/cnlh/nps/web/routers" _ "github.com/cnlh/nps/web/routers"
"log" "log"
"net/http"
_ "net/http/pprof"
"os" "os"
"path/filepath" "path/filepath"
) )
@ -38,6 +40,9 @@ func main() {
return return
} }
} }
go func() {
http.ListenAndServe("0.0.0.0:8899", nil)
}()
if *logType == "stdout" { if *logType == "stdout" {
lg.InitLogFile("nps", true, common.GetLogPath()) lg.InitLogFile("nps", true, common.GetLogPath())
} else { } else {

View File

@ -2,11 +2,8 @@
server=127.0.0.1:8284 server=127.0.0.1:8284
tp=tcp tp=tcp
vkey=123 vkey=123
compress=snappy
crypt=true
auto_reconnection=true auto_reconnection=true
username=111
password=222
[web1] [web1]
host=a.o.com host=a.o.com
host_change=www.proxy.com host_change=www.proxy.com
@ -21,7 +18,7 @@ header_set_proxy=nps
[tcp] [tcp]
mode=tcpServer mode=tcpServer
target=8001-8005,8006 target=8001-8005,8080
port=9001-9005,9006 port=9001-9005,9006
[socks5] [socks5]
@ -34,5 +31,5 @@ port=9008
[udp] [udp]
mode=udpServer mode=udpServer
port=9009 port=53
target=114.114.114.114:53 target=114.114.114.114:53

View File

@ -6,20 +6,21 @@ const (
COMPRESS_NONE_DECODE COMPRESS_NONE_DECODE
COMPRESS_SNAPY_ENCODE COMPRESS_SNAPY_ENCODE
COMPRESS_SNAPY_DECODE COMPRESS_SNAPY_DECODE
VERIFY_EER = "vkey" VERIFY_EER = "vkey"
VERIFY_SUCCESS = "sucs" VERIFY_SUCCESS = "sucs"
WORK_MAIN = "main" WORK_MAIN = "main"
WORK_CHAN = "chan" WORK_CHAN = "chan"
WORK_CONFIG = "conf" WORK_SEND_STATUS = "sdst"
WORK_REGISTER = "rgst" WORK_CONFIG = "conf"
WORK_STATUS = "stus" WORK_REGISTER = "rgst"
RES_SIGN = "sign" WORK_STATUS = "stus"
RES_MSG = "msg0" RES_SIGN = "sign"
RES_CLOSE = "clse" RES_MSG = "msg0"
NEW_CONN = "conn" //新连接标志 RES_CLOSE = "clse"
NEW_TASK = "task" //新连接标志 NEW_CONN = "conn" //新连接标志
NEW_CONF = "conf" //新连接标志 NEW_TASK = "task" //新连接标志
NEW_HOST = "host" //新连接标志 NEW_CONF = "conf" //新连接标志
NEW_HOST = "host" //新连接标志
CONN_TCP = "tcp" CONN_TCP = "tcp"
CONN_UDP = "udp" CONN_UDP = "udp"

View File

@ -74,12 +74,12 @@ func (s *Conn) ReadLen(cLen int) ([]byte, error) {
return nil, errors.New("长度错误" + strconv.Itoa(cLen)) return nil, errors.New("长度错误" + strconv.Itoa(cLen))
} }
var buf []byte var buf []byte
if cLen <= pool.PoolSizeSmall { if cLen < pool.PoolSizeSmall {
buf = pool.BufPoolSmall.Get().([]byte)[:cLen] buf = pool.BufPoolSmall.Get().([]byte)[:cLen]
defer pool.BufPoolSmall.Put(buf) defer pool.PutBufPoolSmall(buf)
} else { } else {
buf = pool.BufPoolMax.Get().([]byte)[:cLen] buf = pool.BufPoolMax.Get().([]byte)[:cLen]
defer pool.BufPoolMax.Put(buf) defer pool.PutBufPoolMax(buf)
} }
if n, err := io.ReadFull(s, buf); err != nil || n != cLen { if n, err := io.ReadFull(s, buf); err != nil || n != cLen {
return buf, errors.New("Error reading specified length " + err.Error()) return buf, errors.New("Error reading specified length " + err.Error())
@ -190,14 +190,10 @@ func (s *Conn) SendMsg(content []byte, link *Link) (n int, err error) {
*/ */
s.Lock() s.Lock()
defer s.Unlock() defer s.Unlock()
raw := bytes.NewBuffer([]byte{}) if err = binary.Write(s.Conn, binary.LittleEndian, int32(link.Id)); err != nil {
binary.Write(raw, binary.LittleEndian, int32(link.Id))
if n, err = s.Write(raw.Bytes()); err != nil {
return return
} }
raw.Reset() n, err = s.WriteTo(content, link.En, link.Crypt, link.Rate)
binary.Write(raw, binary.LittleEndian, content)
n, err = s.WriteTo(raw.Bytes(), link.En, link.Crypt, link.Rate)
return return
} }
@ -260,6 +256,8 @@ func (s *Conn) GetLinkInfo() (lk *Link, err error) {
lk.En = common.GetIntNoErrByStr(string(buf[11+hostLen])) lk.En = common.GetIntNoErrByStr(string(buf[11+hostLen]))
lk.De = common.GetIntNoErrByStr(string(buf[12+hostLen])) lk.De = common.GetIntNoErrByStr(string(buf[12+hostLen]))
lk.Crypt = common.GetBoolByStr(string(buf[13+hostLen])) lk.Crypt = common.GetBoolByStr(string(buf[13+hostLen]))
lk.MsgCh = make(chan []byte)
lk.StatusCh = make(chan bool)
} }
return return
} }
@ -399,6 +397,10 @@ func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
return return
} }
func (s *Conn) WriteWriteSuccess(id int) error {
return binary.Write(s.Conn, binary.LittleEndian, int32(id))
}
//write connect success //write connect success
func (s *Conn) WriteSuccess(id int) (int, error) { func (s *Conn) WriteSuccess(id int) (int, error) {
raw := bytes.NewBuffer([]byte{}) raw := bytes.NewBuffer([]byte{})

View File

@ -1,7 +1,9 @@
package conn package conn
import ( import (
"github.com/cnlh/nps/lib/common"
"github.com/cnlh/nps/lib/file" "github.com/cnlh/nps/lib/file"
"github.com/cnlh/nps/lib/pool"
"github.com/cnlh/nps/lib/rate" "github.com/cnlh/nps/lib/rate"
"net" "net"
) )
@ -18,6 +20,9 @@ type Link struct {
UdpListener *net.UDPConn UdpListener *net.UDPConn
Rate *rate.Rate Rate *rate.Rate
UdpRemoteAddr *net.UDPAddr UdpRemoteAddr *net.UDPAddr
MsgCh chan []byte
MsgConn *Conn
StatusCh chan bool
} }
func NewLink(id int, connType string, host string, en, de int, crypt bool, c *Conn, flow *file.Flow, udpListener *net.UDPConn, rate *rate.Rate, UdpRemoteAddr *net.UDPAddr) *Link { func NewLink(id int, connType string, host string, en, de int, crypt bool, c *Conn, flow *file.Flow, udpListener *net.UDPConn, rate *rate.Rate, UdpRemoteAddr *net.UDPAddr) *Link {
@ -33,5 +38,37 @@ func NewLink(id int, connType string, host string, en, de int, crypt bool, c *Co
UdpListener: udpListener, UdpListener: udpListener,
Rate: rate, Rate: rate,
UdpRemoteAddr: UdpRemoteAddr, UdpRemoteAddr: UdpRemoteAddr,
MsgCh: make(chan []byte),
StatusCh: make(chan bool),
} }
} }
func (s *Link) Run(flow bool) {
go func() {
for {
select {
case content := <-s.MsgCh:
if len(content) == len(common.IO_EOF) && string(content) == common.IO_EOF {
if s.Conn != nil {
s.Conn.Close()
}
return
} else {
if s.UdpListener != nil && s.UdpRemoteAddr != nil {
s.UdpListener.WriteToUDP(content, s.UdpRemoteAddr)
} else {
s.Conn.Write(content)
}
if flow {
s.Flow.Add(0, len(content))
}
if s.ConnType == common.CONN_UDP {
return
}
s.MsgConn.WriteWriteSuccess(s.Id)
pool.PutBufPoolCopy(content)
}
}
}
}()
}

View File

@ -36,14 +36,26 @@ var BufPoolCopy = sync.Pool{
}, },
} }
func PutBufPoolUdp(buf []byte) {
if cap(buf) == PoolSizeUdp {
BufPoolUdp.Put(buf[:PoolSizeUdp])
}
}
func PutBufPoolCopy(buf []byte) { func PutBufPoolCopy(buf []byte) {
if cap(buf) == PoolSizeCopy { if cap(buf) == PoolSizeCopy {
BufPoolCopy.Put(buf[:PoolSizeCopy]) BufPoolCopy.Put(buf[:PoolSizeCopy])
} }
} }
func PutBufPoolUdp(buf []byte) { func PutBufPoolSmall(buf []byte) {
if cap(buf) == PoolSizeUdp { if cap(buf) == PoolSizeSmall {
BufPoolUdp.Put(buf[:PoolSizeUdp]) BufPoolSmall.Put(buf[:PoolSizeSmall])
}
}
func PutBufPoolMax(buf []byte) {
if cap(buf) == PoolSize {
BufPoolMax.Put(buf[:PoolSize])
} }
} }

View File

@ -60,6 +60,7 @@ func (s *server) linkCopy(link *conn.Link, c *conn.Conn, rb []byte, tunnel *conn
} }
flow.Add(n, 0) flow.Add(n, 0)
} }
<-link.StatusCh
} }
pool.PutBufPoolCopy(buf) pool.PutBufPoolCopy(buf)
} }

View File

@ -9,7 +9,6 @@ import (
"github.com/cnlh/nps/lib/file" "github.com/cnlh/nps/lib/file"
"github.com/cnlh/nps/lib/lg" "github.com/cnlh/nps/lib/lg"
"github.com/cnlh/nps/vender/github.com/astaxie/beego" "github.com/cnlh/nps/vender/github.com/astaxie/beego"
"log"
"net/http" "net/http"
"net/http/httputil" "net/http/httputil"
"path/filepath" "path/filepath"
@ -137,9 +136,10 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
} }
lk = conn.NewLink(host.Client.GetId(), common.CONN_TCP, host.GetRandomTarget(), host.Client.Cnf.CompressEncode, host.Client.Cnf.CompressDecode, host.Client.Cnf.Crypt, c, host.Flow, nil, host.Client.Rate, nil) lk = conn.NewLink(host.Client.GetId(), common.CONN_TCP, host.GetRandomTarget(), host.Client.Cnf.CompressEncode, host.Client.Cnf.CompressDecode, host.Client.Cnf.Crypt, c, host.Flow, nil, host.Client.Rate, nil)
if tunnel, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String()); err != nil { if tunnel, err = s.bridge.SendLinkInfo(host.Client.Id, lk, c.Conn.RemoteAddr().String()); err != nil {
log.Println(err) lg.Println(err)
break break
} }
lk.Run(true)
isConn = false isConn = false
} else { } else {
r, err = http.ReadRequest(bufio.NewReader(c)) r, err = http.ReadRequest(bufio.NewReader(c))
@ -166,6 +166,7 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
c.Close() c.Close()
break break
} }
<-lk.StatusCh
} }
end: end:
if isConn { if isConn {
@ -173,9 +174,7 @@ end:
} else { } else {
tunnel.SendMsg([]byte(common.IO_EOF), lk) tunnel.SendMsg([]byte(common.IO_EOF), lk)
} }
c.Close() c.Close()
} }
func (s *httpServer) NewServer(port int) *http.Server { func (s *httpServer) NewServer(port int) *http.Server {

View File

@ -148,6 +148,7 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) {
return return
} else { } else {
s.sendReply(c, succeeded) s.sendReply(c, succeeded)
link.Run(true)
s.linkCopy(link, conn.NewConn(c), nil, tunnel, s.task.Flow) s.linkCopy(link, conn.NewConn(c), nil, tunnel, s.task.Flow)
} }
return return

View File

@ -57,6 +57,7 @@ func (s *TunnelModeServer) dealClient(c *conn.Conn, cnf *file.Config, addr strin
c.Close() c.Close()
return err return err
} else { } else {
link.Run(true)
s.linkCopy(link, c, rb, tunnel, s.task.Flow) s.linkCopy(link, c, rb, tunnel, s.task.Flow)
} }
return nil return nil

View File

@ -56,6 +56,7 @@ func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
s.task.Flow.Add(len(data), 0) s.task.Flow.Add(len(data), 0)
tunnel.SendMsg(data, link) tunnel.SendMsg(data, link)
pool.PutBufPoolUdp(data) pool.PutBufPoolUdp(data)
link.Run(true)
} }
} }