util.go 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234
  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. var bufPool = sync.Pool{
  135. New: func() interface{} {
  136. return make([]byte, poolSize)
  137. },
  138. }
  139. var bufPoolSmall = sync.Pool{
  140. New: func() interface{} {
  141. return make([]byte, poolSizeSmall)
  142. },
  143. }
  144. // io.copy的优化版,读取buffer长度原为32*1024,与snappy不同,导致读取出的内容存在差异,不利于解密,特此修改
  145. //废除
  146. func copyBuffer(dst io.Writer, src io.Reader) (written int64, err error) {
  147. //TODO 回收问题
  148. buf := bufPool.Get().([]byte)[:32*1024]
  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. }
  189. //wait replay group
  190. func ReplayWaitGroup(conn1 net.Conn, conn2 net.Conn, compressEncode, compressDecode int, crypt, mux bool) {
  191. var wg sync.WaitGroup
  192. wg.Add(1)
  193. go func() {
  194. Relay(conn1, conn2, compressEncode, crypt, mux)
  195. wg.Done()
  196. }()
  197. Relay(conn2, conn1, compressDecode, crypt, mux)
  198. wg.Wait()
  199. }
  200. func ChangeHostAndHeader(r *http.Request, host string, header string, addr string) {
  201. if host != "" {
  202. r.Host = host
  203. }
  204. if header != "" {
  205. h := strings.Split(header, "\n")
  206. for _, v := range h {
  207. hd := strings.Split(v, ":")
  208. if len(hd) == 2 {
  209. r.Header.Set(hd[0], hd[1])
  210. }
  211. }
  212. }
  213. addr = strings.Split(addr, ":")[0]
  214. r.Header.Set("X-Forwarded-For", addr)
  215. r.Header.Set("X-Real-IP", addr)
  216. }