util.go 4.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  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. if mux {
  41. out.Close()
  42. NewSnappyConn(in, crypt).Write([]byte(IO_EOF))
  43. }
  44. case COMPRESS_SNAPY_DECODE:
  45. copyBuffer(in, NewSnappyConn(out, crypt))
  46. if mux {
  47. in.Close()
  48. }
  49. case COMPRESS_NONE_ENCODE:
  50. copyBuffer(NewCryptConn(in, crypt), out)
  51. if mux {
  52. out.Close()
  53. NewCryptConn(in, crypt).Write([]byte(IO_EOF))
  54. }
  55. case COMPRESS_NONE_DECODE:
  56. copyBuffer(in, NewCryptConn(out, crypt))
  57. if mux {
  58. in.Close()
  59. }
  60. }
  61. if !mux {
  62. in.Close()
  63. out.Close()
  64. }
  65. }
  66. //判断压缩方式
  67. func GetCompressType(compress string) (int, int) {
  68. switch compress {
  69. case "":
  70. return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
  71. case "snappy":
  72. return COMPRESS_SNAPY_DECODE, COMPRESS_SNAPY_ENCODE
  73. default:
  74. log.Fatalln("数据压缩格式错误")
  75. }
  76. return COMPRESS_NONE_DECODE, COMPRESS_NONE_ENCODE
  77. }
  78. //通过host获取对应的ip地址
  79. func Gethostbyname(hostname string) string {
  80. if !DomainCheck(hostname) {
  81. return hostname
  82. }
  83. ips, _ := net.LookupIP(hostname)
  84. if ips != nil {
  85. for _, v := range ips {
  86. if v.To4() != nil {
  87. return v.String()
  88. }
  89. }
  90. }
  91. return ""
  92. }
  93. //检查是否是域名
  94. func DomainCheck(domain string) bool {
  95. var match bool
  96. IsLine := "^((http://)|(https://))?([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}(/)"
  97. NotLine := "^((http://)|(https://))?([a-zA-Z0-9]([a-zA-Z0-9\\-]{0,61}[a-zA-Z0-9])?\\.)+[a-zA-Z]{2,6}"
  98. match, _ = regexp.MatchString(IsLine, domain)
  99. if !match {
  100. match, _ = regexp.MatchString(NotLine, domain)
  101. }
  102. return match
  103. }
  104. //检查basic认证
  105. func CheckAuth(r *http.Request, user, passwd string) bool {
  106. s := strings.SplitN(r.Header.Get("Authorization"), " ", 2)
  107. if len(s) != 2 {
  108. return false
  109. }
  110. b, err := base64.StdEncoding.DecodeString(s[1])
  111. if err != nil {
  112. return false
  113. }
  114. pair := strings.SplitN(string(b), ":", 2)
  115. if len(pair) != 2 {
  116. return false
  117. }
  118. return pair[0] == user && pair[1] == passwd
  119. }
  120. //get bool by str
  121. func GetBoolByStr(s string) bool {
  122. switch s {
  123. case "1", "true":
  124. return true
  125. }
  126. return false
  127. }
  128. //get str by bool
  129. func GetStrByBool(b bool) string {
  130. if b {
  131. return "1"
  132. }
  133. return "0"
  134. }
  135. //int
  136. func GetIntNoerrByStr(str string) int {
  137. i, _ := strconv.Atoi(str)
  138. return i
  139. }
  140. var bufPool = sync.Pool{
  141. New: func() interface{} {
  142. return make([]byte, 65535)
  143. },
  144. }
  145. // io.copy的优化版,读取buffer长度原为32*1024,与snappy不同,导致读取出的内容存在差异,不利于解密,特此修改
  146. func copyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
  147. //TODO 回收问题
  148. buf := bufPool.Get().([]byte)
  149. for {
  150. nr, er := src.Read(buf)
  151. if nr > 0 {
  152. nw, ew := dst.Write(buf[0:nr])
  153. if nw > 0 {
  154. written += int64(nw)
  155. }
  156. if ew != nil {
  157. err = ew
  158. break
  159. }
  160. if nr != nw {
  161. err = io.ErrShortWrite
  162. break
  163. }
  164. }
  165. if er != nil {
  166. if er != io.EOF {
  167. err = er
  168. }
  169. break
  170. }
  171. }
  172. return written, err
  173. }
  174. //连接重置 清空缓存区
  175. func FlushConn(c net.Conn) {
  176. c.SetReadDeadline(time.Now().Add(time.Second * 3))
  177. buf := bufPool.Get().([]byte)
  178. for {
  179. if _, err := c.Read(buf); err != nil {
  180. break
  181. }
  182. }
  183. c.SetReadDeadline(time.Time{})
  184. }
  185. //简单的一个校验值
  186. func Getverifyval(vkey string) string {
  187. return Md5(vkey)
  188. }