From 9202db49b820895223cf26bbe545d434736d778d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E5=88=98=E6=B2=B3?= Date: Fri, 4 Jan 2019 00:21:23 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BB=A3=E7=A0=81=E8=B0=83=E6=95=B4?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- conf/app.conf | 14 +- conf/hosts.csv | 4 +- conf/tasks.csv | 3 +- lib/.socks5.go.swp | Bin 0 -> 16384 bytes lib/client.go | 9 +- lib/conn.go | 140 +++++++----------- lib/crypt.go | 16 +- lib/csv.go | 285 ------------------------------------ lib/init.go | 2 +- lib/server.go | 101 ++++++------- lib/{sock5.go => socks5.go} | 10 ++ lib/udp.go | 8 +- lib/util.go | 17 +-- 13 files changed, 133 insertions(+), 476 deletions(-) create mode 100644 lib/.socks5.go.swp delete mode 100644 lib/csv.go rename lib/{sock5.go => socks5.go} (98%) diff --git a/conf/app.conf b/conf/app.conf index 8da3d29..86b9d35 100755 --- a/conf/app.conf +++ b/conf/app.conf @@ -1,10 +1,10 @@ -appname = httpMonitor +appname = easyProxy #web管理端口 httpport = 8080 #启动模式dev|pro -runmode = dev +runmode = pro #web管理密码 password=123 @@ -12,9 +12,9 @@ password=123 #http监听端口 hostPort=8028 -#basic auth认证用户名和密码,为空则不验证 -auth.user=test -auth.password=1234 +#basic auth认证用户名和密码,为空则不验证,全局控制 +auth.user= +auth.password= -#是否加密传输(0|1) -crypt=1 \ No newline at end of file +#是否加密传输(0|1),全局控制 +crypt=0 \ No newline at end of file diff --git a/conf/hosts.csv b/conf/hosts.csv index e6f454c..30ba681 100644 --- a/conf/hosts.csv +++ b/conf/hosts.csv @@ -1,3 +1,3 @@ -a.proxy.com,127.0.0.1:81,o2430bnq22jgnmcl b.proxy.com,127.0.0.1:82,o2430bnq22jgnmcl -a.o.com,10.1.50.203:80,o2430bnq22jgnmcl +b.o.com,127.0.0.1:88,ts08z6vk5nc72fs8 +a.o.com,127.0.0.1:88,ts08z6vk5nc72fs8 diff --git a/conf/tasks.csv b/conf/tasks.csv index 4c19909..7f430fc 100644 --- a/conf/tasks.csv +++ b/conf/tasks.csv @@ -1 +1,2 @@ -8001,tunnelServer,10.1.50.196:4000,jq5i7n0sjs1h0jje,,,,1,1 +0,hostServer,,ts08z6vk5nc72fs8,,,,1,0 +8001,tunnelServer,127.0.0.1:88,jq5i7n0sjs1h0jje,,,,1,1 diff --git a/lib/.socks5.go.swp b/lib/.socks5.go.swp new file mode 100644 index 0000000000000000000000000000000000000000..e914acde2faa73c886c40e2065356ce6d6f29dbf GIT binary patch literal 16384 zcmeI2e~2VU6~`+%V;sHnCy750txVvqXK%J=W_NaT9u8)2_u{R&-5YjhHy-DC^mfMKU zXXh>#2mu9a*iUy?)vH%kuU`G=>Rqj_%rEeLW|iUhYR0}XWxnU`H$Td5KF65nrd>ht z&-0UVj##kl13|Dp-i!j%3vA09&GvpNSP@pd37M0d70+F*#DTpYPnm1MsI(4i3up_x zxE9#OCMRlgs9#&WhQIE$%P+2atxa1%TR>YtTR>YtTR>YtTR>YtTi}1%0!g@oeE>DQ zJgeoI?0(tE{omQ|V_EzIBk4P`@N2SrHB*r5$)fd5TR>YtTR>YtTR>YtTR>YtTR>Yt zTR>YtTR>ajzhD8&VeBm^_v>^3fbaijvO4_bRgC=^{2u%i`~aK>-vZ~rL*PO105}6a z4ekIwI11)K1-uD7@k+*S1r_l3U5x!2{1Q9`egeJ;9s-{S_kj0-o56d*JeUMEPz46q z3I4c~u^)r4fvI@Op4HxB~pDz}Sz#li)n~F8B)g9JmYgfddx6+rb3b2^jd-%NYA7_y_nC zcmzBM?g#gQPk__lqu?XJ0eiva;HfLoU*NN#17^VWpbAVd4z2~?c`0LO!M)%^AOJRa z2dIKKf?eQuS1|T-@C0}mdC~`m8q`iIEpIl(?r-qeT#a03 zO_=W#Njvp@;TdZp>5ItiZ1yeBh|T_uVzY!wn8Ke8dSN8um_m*i4%yLWn4mZ^6RGt@ zV!kVIeKKJ)h!UfV2V_ekbVJ{qPXfz8HH{Eyr4lk$DzFlYw-cTOoTOP{)%C4t(_9jk zLuSZ=2i&!TzT;YcneUd_l?CaMr_foO#*m?Y%K91YmYs_j)y235QEV=X4Wl@N`l3Oc zI+^=H0$YcqNjOEa=SW9T>)Mc943btZ2Qf!O5|u1s&&TEDo~dZxAhTw3efwbr3E-f$DUD+eFh z{aE#QK47Gw^YM~ZJ?|bAls^v2$_-pAu}B_eoy33i%QK4{po zsT3*?MlU(nz7jV=`foH!;$upH+)6rC3AL+KoItv=oNH_~lNb?=F_=(P4w4~nXj)M$=9^075WK%+wu3r3l*~jiWj@HCDW{CB&~p<4aPhpJyRLBd6@n=kb*{O%dyl5ua)7bRl1;cbeqCOH56G@m)~}Y{vMiThx!`| z)aX&&DfP+Dq)Ejdnr%mBhisOA?#UrGyI2K0fn~w4(NH;lMivAbO1azt7alSYgi|Pmd!_8eTw(uIGt0%j1!_B^7Z}l+!568C_Eb z%O{NP26CpmA@w|(vsJO=`0D8b*PMjDu?lLjcN{-?$*y^55FDhF5rd=<0MH)a|EQMYPDaHdB)U^g~`=> zWHzUAQtT$+?r6~wxhwHv{FAE_FT#<)RZZL4h0I*Hk-Y1!){ zX}Pxw$kgiBP0Rfm(s(FScuYy~&DvD8%4z3|oLr5gNHCRuypl6k9b6lKCd5{WPkY%`mZvxPF~? zF-$Bzp(>T7m8Bf&fh1olqH%`SxV^Nutwku^@;74piOZf-zVwG)<4z8yGt_o%3?N0GTb+D?!QQ`FRO1%JNPT^02DG=|;h!a^O5Pr7vv7 zBHz86huI^(wdEhzkQJv^YY@fJZhoBA;Q1q>)p7cUF>;8NeXPKzs*waE&r4@w_!NLo u2-(3J4l1Z9o}G>1%y#hEPRVYWM}?&+)tLdlb;wgeI@2p%@O=bFY5xJ9`5t8e literal 0 HcmV?d00001 diff --git a/lib/client.go b/lib/client.go index e7b5e7a..95216c6 100755 --- a/lib/client.go +++ b/lib/client.go @@ -16,6 +16,7 @@ type TRPClient struct { vKey string } +//new client func NewRPClient(svraddr string, tcpNum int, vKey string) *TRPClient { c := new(TRPClient) c.svrAddr = svraddr @@ -24,6 +25,7 @@ func NewRPClient(svraddr string, tcpNum int, vKey string) *TRPClient { return c } +//start func (s *TRPClient) Start() error { for i := 0; i < s.tcpNum; i++ { go s.newConn() @@ -46,6 +48,7 @@ func (s *TRPClient) newConn() error { return s.process(NewConn(conn)) } +//处理 func (s *TRPClient) process(c *Conn) error { c.SetAlive() if _, err := c.Write([]byte(getverifyval(s.vKey))); err != nil { @@ -119,8 +122,8 @@ func (s *TRPClient) dealChan() error { //http模式处理 func (s *TRPClient) dealHttp(c *Conn) error { buf := make([]byte, 1024*32) - en, de, _ := c.GetConnInfoFromConn() - n, err := c.ReadFromCompress(buf, de) + en, de, crypt := c.GetConnInfoFromConn() + n, err := c.ReadFrom(buf, de, crypt) if err != nil { c.wError() return err @@ -136,7 +139,7 @@ func (s *TRPClient) dealHttp(c *Conn) error { return err } c.wSign() - n, err = c.WriteCompress(respBytes, en) + n, err = c.WriteTo(respBytes, en, crypt) if err != nil { return err } diff --git a/lib/conn.go b/lib/conn.go index 683012c..008f67d 100755 --- a/lib/conn.go +++ b/lib/conn.go @@ -3,11 +3,10 @@ package lib import ( "bufio" "bytes" - "compress/gzip" "encoding/binary" "errors" - "fmt" "github.com/golang/snappy" + "io" "log" "net" "net/http" @@ -29,6 +28,7 @@ func NewCryptConn(conn net.Conn, crypt bool) *CryptConn { return c } +//加密写 func (s *CryptConn) Write(b []byte) (n int, err error) { n = len(b) if s.crypt { @@ -43,6 +43,7 @@ func (s *CryptConn) Write(b []byte) (n int, err error) { return } +//解密读 func (s *CryptConn) Read(b []byte) (n int, err error) { if s.crypt { var lens int @@ -78,6 +79,7 @@ func NewSnappyConn(conn net.Conn, crypt bool) *SnappyConn { return c } +//snappy压缩写 包含加密 func (s *SnappyConn) Write(b []byte) (n int, err error) { n = len(b) if s.crypt { @@ -93,6 +95,7 @@ func (s *SnappyConn) Write(b []byte) (n int, err error) { return } +//snappy压缩读 包含解密 func (s *SnappyConn) Read(b []byte) (n int, err error) { if n, err = s.r.Read(b); err != nil { return @@ -109,64 +112,21 @@ func (s *SnappyConn) Read(b []byte) (n int, err error) { return } -type GzipConn struct { - w *gzip.Writer - r *gzip.Reader - crypt bool -} - -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) { - 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() - return -} - -func (s *GzipConn) Read(b []byte) (n int, err error) { - 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 { conn net.Conn } +//new conn func NewConn(conn net.Conn) *Conn { c := new(Conn) c.conn = conn return c } -//读取指定内容长度 +//读取指定长度内容 func (s *Conn) ReadLen(len int) ([]byte, error) { buf := make([]byte, len) - if n, err := s.Read(buf); err != nil || n != len { + if n, err := io.ReadFull(s, buf); err != nil || n != len { return buf, errors.New("读取指定长度错误" + err.Error()) } return buf, nil @@ -174,14 +134,14 @@ func (s *Conn) ReadLen(len int) ([]byte, error) { //获取长度 func (s *Conn) GetLen() (int, error) { - val := make([]byte, 4) - if _, err := s.Read(val); err != nil { + val, err := s.ReadLen(4) + if err != nil { return 0, err } return GetLenByBytes(val) } -//写入长度 +//写入长度+内容 粘包 func (s *Conn) WriteLen(buf []byte) (int, error) { var b []byte if b, err = GetLenBytes(buf); err != nil { @@ -192,8 +152,8 @@ func (s *Conn) WriteLen(buf []byte) (int, error) { //读取flag func (s *Conn) ReadFlag() (string, error) { - val := make([]byte, 4) - if _, err := s.Read(val); err != nil { + val, err := s.ReadLen(4) + if err != nil { return "", err } return string(val), err @@ -202,20 +162,20 @@ func (s *Conn) ReadFlag() (string, error) { //读取host 连接地址 压缩类型 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, crypt = s.GetConnInfoFromConn() - goto retry - } - len, err := s.GetLen() + lType, err := s.ReadLen(3) if err != nil { return } - hostByte := make([]byte, len) - if _, err = s.Read(hostByte); err != nil { + if typeStr = string(lType); typeStr == TEST_FLAG { + en, de, crypt = s.GetConnInfoFromConn() + goto retry + } + cLen, err := s.GetLen() + if err != nil { + return + } + hostByte, err := s.ReadLen(cLen) + if err != nil { return } host = string(hostByte) @@ -239,7 +199,7 @@ func (s *Conn) SetAlive() { conn.SetKeepAlivePeriod(time.Duration(2 * time.Second)) } -//从tcp报文中解析出host +//从tcp报文中解析出host,连接类型等 func (s *Conn) GetHost() (method, address string, rb []byte, err error, r *http.Request) { var b [32 * 1024]byte var n int @@ -268,76 +228,76 @@ func (s *Conn) GetHost() (method, address string, rb []byte, err error, r *http. return } -//压缩方式读 -func (s *Conn) ReadFromCompress(b []byte, compress int) (int, error) { - switch compress { - case COMPRESS_SNAPY_DECODE: - r := snappy.NewReader(s) - return r.Read(b) - default: - return s.Read(b) +//单独读(加密|压缩) +func (s *Conn) ReadFrom(b []byte, compress int, crypt bool) (int, error) { + if COMPRESS_SNAPY_DECODE == compress { + return NewSnappyConn(s.conn, crypt).Read(b) } - return 0, nil + return NewCryptConn(s.conn, crypt).Read(b) } -//压缩方式写 -func (s *Conn) WriteCompress(b []byte, compress int) (n int, err error) { - switch compress { - case COMPRESS_SNAPY_ENCODE: - w := snappy.NewBufferedWriter(s) - if n, err = w.Write(b); err == nil { - w.Flush() - } - err = w.Close() - default: - n, err = s.Write(b) +//单独写(加密|压缩) +func (s *Conn) WriteTo(b []byte, compress int, crypt bool) (n int, err error) { + if COMPRESS_SNAPY_ENCODE == compress { + return NewSnappyConn(s.conn, crypt).Write(b) } - return + return NewCryptConn(s.conn, crypt).Write(b) } -//写压缩方式 +//写压缩方式,加密 func (s *Conn) WriteConnInfo(en, de int, crypt bool) { s.Write([]byte(strconv.Itoa(en) + strconv.Itoa(de) + GetStrByBool(crypt))) } -//获取压缩方式 +//获取压缩方式,是否加密 func (s *Conn) GetConnInfoFromConn() (en, de int, crypt bool) { - buf := make([]byte, 3) - s.Read(buf) + buf, err := s.ReadLen(3) + //TODO:错误处理 + if err != nil { + return + } en, _ = strconv.Atoi(string(buf[0])) de, _ = strconv.Atoi(string(buf[1])) crypt = GetBoolByStr(string(buf[2])) return } +//close func (s *Conn) Close() error { return s.conn.Close() } +//write func (s *Conn) Write(b []byte) (int, error) { return s.conn.Write(b) } +//read func (s *Conn) Read(b []byte) (int, error) { return s.conn.Read(b) } +//write error func (s *Conn) wError() (int, error) { return s.Write([]byte(RES_MSG)) } +//write sign flag func (s *Conn) wSign() (int, error) { return s.Write([]byte(RES_SIGN)) } +//write main func (s *Conn) wMain() (int, error) { return s.Write([]byte(WORK_MAIN)) } +//write chan func (s *Conn) wChan() (int, error) { return s.Write([]byte(WORK_CHAN)) } +//write test func (s *Conn) wTest() (int, error) { return s.Write([]byte(TEST_FLAG)) } diff --git a/lib/crypt.go b/lib/crypt.go index 7e6a19d..4d98224 100644 --- a/lib/crypt.go +++ b/lib/crypt.go @@ -10,6 +10,7 @@ import ( "time" ) +//en func AesEncrypt(origData, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { @@ -26,6 +27,7 @@ func AesEncrypt(origData, key []byte) ([]byte, error) { return crypted, nil } +//de func AesDecrypt(crypted, key []byte) ([]byte, error) { block, err := aes.NewCipher(key) if err != nil { @@ -41,24 +43,14 @@ func AesDecrypt(crypted, key []byte) ([]byte, error) { 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 次 diff --git a/lib/csv.go b/lib/csv.go deleted file mode 100644 index 28d1cb6..0000000 --- a/lib/csv.go +++ /dev/null @@ -1,285 +0,0 @@ -package lib - -import ( - "encoding/csv" - "errors" - "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 //客户端状态 -} - -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), - } - 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, - } - 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 -} diff --git a/lib/init.go b/lib/init.go index 2ba97f2..ed101a3 100644 --- a/lib/init.go +++ b/lib/init.go @@ -19,7 +19,7 @@ var ( verifyKey = flag.String("vkey", "", "验证密钥") u = flag.String("u", "", "socks5验证用户名") p = flag.String("p", "", "socks5验证密码") - compress = flag.String("compress", "", "数据压缩方式(gzip|snappy)") + compress = flag.String("compress", "", "数据压缩方式(snappy)") serverAddr = flag.String("server", "", "服务器地址ip:端口") crypt = flag.String("crypt", "", "是否加密(1|0)") config Config diff --git a/lib/server.go b/lib/server.go index 3bb3f2b..885b1e7 100755 --- a/lib/server.go +++ b/lib/server.go @@ -30,6 +30,8 @@ WWW-Authenticate: Basic realm="easyProxy" 401 Unauthorized` ) +type process func(c *Conn, s *TunnelModeServer) error + type HttpModeServer struct { bridge *Tunnel httpPort int @@ -39,6 +41,7 @@ type HttpModeServer struct { crypt bool } +//http func NewHttpModeServer(httpPort int, bridge *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *HttpModeServer { s := new(HttpModeServer) s.bridge = bridge @@ -93,7 +96,7 @@ func (s *HttpModeServer) writeRequest(r *http.Request, conn *Conn) error { } conn.wSign() conn.WriteConnInfo(s.enCompress, s.deCompress, s.crypt) - c, err := conn.WriteCompress(raw, s.enCompress) + c, err := conn.WriteTo(raw, s.enCompress, s.crypt) if err != nil { return err } @@ -112,7 +115,7 @@ func (s *HttpModeServer) writeResponse(w http.ResponseWriter, c *Conn) error { switch flags { case RES_SIGN: buf := make([]byte, 1024*1024*32) - n, err := c.ReadFromCompress(buf, s.deCompress) + n, err := c.ReadFrom(buf, s.deCompress, s.crypt) if err != nil { return err } @@ -141,8 +144,6 @@ func (s *HttpModeServer) writeResponse(w http.ResponseWriter, c *Conn) error { return nil } -type process func(c *Conn, s *TunnelModeServer) error - type TunnelModeServer struct { httpPort int tunnelTarget string @@ -157,6 +158,7 @@ type TunnelModeServer struct { crypt bool } +//tcp|http|host 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 @@ -191,6 +193,8 @@ func (s *TunnelModeServer) Start() error { } return nil } + +//权限认证 func (s *TunnelModeServer) auth(r *http.Request, c *Conn) error { if s.basicUser != "" && s.basicPassword != "" && !checkAuth(r, s.basicUser, s.basicPassword) { c.Write([]byte(Unauthorized_BYTES)) @@ -200,27 +204,44 @@ func (s *TunnelModeServer) auth(r *http.Request, c *Conn) error { return nil } +//与客户端建立通道 +func (s *TunnelModeServer) dealClient(vKey string, en, de int, c *Conn, target string, method string, rb []byte) error { + link, err := s.bridge.GetTunnel(getverifyval(vKey), en, de, s.crypt) + if err != nil { + log.Println(err) + c.Close() + return err + } + if _, err := link.WriteHost(CONN_TCP, target); err != nil { + c.Close() + link.Close() + log.Println(err) + return err + } + if method == "CONNECT" { + fmt.Fprint(c, "HTTP/1.1 200 Connection established\r\n") + } else { + link.WriteTo(rb, en, s.crypt) + } + go relay(link, c, en, s.crypt) + relay(c, link, de, s.crypt) + return nil +} + +//close func (s *TunnelModeServer) Close() error { return s.listener.Close() } //tcp隧道模式 func ProcessTunnel(c *Conn, s *TunnelModeServer) error { - link, err := s.bridge.GetTunnel(getverifyval(s.vKey), s.enCompress, s.deCompress, s.crypt) - if err != nil { - log.Println(err) - c.Close() - return err + method, _, rb, err, r := c.GetHost() + if err == nil { + if err := s.auth(r, c); err != nil { + return err + } } - if _, err := link.WriteHost(CONN_TCP, s.tunnelTarget); err != nil { - link.Close() - c.Close() - log.Println(err) - return err - } - go relay(link, c, s.enCompress, s.crypt) - relay(c, link, s.deCompress, s.crypt) - return nil + return s.dealClient(s.vKey, s.enCompress, s.deCompress, c, s.tunnelTarget, method, rb) } //http代理模式 @@ -233,26 +254,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, s.crypt) - if err != nil { - log.Println(err) - c.Close() - return err - } - if _, err := link.WriteHost(CONN_TCP, addr); err != nil { - c.Close() - link.Close() - log.Println(err) - return err - } - if method == "CONNECT" { - fmt.Fprint(c, "HTTP/1.1 200 Connection established\r\n") - } else { - link.WriteCompress(rb, s.enCompress) - } - go relay(link, c, s.enCompress, s.crypt) - relay(c, link, s.deCompress, s.crypt) - return nil + return s.dealClient(s.vKey, s.enCompress, s.deCompress, c, addr, method, rb) } //多客户端域名代理 @@ -271,26 +273,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, s.crypt) - if err != nil { - log.Println(err) - c.Close() - return err - } - if _, err := link.WriteHost(CONN_TCP, host.Target); err != nil { - c.Close() - link.Close() - log.Println(err) - return err - } - if method == "CONNECT" { - fmt.Fprint(c, "HTTP/1.1 200 Connection established\r\n") - } else { - link.WriteCompress(rb, en) - } - go relay(link, c, en, s.crypt) - relay(c, link, de, s.crypt) - return nil + return s.dealClient(host.Vkey, en, de, c, host.Target, method, rb) } //web管理方式 @@ -320,6 +303,7 @@ func (s *WebServer) Start() { beego.Run() } +//new func NewWebServer(bridge *Tunnel) *WebServer { s := new(WebServer) s.bridge = bridge @@ -343,6 +327,7 @@ func NewHostServer(crypt bool) *HostServer { return s } +//close func (s *HostServer) Close() error { return nil } diff --git a/lib/sock5.go b/lib/socks5.go similarity index 98% rename from lib/sock5.go rename to lib/socks5.go index da58b48..ad6db6f 100755 --- a/lib/sock5.go +++ b/lib/socks5.go @@ -56,6 +56,7 @@ type Sock5ModeServer struct { crypt bool } +//req func (s *Sock5ModeServer) handleRequest(c net.Conn) { /* The SOCKS request is formed as follows: @@ -88,6 +89,7 @@ func (s *Sock5ModeServer) handleRequest(c net.Conn) { } } +//reply func (s *Sock5ModeServer) sendReply(c net.Conn, rep uint8) { reply := []byte{ 5, @@ -108,6 +110,7 @@ func (s *Sock5ModeServer) sendReply(c net.Conn, rep uint8) { c.Write(reply) } +//do conn func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) (proxyConn *Conn, err error) { addrType := make([]byte, 1) c.Read(addrType) @@ -154,6 +157,7 @@ func (s *Sock5ModeServer) doConnect(c net.Conn, command uint8) (proxyConn *Conn, return client, nil } +//conn func (s *Sock5ModeServer) handleConnect(c net.Conn) { proxyConn, err := s.doConnect(c, connectMethod) if err != nil { @@ -170,6 +174,7 @@ func (s *Sock5ModeServer) handleConnect(c net.Conn) { func (s *Sock5ModeServer) handleBind(c net.Conn) { } +//udp func (s *Sock5ModeServer) handleUDP(c net.Conn) { log.Println("UDP Associate") /* @@ -198,6 +203,7 @@ func (s *Sock5ModeServer) handleUDP(c net.Conn) { } } +//new conn func (s *Sock5ModeServer) handleNewConn(c net.Conn) { buf := make([]byte, 2) if _, err := io.ReadFull(c, buf); err != nil { @@ -234,6 +240,7 @@ func (s *Sock5ModeServer) handleNewConn(c net.Conn) { s.handleRequest(c) } +//socks5 auth func (s *Sock5ModeServer) Auth(c net.Conn) error { header := []byte{0, 0} if _, err := io.ReadAtLeast(c, header, 2); err != nil { @@ -269,6 +276,7 @@ func (s *Sock5ModeServer) Auth(c net.Conn) error { return errors.New("未知错误") } +//start func (s *Sock5ModeServer) Start() error { s.listener, err = net.Listen("tcp", ":"+strconv.Itoa(s.httpPort)) if err != nil { @@ -287,10 +295,12 @@ func (s *Sock5ModeServer) Start() error { return nil } +//close func (s *Sock5ModeServer) Close() error { return s.listener.Close() } +//new func NewSock5ModeServer(httpPort int, u, p string, brige *Tunnel, enCompress int, deCompress int, vKey string, crypt bool) *Sock5ModeServer { s := new(Sock5ModeServer) s.httpPort = httpPort diff --git a/lib/udp.go b/lib/udp.go index aefad6b..97f462b 100755 --- a/lib/udp.go +++ b/lib/udp.go @@ -1,7 +1,6 @@ package lib import ( - "fmt" "io" "log" "net" @@ -47,7 +46,6 @@ func (s *UdpModeServer) Start() error { if strings.Contains(err.Error(), "use of closed network connection") { break } - log.Println(err) continue } go s.process(addr, data[:n]) @@ -57,8 +55,6 @@ func (s *UdpModeServer) Start() error { //TODO:效率问题有待解决 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, s.crypt) if err != nil { log.Println(err) @@ -68,11 +64,11 @@ func (s *UdpModeServer) process(addr *net.UDPAddr, data []byte) { conn.Close() return } - conn.WriteCompress(data, s.enCompress) + conn.WriteTo(data, s.enCompress,s.crypt) go func(addr *net.UDPAddr, conn *Conn) { buf := make([]byte, 1024) conn.conn.SetReadDeadline(time.Now().Add(time.Duration(time.Second * 3))) - n, err := conn.ReadFromCompress(buf, s.deCompress) + n, err := conn.ReadFrom(buf, s.deCompress,s.crypt) if err != nil || err == io.EOF { conn.Close() return diff --git a/lib/util.go b/lib/util.go index c8051de..675d1a6 100755 --- a/lib/util.go +++ b/lib/util.go @@ -16,19 +16,11 @@ import ( "regexp" "strconv" "strings" - "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_ENCODE = iota @@ -37,6 +29,7 @@ const ( COMPRESS_SNAPY_DECODE ) +//error func BadRequest(w http.ResponseWriter) { http.Error(w, http.StatusText(http.StatusBadRequest), http.StatusBadRequest) } @@ -95,7 +88,7 @@ func DecodeRequest(data []byte) (*http.Request, error) { return req, nil } -//// 将response转为字节 +// 将response转为字节 func EncodeResponse(r *http.Response) ([]byte, error) { respBytes, err := httputil.DumpResponse(r, true) if err != nil { @@ -116,6 +109,7 @@ func DecodeResponse(data []byte) (*http.Response, error) { return resp, nil } +// 根据host地址从配置是文件中查找对应目标 func getHost(str string) (string, error) { for _, v := range config.SiteList { if v.Host == str { @@ -125,6 +119,7 @@ func getHost(str string) (string, error) { return "", errors.New("没有找到解析的的host!") } +//替换 func replaceHost(resp []byte) []byte { str := string(resp) for _, v := range config.SiteList { @@ -134,8 +129,8 @@ func replaceHost(resp []byte) []byte { return []byte(str) } +//copy func relay(in, out *Conn, compressType int, crypt bool) { - fmt.Println(crypt) switch compressType { case COMPRESS_SNAPY_ENCODE: copyBuffer(NewSnappyConn(in.conn, crypt), out) @@ -264,7 +259,7 @@ func GetStrByBool(b bool) string { return "0" } -// io.copy的优化版,读取buffer长度原为32*1024,与snappy不同,导致读取出的内容存在差异,不利于解密 +// 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.