mirror of
https://github.com/ehang-io/nps.git
synced 2025-07-02 04:00:42 +00:00
加密传输,代码优化
This commit is contained in:
parent
4dad726129
commit
1d89e7dae2
@ -1,12 +1,20 @@
|
||||
appname = httpMonitor
|
||||
|
||||
#web管理端口
|
||||
httpport = 8080
|
||||
|
||||
#启动模式dev|pro
|
||||
runmode = dev
|
||||
|
||||
#web管理密码
|
||||
password=123
|
||||
|
||||
#http监听端口
|
||||
hostPort=8028
|
||||
#basic auth认证用户名和密码
|
||||
|
||||
#basic auth认证用户名和密码,为空则不验证
|
||||
auth.user=test
|
||||
auth.password=1234
|
||||
auth.password=1234
|
||||
|
||||
#是否加密传输(0|1)
|
||||
crypt=1
|
@ -1,8 +1 @@
|
||||
8021,tunnelServer,10.1.50.203:80,um80bbyvcaiw7n17,,,,1
|
||||
8001,tunnelServer,10.1.50.101:22,h8vcpciko9lczxmb,,,gzip,0
|
||||
8022,tunnelServer,10.1.50.196:4000,vcerzo01q16cdn9n,,,snappy,1
|
||||
8002,udpServer,10.1.50.102:53,zcbsx5kp53cg5yqv,,,,0
|
||||
8003,sock5Server,,9mq856pqq3jq05qv,,,snappy,1
|
||||
8010,sock5Server,,0aj2xfec0mbkann5,test,test,gzip,0
|
||||
8004,httpProxyServer,,y72zj8t074lslln0,,,gzip,0
|
||||
0,hostServer,,o2430bnq22jgnmcl,,,,1
|
||||
8001,tunnelServer,10.1.50.196:4000,jq5i7n0sjs1h0jje,,,,1,1
|
||||
|
|
@ -64,6 +64,7 @@ func (s *IndexController) Add() {
|
||||
U: s.GetString("u"),
|
||||
P: s.GetString("p"),
|
||||
Compress: s.GetString("compress"),
|
||||
Crypt: s.GetString("crypt"),
|
||||
IsRun: 0,
|
||||
}
|
||||
lib.CsvDb.NewTask(t)
|
||||
@ -96,6 +97,7 @@ func (s *IndexController) Edit() {
|
||||
t.U = s.GetString("u")
|
||||
t.P = s.GetString("p")
|
||||
t.Compress = s.GetString("compress")
|
||||
t.Crypt = s.GetString("crypt")
|
||||
lib.CsvDb.UpdateTask(t)
|
||||
lib.StopServer(t.VerifyKey)
|
||||
lib.StartTask(t.VerifyKey)
|
||||
|
@ -86,10 +86,12 @@ func (s *TRPClient) dealChan() error {
|
||||
//创建一个tcp连接
|
||||
conn, err := net.Dial("tcp", s.svrAddr)
|
||||
if err != nil {
|
||||
log.Println("connect to ", s.svrAddr, "error:", err)
|
||||
return err
|
||||
}
|
||||
//验证
|
||||
if _, err := conn.Write([]byte(getverifyval(s.vKey))); err != nil {
|
||||
log.Println("connect to ", s.svrAddr, "error:", err)
|
||||
return err
|
||||
}
|
||||
//默认长连接保持
|
||||
@ -98,25 +100,26 @@ func (s *TRPClient) dealChan() error {
|
||||
//写标志
|
||||
c.wChan()
|
||||
//获取连接的host type(tcp or udp)
|
||||
typeStr, host, en, de, err := c.GetHostFromConn()
|
||||
typeStr, host, en, de, crypt, err := c.GetHostFromConn()
|
||||
if err != nil {
|
||||
log.Println("get host info error:", err)
|
||||
return err
|
||||
}
|
||||
//与目标建立连接
|
||||
server, err := net.Dial(typeStr, host)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
log.Println("connect to ", host, "error:", err)
|
||||
return err
|
||||
}
|
||||
go relay(NewConn(server), c, de)
|
||||
relay(c, NewConn(server), en)
|
||||
go relay(NewConn(server), c, de, crypt)
|
||||
relay(c, NewConn(server), en, crypt)
|
||||
return nil
|
||||
}
|
||||
|
||||
//http模式处理
|
||||
func (s *TRPClient) dealHttp(c *Conn) error {
|
||||
buf := make([]byte, 1024*32)
|
||||
en, de := c.GetCompressTypeFromConn()
|
||||
en, de, _ := c.GetConnInfoFromConn()
|
||||
n, err := c.ReadFromCompress(buf, de)
|
||||
if err != nil {
|
||||
c.wError()
|
||||
|
207
lib/conn.go
207
lib/conn.go
@ -8,7 +8,6 @@ import (
|
||||
"errors"
|
||||
"fmt"
|
||||
"github.com/golang/snappy"
|
||||
"io"
|
||||
"log"
|
||||
"net"
|
||||
"net/http"
|
||||
@ -18,20 +17,76 @@ import (
|
||||
"time"
|
||||
)
|
||||
|
||||
type SnappyConn struct {
|
||||
w *snappy.Writer
|
||||
r *snappy.Reader
|
||||
type CryptConn struct {
|
||||
conn net.Conn
|
||||
crypt bool
|
||||
}
|
||||
|
||||
func NewSnappyConn(conn net.Conn) *SnappyConn {
|
||||
func NewCryptConn(conn net.Conn, crypt bool) *CryptConn {
|
||||
c := new(CryptConn)
|
||||
c.conn = conn
|
||||
c.crypt = crypt
|
||||
return c
|
||||
}
|
||||
|
||||
func (s *CryptConn) Write(b []byte) (n int, err error) {
|
||||
n = len(b)
|
||||
if s.crypt {
|
||||
if b, err = AesEncrypt(b, []byte(cryptKey)); err != nil {
|
||||
return
|
||||
}
|
||||
if b, err = GetLenBytes(b); err != nil {
|
||||
return
|
||||
}
|
||||
}
|
||||
_, err = s.conn.Write(b)
|
||||
return
|
||||
}
|
||||
|
||||
func (s *CryptConn) Read(b []byte) (n int, err error) {
|
||||
if s.crypt {
|
||||
var lens int
|
||||
var buf, bs []byte
|
||||
c := NewConn(s.conn)
|
||||
if lens, err = c.GetLen(); err != nil {
|
||||
return
|
||||
}
|
||||
if buf, err = c.ReadLen(lens); err != nil {
|
||||
return
|
||||
}
|
||||
if bs, err = AesDecrypt(buf, []byte(cryptKey)); err != nil {
|
||||
return
|
||||
}
|
||||
n = len(bs)
|
||||
copy(b, bs)
|
||||
return
|
||||
}
|
||||
return s.conn.Read(b)
|
||||
}
|
||||
|
||||
type SnappyConn struct {
|
||||
w *snappy.Writer
|
||||
r *snappy.Reader
|
||||
crypt bool
|
||||
}
|
||||
|
||||
func NewSnappyConn(conn net.Conn, crypt bool) *SnappyConn {
|
||||
c := new(SnappyConn)
|
||||
c.w = snappy.NewBufferedWriter(conn)
|
||||
c.r = snappy.NewReader(conn)
|
||||
c.crypt = crypt
|
||||
return c
|
||||
}
|
||||
|
||||
func (s *SnappyConn) Write(b []byte) (n int, err error) {
|
||||
if n, err = s.w.Write(b); err != nil {
|
||||
n = len(b)
|
||||
if s.crypt {
|
||||
if b, err = AesEncrypt(b, []byte(cryptKey)); err != nil {
|
||||
log.Println("encode crypt error:", err)
|
||||
return
|
||||
}
|
||||
}
|
||||
if _, err = s.w.Write(b); err != nil {
|
||||
return
|
||||
}
|
||||
err = s.w.Flush()
|
||||
@ -39,25 +94,42 @@ func (s *SnappyConn) Write(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (s *SnappyConn) Read(b []byte) (n int, err error) {
|
||||
return s.r.Read(b)
|
||||
if n, err = s.r.Read(b); err != nil {
|
||||
return
|
||||
}
|
||||
if s.crypt {
|
||||
var bs []byte
|
||||
if bs, err = AesDecrypt(b[:n], []byte(cryptKey)); err != nil {
|
||||
log.Println("decode crypt error:", err)
|
||||
return
|
||||
}
|
||||
n = len(bs)
|
||||
copy(b, bs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type GzipConn struct {
|
||||
w *gzip.Writer
|
||||
r *gzip.Reader
|
||||
w *gzip.Writer
|
||||
r *gzip.Reader
|
||||
crypt bool
|
||||
}
|
||||
|
||||
func NewGzipConn(conn net.Conn) *GzipConn {
|
||||
func NewGzipConn(conn net.Conn, crypt bool) *GzipConn {
|
||||
c := new(GzipConn)
|
||||
c.crypt = crypt
|
||||
c.w = gzip.NewWriter(conn)
|
||||
c.r, err = gzip.NewReader(conn)
|
||||
fmt.Println("err", err)
|
||||
//错误处理
|
||||
return c
|
||||
}
|
||||
|
||||
func (s *GzipConn) Write(b []byte) (n int, err error) {
|
||||
if n, err = s.w.Write(b); err != nil || err == io.EOF {
|
||||
err = s.w.Flush()
|
||||
s.w.Close()
|
||||
fmt.Println(string(b))
|
||||
if n, err = s.w.Write(b); err != nil {
|
||||
//err = s.w.Flush()
|
||||
//s.w.Close()
|
||||
return
|
||||
}
|
||||
err = s.w.Flush()
|
||||
@ -65,7 +137,20 @@ func (s *GzipConn) Write(b []byte) (n int, err error) {
|
||||
}
|
||||
|
||||
func (s *GzipConn) Read(b []byte) (n int, err error) {
|
||||
return s.r.Read(b)
|
||||
fmt.Println("read")
|
||||
if n, err = s.r.Read(b); err != nil {
|
||||
return
|
||||
}
|
||||
if s.crypt {
|
||||
var bs []byte
|
||||
if bs, err = AesDecrypt(b[:n], []byte(cryptKey)); err != nil {
|
||||
log.Println("decode crypt error:", err)
|
||||
return
|
||||
}
|
||||
n = len(bs)
|
||||
copy(b, bs)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
type Conn struct {
|
||||
@ -80,72 +165,49 @@ func NewConn(conn net.Conn) *Conn {
|
||||
|
||||
//读取指定内容长度
|
||||
func (s *Conn) ReadLen(len int) ([]byte, error) {
|
||||
raw := make([]byte, 0)
|
||||
buff := make([]byte, 1024)
|
||||
c := 0
|
||||
for {
|
||||
clen, err := s.Read(buff)
|
||||
if err != nil && err != io.EOF {
|
||||
return raw, err
|
||||
}
|
||||
raw = append(raw, buff[:clen]...)
|
||||
if c += clen; c >= len {
|
||||
break
|
||||
}
|
||||
buf := make([]byte, len)
|
||||
if n, err := s.Read(buf); err != nil || n != len {
|
||||
return buf, errors.New("读取指定长度错误" + err.Error())
|
||||
}
|
||||
if c != len {
|
||||
return raw, errors.New(fmt.Sprintf("已读取长度错误,已读取%dbyte,需要读取%dbyte。", c, len))
|
||||
}
|
||||
return raw, nil
|
||||
return buf, nil
|
||||
}
|
||||
|
||||
//获取长度
|
||||
func (s *Conn) GetLen() (int, error) {
|
||||
val := make([]byte, 4)
|
||||
_, err := s.Read(val)
|
||||
if err != nil {
|
||||
if _, err := s.Read(val); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
nlen := binary.LittleEndian.Uint32(val)
|
||||
if nlen <= 0 {
|
||||
return 0, errors.New("数据长度错误")
|
||||
}
|
||||
return int(nlen), nil
|
||||
return GetLenByBytes(val)
|
||||
}
|
||||
|
||||
//写入长度
|
||||
func (s *Conn) WriteLen(buf []byte) (int, error) {
|
||||
raw := bytes.NewBuffer([]byte{})
|
||||
if err := binary.Write(raw, binary.LittleEndian, int32(len(buf))); err != nil {
|
||||
log.Println(err)
|
||||
var b []byte
|
||||
if b, err = GetLenBytes(buf); err != nil {
|
||||
return 0, err
|
||||
}
|
||||
if err = binary.Write(raw, binary.LittleEndian, buf); err != nil {
|
||||
log.Println(err)
|
||||
return 0, err
|
||||
}
|
||||
return s.Write(raw.Bytes())
|
||||
return s.Write(b)
|
||||
}
|
||||
|
||||
//读取flag
|
||||
func (s *Conn) ReadFlag() (string, error) {
|
||||
val := make([]byte, 4)
|
||||
_, err := s.Read(val)
|
||||
if err != nil {
|
||||
if _, err := s.Read(val); err != nil {
|
||||
return "", err
|
||||
}
|
||||
return string(val), err
|
||||
}
|
||||
|
||||
//读取host 连接地址 压缩类型
|
||||
func (s *Conn) GetHostFromConn() (typeStr string, host string, en, de int, err error) {
|
||||
func (s *Conn) GetHostFromConn() (typeStr string, host string, en, de int, crypt bool, err error) {
|
||||
retry:
|
||||
ltype := make([]byte, 3)
|
||||
if _, err = s.Read(ltype); err != nil {
|
||||
return
|
||||
}
|
||||
if typeStr = string(ltype); typeStr == TEST_FLAG {
|
||||
en, de = s.GetCompressTypeFromConn()
|
||||
en, de, crypt = s.GetConnInfoFromConn()
|
||||
goto retry
|
||||
}
|
||||
len, err := s.GetLen()
|
||||
@ -209,16 +271,10 @@ func (s *Conn) GetHost() (method, address string, rb []byte, err error, r *http.
|
||||
//压缩方式读
|
||||
func (s *Conn) ReadFromCompress(b []byte, compress int) (int, error) {
|
||||
switch compress {
|
||||
case COMPRESS_GZIP_DECODE:
|
||||
r, err := gzip.NewReader(s)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return r.Read(b)
|
||||
case COMPRESS_SNAPY_DECODE:
|
||||
r := snappy.NewReader(s)
|
||||
return r.Read(b)
|
||||
case COMPRESS_NONE:
|
||||
default:
|
||||
return s.Read(b)
|
||||
}
|
||||
return 0, nil
|
||||
@ -227,35 +283,30 @@ func (s *Conn) ReadFromCompress(b []byte, compress int) (int, error) {
|
||||
//压缩方式写
|
||||
func (s *Conn) WriteCompress(b []byte, compress int) (n int, err error) {
|
||||
switch compress {
|
||||
case COMPRESS_GZIP_ENCODE:
|
||||
w := gzip.NewWriter(s)
|
||||
if n, err = w.Write(b); err == nil {
|
||||
w.Flush()
|
||||
}
|
||||
err = w.Close()
|
||||
case COMPRESS_SNAPY_ENCODE:
|
||||
w := snappy.NewBufferedWriter(s)
|
||||
if n, err = w.Write(b); err == nil {
|
||||
w.Flush()
|
||||
}
|
||||
err = w.Close()
|
||||
case COMPRESS_NONE:
|
||||
default:
|
||||
n, err = s.Write(b)
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
//写压缩方式
|
||||
func (s *Conn) WriteCompressType(en, de int) {
|
||||
s.Write([]byte(strconv.Itoa(en) + strconv.Itoa(de)))
|
||||
func (s *Conn) WriteConnInfo(en, de int, crypt bool) {
|
||||
s.Write([]byte(strconv.Itoa(en) + strconv.Itoa(de) + GetStrByBool(crypt)))
|
||||
}
|
||||
|
||||
//获取压缩方式
|
||||
func (s *Conn) GetCompressTypeFromConn() (en, de int) {
|
||||
buf := make([]byte, 2)
|
||||
func (s *Conn) GetConnInfoFromConn() (en, de int, crypt bool) {
|
||||
buf := make([]byte, 3)
|
||||
s.Read(buf)
|
||||
en, _ = strconv.Atoi(string(buf[0]))
|
||||
de, _ = strconv.Atoi(string(buf[1]))
|
||||
crypt = GetBoolByStr(string(buf[2]))
|
||||
return
|
||||
}
|
||||
|
||||
@ -290,3 +341,25 @@ func (s *Conn) wChan() (int, error) {
|
||||
func (s *Conn) wTest() (int, error) {
|
||||
return s.Write([]byte(TEST_FLAG))
|
||||
}
|
||||
|
||||
//获取长度+内容
|
||||
func GetLenBytes(buf []byte) (b []byte, err error) {
|
||||
raw := bytes.NewBuffer([]byte{})
|
||||
if err = binary.Write(raw, binary.LittleEndian, int32(len(buf))); err != nil {
|
||||
return
|
||||
}
|
||||
if err = binary.Write(raw, binary.LittleEndian, buf); err != nil {
|
||||
return
|
||||
}
|
||||
b = raw.Bytes()
|
||||
return
|
||||
}
|
||||
|
||||
//解析出长度
|
||||
func GetLenByBytes(buf []byte) (int, error) {
|
||||
nlen := binary.LittleEndian.Uint32(buf)
|
||||
if nlen <= 0 {
|
||||
return 0, errors.New("数据长度错误")
|
||||
}
|
||||
return int(nlen), nil
|
||||
}
|
||||
|
86
lib/crypt.go
Normal file
86
lib/crypt.go
Normal file
@ -0,0 +1,86 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"crypto/aes"
|
||||
"crypto/cipher"
|
||||
"crypto/md5"
|
||||
"encoding/hex"
|
||||
"math/rand"
|
||||
"time"
|
||||
)
|
||||
|
||||
func AesEncrypt(origData, key []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockSize := block.BlockSize()
|
||||
origData = PKCS5Padding(origData, blockSize)
|
||||
// origData = ZeroPadding(origData, block.BlockSize())
|
||||
blockMode := cipher.NewCBCEncrypter(block, key[:blockSize])
|
||||
crypted := make([]byte, len(origData))
|
||||
// 根据CryptBlocks方法的说明,如下方式初始化crypted也可以
|
||||
// crypted := origData
|
||||
blockMode.CryptBlocks(crypted, origData)
|
||||
return crypted, nil
|
||||
}
|
||||
|
||||
func AesDecrypt(crypted, key []byte) ([]byte, error) {
|
||||
block, err := aes.NewCipher(key)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
blockSize := block.BlockSize()
|
||||
blockMode := cipher.NewCBCDecrypter(block, key[:blockSize])
|
||||
origData := make([]byte, len(crypted))
|
||||
// origData := crypted
|
||||
blockMode.CryptBlocks(origData, crypted)
|
||||
origData = PKCS5UnPadding(origData)
|
||||
// origData = ZeroUnPadding(origData)
|
||||
return origData, nil
|
||||
}
|
||||
|
||||
func ZeroPadding(ciphertext []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(ciphertext)%blockSize
|
||||
padtext := bytes.Repeat([]byte{0}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
func ZeroUnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
|
||||
func PKCS5Padding(ciphertext []byte, blockSize int) []byte {
|
||||
padding := blockSize - len(ciphertext)%blockSize
|
||||
padtext := bytes.Repeat([]byte{byte(padding)}, padding)
|
||||
return append(ciphertext, padtext...)
|
||||
}
|
||||
|
||||
func PKCS5UnPadding(origData []byte) []byte {
|
||||
length := len(origData)
|
||||
// 去掉最后一个字节 unpadding 次
|
||||
unpadding := int(origData[length-1])
|
||||
return origData[:(length - unpadding)]
|
||||
}
|
||||
|
||||
//生成32位md5字串
|
||||
func Md5(s string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
//生成随机验证密钥
|
||||
func GetRandomString(l int) string {
|
||||
str := "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
bytes := []byte(str)
|
||||
result := []byte{}
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
for i := 0; i < l; i++ {
|
||||
result = append(result, bytes[r.Intn(len(bytes))])
|
||||
}
|
||||
return string(result)
|
||||
}
|
318
lib/file.go
Normal file
318
lib/file.go
Normal file
@ -0,0 +1,318 @@
|
||||
package lib
|
||||
|
||||
import (
|
||||
"encoding/csv"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"os"
|
||||
"strconv"
|
||||
)
|
||||
|
||||
type TaskList struct {
|
||||
TcpPort int //服务端与客户端通信端口
|
||||
Mode string //启动方式
|
||||
Target string //目标
|
||||
VerifyKey string //flag
|
||||
U string //socks5验证用户名
|
||||
P string //socks5验证密码
|
||||
Compress string //压缩方式
|
||||
Start int //是否开启
|
||||
IsRun int //是否在运行
|
||||
ClientStatus int //客户端状态
|
||||
Crypt string //是否加密
|
||||
}
|
||||
|
||||
type HostList struct {
|
||||
Vkey string //服务端与客户端通信端口
|
||||
Host string //启动方式
|
||||
Target string //目标
|
||||
}
|
||||
|
||||
func NewCsv(path string, bridge *Tunnel, runList map[string]interface{}) *Csv {
|
||||
c := new(Csv)
|
||||
c.Path = path
|
||||
c.Bridge = bridge
|
||||
c.RunList = runList
|
||||
return c
|
||||
}
|
||||
|
||||
type Csv struct {
|
||||
Tasks []*TaskList
|
||||
Path string
|
||||
Bridge *Tunnel
|
||||
RunList map[string]interface{}
|
||||
Hosts []*HostList //域名列表
|
||||
}
|
||||
|
||||
func (s *Csv) Init() {
|
||||
s.LoadTaskFromCsv()
|
||||
s.LoadHostFromCsv()
|
||||
}
|
||||
|
||||
func (s *Csv) StoreTasksToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(s.Path + "tasks.csv")
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
defer csvFile.Close()
|
||||
writer := csv.NewWriter(csvFile)
|
||||
for _, task := range s.Tasks {
|
||||
record := []string{
|
||||
strconv.Itoa(task.TcpPort),
|
||||
task.Mode,
|
||||
task.Target,
|
||||
task.VerifyKey,
|
||||
task.U,
|
||||
task.P,
|
||||
task.Compress,
|
||||
strconv.Itoa(task.Start),
|
||||
task.Crypt,
|
||||
}
|
||||
err := writer.Write(record)
|
||||
if err != nil {
|
||||
log.Fatalf(err.Error())
|
||||
}
|
||||
}
|
||||
writer.Flush()
|
||||
}
|
||||
|
||||
func (s *Csv) LoadTaskFromCsv() {
|
||||
// 打开文件
|
||||
file, err := os.Open(s.Path + "tasks.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 tasks []*TaskList
|
||||
// 将每一行数据保存到内存slice中
|
||||
for _, item := range records {
|
||||
tcpPort, _ := strconv.Atoi(item[0])
|
||||
Start, _ := strconv.Atoi(item[7])
|
||||
post := &TaskList{
|
||||
TcpPort: tcpPort,
|
||||
Mode: item[1],
|
||||
Target: item[2],
|
||||
VerifyKey: item[3],
|
||||
U: item[4],
|
||||
P: item[5],
|
||||
Compress: item[6],
|
||||
Start: Start,
|
||||
Crypt: item[8],
|
||||
}
|
||||
tasks = append(tasks, post)
|
||||
}
|
||||
s.Tasks = tasks
|
||||
}
|
||||
|
||||
func (s *Csv) StoreHostToCsv() {
|
||||
// 创建文件
|
||||
csvFile, err := os.Create(s.Path + "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(s.Path + "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) GetTaskList(start, length int, typeVal string) ([]*TaskList, int) {
|
||||
list := make([]*TaskList, 0)
|
||||
var cnt int
|
||||
for _, v := range s.Tasks {
|
||||
if v.Mode != typeVal {
|
||||
continue
|
||||
}
|
||||
cnt++
|
||||
if start--; start < 0 {
|
||||
if length--; length > 0 {
|
||||
if _, ok := s.RunList[v.VerifyKey]; ok {
|
||||
v.IsRun = 1
|
||||
} else {
|
||||
v.IsRun = 0
|
||||
}
|
||||
if s, ok := s.Bridge.signalList[getverifyval(v.VerifyKey)]; ok {
|
||||
if s.Len() > 0 {
|
||||
v.ClientStatus = 1
|
||||
} else {
|
||||
v.ClientStatus = 0
|
||||
}
|
||||
} else {
|
||||
v.ClientStatus = 0
|
||||
}
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
return list, cnt
|
||||
}
|
||||
|
||||
func (s *Csv) NewTask(t *TaskList) {
|
||||
s.Tasks = append(s.Tasks, t)
|
||||
s.StoreTasksToCsv()
|
||||
}
|
||||
|
||||
func (s *Csv) UpdateTask(t *TaskList) error {
|
||||
for k, v := range s.Tasks {
|
||||
if v.VerifyKey == t.VerifyKey {
|
||||
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
|
||||
s.Tasks = append(s.Tasks, t)
|
||||
s.StoreTasksToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
//TODO:待测试
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) AddRunList(vKey string, svr interface{}) {
|
||||
s.RunList[vKey] = svr
|
||||
}
|
||||
|
||||
func (s *Csv) DelRunList(vKey string) {
|
||||
delete(s.RunList, vKey)
|
||||
}
|
||||
|
||||
func (s *Csv) DelTask(vKey string) error {
|
||||
for k, v := range s.Tasks {
|
||||
if v.VerifyKey == vKey {
|
||||
s.Tasks = append(s.Tasks[:k], s.Tasks[k+1:]...)
|
||||
s.StoreTasksToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) GetTask(vKey string) (v *TaskList, err error) {
|
||||
for _, v = range s.Tasks {
|
||||
if v.VerifyKey == vKey {
|
||||
return
|
||||
}
|
||||
}
|
||||
err = errors.New("未找到")
|
||||
return
|
||||
}
|
||||
|
||||
func (s *Csv) DelHost(host string) error {
|
||||
for k, v := range s.Hosts {
|
||||
if v.Host == host {
|
||||
s.Hosts = append(s.Hosts[:k], s.Hosts[k+1:]...)
|
||||
s.StoreHostToCsv()
|
||||
return nil
|
||||
}
|
||||
}
|
||||
return errors.New("不存在")
|
||||
}
|
||||
|
||||
func (s *Csv) NewHost(t *HostList) {
|
||||
s.Hosts = append(s.Hosts, t)
|
||||
s.StoreHostToCsv()
|
||||
|
||||
}
|
||||
|
||||
func (s *Csv) GetHostList(start, length int, vKey string) ([]*HostList, int) {
|
||||
list := make([]*HostList, 0)
|
||||
var cnt int
|
||||
for _, v := range s.Hosts {
|
||||
if v.Vkey == vKey {
|
||||
cnt++
|
||||
if start--; start < 0 {
|
||||
if length--; length > 0 {
|
||||
list = append(list, v)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return list, cnt
|
||||
}
|
||||
|
||||
type Site struct {
|
||||
Host string
|
||||
Url string
|
||||
Port int
|
||||
}
|
||||
type Config struct {
|
||||
SiteList []Site
|
||||
Replace int
|
||||
}
|
||||
type JsonStruct struct {
|
||||
}
|
||||
|
||||
func NewJsonStruct() *JsonStruct {
|
||||
return &JsonStruct{}
|
||||
}
|
||||
func (jst *JsonStruct) Load(filename string) (Config, error) {
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
config := Config{}
|
||||
if err != nil {
|
||||
return config, errors.New("配置文件打开错误")
|
||||
}
|
||||
err = json.Unmarshal(data, &config)
|
||||
if err != nil {
|
||||
return config, errors.New("配置文件解析错误")
|
||||
}
|
||||
return config, nil
|
||||
}
|
30
lib/init.go
30
lib/init.go
@ -21,13 +21,17 @@ var (
|
||||
p = flag.String("p", "", "socks5验证密码")
|
||||
compress = flag.String("compress", "", "数据压缩方式(gzip|snappy)")
|
||||
serverAddr = flag.String("server", "", "服务器地址ip:端口")
|
||||
crypt = flag.String("crypt", "", "是否加密(1|0)")
|
||||
config Config
|
||||
err error
|
||||
RunList map[string]interface{} //运行中的任务
|
||||
bridge *Tunnel
|
||||
CsvDb *Csv
|
||||
//crypt = GetBoolNoErrFromConfig("crypt")
|
||||
)
|
||||
|
||||
const cryptKey = "1234567812345678"
|
||||
|
||||
func init() {
|
||||
RunList = make(map[string]interface{})
|
||||
}
|
||||
@ -52,7 +56,7 @@ func InitMode() {
|
||||
log.Fatalln("服务端开启失败", err)
|
||||
}
|
||||
log.Println("服务端启动,监听tcp服务端端口:", *TcpPort)
|
||||
if svr := newMode(*rpMode, bridge, *httpPort, *tunnelTarget, *u, *p, en, de, *verifyKey); svr != nil {
|
||||
if svr := newMode(*rpMode, bridge, *httpPort, *tunnelTarget, *u, *p, en, de, *verifyKey, *crypt); svr != nil {
|
||||
reflect.ValueOf(svr).MethodByName("Start").Call(nil)
|
||||
} else {
|
||||
log.Fatalln("启动模式不正确")
|
||||
@ -71,29 +75,33 @@ func InitFromCsv() {
|
||||
}
|
||||
}
|
||||
|
||||
func newMode(mode string, bridge *Tunnel, httpPort int, tunnelTarget string, u string, p string, enCompress int, deCompress int, vkey string) interface{} {
|
||||
if u == "" || p == "" { //如果web管理中设置了用户名和密码,则覆盖配置文件
|
||||
func newMode(mode string, bridge *Tunnel, httpPort int, tunnelTarget string, u string, p string, enCompress int, deCompress int, vkey string, crypt string) interface{} {
|
||||
if u == "" || p == "" { //如果web管理或者命令中设置了用户名和密码,则覆盖配置文件
|
||||
u = beego.AppConfig.String("auth.user")
|
||||
p = beego.AppConfig.String("auth.password")
|
||||
}
|
||||
if crypt == "" { //如果web管理或者命令中设置了是否加密,则覆盖配置文件
|
||||
crypt = beego.AppConfig.String("crypt")
|
||||
}
|
||||
bCrypt := GetBoolByStr(crypt)
|
||||
switch mode {
|
||||
case "httpServer":
|
||||
return NewHttpModeServer(httpPort, bridge, enCompress, deCompress, vkey)
|
||||
return NewHttpModeServer(httpPort, bridge, enCompress, deCompress, vkey, bCrypt)
|
||||
case "tunnelServer":
|
||||
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessTunnel, bridge, enCompress, deCompress, vkey, u, p)
|
||||
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessTunnel, bridge, enCompress, deCompress, vkey, u, p, bCrypt)
|
||||
case "sock5Server":
|
||||
return NewSock5ModeServer(httpPort, u, p, bridge, enCompress, deCompress, vkey)
|
||||
return NewSock5ModeServer(httpPort, u, p, bridge, enCompress, deCompress, vkey, bCrypt)
|
||||
case "httpProxyServer":
|
||||
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHttp, bridge, enCompress, deCompress, vkey, u, p)
|
||||
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHttp, bridge, enCompress, deCompress, vkey, u, p, bCrypt)
|
||||
case "udpServer":
|
||||
return NewUdpModeServer(httpPort, tunnelTarget, bridge, enCompress, deCompress, vkey)
|
||||
return NewUdpModeServer(httpPort, tunnelTarget, bridge, enCompress, deCompress, vkey, bCrypt)
|
||||
case "webServer":
|
||||
InitCsvDb()
|
||||
return NewWebServer(bridge)
|
||||
case "hostServer":
|
||||
return NewHostServer()
|
||||
return NewHostServer(bCrypt)
|
||||
case "httpHostServer":
|
||||
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHost, bridge, enCompress, deCompress, vkey, u, p)
|
||||
return NewTunnelModeServer(httpPort, tunnelTarget, ProcessHost, bridge, enCompress, deCompress, vkey, u, p, bCrypt)
|
||||
}
|
||||
return nil
|
||||
}
|
||||
@ -119,7 +127,7 @@ func StopServer(cFlag string) error {
|
||||
|
||||
func AddTask(t *TaskList) error {
|
||||
de, en := getCompressType(t.Compress)
|
||||
if svr := newMode(t.Mode, bridge, t.TcpPort, t.Target, t.U, t.P, en, de, t.VerifyKey); svr != nil {
|
||||
if svr := newMode(t.Mode, bridge, t.TcpPort, t.Target, t.U, t.P, en, de, t.VerifyKey, t.Crypt); svr != nil {
|
||||
RunList[t.VerifyKey] = svr
|
||||
go func() {
|
||||
err := reflect.ValueOf(svr).MethodByName("Start").Call(nil)[0]
|
||||
|
@ -36,15 +36,17 @@ type HttpModeServer struct {
|
||||
enCompress int
|
||||
deCompress int
|
||||
vKey string
|
||||
crypt bool
|
||||
}
|
||||
|
||||
func NewHttpModeServer(httpPort int, bridge *Tunnel, enCompress int, deCompress int, vKey string) *HttpModeServer {
|
||||
func NewHttpModeServer(httpPort int, bridge *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *HttpModeServer {
|
||||
s := new(HttpModeServer)
|
||||
s.bridge = bridge
|
||||
s.httpPort = httpPort
|
||||
s.enCompress = enCompress
|
||||
s.deCompress = deCompress
|
||||
s.vKey = vKey
|
||||
s.crypt = crypt
|
||||
return s
|
||||
}
|
||||
|
||||
@ -90,7 +92,7 @@ func (s *HttpModeServer) writeRequest(r *http.Request, conn *Conn) error {
|
||||
return err
|
||||
}
|
||||
conn.wSign()
|
||||
conn.WriteCompressType(s.enCompress, s.deCompress)
|
||||
conn.WriteConnInfo(s.enCompress, s.deCompress, s.crypt)
|
||||
c, err := conn.WriteCompress(raw, s.enCompress)
|
||||
if err != nil {
|
||||
return err
|
||||
@ -152,9 +154,10 @@ type TunnelModeServer struct {
|
||||
basicUser string
|
||||
basicPassword string
|
||||
vKey string
|
||||
crypt bool
|
||||
}
|
||||
|
||||
func NewTunnelModeServer(httpPort int, tunnelTarget string, process process, bridge *Tunnel, enCompress, deCompress int, vKey, basicUser, basicPasswd string) *TunnelModeServer {
|
||||
func NewTunnelModeServer(httpPort int, tunnelTarget string, process process, bridge *Tunnel, enCompress, deCompress int, vKey, basicUser, basicPasswd string, crypt bool) *TunnelModeServer {
|
||||
s := new(TunnelModeServer)
|
||||
s.httpPort = httpPort
|
||||
s.bridge = bridge
|
||||
@ -165,6 +168,7 @@ func NewTunnelModeServer(httpPort int, tunnelTarget string, process process, bri
|
||||
s.vKey = vKey
|
||||
s.basicUser = basicUser
|
||||
s.basicPassword = basicPasswd
|
||||
s.crypt = crypt
|
||||
return s
|
||||
}
|
||||
|
||||
@ -202,7 +206,7 @@ func (s *TunnelModeServer) Close() error {
|
||||
|
||||
//tcp隧道模式
|
||||
func ProcessTunnel(c *Conn, s *TunnelModeServer) error {
|
||||
link, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
|
||||
link, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress, s.crypt)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
c.Close()
|
||||
@ -214,8 +218,8 @@ func ProcessTunnel(c *Conn, s *TunnelModeServer) error {
|
||||
log.Println(err)
|
||||
return err
|
||||
}
|
||||
go relay(link, c, s.enCompress)
|
||||
relay(c, link, s.deCompress)
|
||||
go relay(link, c, s.enCompress, s.crypt)
|
||||
relay(c, link, s.deCompress, s.crypt)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -229,7 +233,7 @@ func ProcessHttp(c *Conn, s *TunnelModeServer) error {
|
||||
if err := s.auth(r, c); err != nil {
|
||||
return err
|
||||
}
|
||||
link, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
|
||||
link, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress, s.crypt)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
c.Close()
|
||||
@ -246,8 +250,8 @@ func ProcessHttp(c *Conn, s *TunnelModeServer) error {
|
||||
} else {
|
||||
link.WriteCompress(rb, s.enCompress)
|
||||
}
|
||||
go relay(link, c, s.enCompress)
|
||||
relay(c, link, s.deCompress)
|
||||
go relay(link, c, s.enCompress, s.crypt)
|
||||
relay(c, link, s.deCompress, s.crypt)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -267,7 +271,7 @@ func ProcessHost(c *Conn, s *TunnelModeServer) error {
|
||||
return err
|
||||
}
|
||||
de, en := getCompressType(task.Compress)
|
||||
link, err := s.bridge.GetTunnel(getverifyval(host.Vkey), en, de)
|
||||
link, err := s.bridge.GetTunnel(getverifyval(host.Vkey), en, de, s.crypt)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
c.Close()
|
||||
@ -284,8 +288,8 @@ func ProcessHost(c *Conn, s *TunnelModeServer) error {
|
||||
} else {
|
||||
link.WriteCompress(rb, en)
|
||||
}
|
||||
go relay(link, c, en)
|
||||
relay(c, link, de)
|
||||
go relay(link, c, en, s.crypt)
|
||||
relay(c, link, de, s.crypt)
|
||||
return nil
|
||||
}
|
||||
|
||||
@ -324,6 +328,7 @@ func NewWebServer(bridge *Tunnel) *WebServer {
|
||||
|
||||
//host
|
||||
type HostServer struct {
|
||||
crypt bool
|
||||
}
|
||||
|
||||
//开始
|
||||
@ -331,9 +336,10 @@ func (s *HostServer) Start() error {
|
||||
return nil
|
||||
}
|
||||
|
||||
//TODO:host模式的客户端,无需指定和监听端口等,此处有待优化
|
||||
func NewHostServer() *HostServer {
|
||||
//TODO:host模式的客户端,无需指定和监听端口等
|
||||
func NewHostServer(crypt bool) *HostServer {
|
||||
s := new(HostServer)
|
||||
s.crypt = crypt
|
||||
return s
|
||||
}
|
||||
|
||||
|
14
lib/sock5.go
14
lib/sock5.go
@ -53,6 +53,7 @@ type Sock5ModeServer struct {
|
||||
isVerify bool
|
||||
listener net.Listener
|
||||
vKey string
|
||||
crypt bool
|
||||
}
|
||||
|
||||
func (s *Sock5ModeServer) handleRequest(c net.Conn) {
|
||||
@ -136,7 +137,7 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) (proxyConn *Conn,
|
||||
binary.Read(c, binary.BigEndian, &port)
|
||||
// connect to host
|
||||
addr := net.JoinHostPort(host, strconv.Itoa(int(port)))
|
||||
client, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
|
||||
client, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress, s.crypt)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
client.Close()
|
||||
@ -159,8 +160,8 @@ func (s *Sock5ModeServer) handleConnect(c net.Conn) {
|
||||
log.Println(err)
|
||||
c.Close()
|
||||
} else {
|
||||
go relay(proxyConn, NewConn(c), s.enCompress)
|
||||
go relay(NewConn(c), proxyConn, s.deCompress)
|
||||
go relay(proxyConn, NewConn(c), s.enCompress, s.crypt)
|
||||
go relay(NewConn(c), proxyConn, s.deCompress, s.crypt)
|
||||
}
|
||||
|
||||
}
|
||||
@ -192,8 +193,8 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) {
|
||||
if err != nil {
|
||||
c.Close()
|
||||
} else {
|
||||
go relay(proxyConn, NewConn(c), s.enCompress)
|
||||
go relay(NewConn(c), proxyConn, s.deCompress)
|
||||
go relay(proxyConn, NewConn(c), s.enCompress, s.crypt)
|
||||
go relay(NewConn(c), proxyConn, s.deCompress, s.crypt)
|
||||
}
|
||||
}
|
||||
|
||||
@ -290,7 +291,7 @@ func (s *Sock5ModeServer) Close() error {
|
||||
return s.listener.Close()
|
||||
}
|
||||
|
||||
func NewSock5ModeServer(httpPort int, u, p string, brige *Tunnel, enCompress int, deCompress int, vKey string) *Sock5ModeServer {
|
||||
func NewSock5ModeServer(httpPort int, u, p string, brige *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *Sock5ModeServer {
|
||||
s := new(Sock5ModeServer)
|
||||
s.httpPort = httpPort
|
||||
s.bridge = brige
|
||||
@ -304,5 +305,6 @@ func NewSock5ModeServer(httpPort int, u, p string, brige *Tunnel, enCompress int
|
||||
s.enCompress = enCompress
|
||||
s.deCompress = deCompress
|
||||
s.vKey = vKey
|
||||
s.crypt = crypt
|
||||
return s
|
||||
}
|
||||
|
@ -141,7 +141,7 @@ retry:
|
||||
}
|
||||
|
||||
//得到一个tcp隧道
|
||||
func (s *Tunnel) GetTunnel(cFlag string, en, de int) (c *Conn, err error) {
|
||||
func (s *Tunnel) GetTunnel(cFlag string, en, de int, crypt bool) (c *Conn, err error) {
|
||||
if v, ok := s.tunnelList[cFlag]; !ok || v.Len() < 10 { //新建通道
|
||||
go s.newChan(cFlag)
|
||||
}
|
||||
@ -154,7 +154,7 @@ retry:
|
||||
c.Close()
|
||||
goto retry
|
||||
}
|
||||
c.WriteCompressType(en, de)
|
||||
c.WriteConnInfo(en, de, crypt)
|
||||
return
|
||||
}
|
||||
|
||||
|
@ -18,9 +18,10 @@ type UdpModeServer struct {
|
||||
enCompress int
|
||||
deCompress int
|
||||
vKey string
|
||||
crypt bool
|
||||
}
|
||||
|
||||
func NewUdpModeServer(udpPort int, tunnelTarget string, bridge *Tunnel, enCompress int, deCompress int, vKey string) *UdpModeServer {
|
||||
func NewUdpModeServer(udpPort int, tunnelTarget string, bridge *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *UdpModeServer {
|
||||
s := new(UdpModeServer)
|
||||
s.udpPort = udpPort
|
||||
s.tunnelTarget = tunnelTarget
|
||||
@ -29,6 +30,7 @@ func NewUdpModeServer(udpPort int, tunnelTarget string, bridge *Tunnel, enCompre
|
||||
s.enCompress = enCompress
|
||||
s.deCompress = deCompress
|
||||
s.vKey = vKey
|
||||
s.crypt = crypt
|
||||
return s
|
||||
}
|
||||
|
||||
@ -57,7 +59,7 @@ func (s *UdpModeServer) Start() error {
|
||||
func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) {
|
||||
fmt.Println(addr.String())
|
||||
fmt.Println(string(data))
|
||||
conn, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress)
|
||||
conn, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress, s.crypt)
|
||||
if err != nil {
|
||||
log.Println(err)
|
||||
return
|
||||
|
165
lib/util.go
165
lib/util.go
@ -3,18 +3,12 @@ package lib
|
||||
import (
|
||||
"bufio"
|
||||
"bytes"
|
||||
"compress/gzip"
|
||||
"crypto/md5"
|
||||
"encoding/base64"
|
||||
"encoding/binary"
|
||||
"encoding/hex"
|
||||
"encoding/json"
|
||||
"errors"
|
||||
"fmt"
|
||||
"io"
|
||||
"io/ioutil"
|
||||
"log"
|
||||
"math/rand"
|
||||
"net"
|
||||
"net/http"
|
||||
"net/http/httputil"
|
||||
@ -22,19 +16,25 @@ import (
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
"sync"
|
||||
)
|
||||
|
||||
var (
|
||||
disabledRedirect = errors.New("disabled redirect.")
|
||||
bufPool = &sync.Pool{
|
||||
New: func() interface{} {
|
||||
return make([]byte, 32*1024)
|
||||
},
|
||||
}
|
||||
)
|
||||
//pool 实现
|
||||
type bufType [32 * 1024]byte
|
||||
|
||||
const (
|
||||
COMPRESS_NONE = iota
|
||||
COMPRESS_NONE_ENCODE = iota
|
||||
COMPRESS_NONE_DECODE
|
||||
COMPRESS_SNAPY_ENCODE
|
||||
COMPRESS_SNAPY_DECODE
|
||||
COMPRESS_GZIP_ENCODE
|
||||
COMPRESS_GZIP_DECODE
|
||||
)
|
||||
|
||||
func BadRequest(w http.ResponseWriter) {
|
||||
@ -134,83 +134,36 @@ func replaceHost(resp []byte) []byte {
|
||||
return []byte(str)
|
||||
}
|
||||
|
||||
func relay(in, out *Conn, compressType int) {
|
||||
buf := make([]byte, 32*1024)
|
||||
func relay(in, out *Conn, compressType int, crypt bool) {
|
||||
fmt.Println(crypt)
|
||||
switch compressType {
|
||||
case COMPRESS_GZIP_ENCODE:
|
||||
//TODO:GZIP压缩存在问题有待解决
|
||||
w := gzip.NewWriter(in)
|
||||
for {
|
||||
n, err := out.Read(buf)
|
||||
if err != nil || err == io.EOF {
|
||||
break
|
||||
}
|
||||
if _, err = w.Write(buf[:n]); err != nil {
|
||||
break
|
||||
}
|
||||
if err = w.Flush(); err != nil {
|
||||
log.Println(err)
|
||||
break
|
||||
}
|
||||
}
|
||||
w.Close()
|
||||
case COMPRESS_SNAPY_ENCODE:
|
||||
io.Copy(NewSnappyConn(in.conn), out)
|
||||
case COMPRESS_GZIP_DECODE:
|
||||
io.Copy(in, NewGzipConn(out.conn))
|
||||
copyBuffer(NewSnappyConn(in.conn, crypt), out)
|
||||
case COMPRESS_SNAPY_DECODE:
|
||||
io.Copy(in, NewSnappyConn(out.conn))
|
||||
default:
|
||||
io.Copy(in, out)
|
||||
copyBuffer(in, NewSnappyConn(out.conn, crypt))
|
||||
case COMPRESS_NONE_ENCODE:
|
||||
copyBuffer(NewCryptConn(in.conn, crypt), out)
|
||||
case COMPRESS_NONE_DECODE:
|
||||
copyBuffer(in, NewCryptConn(out.conn, crypt))
|
||||
}
|
||||
out.Close()
|
||||
in.Close()
|
||||
}
|
||||
|
||||
type Site struct {
|
||||
Host string
|
||||
Url string
|
||||
Port int
|
||||
}
|
||||
type Config struct {
|
||||
SiteList []Site
|
||||
Replace int
|
||||
}
|
||||
type JsonStruct struct {
|
||||
}
|
||||
|
||||
func NewJsonStruct() *JsonStruct {
|
||||
return &JsonStruct{}
|
||||
}
|
||||
func (jst *JsonStruct) Load(filename string) (Config, error) {
|
||||
data, err := ioutil.ReadFile(filename)
|
||||
config := Config{}
|
||||
if err != nil {
|
||||
return config, errors.New("配置文件打开错误")
|
||||
}
|
||||
err = json.Unmarshal(data, &config)
|
||||
if err != nil {
|
||||
return config, errors.New("配置文件解析错误")
|
||||
}
|
||||
return config, nil
|
||||
}
|
||||
|
||||
//判断压缩方式
|
||||
func getCompressType(compress string) (int, int) {
|
||||
switch compress {
|
||||
case "":
|
||||
return COMPRESS_NONE, COMPRESS_NONE
|
||||
case "gzip":
|
||||
return COMPRESS_GZIP_DECODE, COMPRESS_GZIP_ENCODE
|
||||
return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
|
||||
case "snappy":
|
||||
return COMPRESS_SNAPY_DECODE, COMPRESS_SNAPY_ENCODE
|
||||
default:
|
||||
log.Fatalln("数据压缩格式错误")
|
||||
}
|
||||
return COMPRESS_NONE, COMPRESS_NONE
|
||||
return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
|
||||
}
|
||||
|
||||
// 简单的一个校验值
|
||||
//简单的一个校验值
|
||||
func getverifyval(vkey string) string {
|
||||
//单客户端模式
|
||||
if *verifyKey != "" {
|
||||
@ -219,6 +172,7 @@ func getverifyval(vkey string) string {
|
||||
return Md5(vkey)
|
||||
}
|
||||
|
||||
//验证
|
||||
func verify(verifyKeyMd5 string) bool {
|
||||
if *verifyKey != "" && getverifyval(*verifyKey) == verifyKeyMd5 {
|
||||
return true
|
||||
@ -233,6 +187,7 @@ func verify(verifyKeyMd5 string) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
//get key by host from x
|
||||
func getKeyByHost(host string) (h *HostList, t *TaskList, err error) {
|
||||
for _, v := range CsvDb.Hosts {
|
||||
if strings.Contains(host, v.Host) {
|
||||
@ -245,25 +200,6 @@ func getKeyByHost(host string) (h *HostList, t *TaskList, err error) {
|
||||
return
|
||||
}
|
||||
|
||||
//生成32位md5字串
|
||||
func Md5(s string) string {
|
||||
h := md5.New()
|
||||
h.Write([]byte(s))
|
||||
return hex.EncodeToString(h.Sum(nil))
|
||||
}
|
||||
|
||||
//生成随机验证密钥
|
||||
func GetRandomString(l int) string {
|
||||
str := "0123456789abcdefghijklmnopqrstuvwxyz"
|
||||
bytes := []byte(str)
|
||||
result := []byte{}
|
||||
r := rand.New(rand.NewSource(time.Now().UnixNano()))
|
||||
for i := 0; i < l; i++ {
|
||||
result = append(result, bytes[r.Intn(len(bytes))])
|
||||
}
|
||||
return string(result)
|
||||
}
|
||||
|
||||
//通过host获取对应的ip地址
|
||||
func Gethostbyname(hostname string) string {
|
||||
if !DomainCheck(hostname) {
|
||||
@ -310,3 +246,58 @@ func checkAuth(r *http.Request, user, passwd string) bool {
|
||||
}
|
||||
return pair[0] == user && pair[1] == passwd
|
||||
}
|
||||
|
||||
//get bool by str
|
||||
func GetBoolByStr(s string) bool {
|
||||
switch s {
|
||||
case "1", "true":
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
//get str by bool
|
||||
func GetStrByBool(b bool) string {
|
||||
if b {
|
||||
return "1"
|
||||
}
|
||||
return "0"
|
||||
}
|
||||
|
||||
// io.copy的优化版,读取buffer长度原为32*1024,与snappy不同,导致读取出的内容存在差异,不利于解密
|
||||
func copyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
|
||||
// If the reader has a WriteTo method, use it to do the copy.
|
||||
// Avoids an allocation and a copy.
|
||||
if wt, ok := src.(io.WriterTo); ok {
|
||||
return wt.WriteTo(dst)
|
||||
}
|
||||
// Similarly, if the writer has a ReadFrom method, use it to do the copy.
|
||||
if rt, ok := dst.(io.ReaderFrom); ok {
|
||||
return rt.ReadFrom(src)
|
||||
}
|
||||
buf := make([]byte, 65535)
|
||||
for {
|
||||
nr, er := src.Read(buf)
|
||||
if nr > 0 {
|
||||
nw, ew := dst.Write(buf[0:nr])
|
||||
if nw > 0 {
|
||||
written += int64(nw)
|
||||
}
|
||||
if ew != nil {
|
||||
err = ew
|
||||
break
|
||||
}
|
||||
if nr != nw {
|
||||
err = io.ErrShortWrite
|
||||
break
|
||||
}
|
||||
}
|
||||
if er != nil {
|
||||
if er != io.EOF {
|
||||
err = er
|
||||
}
|
||||
break
|
||||
}
|
||||
}
|
||||
return written, err
|
||||
}
|
||||
|
@ -34,10 +34,16 @@
|
||||
<label class="control-label">数据压缩方式</label>
|
||||
<select class="form-control" name="compress">
|
||||
<option value="">不压缩</option>
|
||||
<option value="gzip">gzip压缩</option>
|
||||
<option value="snappy">snappy</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="compress">
|
||||
<label class="control-label">是否加密传输</label>
|
||||
<select class="form-control" name="crypt">
|
||||
<option value="0">不加密</option>
|
||||
<option value="1">加密</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="u">
|
||||
<label class="control-label">验证用户名(socks5、HTTP代理模式)</label>
|
||||
<input class="form-control" type="text" name="u" placeholder="不填则无需验证">
|
||||
|
@ -7,7 +7,7 @@
|
||||
<input type="hidden" name="vKey" value="{{.t.VerifyKey}}">
|
||||
<div class="form-group">
|
||||
<label class="control-label">模式</label>
|
||||
<select class="form-control" name="type" id="type">
|
||||
<select class="form-control" name="type" id="type">
|
||||
<option {{if eq "tunnelServer" .t.Mode}}selected{{end}} value="tunnelServer">tcp隧道</option>
|
||||
<option {{if eq "udpServer" .t.Mode}}selected{{end}} value="udpServer">udp隧道</option>
|
||||
<option {{if eq "sock5Server" .t.Mode}}selected{{end}} value="sock5Server">socks5代理</option>
|
||||
@ -29,10 +29,16 @@
|
||||
<label class="control-label">数据压缩方式(所有模式均支持)</label>
|
||||
<select class="form-control" name="compress">
|
||||
<option {{if eq "" .t.Compress}}selected{{end}} value="">不压缩</option>
|
||||
<option {{if eq "gzip" .t.Compress}}selected{{end}} value="gzip">gzip压缩</option>
|
||||
<option {{if eq "snappy" .t.Compress}}selected{{end}} value="snappy">snappy压缩</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="compress">
|
||||
<label class="control-label">是否加密传输(所有模式均支持)</label>
|
||||
<select class="form-control" name="crypt">
|
||||
<option {{if eq "0" .t.Crypt}}selected{{end}} value="0">不加密</option>
|
||||
<option {{if eq "1" .t.Crypt}}selected{{end}} value="1">加密</option>
|
||||
</select>
|
||||
</div>
|
||||
<div class="form-group" id="u">
|
||||
<label class="control-label">验证用户名(socks5、HTTP代理模式)</label>
|
||||
<input class="form-control" value="{{.t.U}}" type="text" name="u"
|
||||
@ -56,7 +62,7 @@
|
||||
</main>
|
||||
<script>
|
||||
var arr = []
|
||||
arr["all"] = ["type", "port", "compress", "u", "p","target"]
|
||||
arr["all"] = ["type", "port", "compress", "u", "p", "target"]
|
||||
arr["tunnelServer"] = ["type", "port", "target", "compress"]
|
||||
arr["udpServer"] = ["type", "port", "target", "compress"]
|
||||
arr["sock5Server"] = ["type", "port", "compress", "u", "p"]
|
||||
@ -72,6 +78,7 @@
|
||||
$("#" + arr[o][i]).css("display", "block")
|
||||
}
|
||||
}
|
||||
|
||||
$(function () {
|
||||
resetForm()
|
||||
$("#type").on("change", function () {
|
||||
|
@ -10,6 +10,7 @@
|
||||
<th>内网目标</th>
|
||||
<th>多客户端模式客户端执行命令</th>
|
||||
<th>压缩方式</th>
|
||||
<th>加密传输</th>
|
||||
<th>用户名</th>
|
||||
<th>密码</th>
|
||||
<th>客户端状态</th>
|
||||
@ -106,6 +107,7 @@
|
||||
{data: 'Target'},
|
||||
{data: 'VerifyKey'},
|
||||
{data: 'Compress'},
|
||||
{data: 'Crypt'},
|
||||
{data: 'U'},
|
||||
{data: 'P'},
|
||||
{data: 'ClientStatus'},
|
||||
@ -146,6 +148,16 @@
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: -6,
|
||||
render: function (data, type, row, meta) {
|
||||
if (data == "0") {
|
||||
return "不加密"
|
||||
} else {
|
||||
return "加密"
|
||||
}
|
||||
}
|
||||
},
|
||||
{
|
||||
targets: 2,
|
||||
render: function (data, type, row, meta) {
|
||||
|
Loading…
x
Reference in New Issue
Block a user