add functions

This commit is contained in:
刘河
2019-02-23 23:29:48 +08:00
parent 2c608ddb7f
commit 750ecb824a
36 changed files with 607 additions and 289 deletions

View File

@@ -6,22 +6,22 @@ const (
COMPRESS_NONE_DECODE
COMPRESS_SNAPY_ENCODE
COMPRESS_SNAPY_DECODE
VERIFY_EER = "vkey"
VERIFY_SUCCESS = "sucs"
WORK_MAIN = "main"
WORK_CHAN = "chan"
WORK_SEND_STATUS = "sdst"
WORK_CONFIG = "conf"
WORK_REGISTER = "rgst"
WORK_STATUS = "stus"
RES_SIGN = "sign"
RES_MSG = "msg0"
RES_CLOSE = "clse"
NEW_CONN = "conn" //新连接标志
NEW_TASK = "task" //新连接标志
NEW_CONF = "conf" //新连接标志
NEW_HOST = "host" //新连接标志
VERIFY_EER = "vkey"
VERIFY_SUCCESS = "sucs"
WORK_MAIN = "main"
WORK_CHAN = "chan"
WORK_SEND_STATUS = "sdst"
WORK_CONFIG = "conf"
WORK_REGISTER = "rgst"
WORD_SECRET = "sert"
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

View File

@@ -5,6 +5,8 @@ import (
"encoding/base64"
"encoding/binary"
"github.com/cnlh/nps/lib/crypt"
"github.com/cnlh/nps/lib/pool"
"io"
"io/ioutil"
"net"
"net/http"
@@ -246,3 +248,10 @@ func GetIpByAddr(addr string) string {
arr := strings.Split(addr, ":")
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
}

View File

@@ -1,6 +1,7 @@
package config
import (
"errors"
"github.com/cnlh/nps/lib/common"
"github.com/cnlh/nps/lib/file"
"regexp"
@@ -14,6 +15,11 @@ type CommonConfig struct {
AutoReconnection bool
Cnf *file.Config
ProxyUrl string
Client *file.Client
}
type LocalServer struct {
Port int
Password string
}
type Config struct {
content string
@@ -21,6 +27,7 @@ type Config struct {
CommonConfig *CommonConfig
Hosts []*file.Host
Tasks []*file.Tunnel
LocalServer []*LocalServer
}
func NewConfig(path string) (c *Config, err error) {
@@ -44,6 +51,11 @@ func NewConfig(path string) (c *Config, err error) {
nextIndex = len(c.content)
}
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] {
case "[common]":
c.CommonConfig = dealCommon(nowContent)
@@ -68,9 +80,11 @@ func getTitleContent(s string) string {
re, _ := regexp.Compile(`[\[\]]`)
return re.ReplaceAllString(s, "")
}
func dealCommon(s string) *CommonConfig {
c := &CommonConfig{}
c.Cnf = new(file.Config)
c.Client = file.NewClient("", true, true)
for _, v := range strings.Split(s, "\n") {
item := strings.Split(v, "=")
if len(item) == 0 {
@@ -97,10 +111,19 @@ func dealCommon(s string) *CommonConfig {
c.Cnf.Crypt = common.GetBoolByStr(item[1])
case "proxy_socks5_url":
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
}
func dealHost(s string) *file.Host {
h := &file.Host{}
var headerChange string
@@ -146,12 +169,35 @@ func dealTunnel(s string) *file.Tunnel {
t.Mode = item[1]
case "target":
t.Target = item[1]
case "targetAddr":
t.TargetAddr = item[1]
case "password":
t.Password = item[1]
}
}
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) {
var re *regexp.Regexp
re, err = regexp.Compile(`\[.+?\]`)
@@ -159,5 +205,13 @@ func getAllTitle(content string) (arr []string, err error) {
return
}
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
}

View File

@@ -6,6 +6,8 @@ import (
"encoding/binary"
"errors"
"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/pool"
"github.com/cnlh/nps/lib/rate"
@@ -317,7 +319,7 @@ func (s *Conn) GetHostInfo() (h *file.Host, err error) {
}
//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:
+----+-----+---------+
@@ -328,14 +330,15 @@ func (s *Conn) SendConfigInfo(c *file.Config) (int, error) {
*/
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)
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()
defer s.Unlock()
return s.Write(raw.Bytes())
}
//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 b []byte
if l, err = s.GetLen(); err != nil {
@@ -344,12 +347,16 @@ func (s *Conn) GetConfigInfo() (c *file.Config, err error) {
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])
c = file.NewClient(crypt.GetRandomString(16), true, false)
c.Cnf.U = arr[0]
c.Cnf.P = arr[1]
c.Cnf.Crypt = common.GetBoolByStr(arr[2])
c.Cnf.Compress = 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
}
@@ -366,7 +373,7 @@ func (s *Conn) SendTaskInfo(t *file.Tunnel) (int, error) {
*/
raw := bytes.NewBuffer([]byte{})
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()
defer s.Unlock()
return s.Write(raw.Bytes())
@@ -390,6 +397,8 @@ func (s *Conn) GetTaskInfo() (t *file.Tunnel, err error) {
t.Status = true
t.Flow = new(file.Flow)
t.Remark = arr[3]
t.TargetAddr = arr[4]
t.Password = arr[5]
t.NoStore = true
}
return

View File

@@ -8,6 +8,18 @@ import (
"net"
)
type Secret struct {
Password string
Conn *Conn
}
func NewSecret(p string, conn *Conn) *Secret {
return &Secret{
Password: p,
Conn: conn,
}
}
type Link struct {
Id int //id
ConnType string //连接类型

View File

@@ -14,7 +14,9 @@ var (
func GetCsvDb() *Csv {
once.Do(func() {
CsvDb = NewCsv(common.GetRunPath())
CsvDb.Init()
CsvDb.LoadClientFromCsv()
CsvDb.LoadTaskFromCsv()
CsvDb.LoadHostFromCsv()
})
return CsvDb
}

View File

@@ -3,9 +3,11 @@ package file
import (
"encoding/csv"
"errors"
"fmt"
"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/vender/github.com/astaxie/beego/logs"
"net/http"
"os"
"path/filepath"
@@ -33,17 +35,11 @@ type Csv struct {
sync.Mutex
}
func (s *Csv) Init() {
s.LoadClientFromCsv()
s.LoadTaskFromCsv()
s.LoadHostFromCsv()
}
func (s *Csv) StoreTasksToCsv() {
// 创建文件
csvFile, err := os.Create(filepath.Join(s.RunPath, "conf", "tasks.csv"))
if err != nil {
lg.Fatalf(err.Error())
logs.Error(err.Error())
}
defer csvFile.Close()
writer := csv.NewWriter(csvFile)
@@ -59,10 +55,13 @@ func (s *Csv) StoreTasksToCsv() {
strconv.Itoa(task.Id),
strconv.Itoa(task.Client.Id),
task.Remark,
strconv.Itoa(int(task.Flow.ExportFlow)),
strconv.Itoa(int(task.Flow.InletFlow)),
task.Password,
}
err := writer.Write(record)
if err != nil {
lg.Fatalf(err.Error())
logs.Error(err.Error())
}
}
writer.Flush()
@@ -90,20 +89,24 @@ func (s *Csv) LoadTaskFromCsv() {
path := filepath.Join(s.RunPath, "conf", "tasks.csv")
records, err := s.openFile(path)
if err != nil {
lg.Fatalln("配置文件打开错误:", path)
logs.Error("Profile Opening Error:", path)
os.Exit(0)
}
var tasks []*Tunnel
// 将每一行数据保存到内存slice中
for _, item := range records {
post := &Tunnel{
Port: common.GetIntNoErrByStr(item[0]),
Mode: item[1],
Target: item[2],
Status: common.GetBoolByStr(item[3]),
Id: common.GetIntNoErrByStr(item[4]),
Remark: item[6],
Port: common.GetIntNoErrByStr(item[0]),
Mode: item[1],
Target: item[2],
Status: common.GetBoolByStr(item[3]),
Id: common.GetIntNoErrByStr(item[4]),
Remark: item[6],
Password: item[9],
}
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 {
continue
}
@@ -142,10 +145,16 @@ func (s *Csv) GetIdByVerifyKey(vKey string, addr string) (int, error) {
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)
s.Tasks = append(s.Tasks, t)
s.StoreTasksToCsv()
return nil
}
func (s *Csv) UpdateTask(t *Tunnel) error {
@@ -171,6 +180,16 @@ func (s *Csv) DelTask(id int) error {
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) {
for _, v = range s.Tasks {
if v.Id == id {
@@ -205,6 +224,8 @@ func (s *Csv) StoreHostToCsv() {
host.Remark,
host.Location,
strconv.Itoa(host.Id),
strconv.Itoa(int(host.Flow.ExportFlow)),
strconv.Itoa(int(host.Flow.InletFlow)),
}
err1 := writer.Write(record)
if err1 != nil {
@@ -219,7 +240,8 @@ func (s *Csv) LoadClientFromCsv() {
path := filepath.Join(s.RunPath, "conf", "clients.csv")
records, err := s.openFile(path)
if err != nil {
lg.Fatalln("配置文件打开错误:", path)
logs.Error("Profile Opening Error:", path)
os.Exit(0)
}
var clients []*Client
// 将每一行数据保存到内存slice中
@@ -236,6 +258,7 @@ func (s *Csv) LoadClientFromCsv() {
Crypt: common.GetBoolByStr(item[6]),
Compress: item[7],
},
MaxConn: common.GetIntNoErrByStr(item[10]),
}
if post.Id > s.ClientIncreaseId {
s.ClientIncreaseId = post.Id
@@ -255,7 +278,8 @@ func (s *Csv) LoadHostFromCsv() {
path := filepath.Join(s.RunPath, "conf", "hosts.csv")
records, err := s.openFile(path)
if err != nil {
lg.Fatalln("配置文件打开错误:", path)
logs.Error("Profile Opening Error:", path)
os.Exit(0)
}
var hosts []*Host
// 将每一行数据保存到内存slice中
@@ -273,6 +297,8 @@ func (s *Csv) LoadHostFromCsv() {
continue
}
post.Flow = new(Flow)
post.Flow.ExportFlow = int64(common.GetIntNoErrByStr(item[8]))
post.Flow.InletFlow = int64(common.GetIntNoErrByStr(item[9]))
hosts = append(hosts, post)
if post.Id > s.HostIncreaseId {
s.HostIncreaseId = post.Id
@@ -350,7 +376,9 @@ func (s *Csv) NewClient(c *Client) {
if c.Id == 0 {
c.Id = s.GetClientId()
}
c.Flow = new(Flow)
if c.Flow == nil {
c.Flow = new(Flow)
}
s.Lock()
defer s.Unlock()
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
func (s *Csv) GetInfoByHost(host string, r *http.Request) (h *Host, err error) {
var hosts []*Host
//Handling Ported Access
host = common.GetIpByAddr(host)
for _, v := range s.Hosts {
//Remove http(s) http(s)://a.proxy.com
//*.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"))
if err != nil {
lg.Fatalln(err.Error())
logs.Error(err.Error())
}
defer csvFile.Close()
writer := csv.NewWriter(csvFile)
@@ -486,10 +516,11 @@ func (s *Csv) StoreClientsToCsv() {
client.Cnf.Compress,
strconv.Itoa(client.RateLimit),
strconv.Itoa(int(client.Flow.FlowLimit)),
strconv.Itoa(int(client.MaxConn)),
}
err := writer.Write(record)
if err != nil {
lg.Fatalln(err.Error())
logs.Error(err.Error())
}
}
writer.Flush()

View File

@@ -33,6 +33,8 @@ type Client struct {
Rate *rate.Rate //速度控制
NoStore bool
NoDisplay bool
MaxConn int //客户端最大连接数
NowConn int //当前连接数
id int
sync.RWMutex
}
@@ -62,18 +64,40 @@ func (s *Client) GetId() int {
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 {
Id int //Id
Port int //服务端监听端口
Mode string //启动方式
Target string //目标
Status bool //设置是否开启
RunStatus bool //当前运行状态
Client *Client //所属客户端id
Ports string //客户端与服务端传递
Flow *Flow
Remark string //备注
NoStore bool
Id int //Id
Port int //服务端监听端口
Mode string //启动方式
Target string //目标
Status bool //设置是否开启
RunStatus bool //当前运行状态
Client *Client //所属客户端id
Ports string //客户端与服务端传递
Flow *Flow
Password string //私密模式密码,唯一
Remark string //备注
TargetAddr string
NoStore bool
}
type Config struct {
@@ -114,15 +138,3 @@ func (s *Host) GetRandomTarget() string {
}
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,
}
}

View File

@@ -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...)
}

8
lib/version/version.go Normal file
View File

@@ -0,0 +1,8 @@
package version
const VERSION = "0.0.16"
const VERSION_OK = "vrok"
func GetVersion() string {
return VERSION
}