mirror of https://github.com/ehang-io/nps
add functions
parent
2c608ddb7f
commit
750ecb824a
|
@ -8,11 +8,11 @@ import (
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/crypt"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
|
"github.com/cnlh/nps/lib/version"
|
||||||
"github.com/cnlh/nps/server/tool"
|
"github.com/cnlh/nps/server/tool"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
"log"
|
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
|
@ -48,6 +48,7 @@ type Bridge struct {
|
||||||
tunnelType string //bridge type kcp or tcp
|
tunnelType string //bridge type kcp or tcp
|
||||||
OpenTask chan *file.Tunnel
|
OpenTask chan *file.Tunnel
|
||||||
CloseClient chan int
|
CloseClient chan int
|
||||||
|
SecretChan chan *conn.Secret
|
||||||
clientLock sync.RWMutex
|
clientLock sync.RWMutex
|
||||||
Register map[string]time.Time
|
Register map[string]time.Time
|
||||||
registerLock sync.RWMutex
|
registerLock sync.RWMutex
|
||||||
|
@ -65,6 +66,7 @@ func NewTunnel(tunnelPort int, tunnelType string, ipVerify bool, runList map[int
|
||||||
t.Register = make(map[string]time.Time)
|
t.Register = make(map[string]time.Time)
|
||||||
t.ipVerify = ipVerify
|
t.ipVerify = ipVerify
|
||||||
t.runList = runList
|
t.runList = runList
|
||||||
|
t.SecretChan = make(chan *conn.Secret)
|
||||||
return t
|
return t
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -80,7 +82,7 @@ func (s *Bridge) StartTunnel() error {
|
||||||
c, err := s.kcpListener.AcceptKCP()
|
c, err := s.kcpListener.AcceptKCP()
|
||||||
conn.SetUdpSession(c)
|
conn.SetUdpSession(c)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println(err)
|
logs.Warn(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go s.cliProcess(conn.NewConn(c))
|
go s.cliProcess(conn.NewConn(c))
|
||||||
|
@ -95,7 +97,7 @@ func (s *Bridge) StartTunnel() error {
|
||||||
for {
|
for {
|
||||||
c, err := s.tcpListener.Accept()
|
c, err := s.tcpListener.Accept()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println(err)
|
logs.Warn(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
go s.cliProcess(conn.NewConn(c))
|
go s.cliProcess(conn.NewConn(c))
|
||||||
|
@ -116,6 +118,12 @@ func (s *Bridge) verifySuccess(c *conn.Conn) {
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Bridge) cliProcess(c *conn.Conn) {
|
func (s *Bridge) cliProcess(c *conn.Conn) {
|
||||||
|
c.Write([]byte(crypt.Md5(version.GetVersion())))
|
||||||
|
if b, err := c.ReadFlag(); err != nil || string(b) != version.VERSION_OK {
|
||||||
|
logs.Info("The client %s version does not match", c.Conn.RemoteAddr())
|
||||||
|
c.Close()
|
||||||
|
return
|
||||||
|
}
|
||||||
c.SetReadDeadline(5, s.tunnelType)
|
c.SetReadDeadline(5, s.tunnelType)
|
||||||
var buf []byte
|
var buf []byte
|
||||||
var err error
|
var err error
|
||||||
|
@ -126,7 +134,7 @@ func (s *Bridge) cliProcess(c *conn.Conn) {
|
||||||
//验证
|
//验证
|
||||||
id, err := file.GetCsvDb().GetIdByVerifyKey(string(buf), c.Conn.RemoteAddr().String())
|
id, err := file.GetCsvDb().GetIdByVerifyKey(string(buf), c.Conn.RemoteAddr().String())
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("当前客户端连接校验错误,关闭此客户端:", c.Conn.RemoteAddr())
|
logs.Info("Current client connection validation error, close this client:", c.Conn.RemoteAddr())
|
||||||
s.verifyError(c)
|
s.verifyError(c)
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
|
@ -136,7 +144,7 @@ func (s *Bridge) cliProcess(c *conn.Conn) {
|
||||||
if flag, err := c.ReadFlag(); err == nil {
|
if flag, err := c.ReadFlag(); err == nil {
|
||||||
s.typeDeal(flag, c, id)
|
s.typeDeal(flag, c, id)
|
||||||
} else {
|
} else {
|
||||||
log.Println(err, flag)
|
logs.Warn(err, flag)
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -182,7 +190,7 @@ func (s *Bridge) typeDeal(typeVal string, c *conn.Conn, id int) {
|
||||||
s.Client[id] = NewClient(nil, c, nil)
|
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())
|
logs.Info("clientId %d connection succeeded, address:%s ", id, c.Conn.RemoteAddr())
|
||||||
go s.GetStatus(id)
|
go s.GetStatus(id)
|
||||||
case common.WORK_CHAN:
|
case common.WORK_CHAN:
|
||||||
s.clientLock.Lock()
|
s.clientLock.Lock()
|
||||||
|
@ -200,6 +208,10 @@ 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.WORD_SECRET:
|
||||||
|
if b, err := c.ReadLen(32); err == nil {
|
||||||
|
s.SecretChan <- conn.NewSecret(string(b), c)
|
||||||
|
}
|
||||||
case common.WORK_SEND_STATUS:
|
case common.WORK_SEND_STATUS:
|
||||||
s.clientLock.Lock()
|
s.clientLock.Lock()
|
||||||
if v, ok := s.Client[id]; ok {
|
if v, ok := s.Client[id]; ok {
|
||||||
|
@ -293,7 +305,7 @@ func (s *Bridge) SendLinkInfo(clientId int, link *conn.Link, linkAddr string) (t
|
||||||
|
|
||||||
v.signal.SendLinkInfo(link)
|
v.signal.SendLinkInfo(link)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("send link information error:", err, link.Id)
|
logs.Warn("send link information error:", err, link.Id)
|
||||||
s.DelClient(clientId)
|
s.DelClient(clientId)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -314,7 +326,7 @@ func (s *Bridge) SendLinkInfo(clientId int, link *conn.Link, linkAddr string) (t
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
s.clientLock.Unlock()
|
s.clientLock.Unlock()
|
||||||
err = errors.New("the connection is not connect")
|
err = errors.New(fmt.Sprintf("the client %d is not connect", clientId))
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -328,6 +340,7 @@ func (s *Bridge) DelClient(id int) {
|
||||||
func (s *Bridge) GetConfig(c *conn.Conn) {
|
func (s *Bridge) GetConfig(c *conn.Conn) {
|
||||||
var client *file.Client
|
var client *file.Client
|
||||||
var fail bool
|
var fail bool
|
||||||
|
|
||||||
for {
|
for {
|
||||||
flag, err := c.ReadFlag()
|
flag, err := c.ReadFlag()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
@ -357,19 +370,15 @@ func (s *Bridge) GetConfig(c *conn.Conn) {
|
||||||
binary.Write(c, binary.LittleEndian, []byte(str))
|
binary.Write(c, binary.LittleEndian, []byte(str))
|
||||||
}
|
}
|
||||||
case common.NEW_CONF:
|
case common.NEW_CONF:
|
||||||
//new client ,Set the client not to store to the file
|
var err error
|
||||||
client = file.NewClient(crypt.GetRandomString(16), true, false)
|
if client, err = c.GetConfigInfo(); err != nil {
|
||||||
client.Remark = "public veky"
|
|
||||||
//Send the key to the client
|
|
||||||
file.GetCsvDb().NewClient(client)
|
|
||||||
c.Write([]byte(client.VerifyKey))
|
c.Write([]byte(client.VerifyKey))
|
||||||
|
|
||||||
if config, err := c.GetConfigInfo(); err != nil {
|
|
||||||
fail = true
|
fail = true
|
||||||
c.WriteAddFail()
|
c.WriteAddFail()
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
client.Cnf = config
|
c.Write([]byte(client.VerifyKey))
|
||||||
|
file.GetCsvDb().NewClient(client)
|
||||||
c.WriteAddOk()
|
c.WriteAddOk()
|
||||||
}
|
}
|
||||||
case common.NEW_HOST:
|
case common.NEW_HOST:
|
||||||
|
@ -380,6 +389,7 @@ func (s *Bridge) GetConfig(c *conn.Conn) {
|
||||||
} else if file.GetCsvDb().IsHostExist(h) {
|
} else if file.GetCsvDb().IsHostExist(h) {
|
||||||
fail = true
|
fail = true
|
||||||
c.WriteAddFail()
|
c.WriteAddFail()
|
||||||
|
break
|
||||||
} else {
|
} else {
|
||||||
h.Client = client
|
h.Client = client
|
||||||
file.GetCsvDb().NewHost(h)
|
file.GetCsvDb().NewHost(h)
|
||||||
|
@ -397,6 +407,13 @@ func (s *Bridge) GetConfig(c *conn.Conn) {
|
||||||
fail = true
|
fail = true
|
||||||
c.WriteAddFail()
|
c.WriteAddFail()
|
||||||
break
|
break
|
||||||
|
} else if t.Mode == "secretServer" {
|
||||||
|
ports = append(ports, 0)
|
||||||
|
}
|
||||||
|
if len(ports) == 0 {
|
||||||
|
fail = true
|
||||||
|
c.WriteAddFail()
|
||||||
|
break
|
||||||
}
|
}
|
||||||
for i := 0; i < len(ports); i++ {
|
for i := 0; i < len(ports); i++ {
|
||||||
tl := new(file.Tunnel)
|
tl := new(file.Tunnel)
|
||||||
|
@ -407,17 +424,24 @@ func (s *Bridge) GetConfig(c *conn.Conn) {
|
||||||
tl.Remark = t.Remark
|
tl.Remark = t.Remark
|
||||||
} else {
|
} else {
|
||||||
tl.Remark = t.Remark + "_" + strconv.Itoa(tl.Port)
|
tl.Remark = t.Remark + "_" + strconv.Itoa(tl.Port)
|
||||||
tl.Target = strconv.Itoa(targets[i])
|
tl.Target = t.TargetAddr + ":" + strconv.Itoa(targets[i])
|
||||||
}
|
}
|
||||||
tl.Id = file.GetCsvDb().GetTaskId()
|
tl.Id = file.GetCsvDb().GetTaskId()
|
||||||
tl.Status = true
|
tl.Status = true
|
||||||
tl.Flow = new(file.Flow)
|
tl.Flow = new(file.Flow)
|
||||||
tl.NoStore = true
|
tl.NoStore = true
|
||||||
tl.Client = client
|
tl.Client = client
|
||||||
file.GetCsvDb().NewTask(tl)
|
tl.Password = t.Password
|
||||||
if b := tool.TestServerPort(tl.Port, tl.Mode); !b {
|
if err := file.GetCsvDb().NewTask(tl); err != nil {
|
||||||
|
logs.Notice("Add task error ", err.Error())
|
||||||
fail = true
|
fail = true
|
||||||
c.WriteAddFail()
|
c.WriteAddFail()
|
||||||
|
break
|
||||||
|
}
|
||||||
|
if b := tool.TestServerPort(tl.Port, tl.Mode); !b && t.Mode != "secretServer" {
|
||||||
|
fail = true
|
||||||
|
c.WriteAddFail()
|
||||||
|
break
|
||||||
} else {
|
} else {
|
||||||
s.OpenTask <- tl
|
s.OpenTask <- tl
|
||||||
}
|
}
|
||||||
|
@ -460,7 +484,7 @@ func (s *Bridge) clientCopy(clientId int) {
|
||||||
|
|
||||||
for {
|
for {
|
||||||
if id, err := client.tunnel.GetLen(); err != nil {
|
if id, err := client.tunnel.GetLen(); err != nil {
|
||||||
lg.Println("read msg content length error close client")
|
logs.Info("read msg content length error close client")
|
||||||
s.delClient(clientId)
|
s.delClient(clientId)
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
|
@ -470,7 +494,7 @@ func (s *Bridge) clientCopy(clientId int) {
|
||||||
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.delClient(clientId)
|
s.delClient(clientId)
|
||||||
lg.Println("read msg content error", err, "close client")
|
logs.Notice("read msg content error", err, "close client")
|
||||||
break
|
break
|
||||||
} else {
|
} else {
|
||||||
link.MsgCh <- content
|
link.MsgCh <- content
|
||||||
|
|
|
@ -3,9 +3,10 @@ package client
|
||||||
import (
|
import (
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"sync"
|
"sync"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
@ -40,11 +41,11 @@ func (s *TRPClient) Start() {
|
||||||
retry:
|
retry:
|
||||||
c, err := NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_MAIN, s.proxyUrl)
|
c, err := NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_MAIN, s.proxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("The connection server failed and will be reconnected in five seconds")
|
logs.Error("The connection server failed and will be reconnected in five seconds")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
goto retry
|
goto retry
|
||||||
}
|
}
|
||||||
lg.Printf("Successful connection with server %s", s.svrAddr)
|
logs.Info("Successful connection with server %s", s.svrAddr)
|
||||||
s.processor(c)
|
s.processor(c)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -65,12 +66,13 @@ func (s *TRPClient) processor(c *conn.Conn) {
|
||||||
for {
|
for {
|
||||||
flags, err := c.ReadFlag()
|
flags, err := c.ReadFlag()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Printf("Accept server data error %s, end this service", err.Error())
|
logs.Error("Accept server data error %s, end this service", err.Error())
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
switch flags {
|
switch flags {
|
||||||
case common.VERIFY_EER:
|
case common.VERIFY_EER:
|
||||||
lg.Fatalf("VKey:%s is incorrect, the server refuses to connect, please check", s.vKey)
|
logs.Error("VKey:%s is incorrect, the server refuses to connect, please check", s.vKey)
|
||||||
|
os.Exit(0)
|
||||||
case common.NEW_CONN:
|
case common.NEW_CONN:
|
||||||
if link, err := c.GetLinkInfo(); err != nil {
|
if link, err := c.GetLinkInfo(); err != nil {
|
||||||
break
|
break
|
||||||
|
@ -83,12 +85,13 @@ func (s *TRPClient) processor(c *conn.Conn) {
|
||||||
link.Run(false)
|
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.")
|
logs.Error("The authentication key is connected by another client or the server closes the client.")
|
||||||
|
os.Exit(0)
|
||||||
case common.RES_MSG:
|
case common.RES_MSG:
|
||||||
lg.Println("Server-side return error")
|
logs.Error("Server-side return error")
|
||||||
break
|
break
|
||||||
default:
|
default:
|
||||||
lg.Println("The error could not be resolved")
|
logs.Warn("The error could not be resolved")
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -103,7 +106,7 @@ func (s *TRPClient) linkProcess(link *conn.Link, c *conn.Conn) {
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.WriteFail(link.Id)
|
c.WriteFail(link.Id)
|
||||||
lg.Println("connect to ", link.Host, "error:", err)
|
logs.Warn("connect to ", link.Host, "error:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
c.WriteSuccess(link.Id)
|
c.WriteSuccess(link.Id)
|
||||||
|
@ -134,7 +137,7 @@ func (s *TRPClient) getMsgStatus() {
|
||||||
var err error
|
var err error
|
||||||
s.msgTunnel, err = NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_SEND_STATUS, s.proxyUrl)
|
s.msgTunnel, err = NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_SEND_STATUS, s.proxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("connect to ", s.svrAddr, "error:", err)
|
logs.Error("connect to ", s.svrAddr, "error:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
@ -160,7 +163,7 @@ func (s *TRPClient) dealChan() {
|
||||||
var err error
|
var err error
|
||||||
s.tunnel, err = NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_CHAN, s.proxyUrl)
|
s.tunnel, err = NewConn(s.bridgeConnType, s.vKey, s.svrAddr, common.WORK_CHAN, s.proxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("connect to ", s.svrAddr, "error:", err)
|
logs.Error("connect to ", s.svrAddr, "error:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
go func() {
|
go func() {
|
||||||
|
|
|
@ -1,11 +1,14 @@
|
||||||
package client
|
package client
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/config"
|
"github.com/cnlh/nps/lib/config"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
|
"github.com/cnlh/nps/lib/version"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
"github.com/cnlh/nps/vender/github.com/xtaci/kcp"
|
||||||
"github.com/cnlh/nps/vender/golang.org/x/net/proxy"
|
"github.com/cnlh/nps/vender/golang.org/x/net/proxy"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
|
@ -39,7 +42,7 @@ func GetTaskStatus(path string) {
|
||||||
if l, err := c.GetLen(); err != nil {
|
if l, err := c.GetLen(); err != nil {
|
||||||
log.Fatalln(err)
|
log.Fatalln(err)
|
||||||
} else if b, err := c.ReadLen(l); err != nil {
|
} else if b, err := c.ReadLen(l); err != nil {
|
||||||
lg.Fatalln(err)
|
log.Fatalln(err)
|
||||||
} else {
|
} else {
|
||||||
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
||||||
for _, v := range cnf.Hosts {
|
for _, v := range cnf.Hosts {
|
||||||
|
@ -74,14 +77,16 @@ var errAdd = errors.New("The server returned an error, which port or host may ha
|
||||||
func StartFromFile(path string) {
|
func StartFromFile(path string) {
|
||||||
first := true
|
first := true
|
||||||
cnf, err := config.NewConfig(path)
|
cnf, err := config.NewConfig(path)
|
||||||
if err != nil {
|
if err != nil || cnf.CommonConfig == nil {
|
||||||
lg.Fatalln(err)
|
logs.Error("Config file %s loading error", path)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
lg.Printf("Loading configuration file %s successfully", path)
|
|
||||||
|
logs.Info("Loading configuration file %s successfully", path)
|
||||||
re:
|
re:
|
||||||
if first || cnf.CommonConfig.AutoReconnection {
|
if first || cnf.CommonConfig.AutoReconnection {
|
||||||
if !first {
|
if !first {
|
||||||
lg.Println("Reconnecting...")
|
logs.Info("Reconnecting...")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -90,48 +95,51 @@ re:
|
||||||
first = false
|
first = false
|
||||||
c, err := NewConn(cnf.CommonConfig.Tp, cnf.CommonConfig.VKey, cnf.CommonConfig.Server, common.WORK_CONFIG, cnf.CommonConfig.ProxyUrl)
|
c, err := NewConn(cnf.CommonConfig.Tp, cnf.CommonConfig.VKey, cnf.CommonConfig.Server, common.WORK_CONFIG, cnf.CommonConfig.ProxyUrl)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
if _, err := c.SendConfigInfo(cnf.CommonConfig.Cnf); err != nil {
|
if _, err := c.SendConfigInfo(cnf.CommonConfig); err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
var b []byte
|
var b []byte
|
||||||
if b, err = c.ReadLen(16); err != nil {
|
if b, err = c.ReadLen(16); err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
goto re
|
goto re
|
||||||
} else {
|
} else {
|
||||||
ioutil.WriteFile(filepath.Join(common.GetTmpPath(), "npc_vkey.txt"), []byte(string(b)), 0600)
|
ioutil.WriteFile(filepath.Join(common.GetTmpPath(), "npc_vkey.txt"), []byte(string(b)), 0600)
|
||||||
}
|
}
|
||||||
if !c.GetAddStatus() {
|
if !c.GetAddStatus() {
|
||||||
lg.Println(errAdd)
|
logs.Error(errAdd)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
|
|
||||||
for _, v := range cnf.Hosts {
|
for _, v := range cnf.Hosts {
|
||||||
if _, err := c.SendHostInfo(v); err != nil {
|
if _, err := c.SendHostInfo(v); err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
if !c.GetAddStatus() {
|
if !c.GetAddStatus() {
|
||||||
lg.Println(errAdd, v.Host)
|
logs.Error(errAdd, v.Host)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
for _, v := range cnf.Tasks {
|
for _, v := range cnf.Tasks {
|
||||||
if _, err := c.SendTaskInfo(v); err != nil {
|
if _, err := c.SendTaskInfo(v); err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
if !c.GetAddStatus() {
|
if !c.GetAddStatus() {
|
||||||
lg.Println(errAdd, v.Ports)
|
logs.Error(errAdd, v.Ports)
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
for _, v := range cnf.LocalServer {
|
||||||
|
go StartLocalServer(v, cnf.CommonConfig)
|
||||||
|
}
|
||||||
c.Close()
|
c.Close()
|
||||||
|
|
||||||
NewRPClient(cnf.CommonConfig.Server, string(b), cnf.CommonConfig.Tp, cnf.CommonConfig.ProxyUrl).Start()
|
NewRPClient(cnf.CommonConfig.Server, string(b), cnf.CommonConfig.Tp, cnf.CommonConfig.ProxyUrl).Start()
|
||||||
|
CloseLocalServer()
|
||||||
goto re
|
goto re
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -163,16 +171,30 @@ func NewConn(tp string, vkey string, server string, connType string, proxyUrl st
|
||||||
return nil, err
|
return nil, err
|
||||||
}
|
}
|
||||||
c := conn.NewConn(connection)
|
c := conn.NewConn(connection)
|
||||||
|
if b, err := c.ReadLen(32); err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
os.Exit(0)
|
||||||
|
} else if crypt.Md5(version.GetVersion()) != string(b) {
|
||||||
|
logs.Error("The client does not match the server version. The current version of the client is", version.GetVersion())
|
||||||
|
os.Exit(0)
|
||||||
|
} else if binary.Write(c, binary.LittleEndian, []byte(version.VERSION_OK)); err != nil {
|
||||||
|
logs.Error(err)
|
||||||
|
os.Exit(0)
|
||||||
|
}
|
||||||
if _, err := c.Write([]byte(common.Getverifyval(vkey))); err != nil {
|
if _, err := c.Write([]byte(common.Getverifyval(vkey))); err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
if s, err := c.ReadFlag(); err != nil {
|
if s, err := c.ReadFlag(); err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
|
os.Exit(0)
|
||||||
} else if s == common.VERIFY_EER {
|
} else if s == common.VERIFY_EER {
|
||||||
lg.Fatalf("Validation key %s incorrect", vkey)
|
logs.Error("Validation key %s incorrect", vkey)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
if _, err := c.Write([]byte(connType)); err != nil {
|
if _, err := c.Write([]byte(connType)); err != nil {
|
||||||
lg.Println(err)
|
logs.Error(err)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
c.SetAlive(tp)
|
c.SetAlive(tp)
|
||||||
|
|
||||||
|
|
|
@ -0,0 +1,54 @@
|
||||||
|
package client
|
||||||
|
|
||||||
|
import (
|
||||||
|
"github.com/cnlh/nps/lib/common"
|
||||||
|
"github.com/cnlh/nps/lib/config"
|
||||||
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
|
"net"
|
||||||
|
"strings"
|
||||||
|
)
|
||||||
|
|
||||||
|
var LocalServer []*net.TCPListener
|
||||||
|
|
||||||
|
func CloseLocalServer() {
|
||||||
|
for _, v := range LocalServer {
|
||||||
|
v.Close()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func StartLocalServer(l *config.LocalServer, config *config.CommonConfig) error {
|
||||||
|
listener, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), l.Port, ""})
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("Local listener startup failed port %d, error %s", l.Port, err.Error())
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
LocalServer = append(LocalServer, listener)
|
||||||
|
logs.Info("Successful start-up of local monitoring, port", l.Port)
|
||||||
|
for {
|
||||||
|
c, err := listener.AcceptTCP()
|
||||||
|
if err != nil {
|
||||||
|
if strings.Contains(err.Error(), "use of closed network connection") {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
logs.Info(err)
|
||||||
|
continue
|
||||||
|
}
|
||||||
|
go process(c, config, l)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func process(conn net.Conn, config *config.CommonConfig, l *config.LocalServer) {
|
||||||
|
c, err := NewConn(config.Tp, config.VKey, config.Server, common.WORD_SECRET, config.ProxyUrl)
|
||||||
|
if err != nil {
|
||||||
|
logs.Error("Local connection server failed ", err.Error())
|
||||||
|
}
|
||||||
|
if _, err := c.Write([]byte(crypt.Md5(l.Password))); err != nil {
|
||||||
|
logs.Error("Local connection server failed ", err.Error())
|
||||||
|
}
|
||||||
|
go common.CopyBuffer(c, conn)
|
||||||
|
common.CopyBuffer(conn, c)
|
||||||
|
c.Close()
|
||||||
|
conn.Close()
|
||||||
|
}
|
|
@ -5,14 +5,12 @@ import (
|
||||||
"github.com/cnlh/nps/client"
|
"github.com/cnlh/nps/client"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/daemon"
|
"github.com/cnlh/nps/lib/daemon"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"os"
|
"os"
|
||||||
"strings"
|
"strings"
|
||||||
"time"
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "v0.0.15"
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
serverAddr = flag.String("server", "", "Server addr (ip:port)")
|
serverAddr = flag.String("server", "", "Server addr (ip:port)")
|
||||||
configPath = flag.String("config", "npc.conf", "Configuration file path")
|
configPath = flag.String("config", "npc.conf", "Configuration file path")
|
||||||
|
@ -20,6 +18,7 @@ var (
|
||||||
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
||||||
connType = flag.String("type", "tcp", "Connection type with the server(kcp|tcp)")
|
connType = flag.String("type", "tcp", "Connection type with the server(kcp|tcp)")
|
||||||
proxyUrl = flag.String("proxy", "", "proxy socks5 url(eg:socks5://111:222@127.0.0.1:9007)")
|
proxyUrl = flag.String("proxy", "", "proxy socks5 url(eg:socks5://111:222@127.0.0.1:9007)")
|
||||||
|
logLevel = flag.String("log_level", "7", "log level 0~7")
|
||||||
registerTime = flag.Int("time", 2, "register time long /h")
|
registerTime = flag.Int("time", 2, "register time long /h")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,14 +36,14 @@ func main() {
|
||||||
}
|
}
|
||||||
daemon.InitDaemon("npc", common.GetRunPath(), common.GetTmpPath())
|
daemon.InitDaemon("npc", common.GetRunPath(), common.GetTmpPath())
|
||||||
if *logType == "stdout" {
|
if *logType == "stdout" {
|
||||||
lg.InitLogFile("npc", true, common.GetLogPath())
|
logs.SetLogger(logs.AdapterConsole, `{"level":`+*logLevel+`,"color":true}`)
|
||||||
} else {
|
} else {
|
||||||
lg.InitLogFile("npc", false, common.GetLogPath())
|
logs.SetLogger(logs.AdapterFile, `{"level":`+*logLevel+`,"filename":"npc_log.log"}`)
|
||||||
}
|
}
|
||||||
if *verifyKey != "" && *serverAddr != "" {
|
if *verifyKey != "" && *serverAddr != "" {
|
||||||
for {
|
for {
|
||||||
client.NewRPClient(*serverAddr, *verifyKey, *connType, *proxyUrl).Start()
|
client.NewRPClient(*serverAddr, *verifyKey, *connType, *proxyUrl).Start()
|
||||||
lg.Println("It will be reconnected in five seconds")
|
logs.Info("It will be reconnected in five seconds")
|
||||||
time.Sleep(time.Second * 5)
|
time.Sleep(time.Second * 5)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
|
|
@ -6,19 +6,18 @@ import (
|
||||||
"github.com/cnlh/nps/lib/daemon"
|
"github.com/cnlh/nps/lib/daemon"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/install"
|
"github.com/cnlh/nps/lib/install"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
|
||||||
"github.com/cnlh/nps/server"
|
"github.com/cnlh/nps/server"
|
||||||
"github.com/cnlh/nps/server/test"
|
"github.com/cnlh/nps/server/test"
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
_ "github.com/cnlh/nps/web/routers"
|
_ "github.com/cnlh/nps/web/routers"
|
||||||
"log"
|
"log"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
)
|
)
|
||||||
|
|
||||||
const VERSION = "v0.0.15"
|
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
level string
|
||||||
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
logType = flag.String("log", "stdout", "Log output mode(stdout|file)")
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -37,17 +36,22 @@ func main() {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if level = beego.AppConfig.String("logLevel"); level == "" {
|
||||||
|
level = "7"
|
||||||
|
}
|
||||||
|
logs.Reset()
|
||||||
if *logType == "stdout" {
|
if *logType == "stdout" {
|
||||||
lg.InitLogFile("nps", true, common.GetLogPath())
|
logs.SetLogger(logs.AdapterConsole, `{"level":`+level+`,"color":true}`)
|
||||||
} else {
|
} else {
|
||||||
lg.InitLogFile("nps", false, common.GetLogPath())
|
logs.SetLogger(logs.AdapterFile, `{"level":`+level+`,"filename":"nps_log.log"}`)
|
||||||
}
|
}
|
||||||
task := &file.Tunnel{
|
task := &file.Tunnel{
|
||||||
Mode: "webServer",
|
Mode: "webServer",
|
||||||
}
|
}
|
||||||
bridgePort, err := beego.AppConfig.Int("bridgePort")
|
bridgePort, err := beego.AppConfig.Int("bridgePort")
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln("Getting bridgePort error", err)
|
logs.Error("Getting bridgePort error", err)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
beego.LoadAppConfig("ini", filepath.Join(common.GetRunPath(), "conf", "app.conf"))
|
beego.LoadAppConfig("ini", filepath.Join(common.GetRunPath(), "conf", "app.conf"))
|
||||||
server.StartNewServer(bridgePort, task, beego.AppConfig.String("bridgeType"))
|
server.StartNewServer(bridgePort, task, beego.AppConfig.String("bridgeType"))
|
||||||
|
|
|
@ -36,4 +36,11 @@ bridgeType=tcp
|
||||||
# After the connection, the server will be able to open relevant ports and parse related domain names according to its own configuration file.
|
# After the connection, the server will be able to open relevant ports and parse related domain names according to its own configuration file.
|
||||||
publicVkey=123
|
publicVkey=123
|
||||||
|
|
||||||
|
#Traffic data persistence interval(minute)
|
||||||
|
#Ignorance means no persistence
|
||||||
|
flowStoreInterval=1
|
||||||
|
|
||||||
|
#log level
|
||||||
|
#LevelEmergency->0 LevelAlert->1 LevelCritical->2 LevelError->3 LevelWarning->4
|
||||||
|
#LevelNotice->5 LevelInformational->6 LevelDebug->7
|
||||||
|
logLevel=7
|
|
@ -1 +1 @@
|
||||||
7,7hv3avgeg2ldzvx7,,true,,,0,,0,0
|
7,7hv3avgeg2ldzvx7,,true,,,1,,0,999,10
|
||||||
|
|
|
|
@ -0,0 +1 @@
|
||||||
|
b.o.com,127.0.0.1:8082,7,,,,/,3,12995709,38827
|
|
|
@ -4,32 +4,24 @@ tp=tcp
|
||||||
vkey=123
|
vkey=123
|
||||||
auto_reconnection=true
|
auto_reconnection=true
|
||||||
crypt=true
|
crypt=true
|
||||||
|
|
||||||
[web1]
|
[web1]
|
||||||
host=a.o.com
|
host=a.o.com
|
||||||
host_change=www.proxy.com
|
host_change=www.proxy.com
|
||||||
target=127.0.0.1:8082
|
target=127.0.0.1:8080
|
||||||
location=/
|
location=/
|
||||||
|
|
||||||
[web2]
|
[web2]
|
||||||
host=a.proxy.com
|
host=127.0.0.1
|
||||||
target=127.0.0.1:8080,127.0.0.1:8082
|
|
||||||
host_change=www.proxy.com
|
host_change=www.proxy.com
|
||||||
header_set_proxy=nps
|
target=127.0.0.1:8080
|
||||||
|
location=/cdn
|
||||||
|
|
||||||
[tcp]
|
[ssh_1118]
|
||||||
mode=tcpServer
|
mode=secretServer
|
||||||
target=8001-8005,8082
|
password=1111
|
||||||
port=9001-9005,9006
|
target=123.206.77.88:22
|
||||||
|
|
||||||
[socks5]
|
[secret_ssh]
|
||||||
mode=socks5Server
|
password=1111
|
||||||
port=9007
|
port=1000
|
||||||
|
|
||||||
[http]
|
|
||||||
mode=httpProxyServer
|
|
||||||
port=9008
|
|
||||||
|
|
||||||
[udp]
|
|
||||||
mode=udpServer
|
|
||||||
port=53
|
|
||||||
target=114.114.114.114:53
|
|
||||||
|
|
|
@ -1 +1,3 @@
|
||||||
9010,socks5Server,,1,27,7,
|
9010,socks5Server,,1,27,7,,0,0,
|
||||||
|
9002,tcpServer,127.0.0.1:8082,1,28,7,,9175971,17054,
|
||||||
|
0,secretServer,123.206.77.88:22,1,30,7,私密隧道测试,15620,12628,tests
|
||||||
|
|
|
|
@ -13,6 +13,7 @@ const (
|
||||||
WORK_SEND_STATUS = "sdst"
|
WORK_SEND_STATUS = "sdst"
|
||||||
WORK_CONFIG = "conf"
|
WORK_CONFIG = "conf"
|
||||||
WORK_REGISTER = "rgst"
|
WORK_REGISTER = "rgst"
|
||||||
|
WORD_SECRET = "sert"
|
||||||
WORK_STATUS = "stus"
|
WORK_STATUS = "stus"
|
||||||
RES_SIGN = "sign"
|
RES_SIGN = "sign"
|
||||||
RES_MSG = "msg0"
|
RES_MSG = "msg0"
|
||||||
|
@ -21,7 +22,6 @@ const (
|
||||||
NEW_TASK = "task" //新连接标志
|
NEW_TASK = "task" //新连接标志
|
||||||
NEW_CONF = "conf" //新连接标志
|
NEW_CONF = "conf" //新连接标志
|
||||||
NEW_HOST = "host" //新连接标志
|
NEW_HOST = "host" //新连接标志
|
||||||
|
|
||||||
CONN_TCP = "tcp"
|
CONN_TCP = "tcp"
|
||||||
CONN_UDP = "udp"
|
CONN_UDP = "udp"
|
||||||
UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
|
UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
|
||||||
|
|
|
@ -5,6 +5,8 @@ import (
|
||||||
"encoding/base64"
|
"encoding/base64"
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"github.com/cnlh/nps/lib/crypt"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
|
"github.com/cnlh/nps/lib/pool"
|
||||||
|
"io"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net"
|
"net"
|
||||||
"net/http"
|
"net/http"
|
||||||
|
@ -246,3 +248,10 @@ func GetIpByAddr(addr string) string {
|
||||||
arr := strings.Split(addr, ":")
|
arr := strings.Split(addr, ":")
|
||||||
return arr[0]
|
return arr[0]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func CopyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||||
|
buf := pool.BufPoolCopy.Get().([]byte)
|
||||||
|
io.CopyBuffer(dst, src, buf)
|
||||||
|
pool.PutBufPoolCopy(buf)
|
||||||
|
return written, err
|
||||||
|
}
|
||||||
|
|
|
@ -1,6 +1,7 @@
|
||||||
package config
|
package config
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"regexp"
|
"regexp"
|
||||||
|
@ -14,6 +15,11 @@ type CommonConfig struct {
|
||||||
AutoReconnection bool
|
AutoReconnection bool
|
||||||
Cnf *file.Config
|
Cnf *file.Config
|
||||||
ProxyUrl string
|
ProxyUrl string
|
||||||
|
Client *file.Client
|
||||||
|
}
|
||||||
|
type LocalServer struct {
|
||||||
|
Port int
|
||||||
|
Password string
|
||||||
}
|
}
|
||||||
type Config struct {
|
type Config struct {
|
||||||
content string
|
content string
|
||||||
|
@ -21,6 +27,7 @@ type Config struct {
|
||||||
CommonConfig *CommonConfig
|
CommonConfig *CommonConfig
|
||||||
Hosts []*file.Host
|
Hosts []*file.Host
|
||||||
Tasks []*file.Tunnel
|
Tasks []*file.Tunnel
|
||||||
|
LocalServer []*LocalServer
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewConfig(path string) (c *Config, err error) {
|
func NewConfig(path string) (c *Config, err error) {
|
||||||
|
@ -44,6 +51,11 @@ func NewConfig(path string) (c *Config, err error) {
|
||||||
nextIndex = len(c.content)
|
nextIndex = len(c.content)
|
||||||
}
|
}
|
||||||
nowContent = c.content[nowIndex:nextIndex]
|
nowContent = c.content[nowIndex:nextIndex]
|
||||||
|
|
||||||
|
if strings.Index(getTitleContent(c.title[i]), "secret") == 0 {
|
||||||
|
c.LocalServer = append(c.LocalServer, delLocalService(nowContent))
|
||||||
|
continue
|
||||||
|
}
|
||||||
switch c.title[i] {
|
switch c.title[i] {
|
||||||
case "[common]":
|
case "[common]":
|
||||||
c.CommonConfig = dealCommon(nowContent)
|
c.CommonConfig = dealCommon(nowContent)
|
||||||
|
@ -68,9 +80,11 @@ func getTitleContent(s string) string {
|
||||||
re, _ := regexp.Compile(`[\[\]]`)
|
re, _ := regexp.Compile(`[\[\]]`)
|
||||||
return re.ReplaceAllString(s, "")
|
return re.ReplaceAllString(s, "")
|
||||||
}
|
}
|
||||||
|
|
||||||
func dealCommon(s string) *CommonConfig {
|
func dealCommon(s string) *CommonConfig {
|
||||||
c := &CommonConfig{}
|
c := &CommonConfig{}
|
||||||
c.Cnf = new(file.Config)
|
c.Cnf = new(file.Config)
|
||||||
|
c.Client = file.NewClient("", true, true)
|
||||||
for _, v := range strings.Split(s, "\n") {
|
for _, v := range strings.Split(s, "\n") {
|
||||||
item := strings.Split(v, "=")
|
item := strings.Split(v, "=")
|
||||||
if len(item) == 0 {
|
if len(item) == 0 {
|
||||||
|
@ -97,10 +111,19 @@ func dealCommon(s string) *CommonConfig {
|
||||||
c.Cnf.Crypt = common.GetBoolByStr(item[1])
|
c.Cnf.Crypt = common.GetBoolByStr(item[1])
|
||||||
case "proxy_socks5_url":
|
case "proxy_socks5_url":
|
||||||
c.ProxyUrl = item[1]
|
c.ProxyUrl = item[1]
|
||||||
|
case "rate_limit":
|
||||||
|
c.Client.RateLimit = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "flow_limit":
|
||||||
|
c.Client.Flow.FlowLimit = int64(common.GetIntNoErrByStr(item[1]))
|
||||||
|
case "max_conn":
|
||||||
|
c.Client.MaxConn = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "remark":
|
||||||
|
c.Client.Remark = item[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return c
|
return c
|
||||||
}
|
}
|
||||||
|
|
||||||
func dealHost(s string) *file.Host {
|
func dealHost(s string) *file.Host {
|
||||||
h := &file.Host{}
|
h := &file.Host{}
|
||||||
var headerChange string
|
var headerChange string
|
||||||
|
@ -146,12 +169,35 @@ func dealTunnel(s string) *file.Tunnel {
|
||||||
t.Mode = item[1]
|
t.Mode = item[1]
|
||||||
case "target":
|
case "target":
|
||||||
t.Target = item[1]
|
t.Target = item[1]
|
||||||
|
case "targetAddr":
|
||||||
|
t.TargetAddr = item[1]
|
||||||
|
case "password":
|
||||||
|
t.Password = item[1]
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return t
|
return t
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func delLocalService(s string) *LocalServer {
|
||||||
|
l := new(LocalServer)
|
||||||
|
for _, v := range strings.Split(s, "\n") {
|
||||||
|
item := strings.Split(v, "=")
|
||||||
|
if len(item) == 0 {
|
||||||
|
continue
|
||||||
|
} else if len(item) == 1 {
|
||||||
|
item = append(item, "")
|
||||||
|
}
|
||||||
|
switch item[0] {
|
||||||
|
case "port":
|
||||||
|
l.Port = common.GetIntNoErrByStr(item[1])
|
||||||
|
case "password":
|
||||||
|
l.Password = item[1]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return l
|
||||||
|
}
|
||||||
|
|
||||||
func getAllTitle(content string) (arr []string, err error) {
|
func getAllTitle(content string) (arr []string, err error) {
|
||||||
var re *regexp.Regexp
|
var re *regexp.Regexp
|
||||||
re, err = regexp.Compile(`\[.+?\]`)
|
re, err = regexp.Compile(`\[.+?\]`)
|
||||||
|
@ -159,5 +205,13 @@ func getAllTitle(content string) (arr []string, err error) {
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
arr = re.FindAllString(content, -1)
|
arr = re.FindAllString(content, -1)
|
||||||
|
m := make(map[string]bool)
|
||||||
|
for _, v := range arr {
|
||||||
|
if _, ok := m[v]; ok {
|
||||||
|
err = errors.New("Item names are not allowed to be duplicated")
|
||||||
|
return
|
||||||
|
}
|
||||||
|
m[v] = true
|
||||||
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,6 +6,8 @@ import (
|
||||||
"encoding/binary"
|
"encoding/binary"
|
||||||
"errors"
|
"errors"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
|
"github.com/cnlh/nps/lib/config"
|
||||||
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
"github.com/cnlh/nps/lib/rate"
|
"github.com/cnlh/nps/lib/rate"
|
||||||
|
@ -317,7 +319,7 @@ func (s *Conn) GetHostInfo() (h *file.Host, err error) {
|
||||||
}
|
}
|
||||||
|
|
||||||
//send task info
|
//send task info
|
||||||
func (s *Conn) SendConfigInfo(c *file.Config) (int, error) {
|
func (s *Conn) SendConfigInfo(c *config.CommonConfig) (int, error) {
|
||||||
/*
|
/*
|
||||||
The task info is formed as follows:
|
The task info is formed as follows:
|
||||||
+----+-----+---------+
|
+----+-----+---------+
|
||||||
|
@ -328,14 +330,15 @@ func (s *Conn) SendConfigInfo(c *file.Config) (int, error) {
|
||||||
*/
|
*/
|
||||||
raw := bytes.NewBuffer([]byte{})
|
raw := bytes.NewBuffer([]byte{})
|
||||||
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_CONF))
|
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_CONF))
|
||||||
common.BinaryWrite(raw, c.U, c.P, common.GetStrByBool(c.Crypt), c.Compress)
|
common.BinaryWrite(raw, c.Cnf.U, c.Cnf.P, common.GetStrByBool(c.Cnf.Crypt), c.Cnf.Compress, strconv.Itoa(c.Client.RateLimit),
|
||||||
|
strconv.Itoa(int(c.Client.Flow.FlowLimit)), strconv.Itoa(c.Client.MaxConn), c.Client.Remark)
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
return s.Write(raw.Bytes())
|
return s.Write(raw.Bytes())
|
||||||
}
|
}
|
||||||
|
|
||||||
//get task info
|
//get task info
|
||||||
func (s *Conn) GetConfigInfo() (c *file.Config, err error) {
|
func (s *Conn) GetConfigInfo() (c *file.Client, err error) {
|
||||||
var l int
|
var l int
|
||||||
var b []byte
|
var b []byte
|
||||||
if l, err = s.GetLen(); err != nil {
|
if l, err = s.GetLen(); err != nil {
|
||||||
|
@ -344,12 +347,16 @@ func (s *Conn) GetConfigInfo() (c *file.Config, err error) {
|
||||||
return
|
return
|
||||||
} else {
|
} else {
|
||||||
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
||||||
c = new(file.Config)
|
c = file.NewClient(crypt.GetRandomString(16), true, false)
|
||||||
c.U = arr[0]
|
c.Cnf.U = arr[0]
|
||||||
c.P = arr[1]
|
c.Cnf.P = arr[1]
|
||||||
c.Crypt = common.GetBoolByStr(arr[2])
|
c.Cnf.Crypt = common.GetBoolByStr(arr[2])
|
||||||
c.Compress = arr[3]
|
c.Cnf.Compress = arr[3]
|
||||||
c.CompressDecode, c.CompressDecode = common.GetCompressType(arr[3])
|
c.RateLimit = common.GetIntNoErrByStr(arr[4])
|
||||||
|
c.Flow.FlowLimit = int64(common.GetIntNoErrByStr(arr[5]))
|
||||||
|
c.MaxConn = common.GetIntNoErrByStr(arr[6])
|
||||||
|
c.Remark = arr[7]
|
||||||
|
c.Cnf.CompressDecode, c.Cnf.CompressDecode = common.GetCompressType(arr[3])
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -366,7 +373,7 @@ func (s *Conn) SendTaskInfo(t *file.Tunnel) (int, error) {
|
||||||
*/
|
*/
|
||||||
raw := bytes.NewBuffer([]byte{})
|
raw := bytes.NewBuffer([]byte{})
|
||||||
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_TASK))
|
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_TASK))
|
||||||
common.BinaryWrite(raw, t.Mode, t.Ports, t.Target, t.Remark)
|
common.BinaryWrite(raw, t.Mode, t.Ports, t.Target, t.Remark, t.TargetAddr, t.Password)
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
return s.Write(raw.Bytes())
|
return s.Write(raw.Bytes())
|
||||||
|
@ -390,6 +397,8 @@ func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
|
||||||
t.Status = true
|
t.Status = true
|
||||||
t.Flow = new(file.Flow)
|
t.Flow = new(file.Flow)
|
||||||
t.Remark = arr[3]
|
t.Remark = arr[3]
|
||||||
|
t.TargetAddr = arr[4]
|
||||||
|
t.Password = arr[5]
|
||||||
t.NoStore = true
|
t.NoStore = true
|
||||||
}
|
}
|
||||||
return
|
return
|
||||||
|
|
|
@ -8,6 +8,18 @@ import (
|
||||||
"net"
|
"net"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
type Secret struct {
|
||||||
|
Password string
|
||||||
|
Conn *Conn
|
||||||
|
}
|
||||||
|
|
||||||
|
func NewSecret(p string, conn *Conn) *Secret {
|
||||||
|
return &Secret{
|
||||||
|
Password: p,
|
||||||
|
Conn: conn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
type Link struct {
|
type Link struct {
|
||||||
Id int //id
|
Id int //id
|
||||||
ConnType string //连接类型
|
ConnType string //连接类型
|
||||||
|
|
|
@ -14,7 +14,9 @@ var (
|
||||||
func GetCsvDb() *Csv {
|
func GetCsvDb() *Csv {
|
||||||
once.Do(func() {
|
once.Do(func() {
|
||||||
CsvDb = NewCsv(common.GetRunPath())
|
CsvDb = NewCsv(common.GetRunPath())
|
||||||
CsvDb.Init()
|
CsvDb.LoadClientFromCsv()
|
||||||
|
CsvDb.LoadTaskFromCsv()
|
||||||
|
CsvDb.LoadHostFromCsv()
|
||||||
})
|
})
|
||||||
return CsvDb
|
return CsvDb
|
||||||
}
|
}
|
||||||
|
|
|
@ -3,9 +3,11 @@ package file
|
||||||
import (
|
import (
|
||||||
"encoding/csv"
|
"encoding/csv"
|
||||||
"errors"
|
"errors"
|
||||||
|
"fmt"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/lib/crypt"
|
||||||
"github.com/cnlh/nps/lib/rate"
|
"github.com/cnlh/nps/lib/rate"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
|
@ -33,17 +35,11 @@ type Csv struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) Init() {
|
|
||||||
s.LoadClientFromCsv()
|
|
||||||
s.LoadTaskFromCsv()
|
|
||||||
s.LoadHostFromCsv()
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Csv) StoreTasksToCsv() {
|
func (s *Csv) StoreTasksToCsv() {
|
||||||
// 创建文件
|
// 创建文件
|
||||||
csvFile, err := os.Create(filepath.Join(s.RunPath, "conf", "tasks.csv"))
|
csvFile, err := os.Create(filepath.Join(s.RunPath, "conf", "tasks.csv"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalf(err.Error())
|
logs.Error(err.Error())
|
||||||
}
|
}
|
||||||
defer csvFile.Close()
|
defer csvFile.Close()
|
||||||
writer := csv.NewWriter(csvFile)
|
writer := csv.NewWriter(csvFile)
|
||||||
|
@ -59,10 +55,13 @@ func (s *Csv) StoreTasksToCsv() {
|
||||||
strconv.Itoa(task.Id),
|
strconv.Itoa(task.Id),
|
||||||
strconv.Itoa(task.Client.Id),
|
strconv.Itoa(task.Client.Id),
|
||||||
task.Remark,
|
task.Remark,
|
||||||
|
strconv.Itoa(int(task.Flow.ExportFlow)),
|
||||||
|
strconv.Itoa(int(task.Flow.InletFlow)),
|
||||||
|
task.Password,
|
||||||
}
|
}
|
||||||
err := writer.Write(record)
|
err := writer.Write(record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalf(err.Error())
|
logs.Error(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.Flush()
|
writer.Flush()
|
||||||
|
@ -90,7 +89,8 @@ func (s *Csv) LoadTaskFromCsv() {
|
||||||
path := filepath.Join(s.RunPath, "conf", "tasks.csv")
|
path := filepath.Join(s.RunPath, "conf", "tasks.csv")
|
||||||
records, err := s.openFile(path)
|
records, err := s.openFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln("配置文件打开错误:", path)
|
logs.Error("Profile Opening Error:", path)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
var tasks []*Tunnel
|
var tasks []*Tunnel
|
||||||
// 将每一行数据保存到内存slice中
|
// 将每一行数据保存到内存slice中
|
||||||
|
@ -102,8 +102,11 @@ func (s *Csv) LoadTaskFromCsv() {
|
||||||
Status: common.GetBoolByStr(item[3]),
|
Status: common.GetBoolByStr(item[3]),
|
||||||
Id: common.GetIntNoErrByStr(item[4]),
|
Id: common.GetIntNoErrByStr(item[4]),
|
||||||
Remark: item[6],
|
Remark: item[6],
|
||||||
|
Password: item[9],
|
||||||
}
|
}
|
||||||
post.Flow = new(Flow)
|
post.Flow = new(Flow)
|
||||||
|
post.Flow.ExportFlow = int64(common.GetIntNoErrByStr(item[7]))
|
||||||
|
post.Flow.InletFlow = int64(common.GetIntNoErrByStr(item[8]))
|
||||||
if post.Client, err = s.GetClient(common.GetIntNoErrByStr(item[5])); err != nil {
|
if post.Client, err = s.GetClient(common.GetIntNoErrByStr(item[5])); err != nil {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
@ -142,10 +145,16 @@ func (s *Csv) GetIdByVerifyKey(vKey string, addr string) (int, error) {
|
||||||
return 0, errors.New("not found")
|
return 0, errors.New("not found")
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) NewTask(t *Tunnel) {
|
func (s *Csv) NewTask(t *Tunnel) error {
|
||||||
|
for _, v := range s.Tasks {
|
||||||
|
if v.Mode == "secretServer" && v.Password == t.Password {
|
||||||
|
return errors.New(fmt.Sprintf("Secret mode keys %s must be unique", t.Password))
|
||||||
|
}
|
||||||
|
}
|
||||||
t.Flow = new(Flow)
|
t.Flow = new(Flow)
|
||||||
s.Tasks = append(s.Tasks, t)
|
s.Tasks = append(s.Tasks, t)
|
||||||
s.StoreTasksToCsv()
|
s.StoreTasksToCsv()
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Csv) UpdateTask(t *Tunnel) error {
|
func (s *Csv) UpdateTask(t *Tunnel) error {
|
||||||
|
@ -171,6 +180,16 @@ func (s *Csv) DelTask(id int) error {
|
||||||
return errors.New("不存在")
|
return errors.New("不存在")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//md5 password
|
||||||
|
func (s *Csv) GetSecretTask(p string) *Tunnel {
|
||||||
|
for _, v := range s.Tasks {
|
||||||
|
if crypt.Md5(v.Password) == p {
|
||||||
|
return v
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
func (s *Csv) GetTask(id int) (v *Tunnel, err error) {
|
func (s *Csv) GetTask(id int) (v *Tunnel, err error) {
|
||||||
for _, v = range s.Tasks {
|
for _, v = range s.Tasks {
|
||||||
if v.Id == id {
|
if v.Id == id {
|
||||||
|
@ -205,6 +224,8 @@ func (s *Csv) StoreHostToCsv() {
|
||||||
host.Remark,
|
host.Remark,
|
||||||
host.Location,
|
host.Location,
|
||||||
strconv.Itoa(host.Id),
|
strconv.Itoa(host.Id),
|
||||||
|
strconv.Itoa(int(host.Flow.ExportFlow)),
|
||||||
|
strconv.Itoa(int(host.Flow.InletFlow)),
|
||||||
}
|
}
|
||||||
err1 := writer.Write(record)
|
err1 := writer.Write(record)
|
||||||
if err1 != nil {
|
if err1 != nil {
|
||||||
|
@ -219,7 +240,8 @@ func (s *Csv) LoadClientFromCsv() {
|
||||||
path := filepath.Join(s.RunPath, "conf", "clients.csv")
|
path := filepath.Join(s.RunPath, "conf", "clients.csv")
|
||||||
records, err := s.openFile(path)
|
records, err := s.openFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln("配置文件打开错误:", path)
|
logs.Error("Profile Opening Error:", path)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
var clients []*Client
|
var clients []*Client
|
||||||
// 将每一行数据保存到内存slice中
|
// 将每一行数据保存到内存slice中
|
||||||
|
@ -236,6 +258,7 @@ func (s *Csv) LoadClientFromCsv() {
|
||||||
Crypt: common.GetBoolByStr(item[6]),
|
Crypt: common.GetBoolByStr(item[6]),
|
||||||
Compress: item[7],
|
Compress: item[7],
|
||||||
},
|
},
|
||||||
|
MaxConn: common.GetIntNoErrByStr(item[10]),
|
||||||
}
|
}
|
||||||
if post.Id > s.ClientIncreaseId {
|
if post.Id > s.ClientIncreaseId {
|
||||||
s.ClientIncreaseId = post.Id
|
s.ClientIncreaseId = post.Id
|
||||||
|
@ -255,7 +278,8 @@ func (s *Csv) LoadHostFromCsv() {
|
||||||
path := filepath.Join(s.RunPath, "conf", "hosts.csv")
|
path := filepath.Join(s.RunPath, "conf", "hosts.csv")
|
||||||
records, err := s.openFile(path)
|
records, err := s.openFile(path)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln("配置文件打开错误:", path)
|
logs.Error("Profile Opening Error:", path)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
var hosts []*Host
|
var hosts []*Host
|
||||||
// 将每一行数据保存到内存slice中
|
// 将每一行数据保存到内存slice中
|
||||||
|
@ -273,6 +297,8 @@ func (s *Csv) LoadHostFromCsv() {
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
post.Flow = new(Flow)
|
post.Flow = new(Flow)
|
||||||
|
post.Flow.ExportFlow = int64(common.GetIntNoErrByStr(item[8]))
|
||||||
|
post.Flow.InletFlow = int64(common.GetIntNoErrByStr(item[9]))
|
||||||
hosts = append(hosts, post)
|
hosts = append(hosts, post)
|
||||||
if post.Id > s.HostIncreaseId {
|
if post.Id > s.HostIncreaseId {
|
||||||
s.HostIncreaseId = post.Id
|
s.HostIncreaseId = post.Id
|
||||||
|
@ -350,7 +376,9 @@ func (s *Csv) NewClient(c *Client) {
|
||||||
if c.Id == 0 {
|
if c.Id == 0 {
|
||||||
c.Id = s.GetClientId()
|
c.Id = s.GetClientId()
|
||||||
}
|
}
|
||||||
|
if c.Flow == nil {
|
||||||
c.Flow = new(Flow)
|
c.Flow = new(Flow)
|
||||||
|
}
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
s.Clients = append(s.Clients, c)
|
s.Clients = append(s.Clients, c)
|
||||||
|
@ -433,6 +461,8 @@ func (s *Csv) GetHostById(id int) (h *Host, err error) {
|
||||||
//get key by host from x
|
//get key by host from x
|
||||||
func (s *Csv) GetInfoByHost(host string, r *http.Request) (h *Host, err error) {
|
func (s *Csv) GetInfoByHost(host string, r *http.Request) (h *Host, err error) {
|
||||||
var hosts []*Host
|
var hosts []*Host
|
||||||
|
//Handling Ported Access
|
||||||
|
host = common.GetIpByAddr(host)
|
||||||
for _, v := range s.Hosts {
|
for _, v := range s.Hosts {
|
||||||
//Remove http(s) http(s)://a.proxy.com
|
//Remove http(s) http(s)://a.proxy.com
|
||||||
//*.proxy.com *.a.proxy.com Do some pan-parsing
|
//*.proxy.com *.a.proxy.com Do some pan-parsing
|
||||||
|
@ -467,7 +497,7 @@ func (s *Csv) StoreClientsToCsv() {
|
||||||
// 创建文件
|
// 创建文件
|
||||||
csvFile, err := os.Create(filepath.Join(s.RunPath, "conf", "clients.csv"))
|
csvFile, err := os.Create(filepath.Join(s.RunPath, "conf", "clients.csv"))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln(err.Error())
|
logs.Error(err.Error())
|
||||||
}
|
}
|
||||||
defer csvFile.Close()
|
defer csvFile.Close()
|
||||||
writer := csv.NewWriter(csvFile)
|
writer := csv.NewWriter(csvFile)
|
||||||
|
@ -486,10 +516,11 @@ func (s *Csv) StoreClientsToCsv() {
|
||||||
client.Cnf.Compress,
|
client.Cnf.Compress,
|
||||||
strconv.Itoa(client.RateLimit),
|
strconv.Itoa(client.RateLimit),
|
||||||
strconv.Itoa(int(client.Flow.FlowLimit)),
|
strconv.Itoa(int(client.Flow.FlowLimit)),
|
||||||
|
strconv.Itoa(int(client.MaxConn)),
|
||||||
}
|
}
|
||||||
err := writer.Write(record)
|
err := writer.Write(record)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln(err.Error())
|
logs.Error(err.Error())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
writer.Flush()
|
writer.Flush()
|
||||||
|
|
|
@ -33,6 +33,8 @@ type Client struct {
|
||||||
Rate *rate.Rate //速度控制
|
Rate *rate.Rate //速度控制
|
||||||
NoStore bool
|
NoStore bool
|
||||||
NoDisplay bool
|
NoDisplay bool
|
||||||
|
MaxConn int //客户端最大连接数
|
||||||
|
NowConn int //当前连接数
|
||||||
id int
|
id int
|
||||||
sync.RWMutex
|
sync.RWMutex
|
||||||
}
|
}
|
||||||
|
@ -62,6 +64,26 @@ func (s *Client) GetId() int {
|
||||||
return s.id
|
return s.id
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *Client) CutConn() {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
s.NowConn++
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Client) AddConn() {
|
||||||
|
s.Lock()
|
||||||
|
defer s.Unlock()
|
||||||
|
s.NowConn--
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Client) GetConn() bool {
|
||||||
|
s.CutConn()
|
||||||
|
if s.MaxConn == 0 || s.NowConn < s.MaxConn {
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
type Tunnel struct {
|
type Tunnel struct {
|
||||||
Id int //Id
|
Id int //Id
|
||||||
Port int //服务端监听端口
|
Port int //服务端监听端口
|
||||||
|
@ -72,7 +94,9 @@ type Tunnel struct {
|
||||||
Client *Client //所属客户端id
|
Client *Client //所属客户端id
|
||||||
Ports string //客户端与服务端传递
|
Ports string //客户端与服务端传递
|
||||||
Flow *Flow
|
Flow *Flow
|
||||||
|
Password string //私密模式密码,唯一
|
||||||
Remark string //备注
|
Remark string //备注
|
||||||
|
TargetAddr string
|
||||||
NoStore bool
|
NoStore bool
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -114,15 +138,3 @@ func (s *Host) GetRandomTarget() string {
|
||||||
}
|
}
|
||||||
return s.TargetArr[s.NowIndex]
|
return s.TargetArr[s.NowIndex]
|
||||||
}
|
}
|
||||||
|
|
||||||
//深拷贝Config
|
|
||||||
func DeepCopyConfig(c *Config) *Config {
|
|
||||||
return &Config{
|
|
||||||
U: c.U,
|
|
||||||
P: c.P,
|
|
||||||
Compress: c.Compress,
|
|
||||||
Crypt: c.Crypt,
|
|
||||||
CompressEncode: c.CompressEncode,
|
|
||||||
CompressDecode: c.CompressDecode,
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
|
@ -1,45 +0,0 @@
|
||||||
package lg
|
|
||||||
|
|
||||||
import (
|
|
||||||
"log"
|
|
||||||
"os"
|
|
||||||
"path/filepath"
|
|
||||||
"runtime"
|
|
||||||
)
|
|
||||||
|
|
||||||
var Log *log.Logger
|
|
||||||
|
|
||||||
func InitLogFile(f string, isStdout bool, logPath string) {
|
|
||||||
var prefix string
|
|
||||||
if !isStdout {
|
|
||||||
logFile, err := os.OpenFile(filepath.Join(logPath, f+"_log.txt"), os.O_RDWR|os.O_CREATE|os.O_APPEND, 0766)
|
|
||||||
if err != nil {
|
|
||||||
log.Fatalln("open file error !", err)
|
|
||||||
}
|
|
||||||
if runtime.GOOS == "windows" {
|
|
||||||
prefix = "\r\n"
|
|
||||||
}
|
|
||||||
Log = log.New(logFile, prefix, log.Ldate|log.Ltime)
|
|
||||||
} else {
|
|
||||||
Log = log.New(os.Stdout, "", log.Ldate|log.Ltime)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func Println(v ...interface{}) {
|
|
||||||
Log.Println(v...)
|
|
||||||
}
|
|
||||||
|
|
||||||
func Fatalln(v ...interface{}) {
|
|
||||||
Log.SetPrefix("error ")
|
|
||||||
Log.Fatalln(v...)
|
|
||||||
Log.SetPrefix("")
|
|
||||||
}
|
|
||||||
func Fatalf(format string, v ...interface{}) {
|
|
||||||
Log.SetPrefix("error ")
|
|
||||||
Log.Fatalf(format, v...)
|
|
||||||
Log.SetPrefix("")
|
|
||||||
}
|
|
||||||
|
|
||||||
func Printf(format string, v ...interface{}) {
|
|
||||||
Log.Printf(format, v...)
|
|
||||||
}
|
|
|
@ -0,0 +1,8 @@
|
||||||
|
package version
|
||||||
|
|
||||||
|
const VERSION = "0.0.16"
|
||||||
|
const VERSION_OK = "vrok"
|
||||||
|
|
||||||
|
func GetVersion() string {
|
||||||
|
return VERSION
|
||||||
|
}
|
|
@ -17,8 +17,8 @@ type Service interface {
|
||||||
Close() error
|
Close() error
|
||||||
}
|
}
|
||||||
|
|
||||||
//server base struct
|
//Server BaseServer struct
|
||||||
type server struct {
|
type BaseServer struct {
|
||||||
id int
|
id int
|
||||||
bridge *bridge.Bridge
|
bridge *bridge.Bridge
|
||||||
task *file.Tunnel
|
task *file.Tunnel
|
||||||
|
@ -26,21 +26,30 @@ type server struct {
|
||||||
sync.Mutex
|
sync.Mutex
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) FlowAdd(in, out int64) {
|
func NewBaseServer(bridge *bridge.Bridge, task *file.Tunnel) *BaseServer {
|
||||||
|
return &BaseServer{
|
||||||
|
bridge: bridge,
|
||||||
|
task: task,
|
||||||
|
errorContent: nil,
|
||||||
|
Mutex: sync.Mutex{},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *BaseServer) FlowAdd(in, out int64) {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
s.task.Flow.ExportFlow += out
|
s.task.Flow.ExportFlow += out
|
||||||
s.task.Flow.InletFlow += in
|
s.task.Flow.InletFlow += in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) FlowAddHost(host *file.Host, in, out int64) {
|
func (s *BaseServer) FlowAddHost(host *file.Host, in, out int64) {
|
||||||
s.Lock()
|
s.Lock()
|
||||||
defer s.Unlock()
|
defer s.Unlock()
|
||||||
host.Flow.ExportFlow += out
|
host.Flow.ExportFlow += out
|
||||||
host.Flow.InletFlow += in
|
host.Flow.InletFlow += in
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) linkCopy(link *conn.Link, c *conn.Conn, rb []byte, tunnel *conn.Conn, flow *file.Flow) {
|
func (s *BaseServer) linkCopy(link *conn.Link, c *conn.Conn, rb []byte, tunnel *conn.Conn, flow *file.Flow) {
|
||||||
if rb != nil {
|
if rb != nil {
|
||||||
if _, err := tunnel.SendMsg(rb, link); err != nil {
|
if _, err := tunnel.SendMsg(rb, link); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
|
@ -68,16 +77,17 @@ func (s *server) linkCopy(link *conn.Link, c *conn.Conn, rb []byte, tunnel *conn
|
||||||
}
|
}
|
||||||
<-link.StatusCh
|
<-link.StatusCh
|
||||||
}
|
}
|
||||||
|
s.task.Client.AddConn()
|
||||||
pool.PutBufPoolCopy(buf)
|
pool.PutBufPoolCopy(buf)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) writeConnFail(c net.Conn) {
|
func (s *BaseServer) writeConnFail(c net.Conn) {
|
||||||
c.Write([]byte(common.ConnectionFailBytes))
|
c.Write([]byte(common.ConnectionFailBytes))
|
||||||
c.Write(s.errorContent)
|
c.Write(s.errorContent)
|
||||||
}
|
}
|
||||||
|
|
||||||
//权限认证
|
//权限认证
|
||||||
func (s *server) auth(r *http.Request, c *conn.Conn, u, p string) error {
|
func (s *BaseServer) auth(r *http.Request, c *conn.Conn, u, p string) error {
|
||||||
if u != "" && p != "" && !common.CheckAuth(r, u, p) {
|
if u != "" && p != "" && !common.CheckAuth(r, u, p) {
|
||||||
c.Write([]byte(common.UnauthorizedBytes))
|
c.Write([]byte(common.UnauthorizedBytes))
|
||||||
c.Close()
|
c.Close()
|
||||||
|
@ -86,9 +96,23 @@ func (s *server) auth(r *http.Request, c *conn.Conn, u, p string) error {
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *server) checkFlow() error {
|
func (s *BaseServer) checkFlow() error {
|
||||||
if s.task.Client.Flow.FlowLimit > 0 && (s.task.Client.Flow.FlowLimit<<20) < (s.task.Client.Flow.ExportFlow+s.task.Client.Flow.InletFlow) {
|
if s.task.Client.Flow.FlowLimit > 0 && (s.task.Client.Flow.FlowLimit<<20) < (s.task.Client.Flow.ExportFlow+s.task.Client.Flow.InletFlow) {
|
||||||
return errors.New("Traffic exceeded")
|
return errors.New("Traffic exceeded")
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
//与客户端建立通道
|
||||||
|
func (s *BaseServer) DealClient(c *conn.Conn, addr string, rb []byte) error {
|
||||||
|
link := conn.NewLink(s.task.Client.GetId(), common.CONN_TCP, addr, s.task.Client.Cnf.CompressEncode, s.task.Client.Cnf.CompressDecode, s.task.Client.Cnf.Crypt, c, s.task.Flow, nil, s.task.Client.Rate, nil)
|
||||||
|
|
||||||
|
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, c.Conn.RemoteAddr().String()); err != nil {
|
||||||
|
c.Close()
|
||||||
|
return err
|
||||||
|
} else {
|
||||||
|
link.Run(true)
|
||||||
|
s.linkCopy(link, c, rb, tunnel, s.task.Flow)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
|
@ -7,17 +7,18 @@ import (
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"net/http"
|
"net/http"
|
||||||
"net/http/httputil"
|
"net/http/httputil"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strconv"
|
"strconv"
|
||||||
"sync"
|
"sync"
|
||||||
)
|
)
|
||||||
|
|
||||||
type httpServer struct {
|
type httpServer struct {
|
||||||
server
|
BaseServer
|
||||||
httpPort int //http端口
|
httpPort int //http端口
|
||||||
httpsPort int //https监听端口
|
httpsPort int //https监听端口
|
||||||
pemPath string
|
pemPath string
|
||||||
|
@ -31,7 +32,7 @@ func NewHttp(bridge *bridge.Bridge, c *file.Tunnel) *httpServer {
|
||||||
pemPath := beego.AppConfig.String("pemPath")
|
pemPath := beego.AppConfig.String("pemPath")
|
||||||
keyPath := beego.AppConfig.String("keyPath")
|
keyPath := beego.AppConfig.String("keyPath")
|
||||||
return &httpServer{
|
return &httpServer{
|
||||||
server: server{
|
BaseServer: BaseServer{
|
||||||
task: c,
|
task: c,
|
||||||
bridge: bridge,
|
bridge: bridge,
|
||||||
Mutex: sync.Mutex{},
|
Mutex: sync.Mutex{},
|
||||||
|
@ -54,26 +55,30 @@ func (s *httpServer) Start() error {
|
||||||
if s.httpPort > 0 {
|
if s.httpPort > 0 {
|
||||||
http = s.NewServer(s.httpPort)
|
http = s.NewServer(s.httpPort)
|
||||||
go func() {
|
go func() {
|
||||||
lg.Println("Start http listener, port is", s.httpPort)
|
logs.Info("Start http listener, port is", s.httpPort)
|
||||||
err := http.ListenAndServe()
|
err := http.ListenAndServe()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln(err)
|
logs.Error(err)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
if s.httpsPort > 0 {
|
if s.httpsPort > 0 {
|
||||||
if !common.FileExists(s.pemPath) {
|
if !common.FileExists(s.pemPath) {
|
||||||
lg.Fatalf("ssl certFile %s is not exist", s.pemPath)
|
logs.Error("ssl certFile %s is not exist", s.pemPath)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
if !common.FileExists(s.keyPath) {
|
if !common.FileExists(s.keyPath) {
|
||||||
lg.Fatalf("ssl keyFile %s exist", s.keyPath)
|
logs.Error("ssl keyFile %s exist", s.keyPath)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
https = s.NewServer(s.httpsPort)
|
https = s.NewServer(s.httpsPort)
|
||||||
go func() {
|
go func() {
|
||||||
lg.Println("Start https listener, port is", s.httpsPort)
|
logs.Info("Start https listener, port is", s.httpsPort)
|
||||||
err := https.ListenAndServeTLS(s.pemPath, s.keyPath)
|
err := https.ListenAndServeTLS(s.pemPath, s.keyPath)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Fatalln(err)
|
logs.Error(err)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
}()
|
}()
|
||||||
}
|
}
|
||||||
|
@ -118,9 +123,14 @@ func (s *httpServer) process(c *conn.Conn, r *http.Request) {
|
||||||
err error
|
err error
|
||||||
)
|
)
|
||||||
if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
|
if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
|
||||||
lg.Printf("the url %s %s can't be parsed!", r.Host, r.RequestURI)
|
logs.Notice("the url %s %s can't be parsed!", r.Host, r.RequestURI)
|
||||||
goto end
|
goto end
|
||||||
|
} else if !host.Client.GetConn() {
|
||||||
|
logs.Notice("Connections exceed the current client %d limit", host.Client.Id)
|
||||||
|
c.Close()
|
||||||
|
return
|
||||||
} else {
|
} else {
|
||||||
|
logs.Trace("New http(s) connection,clientId %d,host %s,url %s,remote address %s", host.Client.Id, r.Host, r.URL, r.RemoteAddr)
|
||||||
lastHost = host
|
lastHost = host
|
||||||
}
|
}
|
||||||
for {
|
for {
|
||||||
|
@ -137,22 +147,24 @@ 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 {
|
||||||
lg.Println(err)
|
logs.Notice(err)
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
lk.Run(true)
|
lk.Run(true)
|
||||||
isConn = false
|
isConn = false
|
||||||
} else {
|
} else {
|
||||||
r, err = http.ReadRequest(bufio.NewReader(c))
|
r, err = http.ReadRequest(bufio.NewReader(c))
|
||||||
|
logs.Trace("New http(s) connection,clientId %d,host %s,url %s,remote address %s", host.Client.Id, r.Host, r.URL, r.RemoteAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
|
if host, err = file.GetCsvDb().GetInfoByHost(r.Host, r); err != nil {
|
||||||
lg.Printf("the url %s %s is not found !", r.Host, r.RequestURI)
|
logs.Notice("the url %s %s can't be parsed!", r.Host, r.RequestURI)
|
||||||
break
|
break
|
||||||
} else if host != lastHost {
|
} else if host != lastHost {
|
||||||
lastHost = host
|
lastHost = host
|
||||||
isConn = true
|
isConn = true
|
||||||
|
host.Client.AddConn()
|
||||||
goto start
|
goto start
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -176,6 +188,9 @@ end:
|
||||||
tunnel.SendMsg([]byte(common.IO_EOF), lk)
|
tunnel.SendMsg([]byte(common.IO_EOF), lk)
|
||||||
}
|
}
|
||||||
c.Close()
|
c.Close()
|
||||||
|
if host != nil {
|
||||||
|
host.Client.AddConn()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *httpServer) NewServer(port int) *http.Server {
|
func (s *httpServer) NewServer(port int) *http.Server {
|
||||||
|
|
|
@ -7,7 +7,7 @@ import (
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"io"
|
"io"
|
||||||
"net"
|
"net"
|
||||||
"strconv"
|
"strconv"
|
||||||
|
@ -48,7 +48,7 @@ const (
|
||||||
)
|
)
|
||||||
|
|
||||||
type Sock5ModeServer struct {
|
type Sock5ModeServer struct {
|
||||||
server
|
BaseServer
|
||||||
listener net.Listener
|
listener net.Listener
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -67,7 +67,7 @@ func (s *Sock5ModeServer) handleRequest(c net.Conn) {
|
||||||
_, err := io.ReadFull(c, header)
|
_, err := io.ReadFull(c, header)
|
||||||
|
|
||||||
if err != nil {
|
if err != nil {
|
||||||
lg.Println("illegal request", err)
|
logs.Warn("illegal request", err)
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -165,7 +165,6 @@ func (s *Sock5ModeServer) handleBind(c net.Conn) {
|
||||||
|
|
||||||
//udp
|
//udp
|
||||||
func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||||
lg.Println("UDP Associate")
|
|
||||||
/*
|
/*
|
||||||
+----+------+------+----------+----------+----------+
|
+----+------+------+----------+----------+----------+
|
||||||
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
|RSV | FRAG | ATYP | DST.ADDR | DST.PORT | DATA |
|
||||||
|
@ -178,7 +177,7 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||||
// relay udp datagram silently, without any notification to the requesting client
|
// relay udp datagram silently, without any notification to the requesting client
|
||||||
if buf[2] != 0 {
|
if buf[2] != 0 {
|
||||||
// does not support fragmentation, drop it
|
// does not support fragmentation, drop it
|
||||||
lg.Println("does not support fragmentation, drop")
|
logs.Warn("does not support fragmentation, drop")
|
||||||
dummy := make([]byte, maxUDPPacketSize)
|
dummy := make([]byte, maxUDPPacketSize)
|
||||||
c.Read(dummy)
|
c.Read(dummy)
|
||||||
}
|
}
|
||||||
|
@ -190,13 +189,13 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||||
func (s *Sock5ModeServer) handleConn(c net.Conn) {
|
func (s *Sock5ModeServer) handleConn(c net.Conn) {
|
||||||
buf := make([]byte, 2)
|
buf := make([]byte, 2)
|
||||||
if _, err := io.ReadFull(c, buf); err != nil {
|
if _, err := io.ReadFull(c, buf); err != nil {
|
||||||
lg.Println("negotiation err", err)
|
logs.Warn("negotiation err", err)
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if version := buf[0]; version != 5 {
|
if version := buf[0]; version != 5 {
|
||||||
lg.Println("only support socks5, request from: ", c.RemoteAddr())
|
logs.Warn("only support socks5, request from: ", c.RemoteAddr())
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -204,7 +203,7 @@ func (s *Sock5ModeServer) handleConn(c net.Conn) {
|
||||||
|
|
||||||
methods := make([]byte, nMethods)
|
methods := make([]byte, nMethods)
|
||||||
if len, err := c.Read(methods); len != int(nMethods) || err != nil {
|
if len, err := c.Read(methods); len != int(nMethods) || err != nil {
|
||||||
lg.Println("wrong method")
|
logs.Warn("wrong method")
|
||||||
c.Close()
|
c.Close()
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -213,7 +212,7 @@ func (s *Sock5ModeServer) handleConn(c net.Conn) {
|
||||||
c.Write(buf)
|
c.Write(buf)
|
||||||
if err := s.Auth(c); err != nil {
|
if err := s.Auth(c); err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
lg.Println("Validation failed:", err)
|
logs.Warn("Validation failed:", err)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -271,9 +270,15 @@ func (s *Sock5ModeServer) Start() error {
|
||||||
if strings.Contains(err.Error(), "use of closed network connection") {
|
if strings.Contains(err.Error(), "use of closed network connection") {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
lg.Fatalln("accept error: ", err)
|
logs.Warn("accept error: ", err)
|
||||||
}
|
}
|
||||||
|
if s.task.Client.GetConn() {
|
||||||
|
logs.Trace("New socks5 connection,client %d,remote address %s", s.task.Client.Id, conn.RemoteAddr())
|
||||||
go s.handleConn(conn)
|
go s.handleConn(conn)
|
||||||
|
} else {
|
||||||
|
logs.Warn("Connections exceed the current client %d limit", s.task.Client.Id)
|
||||||
|
conn.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,15 +6,16 @@ import (
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"net"
|
"net"
|
||||||
|
"os"
|
||||||
"path/filepath"
|
"path/filepath"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type TunnelModeServer struct {
|
type TunnelModeServer struct {
|
||||||
server
|
BaseServer
|
||||||
process process
|
process process
|
||||||
listener *net.TCPListener
|
listener *net.TCPListener
|
||||||
}
|
}
|
||||||
|
@ -41,24 +42,16 @@ func (s *TunnelModeServer) Start() error {
|
||||||
if strings.Contains(err.Error(), "use of closed network connection") {
|
if strings.Contains(err.Error(), "use of closed network connection") {
|
||||||
break
|
break
|
||||||
}
|
}
|
||||||
lg.Println(err)
|
logs.Info(err)
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
if s.task.Client.GetConn() {
|
||||||
|
logs.Trace("New tcp connection,client %d,remote address %s", s.task.Client.Id, c.RemoteAddr())
|
||||||
go s.process(conn.NewConn(c), s)
|
go s.process(conn.NewConn(c), s)
|
||||||
}
|
|
||||||
return nil
|
|
||||||
}
|
|
||||||
|
|
||||||
//与客户端建立通道
|
|
||||||
func (s *TunnelModeServer) dealClient(c *conn.Conn, cnf *file.Config, addr string, method string, rb []byte) error {
|
|
||||||
link := conn.NewLink(s.task.Client.GetId(), common.CONN_TCP, addr, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, c, s.task.Flow, nil, s.task.Client.Rate, nil)
|
|
||||||
|
|
||||||
if tunnel, err := s.bridge.SendLinkInfo(s.task.Client.Id, link, c.Conn.RemoteAddr().String()); err != nil {
|
|
||||||
c.Close()
|
|
||||||
return err
|
|
||||||
} else {
|
} else {
|
||||||
link.Run(true)
|
logs.Info("Connections exceed the current client %d limit", s.task.Client.Id)
|
||||||
s.linkCopy(link, c, rb, tunnel, s.task.Flow)
|
c.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -70,17 +63,18 @@ func (s *TunnelModeServer) Close() error {
|
||||||
|
|
||||||
//web管理方式
|
//web管理方式
|
||||||
type WebServer struct {
|
type WebServer struct {
|
||||||
server
|
BaseServer
|
||||||
}
|
}
|
||||||
|
|
||||||
//开始
|
//开始
|
||||||
func (s *WebServer) Start() error {
|
func (s *WebServer) Start() error {
|
||||||
p, _ := beego.AppConfig.Int("httpport")
|
p, _ := beego.AppConfig.Int("httpport")
|
||||||
if !common.TestTcpPort(p) {
|
if !common.TestTcpPort(p) {
|
||||||
lg.Fatalf("Web management port %d is occupied", p)
|
logs.Error("Web management port %d is occupied", p)
|
||||||
|
os.Exit(0)
|
||||||
}
|
}
|
||||||
beego.BConfig.WebConfig.Session.SessionOn = true
|
beego.BConfig.WebConfig.Session.SessionOn = true
|
||||||
lg.Println("Web management start, access port is", p)
|
logs.Info("Web management start, access port is", p)
|
||||||
beego.SetStaticPath("/static", filepath.Join(common.GetRunPath(), "web", "static"))
|
beego.SetStaticPath("/static", filepath.Join(common.GetRunPath(), "web", "static"))
|
||||||
beego.SetViewsPath(filepath.Join(common.GetRunPath(), "web", "views"))
|
beego.SetViewsPath(filepath.Join(common.GetRunPath(), "web", "views"))
|
||||||
beego.Run()
|
beego.Run()
|
||||||
|
@ -102,23 +96,23 @@ type process func(c *conn.Conn, s *TunnelModeServer) error
|
||||||
|
|
||||||
//tcp隧道模式
|
//tcp隧道模式
|
||||||
func ProcessTunnel(c *conn.Conn, s *TunnelModeServer) error {
|
func ProcessTunnel(c *conn.Conn, s *TunnelModeServer) error {
|
||||||
return s.dealClient(c, s.task.Client.Cnf, s.task.Target, "", nil)
|
return s.DealClient(c, s.task.Target, nil)
|
||||||
}
|
}
|
||||||
|
|
||||||
//http代理模式
|
//http代理模式
|
||||||
func ProcessHttp(c *conn.Conn, s *TunnelModeServer) error {
|
func ProcessHttp(c *conn.Conn, s *TunnelModeServer) error {
|
||||||
method, addr, rb, err, r := c.GetHost()
|
_, addr, rb, err, r := c.GetHost()
|
||||||
if err != nil {
|
if err != nil {
|
||||||
c.Close()
|
c.Close()
|
||||||
lg.Println(err)
|
logs.Info(err)
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if r.Method == "CONNECT" {
|
if r.Method == "CONNECT" {
|
||||||
c.Write([]byte("HTTP/1.1 200 Connection Established\r\n"))
|
c.Write([]byte("HTTP/1.1 200 Connection Established\r\n"))
|
||||||
rb = nil //reset
|
rb = nil
|
||||||
}
|
}
|
||||||
if err := s.auth(r, c, s.task.Client.Cnf.U, s.task.Client.Cnf.P); err != nil {
|
if err := s.auth(r, c, s.task.Client.Cnf.U, s.task.Client.Cnf.P); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
return s.dealClient(c, s.task.Client.Cnf, addr, method, rb)
|
return s.DealClient(c, addr, rb)
|
||||||
}
|
}
|
||||||
|
|
|
@ -6,12 +6,13 @@ import (
|
||||||
"github.com/cnlh/nps/lib/conn"
|
"github.com/cnlh/nps/lib/conn"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/pool"
|
"github.com/cnlh/nps/lib/pool"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
"net"
|
"net"
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
type UdpModeServer struct {
|
type UdpModeServer struct {
|
||||||
server
|
BaseServer
|
||||||
listener *net.UDPConn
|
listener *net.UDPConn
|
||||||
udpMap map[string]*conn.Conn
|
udpMap map[string]*conn.Conn
|
||||||
}
|
}
|
||||||
|
@ -40,6 +41,7 @@ func (s *UdpModeServer) Start() error {
|
||||||
}
|
}
|
||||||
continue
|
continue
|
||||||
}
|
}
|
||||||
|
logs.Trace("New ydo connection,client %d,remote address %s", s.task.Client.Id, addr)
|
||||||
go s.process(addr, buf[:n])
|
go s.process(addr, buf[:n])
|
||||||
}
|
}
|
||||||
return nil
|
return nil
|
||||||
|
|
|
@ -5,10 +5,12 @@ import (
|
||||||
"github.com/cnlh/nps/bridge"
|
"github.com/cnlh/nps/bridge"
|
||||||
"github.com/cnlh/nps/lib/common"
|
"github.com/cnlh/nps/lib/common"
|
||||||
"github.com/cnlh/nps/lib/file"
|
"github.com/cnlh/nps/lib/file"
|
||||||
"github.com/cnlh/nps/lib/lg"
|
|
||||||
"github.com/cnlh/nps/server/proxy"
|
"github.com/cnlh/nps/server/proxy"
|
||||||
"github.com/cnlh/nps/server/tool"
|
"github.com/cnlh/nps/server/tool"
|
||||||
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego"
|
||||||
|
"github.com/cnlh/nps/vender/github.com/astaxie/beego/logs"
|
||||||
|
"os"
|
||||||
|
"time"
|
||||||
)
|
)
|
||||||
|
|
||||||
var (
|
var (
|
||||||
|
@ -31,7 +33,6 @@ func InitFromCsv() {
|
||||||
//Initialize services in server-side files
|
//Initialize services in server-side files
|
||||||
for _, v := range file.GetCsvDb().Tasks {
|
for _, v := range file.GetCsvDb().Tasks {
|
||||||
if v.Status {
|
if v.Status {
|
||||||
lg.Println("task start info: mode:", v.Mode, "port:", v.Port)
|
|
||||||
AddTask(v)
|
AddTask(v)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -45,6 +46,19 @@ func DealBridgeTask() {
|
||||||
case id := <-Bridge.CloseClient:
|
case id := <-Bridge.CloseClient:
|
||||||
DelTunnelAndHostByClientId(id)
|
DelTunnelAndHostByClientId(id)
|
||||||
file.GetCsvDb().DelClient(id)
|
file.GetCsvDb().DelClient(id)
|
||||||
|
case s := <-Bridge.SecretChan:
|
||||||
|
logs.Trace("New secret connection, addr", s.Conn.Conn.RemoteAddr())
|
||||||
|
if t := file.GetCsvDb().GetSecretTask(s.Password); t != nil {
|
||||||
|
if !t.Client.GetConn() {
|
||||||
|
logs.Info("Connections exceed the current client %d limit", t.Client.Id)
|
||||||
|
s.Conn.Close()
|
||||||
|
} else {
|
||||||
|
go proxy.NewBaseServer(Bridge, t).DealClient(s.Conn, t.Target, nil)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
logs.Trace("This key %s cannot be processed", s.Password)
|
||||||
|
s.Conn.Close()
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -53,18 +67,19 @@ func DealBridgeTask() {
|
||||||
func StartNewServer(bridgePort int, cnf *file.Tunnel, bridgeType string) {
|
func StartNewServer(bridgePort int, cnf *file.Tunnel, bridgeType string) {
|
||||||
Bridge = bridge.NewTunnel(bridgePort, bridgeType, common.GetBoolByStr(beego.AppConfig.String("ipLimit")), RunList)
|
Bridge = bridge.NewTunnel(bridgePort, bridgeType, common.GetBoolByStr(beego.AppConfig.String("ipLimit")), RunList)
|
||||||
if err := Bridge.StartTunnel(); err != nil {
|
if err := Bridge.StartTunnel(); err != nil {
|
||||||
lg.Fatalln("服务端开启失败", err)
|
logs.Error("服务端开启失败", err)
|
||||||
|
os.Exit(0)
|
||||||
} else {
|
} else {
|
||||||
lg.Printf("Server startup, the bridge type is %s, the bridge port is %d", bridgeType, bridgePort)
|
logs.Info("Server startup, the bridge type is %s, the bridge port is %d", bridgeType, bridgePort)
|
||||||
}
|
}
|
||||||
go DealBridgeTask()
|
go DealBridgeTask()
|
||||||
if svr := NewMode(Bridge, cnf); svr != nil {
|
if svr := NewMode(Bridge, cnf); svr != nil {
|
||||||
if err := svr.Start(); err != nil {
|
if err := svr.Start(); err != nil {
|
||||||
lg.Fatalln(err)
|
logs.Error(err)
|
||||||
}
|
}
|
||||||
RunList[cnf.Id] = svr
|
RunList[cnf.Id] = svr
|
||||||
} else {
|
} else {
|
||||||
lg.Fatalln("启动模式%s不正确", cnf.Mode)
|
logs.Error("Incorrect startup mode %s", cnf.Mode)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -103,13 +118,13 @@ func StopServer(id int) error {
|
||||||
if err := svr.Close(); err != nil {
|
if err := svr.Close(); err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
}
|
||||||
if t, err := file.GetCsvDb().GetTask(id); err != nil {
|
if t, err := file.GetCsvDb().GetTask(id); err != nil {
|
||||||
return err
|
return err
|
||||||
} else {
|
} else {
|
||||||
t.Status = false
|
t.Status = false
|
||||||
file.GetCsvDb().UpdateTask(t)
|
file.GetCsvDb().UpdateTask(t)
|
||||||
}
|
}
|
||||||
}
|
|
||||||
delete(RunList, id)
|
delete(RunList, id)
|
||||||
return nil
|
return nil
|
||||||
}
|
}
|
||||||
|
@ -118,15 +133,24 @@ func StopServer(id int) error {
|
||||||
|
|
||||||
//add task
|
//add task
|
||||||
func AddTask(t *file.Tunnel) error {
|
func AddTask(t *file.Tunnel) error {
|
||||||
|
if t.Mode == "secretServer" {
|
||||||
|
logs.Info("secret task %s start ", t.Remark)
|
||||||
|
RunList[t.Id] = nil
|
||||||
|
return nil
|
||||||
|
}
|
||||||
if b := tool.TestServerPort(t.Port, t.Mode); !b && t.Mode != "httpHostServer" {
|
if b := tool.TestServerPort(t.Port, t.Mode); !b && t.Mode != "httpHostServer" {
|
||||||
lg.Printf("taskId %d start error port %d Open Failed", t.Id, t.Port)
|
logs.Error("taskId %d start error port %d open failed", t.Id, t.Port)
|
||||||
return errors.New("the port open error")
|
return errors.New("the port open error")
|
||||||
}
|
}
|
||||||
|
if minute, err := beego.AppConfig.Int("flowStoreInterval"); err == nil && minute > 0 {
|
||||||
|
go flowSession(time.Minute * time.Duration(minute))
|
||||||
|
}
|
||||||
if svr := NewMode(Bridge, t); svr != nil {
|
if svr := NewMode(Bridge, t); svr != nil {
|
||||||
|
logs.Info("tunnel task %s start mode:%s port %d", t.Remark, t.Mode, t.Port)
|
||||||
RunList[t.Id] = svr
|
RunList[t.Id] = svr
|
||||||
go func() {
|
go func() {
|
||||||
if err := svr.Start(); err != nil {
|
if err := svr.Start(); err != nil {
|
||||||
lg.Println("clientId %d taskId %d start error %s", t.Client.Id, t.Id, err)
|
logs.Error("clientId %d taskId %d start error %s", t.Client.Id, t.Id, err)
|
||||||
delete(RunList, t.Id)
|
delete(RunList, t.Id)
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
@ -272,5 +296,21 @@ func GetDashboardData() map[string]int {
|
||||||
data["udpServerCount"] += 1
|
data["udpServerCount"] += 1
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
tcpCount := 0
|
||||||
|
for _, v := range file.GetCsvDb().Clients {
|
||||||
|
tcpCount += v.NowConn
|
||||||
|
}
|
||||||
|
data["tcpCount"] = tcpCount
|
||||||
return data
|
return data
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func flowSession(m time.Duration) {
|
||||||
|
ticker := time.NewTicker(m)
|
||||||
|
for {
|
||||||
|
select {
|
||||||
|
case <-ticker.C:
|
||||||
|
file.GetCsvDb().StoreHostToCsv()
|
||||||
|
file.GetCsvDb().StoreTasksToCsv()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
|
@ -13,6 +13,9 @@ func init() {
|
||||||
}
|
}
|
||||||
|
|
||||||
func TestServerPort(p int, m string) (b bool) {
|
func TestServerPort(p int, m string) (b bool) {
|
||||||
|
if p > 65535 || p <= 0 {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if len(ports) != 0 {
|
if len(ports) != 0 {
|
||||||
if !common.InIntArr(ports, p) {
|
if !common.InIntArr(ports, p) {
|
||||||
return false
|
return false
|
||||||
|
|
|
@ -42,6 +42,7 @@ func (s *ClientController) Add() {
|
||||||
Crypt: s.GetBoolNoErr("crypt"),
|
Crypt: s.GetBoolNoErr("crypt"),
|
||||||
},
|
},
|
||||||
RateLimit: s.GetIntNoErr("rate_limit"),
|
RateLimit: s.GetIntNoErr("rate_limit"),
|
||||||
|
MaxConn: s.GetIntNoErr("max_conn"),
|
||||||
Flow: &file.Flow{
|
Flow: &file.Flow{
|
||||||
ExportFlow: 0,
|
ExportFlow: 0,
|
||||||
InletFlow: 0,
|
InletFlow: 0,
|
||||||
|
@ -94,6 +95,7 @@ func (s *ClientController) Edit() {
|
||||||
c.Cnf.Crypt = s.GetBoolNoErr("crypt")
|
c.Cnf.Crypt = s.GetBoolNoErr("crypt")
|
||||||
c.Flow.FlowLimit = int64(s.GetIntNoErr("flow_limit"))
|
c.Flow.FlowLimit = int64(s.GetIntNoErr("flow_limit"))
|
||||||
c.RateLimit = s.GetIntNoErr("rate_limit")
|
c.RateLimit = s.GetIntNoErr("rate_limit")
|
||||||
|
c.MaxConn = s.GetIntNoErr("max_conn")
|
||||||
if c.Rate != nil {
|
if c.Rate != nil {
|
||||||
c.Rate.Stop()
|
c.Rate.Stop()
|
||||||
}
|
}
|
||||||
|
|
|
@ -44,6 +44,12 @@ func (s *IndexController) Http() {
|
||||||
s.display("index/list")
|
s.display("index/list")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (s *IndexController) Secret() {
|
||||||
|
s.SetInfo("私密代理管理")
|
||||||
|
s.SetType("secretServer")
|
||||||
|
s.display("index/list")
|
||||||
|
}
|
||||||
|
|
||||||
func (s *IndexController) Host() {
|
func (s *IndexController) Host() {
|
||||||
s.SetInfo("host模式管理")
|
s.SetInfo("host模式管理")
|
||||||
s.SetType("hostServer")
|
s.SetType("hostServer")
|
||||||
|
@ -80,6 +86,7 @@ func (s *IndexController) Add() {
|
||||||
Id: file.GetCsvDb().GetTaskId(),
|
Id: file.GetCsvDb().GetTaskId(),
|
||||||
Status: true,
|
Status: true,
|
||||||
Remark: s.GetString("remark"),
|
Remark: s.GetString("remark"),
|
||||||
|
Password: s.GetString("password"),
|
||||||
Flow: &file.Flow{},
|
Flow: &file.Flow{},
|
||||||
}
|
}
|
||||||
if !tool.TestServerPort(t.Port, t.Mode) {
|
if !tool.TestServerPort(t.Port, t.Mode) {
|
||||||
|
@ -126,6 +133,7 @@ func (s *IndexController) Edit() {
|
||||||
t.Port = s.GetIntNoErr("port")
|
t.Port = s.GetIntNoErr("port")
|
||||||
t.Mode = s.GetString("type")
|
t.Mode = s.GetString("type")
|
||||||
t.Target = s.GetString("target")
|
t.Target = s.GetString("target")
|
||||||
|
t.Password = s.GetString("password")
|
||||||
t.Id = id
|
t.Id = id
|
||||||
t.Remark = s.GetString("remark")
|
t.Remark = s.GetString("remark")
|
||||||
if t.Client, err = file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
if t.Client, err = file.GetCsvDb().GetClient(s.GetIntNoErr("client_id")); err != nil {
|
||||||
|
|
|
@ -16,6 +16,10 @@
|
||||||
<label class="control-label">速度限制(单位:KB,为空不限制)</label>
|
<label class="control-label">速度限制(单位:KB,为空不限制)</label>
|
||||||
<input class="form-control" type="text" name="rate_limit" placeholder="为空不限制">
|
<input class="form-control" type="text" name="rate_limit" placeholder="为空不限制">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" id="max_conn">
|
||||||
|
<label class="control-label">最大客户端连接数</label>
|
||||||
|
<input class="form-control" type="text" name="max_conn" placeholder="为空不限制">
|
||||||
|
</div>
|
||||||
<div class="form-group" id="u">
|
<div class="form-group" id="u">
|
||||||
<label class="control-label">验证用户名(仅socks5,web穿透支持)</label>
|
<label class="control-label">验证用户名(仅socks5,web穿透支持)</label>
|
||||||
<input class="form-control" type="text" name="u" placeholder="不填则无需验证">
|
<input class="form-control" type="text" name="u" placeholder="不填则无需验证">
|
||||||
|
|
|
@ -19,6 +19,11 @@
|
||||||
<input class="form-control" value="{{.c.RateLimit}}" type="text" name="rate_limit"
|
<input class="form-control" value="{{.c.RateLimit}}" type="text" name="rate_limit"
|
||||||
placeholder="为空不限制">
|
placeholder="为空不限制">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" id="max_conn">
|
||||||
|
<label class="control-label">最大客户端连接数</label>
|
||||||
|
<input class="form-control" value="{{.c.MaxConn}}" type="text" name="max_conn"
|
||||||
|
placeholder="为空不限制">
|
||||||
|
</div>
|
||||||
<div class="form-group" id="u">
|
<div class="form-group" id="u">
|
||||||
<label class="control-label">验证用户名(仅socks5,web穿透支持)</label>
|
<label class="control-label">验证用户名(仅socks5,web穿透支持)</label>
|
||||||
<input class="form-control" value="{{.c.Cnf.U}}" type="text" name="u"
|
<input class="form-control" value="{{.c.Cnf.U}}" type="text" name="u"
|
||||||
|
|
|
@ -11,6 +11,7 @@
|
||||||
<option {{if eq "udpServer" .type}}selected{{end}} value="udpServer">udp隧道</option>
|
<option {{if eq "udpServer" .type}}selected{{end}} value="udpServer">udp隧道</option>
|
||||||
<option {{if eq "socks5Server" .type}}selected{{end}} value="socks5Server">socks5代理</option>
|
<option {{if eq "socks5Server" .type}}selected{{end}} value="socks5Server">socks5代理</option>
|
||||||
<option {{if eq "httpProxyServer" .type}}selected{{end}} value="httpProxyServer">http代理
|
<option {{if eq "httpProxyServer" .type}}selected{{end}} value="httpProxyServer">http代理
|
||||||
|
<option {{if eq "secretServer" .type}}selected{{end}} value="secretServer">私密代理
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -30,6 +31,11 @@
|
||||||
<input value="{{.client_id}}" class="form-control" type="text" name="client_id"
|
<input value="{{.client_id}}" class="form-control" type="text" name="client_id"
|
||||||
placeholder="客户端id">
|
placeholder="客户端id">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" id="password">
|
||||||
|
<label class="control-label">私密模式唯一密钥</label>
|
||||||
|
<input class="form-control" type="text" name="password"
|
||||||
|
placeholder="私密模式唯一密钥">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile-footer">
|
<div class="tile-footer">
|
||||||
|
@ -48,6 +54,7 @@
|
||||||
arr["udpServer"] = ["type", "port", "target", "compress", "udp隧道模式,提供一条udp隧道,适用于dns、内网dns访问等,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的udp目标端口"]
|
arr["udpServer"] = ["type", "port", "target", "compress", "udp隧道模式,提供一条udp隧道,适用于dns、内网dns访问等,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,访问公网服务器的设定端口,则相当于访问内网目标地址的udp目标端口"]
|
||||||
arr["socks5Server"] = ["type", "port", "compress", "u", "p", "socks5代理模式,内网socks5代理,配合proxifer,可如同使用vpn一样访问内网设备或资源,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置socks5代理,即访问内网设备或者资源 "]
|
arr["socks5Server"] = ["type", "port", "compress", "u", "p", "socks5代理模式,内网socks5代理,配合proxifer,可如同使用vpn一样访问内网设备或资源,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置socks5代理,即访问内网设备或者资源 "]
|
||||||
arr["httpProxyServer"] = ["type", "port", "compress", "u", "p", " http代理模式,内网http代理,可访问内网网站,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置http代理,即访问内网站点"]
|
arr["httpProxyServer"] = ["type", "port", "compress", "u", "p", " http代理模式,内网http代理,可访问内网网站,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置http代理,即访问内网站点"]
|
||||||
|
arr["secretServer"] = ["type", "target", "compress", "password", "u", "p", " http代理模式,内网http代理,可访问内网网站,添加后会自动生成一个客户端验证key<br>在内网机器执行<span style='color: red'>./easyProxy -vkey=生成的key -server=公网服务器ip:下面设定的端口</span><br>建立成功后,在外网环境下本机配置http代理,即访问内网站点"]
|
||||||
arrClientHide = ["compress", "u", "p", "crypt", "mux"]
|
arrClientHide = ["compress", "u", "p", "crypt", "mux"]
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
|
|
|
@ -13,6 +13,7 @@
|
||||||
<option {{if eq "socks5Server" .t.Mode}}selected{{end}} value="socks5Server">socks5代理
|
<option {{if eq "socks5Server" .t.Mode}}selected{{end}} value="socks5Server">socks5代理
|
||||||
</option>
|
</option>
|
||||||
<option {{if eq "httpProxyServer" .t.Mode}}selected{{end}} value="httpProxyServer">http代理
|
<option {{if eq "httpProxyServer" .t.Mode}}selected{{end}} value="httpProxyServer">http代理
|
||||||
|
<option {{if eq "secretServer" .t.Mode}}selected{{end}} value="secretServer">私密代理
|
||||||
</select>
|
</select>
|
||||||
</div>
|
</div>
|
||||||
<div class="form-group">
|
<div class="form-group">
|
||||||
|
@ -34,6 +35,11 @@
|
||||||
<input class="form-control" value="{{.t.Client.Id}}" type="text" name="client_id"
|
<input class="form-control" value="{{.t.Client.Id}}" type="text" name="client_id"
|
||||||
placeholder="客户端id">
|
placeholder="客户端id">
|
||||||
</div>
|
</div>
|
||||||
|
<div class="form-group" id="password">
|
||||||
|
<label class="control-label">私密模式唯一密钥</label>
|
||||||
|
<input class="form-control" value="{{.t.Password}}" type="text" name="password"
|
||||||
|
placeholder="私密模式唯一密钥">
|
||||||
|
</div>
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
<div class="tile-footer">
|
<div class="tile-footer">
|
||||||
|
@ -52,6 +58,7 @@
|
||||||
arr["udpServer"] = ["type", "port", "target", "compress"]
|
arr["udpServer"] = ["type", "port", "target", "compress"]
|
||||||
arr["socks5Server"] = ["type", "port", "compress", "u", "p"]
|
arr["socks5Server"] = ["type", "port", "compress", "u", "p"]
|
||||||
arr["httpProxyServer"] = ["type", "port", "compress", "u", "p"]
|
arr["httpProxyServer"] = ["type", "port", "compress", "u", "p"]
|
||||||
|
arr["secretServer"] = ["type", "target", "compress", "u", "p","password"]
|
||||||
arrClientHide = ["compress", "u", "p", "crypt", "mux"]
|
arrClientHide = ["compress", "u", "p", "crypt", "mux"]
|
||||||
|
|
||||||
function resetForm() {
|
function resetForm() {
|
||||||
|
|
|
@ -10,8 +10,8 @@
|
||||||
<div class="col-md-3">
|
<div class="col-md-3">
|
||||||
<div class="widget-small danger coloured-icon"><i class="icon fa fa-home fa-3x"></i>
|
<div class="widget-small danger coloured-icon"><i class="icon fa fa-home fa-3x"></i>
|
||||||
<div class="info">
|
<div class="info">
|
||||||
<h4>域名解析数</h4>
|
<h4>当前TCP连接总数</h4>
|
||||||
<p><b>{{.data.hostCount}}</b></p>
|
<p><b>{{.data.tcpCount}}</b></p>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
</div>
|
</div>
|
||||||
|
|
|
@ -51,9 +51,11 @@
|
||||||
<li><a class="app-menu__item {{if eq "udp" .menu}}active{{end}}" href="/index/udp"><i
|
<li><a class="app-menu__item {{if eq "udp" .menu}}active{{end}}" href="/index/udp"><i
|
||||||
class="app-menu__icon fa fa-laptop"></i><span class="app-menu__label">udp隧道管理</span></a></li>
|
class="app-menu__icon fa fa-laptop"></i><span class="app-menu__label">udp隧道管理</span></a></li>
|
||||||
<li><a class="app-menu__item {{if eq "socks5" .menu}}active{{end}}" href="/index/socks5"><i
|
<li><a class="app-menu__item {{if eq "socks5" .menu}}active{{end}}" href="/index/socks5"><i
|
||||||
class="app-menu__icon fa fa-lightbulb-o"></i><span class="app-menu__label">socks5代理</span></a></li>
|
class="app-menu__icon fa fa-lightbulb-o"></i><span class="app-menu__label">socks5代理管理</span></a></li>
|
||||||
<li><a class="app-menu__item {{if eq "http" .menu}}active{{end}}" href="/index/http"><i
|
<li><a class="app-menu__item {{if eq "http" .menu}}active{{end}}" href="/index/http"><i
|
||||||
class="app-menu__icon fa fa-magic"></i><span class="app-menu__label">http代理</span></a></li>
|
class="app-menu__icon fa fa-magic"></i><span class="app-menu__label">http代理管理</span></a></li>
|
||||||
|
<li><a class="app-menu__item {{if eq "secret" .menu}}active{{end}}" href="/index/secret"><i
|
||||||
|
class="app-menu__icon fa fa-dashcube"></i><span class="app-menu__label">私密代理管理</span></a></li>
|
||||||
<li><a class="app-menu__item {{if eq "help" .menu}}active{{end}}" href="/index/help"><i
|
<li><a class="app-menu__item {{if eq "help" .menu}}active{{end}}" href="/index/help"><i
|
||||||
class="app-menu__icon fa fa-question-circle"></i><span class="app-menu__label">使用说明</span></a></li>
|
class="app-menu__icon fa fa-question-circle"></i><span class="app-menu__label">使用说明</span></a></li>
|
||||||
</ul>
|
</ul>
|
||||||
|
|
Loading…
Reference in New Issue