mirror of
https://github.com/ehang-io/nps.git
synced 2025-09-01 19:06:52 +00:00
客户端配置,端口白名单等
This commit is contained in:
@@ -1,19 +1,25 @@
|
||||
package common
|
||||
|
||||
const (
|
||||
CONN_DATA_SEQ = "*#*"
|
||||
COMPRESS_NONE_ENCODE = iota
|
||||
COMPRESS_NONE_DECODE
|
||||
COMPRESS_SNAPY_ENCODE
|
||||
COMPRESS_SNAPY_DECODE
|
||||
VERIFY_EER = "vkey"
|
||||
WORK_MAIN = "main"
|
||||
WORK_CHAN = "chan"
|
||||
RES_SIGN = "sign"
|
||||
RES_MSG = "msg0"
|
||||
RES_CLOSE = "clse"
|
||||
NEW_CONN = "conn" //新连接标志
|
||||
NEW_TASK = "task" //新连接标志
|
||||
CONN_SUCCESS = "sucs"
|
||||
VERIFY_EER = "vkey"
|
||||
VERIFY_SUCCESS = "sucs"
|
||||
WORK_MAIN = "main"
|
||||
WORK_CHAN = "chan"
|
||||
WORK_CONFIG = "conf"
|
||||
WORK_STATUS = "stus"
|
||||
RES_SIGN = "sign"
|
||||
RES_MSG = "msg0"
|
||||
RES_CLOSE = "clse"
|
||||
NEW_CONN = "conn" //新连接标志
|
||||
NEW_TASK = "task" //新连接标志
|
||||
NEW_CONF = "conf" //新连接标志
|
||||
NEW_HOST = "host" //新连接标志
|
||||
|
||||
CONN_TCP = "tcp"
|
||||
CONN_UDP = "udp"
|
||||
UnauthorizedBytes = `HTTP/1.1 401 Unauthorized
|
||||
|
@@ -56,7 +56,7 @@ func GetLogPath() string {
|
||||
}
|
||||
|
||||
//interface pid file path
|
||||
func GetPidPath() string {
|
||||
func GetTmpPath() string {
|
||||
var path string
|
||||
if IsWindows() {
|
||||
path = "./"
|
||||
|
@@ -144,7 +144,11 @@ func FileExists(name string) bool {
|
||||
//Judge whether the TCP port can open normally
|
||||
func TestTcpPort(port int) bool {
|
||||
l, err := net.ListenTCP("tcp", &net.TCPAddr{net.ParseIP("0.0.0.0"), port, ""})
|
||||
defer l.Close()
|
||||
defer func() {
|
||||
if l != nil {
|
||||
l.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@@ -154,7 +158,11 @@ func TestTcpPort(port int) bool {
|
||||
//Judge whether the UDP port can open normally
|
||||
func TestUdpPort(port int) bool {
|
||||
l, err := net.ListenUDP("udp", &net.UDPAddr{net.ParseIP("0.0.0.0"), port, ""})
|
||||
defer l.Close()
|
||||
defer func() {
|
||||
if l != nil {
|
||||
l.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
return false
|
||||
}
|
||||
@@ -168,9 +176,28 @@ func BinaryWrite(raw *bytes.Buffer, v ...string) {
|
||||
buffer := new(bytes.Buffer)
|
||||
var l int32
|
||||
for _, v := range v {
|
||||
l += int32(len([]byte(v))) + int32(len([]byte("#")))
|
||||
l += int32(len([]byte(v))) + int32(len([]byte(CONN_DATA_SEQ)))
|
||||
binary.Write(buffer, binary.LittleEndian, []byte(v))
|
||||
binary.Write(buffer, binary.LittleEndian, []byte("#"))
|
||||
binary.Write(buffer, binary.LittleEndian, []byte(CONN_DATA_SEQ))
|
||||
}
|
||||
binary.Write(raw, binary.LittleEndian, l)
|
||||
binary.Write(raw, binary.LittleEndian, buffer.Bytes())
|
||||
}
|
||||
|
||||
func InArr(arr []string, val string) bool {
|
||||
for _, v := range arr {
|
||||
if v == val {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func InIntArr(arr []int, val int) bool {
|
||||
for _, v := range arr {
|
||||
if v == val {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
158
lib/config/config.go
Normal file
158
lib/config/config.go
Normal file
@@ -0,0 +1,158 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"github.com/cnlh/nps/lib/common"
|
||||
"github.com/cnlh/nps/lib/file"
|
||||
"regexp"
|
||||
"strings"
|
||||
)
|
||||
|
||||
type CommonConfig struct {
|
||||
Server string
|
||||
VKey string
|
||||
Tp string //bridgeType kcp or tcp
|
||||
AutoReconnection bool
|
||||
Cnf *file.Config
|
||||
}
|
||||
type Config struct {
|
||||
content string
|
||||
title []string
|
||||
CommonConfig *CommonConfig
|
||||
Hosts []*file.Host
|
||||
Tasks []*file.Tunnel
|
||||
}
|
||||
|
||||
func NewConfig(path string) (c *Config, err error) {
|
||||
c = new(Config)
|
||||
var b []byte
|
||||
if b, err = common.ReadAllFromFile(path); err != nil {
|
||||
return
|
||||
} else {
|
||||
c.content = string(b)
|
||||
if c.title, err = getAllTitle(c.content); err != nil {
|
||||
return
|
||||
}
|
||||
var nowIndex int
|
||||
var nextIndex int
|
||||
var nowContent string
|
||||
for i := 0; i < len(c.title); i++ {
|
||||
nowIndex = strings.Index(c.content, c.title[i]) + len(c.title[i])
|
||||
if i < len(c.title)-1 {
|
||||
nextIndex = strings.Index(c.content, c.title[i+1])
|
||||
} else {
|
||||
nextIndex = len(c.content)
|
||||
}
|
||||
nowContent = c.content[nowIndex:nextIndex]
|
||||
switch c.title[i] {
|
||||
case "[common]":
|
||||
c.CommonConfig = dealCommon(nowContent)
|
||||
default:
|
||||
if strings.Index(nowContent, "host") > -1 {
|
||||
h := dealHost(nowContent)
|
||||
h.Remark = getTitleContent(c.title[i])
|
||||
c.Hosts = append(c.Hosts, h)
|
||||
} else {
|
||||
t := dealTunnel(nowContent)
|
||||
t.Remark = getTitleContent(c.title[i])
|
||||
c.Tasks = append(c.Tasks, t)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
func getTitleContent(s string) string {
|
||||
re, _ := regexp.Compile(`[\[\]]`)
|
||||
return re.ReplaceAllString(s, "")
|
||||
}
|
||||
func dealCommon(s string) *CommonConfig {
|
||||
c := &CommonConfig{}
|
||||
c.Cnf = new(file.Config)
|
||||
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 "server":
|
||||
c.Server = item[1]
|
||||
case "vkey":
|
||||
c.VKey = item[1]
|
||||
case "tp":
|
||||
c.Tp = item[1]
|
||||
case "auto_reconnection":
|
||||
c.AutoReconnection = common.GetBoolByStr(item[1])
|
||||
case "username":
|
||||
c.Cnf.U = item[1]
|
||||
case "password":
|
||||
c.Cnf.P = item[1]
|
||||
case "compress":
|
||||
c.Cnf.Compress = item[1]
|
||||
case "crypt":
|
||||
c.Cnf.Crypt = common.GetBoolByStr(item[1])
|
||||
}
|
||||
}
|
||||
return c
|
||||
}
|
||||
func dealHost(s string) *file.Host {
|
||||
h := &file.Host{}
|
||||
var headerChange string
|
||||
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 "host":
|
||||
h.Host = item[1]
|
||||
case "target":
|
||||
h.Target = strings.Replace(item[1], ",", "\n", -1)
|
||||
case "host_change":
|
||||
h.HostChange = item[1]
|
||||
default:
|
||||
if strings.Contains(item[0], "header") {
|
||||
headerChange += strings.Replace(item[0], "header_", "", -1) + ":" + item[1] + "\n"
|
||||
}
|
||||
h.HeaderChange = headerChange
|
||||
}
|
||||
}
|
||||
return h
|
||||
}
|
||||
|
||||
func dealTunnel(s string) *file.Tunnel {
|
||||
t := &file.Tunnel{}
|
||||
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":
|
||||
t.Port = common.GetIntNoErrByStr(item[1])
|
||||
case "mode":
|
||||
t.Mode = item[1]
|
||||
case "target":
|
||||
t.Target = item[1]
|
||||
}
|
||||
}
|
||||
return t
|
||||
|
||||
}
|
||||
|
||||
func getAllTitle(content string) (arr []string, err error) {
|
||||
var re *regexp.Regexp
|
||||
re, err = regexp.Compile(`\[.+?\]`)
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
arr = re.FindAllString(content, -1)
|
||||
return
|
||||
}
|
69
lib/config/config_test.go
Normal file
69
lib/config/config_test.go
Normal file
@@ -0,0 +1,69 @@
|
||||
package config
|
||||
|
||||
import (
|
||||
"log"
|
||||
"regexp"
|
||||
"testing"
|
||||
)
|
||||
|
||||
func TestReg(t *testing.T) {
|
||||
content := `
|
||||
[common]
|
||||
server=127.0.0.1:8284
|
||||
tp=tcp
|
||||
vkey=123
|
||||
[web2]
|
||||
host=www.baidu.com
|
||||
host_change=www.sina.com
|
||||
target=127.0.0.1:8080,127.0.0.1:8082
|
||||
header_cookkile=122123
|
||||
header_user-Agent=122123
|
||||
[web2]
|
||||
host=www.baidu.com
|
||||
host_change=www.sina.com
|
||||
target=127.0.0.1:8080,127.0.0.1:8082
|
||||
header_cookkile="122123"
|
||||
header_user-Agent=122123
|
||||
[tunnel1]
|
||||
type=udp
|
||||
target=127.0.0.1:8080
|
||||
port=9001
|
||||
compress=snappy
|
||||
crypt=true
|
||||
u=1
|
||||
p=2
|
||||
[tunnel2]
|
||||
type=tcp
|
||||
target=127.0.0.1:8080
|
||||
port=9001
|
||||
compress=snappy
|
||||
crypt=true
|
||||
u=1
|
||||
p=2
|
||||
`
|
||||
re, err := regexp.Compile(`\[.+?\]`)
|
||||
if err != nil {
|
||||
t.Fail()
|
||||
}
|
||||
log.Println(re.FindAllString(content, -1))
|
||||
}
|
||||
|
||||
func TestDealCommon(t *testing.T) {
|
||||
s := `server=127.0.0.1:8284
|
||||
tp=tcp
|
||||
vkey=123`
|
||||
f := new(CommonConfig)
|
||||
f.Server = "127.0.0.1:8284"
|
||||
f.Tp = "tcp"
|
||||
f.VKey = "123"
|
||||
if c := dealCommon(s); *c != *f {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
||||
|
||||
func TestGetTitleContent(t *testing.T) {
|
||||
s := "[common]"
|
||||
if getTitleContent(s) != "common" {
|
||||
t.Fail()
|
||||
}
|
||||
}
|
120
lib/conn/conn.go
120
lib/conn/conn.go
@@ -264,6 +264,98 @@ func (s *Conn) GetLinkInfo() (lk *Link, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//send host info
|
||||
func (s *Conn) SendHostInfo(h *file.Host) (int, error) {
|
||||
/*
|
||||
The task info is formed as follows:
|
||||
+----+-----+---------+
|
||||
|type| len | content |
|
||||
+----+---------------+
|
||||
| 4 | 4 | ... |
|
||||
+----+---------------+
|
||||
*/
|
||||
raw := bytes.NewBuffer([]byte{})
|
||||
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_HOST))
|
||||
common.BinaryWrite(raw, h.Host, h.Target, h.HeaderChange, h.HostChange, h.Remark)
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.Write(raw.Bytes())
|
||||
}
|
||||
|
||||
func (s *Conn) GetAddStatus() (b bool) {
|
||||
binary.Read(s.Conn, binary.LittleEndian, &b)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Conn) WriteAddOk() error {
|
||||
return binary.Write(s.Conn, binary.LittleEndian, true)
|
||||
}
|
||||
|
||||
func (s *Conn) WriteAddFail() error {
|
||||
defer s.Close()
|
||||
return binary.Write(s.Conn, binary.LittleEndian, false)
|
||||
}
|
||||
|
||||
//get task info
|
||||
func (s *Conn) GetHostInfo() (h *file.Host, err error) {
|
||||
var l int
|
||||
var b []byte
|
||||
if l, err = s.GetLen(); err != nil {
|
||||
return
|
||||
} else if b, err = s.ReadLen(l); err != nil {
|
||||
return
|
||||
} else {
|
||||
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
||||
h = new(file.Host)
|
||||
h.Host = arr[0]
|
||||
h.Target = arr[1]
|
||||
h.HeaderChange = arr[2]
|
||||
h.HostChange = arr[3]
|
||||
h.Remark = arr[4]
|
||||
h.Flow = new(file.Flow)
|
||||
h.NoStore = true
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//send task info
|
||||
func (s *Conn) SendConfigInfo(c *file.Config) (int, error) {
|
||||
/*
|
||||
The task info is formed as follows:
|
||||
+----+-----+---------+
|
||||
|type| len | content |
|
||||
+----+---------------+
|
||||
| 4 | 4 | ... |
|
||||
+----+---------------+
|
||||
*/
|
||||
raw := bytes.NewBuffer([]byte{})
|
||||
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_CONF))
|
||||
common.BinaryWrite(raw, c.U, c.P, common.GetStrByBool(c.Crypt), c.Compress)
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.Write(raw.Bytes())
|
||||
}
|
||||
|
||||
//get task info
|
||||
func (s *Conn) GetConfigInfo() (c *file.Config, err error) {
|
||||
var l int
|
||||
var b []byte
|
||||
if l, err = s.GetLen(); err != nil {
|
||||
return
|
||||
} else if b, err = s.ReadLen(l); err != nil {
|
||||
return
|
||||
} else {
|
||||
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
||||
c = new(file.Config)
|
||||
c.U = arr[0]
|
||||
c.P = arr[1]
|
||||
c.Crypt = common.GetBoolByStr(arr[2])
|
||||
c.Compress = arr[3]
|
||||
c.CompressDecode, c.CompressDecode = common.GetCompressType(arr[3])
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//send task info
|
||||
func (s *Conn) SendTaskInfo(t *file.Tunnel) (int, error) {
|
||||
/*
|
||||
@@ -275,8 +367,8 @@ func (s *Conn) SendTaskInfo(t *file.Tunnel) (int, error) {
|
||||
+----+---------------+
|
||||
*/
|
||||
raw := bytes.NewBuffer([]byte{})
|
||||
binary.Write(raw, binary.LittleEndian, common.NEW_TASK)
|
||||
common.BinaryWrite(raw, t.Mode, string(t.TcpPort), string(t.Target), string(t.Config.U), string(t.Config.P), common.GetStrByBool(t.Config.Crypt), t.Config.Compress, t.Remark)
|
||||
binary.Write(raw, binary.LittleEndian, []byte(common.NEW_TASK))
|
||||
common.BinaryWrite(raw, t.Mode, strconv.Itoa(t.Port), t.Target, t.Remark)
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.Write(raw.Bytes())
|
||||
@@ -291,23 +383,16 @@ func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
|
||||
} else if b, err = s.ReadLen(l); err != nil {
|
||||
return
|
||||
} else {
|
||||
arr := strings.Split(string(b), "#")
|
||||
arr := strings.Split(string(b), common.CONN_DATA_SEQ)
|
||||
t = new(file.Tunnel)
|
||||
t.Mode = arr[0]
|
||||
t.TcpPort, _ = strconv.Atoi(arr[1])
|
||||
t.Port, _ = strconv.Atoi(arr[1])
|
||||
t.Target = arr[2]
|
||||
t.Config = new(file.Config)
|
||||
t.Config.U = arr[3]
|
||||
t.Config.P = arr[4]
|
||||
t.Config.Compress = arr[5]
|
||||
t.Config.CompressDecode, t.Config.CompressDecode = common.GetCompressType(arr[5])
|
||||
t.Id = file.GetCsvDb().GetTaskId()
|
||||
t.Status = true
|
||||
if t.Client, err = file.GetCsvDb().GetClient(0); err != nil {
|
||||
return
|
||||
}
|
||||
t.Flow = new(file.Flow)
|
||||
t.Remark = arr[6]
|
||||
t.UseClientCnf = false
|
||||
t.Remark = arr[3]
|
||||
t.NoStore = true
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -369,6 +454,13 @@ func (s *Conn) WriteMain() (int, error) {
|
||||
return s.Write([]byte(common.WORK_MAIN))
|
||||
}
|
||||
|
||||
//write main
|
||||
func (s *Conn) WriteConfig() (int, error) {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
return s.Write([]byte(common.WORK_CONFIG))
|
||||
}
|
||||
|
||||
//write chan
|
||||
func (s *Conn) WriteChan() (int, error) {
|
||||
s.Lock()
|
||||
|
@@ -18,6 +18,7 @@ type Link struct {
|
||||
UdpListener *net.UDPConn
|
||||
Rate *rate.Rate
|
||||
UdpRemoteAddr *net.UDPAddr
|
||||
Stop chan bool
|
||||
}
|
||||
|
||||
func NewLink(id int, connType string, host string, en, de int, crypt bool, c *Conn, flow *file.Flow, udpListener *net.UDPConn, rate *rate.Rate, UdpRemoteAddr *net.UDPAddr) *Link {
|
||||
|
@@ -45,20 +45,17 @@ func (s *Csv) StoreTasksToCsv() {
|
||||
defer csvFile.Close()
|
||||
writer := csv.NewWriter(csvFile)
|
||||
for _, task := range s.Tasks {
|
||||
if task.NoStore {
|
||||
continue
|
||||
}
|
||||
lg.Println(task)
|
||||
record := []string{
|
||||
strconv.Itoa(task.TcpPort),
|
||||
strconv.Itoa(task.Port),
|
||||
task.Mode,
|
||||
task.Target,
|
||||
task.Config.U,
|
||||
task.Config.P,
|
||||
task.Config.Compress,
|
||||
common.GetStrByBool(task.Status),
|
||||
common.GetStrByBool(task.Config.Crypt),
|
||||
strconv.Itoa(task.Config.CompressEncode),
|
||||
strconv.Itoa(task.Config.CompressDecode),
|
||||
strconv.Itoa(task.Id),
|
||||
strconv.Itoa(task.Client.Id),
|
||||
strconv.FormatBool(task.UseClientCnf),
|
||||
task.Remark,
|
||||
}
|
||||
err := writer.Write(record)
|
||||
@@ -97,24 +94,15 @@ func (s *Csv) LoadTaskFromCsv() {
|
||||
// 将每一行数据保存到内存slice中
|
||||
for _, item := range records {
|
||||
post := &Tunnel{
|
||||
TcpPort: common.GetIntNoErrByStr(item[0]),
|
||||
Mode: item[1],
|
||||
Target: item[2],
|
||||
Config: &Config{
|
||||
U: item[3],
|
||||
P: item[4],
|
||||
Compress: item[5],
|
||||
Crypt: common.GetBoolByStr(item[7]),
|
||||
CompressEncode: common.GetIntNoErrByStr(item[8]),
|
||||
CompressDecode: common.GetIntNoErrByStr(item[9]),
|
||||
},
|
||||
Status: common.GetBoolByStr(item[6]),
|
||||
Id: common.GetIntNoErrByStr(item[10]),
|
||||
UseClientCnf: common.GetBoolByStr(item[12]),
|
||||
Remark: item[13],
|
||||
Port: common.GetIntNoErrByStr(item[0]),
|
||||
Mode: item[1],
|
||||
Target: item[2],
|
||||
Status: common.GetBoolByStr(item[3]),
|
||||
Id: common.GetIntNoErrByStr(item[4]),
|
||||
Remark: item[6],
|
||||
}
|
||||
post.Flow = new(Flow)
|
||||
if post.Client, err = s.GetClient(common.GetIntNoErrByStr(item[11])); err != nil {
|
||||
if post.Client, err = s.GetClient(common.GetIntNoErrByStr(item[5])); err != nil {
|
||||
continue
|
||||
}
|
||||
tasks = append(tasks, post)
|
||||
@@ -197,6 +185,9 @@ func (s *Csv) StoreHostToCsv() {
|
||||
// 将map中的Post转换成slice,因为csv的Write需要slice参数
|
||||
// 并写入csv文件
|
||||
for _, host := range s.Hosts {
|
||||
if host.NoStore {
|
||||
continue
|
||||
}
|
||||
record := []string{
|
||||
host.Host,
|
||||
host.Target,
|
||||
@@ -286,11 +277,22 @@ func (s *Csv) DelHost(host string) error {
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) IsHostExist(host string) bool {
|
||||
for _, v := range s.Hosts {
|
||||
if v.Host == host {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func (s *Csv) NewHost(t *Host) {
|
||||
if s.IsHostExist(t.Host) {
|
||||
return
|
||||
}
|
||||
t.Flow = new(Flow)
|
||||
s.Hosts = append(s.Hosts, t)
|
||||
s.StoreHostToCsv()
|
||||
|
||||
}
|
||||
|
||||
func (s *Csv) UpdateHost(t *Host) error {
|
||||
@@ -333,9 +335,12 @@ func (s *Csv) DelClient(id int) error {
|
||||
}
|
||||
|
||||
func (s *Csv) NewClient(c *Client) {
|
||||
if c.Id == 0 {
|
||||
c.Id = s.GetClientId()
|
||||
}
|
||||
c.Flow = new(Flow)
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
c.Flow = new(Flow)
|
||||
s.Clients = append(s.Clients, c)
|
||||
s.StoreClientsToCsv()
|
||||
}
|
||||
@@ -369,6 +374,9 @@ func (s *Csv) GetClientList(start, length int) ([]*Client, int) {
|
||||
list := make([]*Client, 0)
|
||||
var cnt int
|
||||
for _, v := range s.Clients {
|
||||
if v.NoDisplay {
|
||||
continue
|
||||
}
|
||||
cnt++
|
||||
if start--; start < 0 {
|
||||
if length--; length > 0 {
|
||||
@@ -385,10 +393,32 @@ func (s *Csv) GetClient(id int) (v *Client, err error) {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New("未找到")
|
||||
err = errors.New("未找到客户端")
|
||||
return
|
||||
}
|
||||
func (s *Csv) GetClientIdByVkey(vkey string) (id int, err error) {
|
||||
for _, v := range s.Clients {
|
||||
if v.VerifyKey == vkey {
|
||||
id = v.Id
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New("未找到客户端")
|
||||
return
|
||||
}
|
||||
|
||||
//get key by host from x
|
||||
func (s *Csv) GetInfoByHost(host string) (h *Host, err error) {
|
||||
for _, v := range s.Hosts {
|
||||
s := strings.Split(host, ":")
|
||||
if s[0] == v.Host {
|
||||
h = v
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New("未找到host对应的内网目标")
|
||||
return
|
||||
}
|
||||
func (s *Csv) StoreClientsToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(filepath.Join(s.RunPath, "conf", "clients.csv"))
|
||||
@@ -398,6 +428,9 @@ func (s *Csv) StoreClientsToCsv() {
|
||||
defer csvFile.Close()
|
||||
writer := csv.NewWriter(csvFile)
|
||||
for _, client := range s.Clients {
|
||||
if client.NoStore {
|
||||
continue
|
||||
}
|
||||
record := []string{
|
||||
strconv.Itoa(client.Id),
|
||||
client.VerifyKey,
|
||||
|
@@ -31,10 +31,30 @@ type Client struct {
|
||||
RateLimit int //速度限制 /kb
|
||||
Flow *Flow //流量
|
||||
Rate *rate.Rate //速度控制
|
||||
NoStore bool
|
||||
NoDisplay bool
|
||||
id int
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
func NewClient(vKey string, noStore bool, noDisplay bool) *Client {
|
||||
return &Client{
|
||||
Cnf: new(Config),
|
||||
Id: 0,
|
||||
VerifyKey: vKey,
|
||||
Addr: "",
|
||||
Remark: "",
|
||||
Status: true,
|
||||
IsConnect: false,
|
||||
RateLimit: 0,
|
||||
Flow: new(Flow),
|
||||
Rate: nil,
|
||||
NoStore: noStore,
|
||||
id: GetCsvDb().GetClientId(),
|
||||
RWMutex: sync.RWMutex{},
|
||||
NoDisplay: noDisplay,
|
||||
}
|
||||
}
|
||||
func (s *Client) GetId() int {
|
||||
s.Lock()
|
||||
defer s.Unlock()
|
||||
@@ -43,16 +63,16 @@ func (s *Client) GetId() int {
|
||||
}
|
||||
|
||||
type Tunnel struct {
|
||||
Id int //Id
|
||||
TcpPort int //服务端监听端口
|
||||
Mode string //启动方式
|
||||
Target string //目标
|
||||
Status bool //是否开启
|
||||
Client *Client //所属客户端id
|
||||
Flow *Flow
|
||||
Config *Config
|
||||
UseClientCnf bool //是否继承客户端配置
|
||||
Remark string //备注
|
||||
Id int //Id
|
||||
Port int //服务端监听端口
|
||||
Mode string //启动方式
|
||||
Target string //目标
|
||||
Status bool //设置是否开启
|
||||
RunStatus bool //当前运行状态
|
||||
Client *Client //所属客户端id
|
||||
Flow *Flow
|
||||
Remark string //备注
|
||||
NoStore bool
|
||||
}
|
||||
|
||||
type Config struct {
|
||||
@@ -74,6 +94,7 @@ type Host struct {
|
||||
Remark string //备注
|
||||
NowIndex int
|
||||
TargetArr []string
|
||||
NoStore bool
|
||||
sync.RWMutex
|
||||
}
|
||||
|
||||
|
@@ -121,7 +121,7 @@ doLit:
|
||||
//
|
||||
// This always copies 16 bytes, instead of only length bytes, but that's
|
||||
// OK. If the input is a valid Snappy encoding then subsequent iterations
|
||||
// will fix up the overrun. Otherwise, Decode returns a nil []byte (and a
|
||||
// will fix up the overserver. Otherwise, Decode returns a nil []byte (and a
|
||||
// non-nil error), so the overrun will be ignored.
|
||||
//
|
||||
// Note that on amd64, it is legal and cheap to issue unaligned 8-byte or
|
||||
|
@@ -473,7 +473,7 @@ emitLiteralFastPath:
|
||||
// (Encode's documentation says that dst and src must not overlap.)
|
||||
//
|
||||
// This always copies 16 bytes, instead of only len(lit) bytes, but that's
|
||||
// OK. Subsequent iterations will fix up the overrun.
|
||||
// OK. Subsequent iterations will fix up the overserver.
|
||||
//
|
||||
// Note that on amd64, it is legal and cheap to issue unaligned 8-byte or
|
||||
// 16-byte loads and stores. This technique probably wouldn't be as
|
||||
|
Reference in New Issue
Block a user