util.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228
  1. package utils
  2. import (
  3. "encoding/base64"
  4. "io"
  5. "log"
  6. "net"
  7. "net/http"
  8. "regexp"
  9. "strconv"
  10. "strings"
  11. "sync"
  12. "time"
  13. )
  14. const (
  15. COMPRESS_NONE_ENCODE = iota
  16. COMPRESS_NONE_DECODE
  17. COMPRESS_SNAPY_ENCODE
  18. COMPRESS_SNAPY_DECODE
  19. VERIFY_EER = "vkey"
  20. WORK_MAIN = "main"
  21. WORK_CHAN = "chan"
  22. RES_SIGN = "sign"
  23. RES_MSG = "msg0"
  24. CONN_SUCCESS = "sucs"
  25. CONN_ERROR = "fail"
  26. TEST_FLAG = "tst"
  27. CONN_TCP = "tcp"
  28. CONN_UDP = "udp"
  29. Unauthorized_BYTES = `HTTP/1.1 401 Unauthorized
  30. Content-Type: text/plain; charset=utf-8
  31. WWW-Authenticate: Basic realm="easyProxy"
  32. 401 Unauthorized`
  33. IO_EOF = "PROXYEOF"
  34. )
  35. //copy
  36. func Relay(in, out net.Conn, compressType int, crypt, mux bool) {
  37. switch compressType {
  38. case COMPRESS_SNAPY_ENCODE:
  39. copyBuffer(NewSnappyConn(in, crypt), out)
  40. out.Close()
  41. NewSnappyConn(in, crypt).Write([]byte(IO_EOF))
  42. case COMPRESS_SNAPY_DECODE:
  43. copyBuffer(in, NewSnappyConn(out, crypt))
  44. in.Close()
  45. if !mux {
  46. out.Close()
  47. }
  48. case COMPRESS_NONE_ENCODE:
  49. copyBuffer(NewCryptConn(in, crypt), out)
  50. out.Close()
  51. NewCryptConn(in, crypt).Write([]byte(IO_EOF))
  52. case COMPRESS_NONE_DECODE:
  53. copyBuffer(in, NewCryptConn(out, crypt))
  54. in.Close()
  55. if !mux {
  56. out.Close()
  57. }
  58. }
  59. }
  60. //判断压缩方式
  61. func GetCompressType(compress string) (int, int) {
  62. switch compress {
  63. case "":
  64. return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
  65. case "snappy":
  66. return COMPRESS_SNAPY_DECODE, COMPRESS_SNAPY_ENCODE
  67. default:
  68. log.Fatalln("数据压缩格式错误")
  69. }
  70. return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
  71. }
  72. //通过host获取对应的ip地址
  73. func Gethostbyname(hostname string) string {
  74. if !DomainCheck(hostname) {
  75. return hostname
  76. }
  77. ips, _ := net.LookupIP(hostname)
  78. if ips != nil {
  79. for _, v := range ips {
  80. if v.To4() != nil {
  81. return v.String()
  82. }
  83. }
  84. }
  85. return ""
  86. }
  87. //检查是否是域名
  88. func DomainCheck(domain string) bool {
  89. var match bool
  90. IsLine := "^((http://)|(https://))?([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/)"
  91. NotLine := "^((http://)|(https://))?([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}"
  92. match, _ = regexp.MatchString(IsLine, domain)
  93. if !match {
  94. match, _ = regexp.MatchString(NotLine, domain)
  95. }
  96. return match
  97. }
  98. //检查basic认证
  99. func CheckAuth(r *http.Request, user, passwd string) bool {
  100. s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
  101. if len(s) != 2 {
  102. return false
  103. }
  104. b, err := base64.StdEncoding.DecodeString(s[1])
  105. if err != nil {
  106. return false
  107. }
  108. pair := strings.SplitN(string(b), ":", 2)
  109. if len(pair) != 2 {
  110. return false
  111. }
  112. return pair[0] == user && pair[1] == passwd
  113. }
  114. //get bool by str
  115. func GetBoolByStr(s string) bool {
  116. switch s {
  117. case "1", "true":
  118. return true
  119. }
  120. return false
  121. }
  122. //get str by bool
  123. func GetStrByBool(b bool) string {
  124. if b {
  125. return "1"
  126. }
  127. return "0"
  128. }
  129. //int
  130. func GetIntNoerrByStr(str string) int {
  131. i, _ := strconv.Atoi(str)
  132. return i
  133. }
  134. // io.copy的优化版,读取buffer长度原为32*1024,与snappy不同,导致读取出的内容存在差异,不利于解密,特此修改
  135. //内存优化 用到pool,快速回收
  136. func copyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
  137. for {
  138. buf := bufPoolCopy.Get().([]byte)
  139. nr, er := src.Read(buf)
  140. if nr > 0 {
  141. nw, ew := dst.Write(buf[0:nr])
  142. bufPoolCopy.Put(buf)
  143. if nw > 0 {
  144. written += int64(nw)
  145. }
  146. if ew != nil {
  147. err = ew
  148. break
  149. }
  150. if nr != nw {
  151. err = io.ErrShortWrite
  152. break
  153. }
  154. }else {
  155. bufPoolCopy.Put(buf)
  156. }
  157. if er != nil {
  158. if er != io.EOF {
  159. err = er
  160. }
  161. break
  162. }
  163. }
  164. return written, err
  165. }
  166. //连接重置 清空缓存区
  167. func FlushConn(c net.Conn) {
  168. c.SetReadDeadline(time.Now().Add(time.Second * 3))
  169. buf := bufPool.Get().([]byte)
  170. defer bufPool.Put(buf)
  171. for {
  172. if _, err := c.Read(buf); err != nil {
  173. break
  174. }
  175. }
  176. c.SetReadDeadline(time.Time{})
  177. }
  178. //简单的一个校验值
  179. func Getverifyval(vkey string) string {
  180. return Md5(vkey)
  181. }
  182. //wait replay group
  183. func ReplayWaitGroup(conn1 net.Conn, conn2 net.Conn, compressEncode, compressDecode int, crypt, mux bool) {
  184. var wg sync.WaitGroup
  185. wg.Add(1)
  186. go func() {
  187. Relay(conn1, conn2, compressEncode, crypt, mux)
  188. wg.Done()
  189. }()
  190. Relay(conn2, conn1, compressDecode, crypt, mux)
  191. wg.Wait()
  192. }
  193. func ChangeHostAndHeader(r *http.Request, host string, header string, addr string) {
  194. if host != "" {
  195. r.Host = host
  196. }
  197. if header != "" {
  198. h := strings.Split(header, "\n")
  199. for _, v := range h {
  200. hd := strings.Split(v, ":")
  201. if len(hd) == 2 {
  202. r.Header.Set(hd[0], hd[1])
  203. }
  204. }
  205. }
  206. addr = strings.Split(addr, ":")[0]
  207. r.Header.Set("X-Forwarded-For", addr)
  208. r.Header.Set("X-Real-IP", addr)
  209. }