mirror of
https://github.com/ehang-io/nps.git
synced 2025-09-02 03:16:53 +00:00
新功能+bug修复
This commit is contained in:
144
server/file.go
144
server/file.go
@@ -23,14 +23,16 @@ type ServerConfig struct {
|
||||
ClientStatus int //客s户端状态
|
||||
Crypt bool //是否加密
|
||||
Mux bool //是否加密
|
||||
CompressEncode int
|
||||
CompressDecode int
|
||||
CompressEncode int //加密方式
|
||||
CompressDecode int //解密方式
|
||||
}
|
||||
|
||||
type HostList struct {
|
||||
Vkey string //服务端与客户端通信端口
|
||||
Host string //启动方式
|
||||
Target string //目标
|
||||
Vkey string //服务端与客户端通信端口
|
||||
Host string //启动方式
|
||||
Target string //目标
|
||||
HeaderChange string //host修改
|
||||
HostChange string //host修改
|
||||
}
|
||||
|
||||
func NewCsv(runList map[string]interface{}) *Csv {
|
||||
@@ -125,64 +127,6 @@ func (s *Csv) LoadTaskFromCsv() {
|
||||
s.Tasks = tasks
|
||||
}
|
||||
|
||||
func (s *Csv) StoreHostToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(beego.AppPath + "/conf/hosts.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer csvFile.Close()
|
||||
// 获取csv的Writer
|
||||
writer := csv.NewWriter(csvFile)
|
||||
// 将map中的Post转换成slice,因为csv的Write需要slice参数
|
||||
// 并写入csv文件
|
||||
for _, host := range s.Hosts {
|
||||
record := []string{
|
||||
host.Host,
|
||||
host.Target,
|
||||
host.Vkey,
|
||||
}
|
||||
err1 := writer.Write(record)
|
||||
if err1 != nil {
|
||||
panic(err1)
|
||||
}
|
||||
}
|
||||
// 确保所有内存数据刷到csv文件
|
||||
writer.Flush()
|
||||
}
|
||||
|
||||
func (s *Csv) LoadHostFromCsv() {
|
||||
// 打开文件
|
||||
file, err := os.Open(beego.AppPath + "/conf/hosts.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 获取csv的reader
|
||||
reader := csv.NewReader(file)
|
||||
|
||||
// 设置FieldsPerRecord为-1
|
||||
reader.FieldsPerRecord = -1
|
||||
|
||||
// 读取文件中所有行保存到slice中
|
||||
records, err := reader.ReadAll()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var hosts []*HostList
|
||||
// 将每一行数据保存到内存slice中
|
||||
for _, item := range records {
|
||||
post := &HostList{
|
||||
Vkey: item[2],
|
||||
Host: item[0],
|
||||
Target: item[1],
|
||||
}
|
||||
hosts = append(hosts, post)
|
||||
}
|
||||
s.Hosts = hosts
|
||||
}
|
||||
|
||||
func (s *Csv) NewTask(t *ServerConfig) {
|
||||
s.Tasks = append(s.Tasks, t)
|
||||
s.StoreTasksToCsv()
|
||||
@@ -200,6 +144,18 @@ func (s *Csv) UpdateTask(t *ServerConfig) error {
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) UpdateHost(t *HostList) error {
|
||||
for k, v := range s.Hosts {
|
||||
if v.Host == t.Host {
|
||||
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
|
||||
s.Hosts = append(s.Hosts, t)
|
||||
s.StoreHostToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) AddRunList(vKey string, svr interface{}) {
|
||||
s.RunList[vKey] = svr
|
||||
}
|
||||
@@ -229,6 +185,68 @@ func (s *Csv) GetTask(vKey string) (v *ServerConfig, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Csv) StoreHostToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(beego.AppPath + "/conf/hosts.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer csvFile.Close()
|
||||
// 获取csv的Writer
|
||||
writer := csv.NewWriter(csvFile)
|
||||
// 将map中的Post转换成slice,因为csv的Write需要slice参数
|
||||
// 并写入csv文件
|
||||
for _, host := range s.Hosts {
|
||||
record := []string{
|
||||
host.Host,
|
||||
host.Target,
|
||||
host.Vkey,
|
||||
host.HeaderChange,
|
||||
host.HostChange,
|
||||
}
|
||||
err1 := writer.Write(record)
|
||||
if err1 != nil {
|
||||
panic(err1)
|
||||
}
|
||||
}
|
||||
// 确保所有内存数据刷到csv文件
|
||||
writer.Flush()
|
||||
}
|
||||
|
||||
func (s *Csv) LoadHostFromCsv() {
|
||||
// 打开文件
|
||||
file, err := os.Open(beego.AppPath + "/conf/hosts.csv")
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
defer file.Close()
|
||||
|
||||
// 获取csv的reader
|
||||
reader := csv.NewReader(file)
|
||||
|
||||
// 设置FieldsPerRecord为-1
|
||||
reader.FieldsPerRecord = -1
|
||||
|
||||
// 读取文件中所有行保存到slice中
|
||||
records, err := reader.ReadAll()
|
||||
if err != nil {
|
||||
panic(err)
|
||||
}
|
||||
var hosts []*HostList
|
||||
// 将每一行数据保存到内存slice中
|
||||
for _, item := range records {
|
||||
post := &HostList{
|
||||
Vkey: item[2],
|
||||
Host: item[0],
|
||||
Target: item[1],
|
||||
HeaderChange: item[3],
|
||||
HostChange: item[4],
|
||||
}
|
||||
hosts = append(hosts, post)
|
||||
}
|
||||
s.Hosts = hosts
|
||||
}
|
||||
|
||||
func (s *Csv) DelHost(host string) error {
|
||||
for k, v := range s.Hosts {
|
||||
if v.Host == host {
|
||||
|
@@ -162,15 +162,14 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) (proxyConn *utils
|
||||
func (s *Sock5ModeServer) handleConnect(c net.Conn) {
|
||||
proxyConn, err := s.doConnect(c, connectMethod)
|
||||
defer func() {
|
||||
if s.config.Mux {
|
||||
if s.config.Mux && proxyConn != nil {
|
||||
s.bridge.ReturnTunnel(proxyConn, getverifyval(s.config.VerifyKey))
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
c.Close()
|
||||
} else {
|
||||
go utils.Relay(proxyConn.Conn, c, s.config.CompressEncode, s.config.Crypt, s.config.Mux)
|
||||
utils.Relay(c, proxyConn.Conn, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
utils.ReplayWaitGroup(proxyConn.Conn, c, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -200,15 +199,14 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||
|
||||
proxyConn, err := s.doConnect(c, associateMethod)
|
||||
defer func() {
|
||||
if s.config.Mux {
|
||||
if s.config.Mux && proxyConn != nil {
|
||||
s.bridge.ReturnTunnel(proxyConn, getverifyval(s.config.VerifyKey))
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
c.Close()
|
||||
} else {
|
||||
go utils.Relay(proxyConn.Conn, c, s.config.CompressEncode, s.config.Crypt, s.config.Mux)
|
||||
utils.Relay(c, proxyConn.Conn, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
utils.ReplayWaitGroup(proxyConn.Conn, c, s.config.CompressEncode, s.config.CompressDecode, s.config.Crypt, s.config.Mux)
|
||||
}
|
||||
}
|
||||
|
||||
|
114
server/tcp.go
114
server/tcp.go
@@ -1,6 +1,7 @@
|
||||
package server
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/astaxie/beego"
|
||||
@@ -9,7 +10,9 @@ import (
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
"strings"
|
||||
"sync"
|
||||
)
|
||||
|
||||
type process func(c *utils.Conn, s *TunnelModeServer) error
|
||||
@@ -61,28 +64,23 @@ func (s *TunnelModeServer) auth(r *http.Request, c *utils.Conn, u, p string) err
|
||||
return nil
|
||||
}
|
||||
|
||||
func (s *TunnelModeServer) dealClient2(c *utils.Conn, cnf *ServerConfig, addr string, method string, rb []byte) error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//与客户端建立通道
|
||||
func (s *TunnelModeServer) dealClient(c *utils.Conn, cnf *ServerConfig, addr string, method string, rb []byte) error {
|
||||
reGet:
|
||||
link, err := s.bridge.GetTunnel(getverifyval(cnf.VerifyKey), cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
var link *utils.Conn
|
||||
var err error
|
||||
defer func() {
|
||||
if cnf.Mux {
|
||||
if cnf.Mux && link != nil {
|
||||
s.bridge.ReturnTunnel(link, getverifyval(cnf.VerifyKey))
|
||||
} else {
|
||||
c.Close()
|
||||
}
|
||||
}()
|
||||
if err != nil {
|
||||
log.Println("conn to client error:", err)
|
||||
c.Close()
|
||||
if link, err = s.GetTunnelAndWriteHost(c, cnf, addr); err != nil {
|
||||
log.Println("get bridge tunnel error: ", err)
|
||||
return err
|
||||
}
|
||||
if _, err := link.WriteHost(utils.CONN_TCP, addr); err != nil {
|
||||
c.Close()
|
||||
link.Close()
|
||||
log.Println(err)
|
||||
goto reGet
|
||||
}
|
||||
if flag, err := link.ReadFlag(); err == nil {
|
||||
if flag == utils.CONN_SUCCESS {
|
||||
if method == "CONNECT" {
|
||||
@@ -90,8 +88,7 @@ reGet:
|
||||
} else if rb != nil {
|
||||
link.WriteTo(rb, cnf.CompressEncode, cnf.Crypt)
|
||||
}
|
||||
go utils.Relay(link.Conn, c.Conn, cnf.CompressEncode, cnf.Crypt, cnf.Mux)
|
||||
utils.Relay(c.Conn, link.Conn, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
utils.ReplayWaitGroup(link.Conn, c.Conn, cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
}
|
||||
}
|
||||
return nil
|
||||
@@ -102,6 +99,19 @@ func (s *TunnelModeServer) Close() error {
|
||||
return s.listener.Close()
|
||||
}
|
||||
|
||||
func (s *TunnelModeServer) GetTunnelAndWriteHost(c *utils.Conn, cnf *ServerConfig, addr string) (*utils.Conn, error) {
|
||||
var err error
|
||||
link, err := s.bridge.GetTunnel(getverifyval(cnf.VerifyKey), cnf.CompressEncode, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
if _, err = link.WriteHost(utils.CONN_TCP, addr); err != nil {
|
||||
link.Close()
|
||||
return nil, err
|
||||
}
|
||||
return link, nil
|
||||
}
|
||||
|
||||
//tcp隧道模式
|
||||
func ProcessTunnel(c *utils.Conn, s *TunnelModeServer) error {
|
||||
_, _, rb, err, r := c.GetHost()
|
||||
@@ -124,29 +134,69 @@ func ProcessHttp(c *utils.Conn, s *TunnelModeServer) error {
|
||||
if err := s.auth(r, c, s.config.U, s.config.P); err != nil {
|
||||
return err
|
||||
}
|
||||
//TODO 效率问题
|
||||
return s.dealClient(c, s.config, addr, method, rb)
|
||||
}
|
||||
|
||||
//多客户端域名代理
|
||||
func ProcessHost(c *utils.Conn, s *TunnelModeServer) error {
|
||||
method, addr, rb, err, r := c.GetHost()
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return err
|
||||
var (
|
||||
isConn = true
|
||||
link *utils.Conn
|
||||
cnf *ServerConfig
|
||||
host *HostList
|
||||
wg sync.WaitGroup
|
||||
)
|
||||
for {
|
||||
r, err := http.ReadRequest(bufio.NewReader(c))
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
//首次获取conn
|
||||
if isConn {
|
||||
isConn = false
|
||||
if host, cnf, err = GetKeyByHost(r.Host); err != nil {
|
||||
log.Printf("the host %s is not found !", r.Host)
|
||||
break
|
||||
}
|
||||
|
||||
if err = s.auth(r, c, cnf.U, cnf.P); err != nil {
|
||||
break
|
||||
}
|
||||
|
||||
if link, err = s.GetTunnelAndWriteHost(c, cnf, host.Target); err != nil {
|
||||
log.Println("get bridge tunnel error: ", err)
|
||||
break
|
||||
}
|
||||
|
||||
if flag, err := link.ReadFlag(); err != nil || flag == utils.CONN_ERROR {
|
||||
log.Printf("the host %s connection to %s error", r.Host, host.Target)
|
||||
break
|
||||
} else {
|
||||
wg.Add(1)
|
||||
go func() {
|
||||
utils.Relay(c.Conn, link.Conn, cnf.CompressDecode, cnf.Crypt, cnf.Mux)
|
||||
wg.Done()
|
||||
}()
|
||||
}
|
||||
}
|
||||
utils.ChangeHostAndHeader(r, host.HostChange, host.HeaderChange, c.Conn.RemoteAddr().String())
|
||||
b, err := httputil.DumpRequest(r, true)
|
||||
if err != nil {
|
||||
break
|
||||
}
|
||||
if _, err := link.WriteTo(b, cnf.CompressEncode, cnf.Crypt); err != nil {
|
||||
break
|
||||
}
|
||||
}
|
||||
host, task, err := GetKeyByHost(addr)
|
||||
if err != nil {
|
||||
return err
|
||||
wg.Wait()
|
||||
if cnf != nil && cnf.Mux && link != nil {
|
||||
link.WriteTo([]byte(utils.IO_EOF), cnf.CompressEncode, cnf.Crypt)
|
||||
s.bridge.ReturnTunnel(link, getverifyval(cnf.VerifyKey))
|
||||
} else if link != nil {
|
||||
link.Close()
|
||||
}
|
||||
if err := s.auth(r, c, task.U, task.P); err != nil {
|
||||
return err
|
||||
}
|
||||
if err != nil {
|
||||
c.Close()
|
||||
return err
|
||||
}
|
||||
return s.dealClient(c, task, host.Target, method, rb)
|
||||
c.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
//web管理方式
|
||||
|
@@ -58,7 +58,7 @@ func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
||||
}
|
||||
if flag, err := conn.ReadFlag(); err == nil {
|
||||
defer func() {
|
||||
if s.config.Mux {
|
||||
if conn != nil && s.config.Mux {
|
||||
conn.WriteTo([]byte(utils.IO_EOF), s.config.CompressEncode, s.config.Crypt)
|
||||
s.bridge.ReturnTunnel(conn, getverifyval(s.config.VerifyKey))
|
||||
} else {
|
||||
|
Reference in New Issue
Block a user