nb.go 7.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204
  1. package main
  2. import (
  3. "fmt"
  4. "io"
  5. "log"
  6. "net"
  7. "os"
  8. "regexp"
  9. "strconv"
  10. "strings"
  11. "sync"
  12. "time"
  13. )
  14. func printWelcome() {
  15. fmt.Println("+----------------------------------------------------------------+")
  16. fmt.Println("| Welcome to use NATBypass Ver1.0.0 . |")
  17. fmt.Println("| Code by cw1997 at 2017-10-19 03:59:51 |")
  18. fmt.Println("| Modified by tobychui as Zoraxy test tool |")
  19. fmt.Println("| If you have some problem when you use the tool, |")
  20. fmt.Println("| please submit issue at : https://github.com/cw1997/NATBypass . |")
  21. fmt.Println("+----------------------------------------------------------------+")
  22. fmt.Println()
  23. // sleep one second because the fmt is not thread-safety.
  24. // if not to do this, fmt.Print will print after the log.Print.
  25. time.Sleep(time.Second)
  26. }
  27. func printHelp() {
  28. fmt.Println(`usage: "-listen port1 port2" example: "nb -listen 1997 2017" `)
  29. fmt.Println(` "-tran port1 ip:port2" example: "nb -tran 1997 192.168.1.2:3389" `)
  30. fmt.Println(` "-slave ip1:port1 ip2:port2" example: "nb -slave 127.0.0.1:3389 8.8.8.8:1997" `)
  31. fmt.Println(`============================================================`)
  32. fmt.Println(`optional argument: "-log logpath" . example: "nb -listen 1997 2017 -log d:/nb" `)
  33. fmt.Println(`log filename format: Y_m_d_H_i_s-agrs1-args2-args3.log`)
  34. fmt.Println(`============================================================`)
  35. fmt.Println(`if you want more help, please read "README.md". `)
  36. }
  37. func checkPort(port string) string {
  38. PortNum, err := strconv.Atoi(port)
  39. if err != nil {
  40. log.Fatalln("[x]", "port should be a number")
  41. }
  42. if PortNum < 1 || PortNum > 65535 {
  43. log.Fatalln("[x]", "port should be a number and the range is [1,65536)")
  44. }
  45. return port
  46. }
  47. func checkIp(address string) bool {
  48. ipAndPort := strings.Split(address, ":")
  49. if len(ipAndPort) != 2 {
  50. log.Fatalln("[x]", "address error. should be a string like [ip:port]. ")
  51. }
  52. ip := ipAndPort[0]
  53. port := ipAndPort[1]
  54. checkPort(port)
  55. pattern := `^(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])\.(\d{1,2}|1\d\d|2[0-4]\d|25[0-5])$`
  56. ok, err := regexp.MatchString(pattern, ip)
  57. if err != nil || !ok {
  58. log.Fatalln("[x]", "ip error. ")
  59. }
  60. return ok
  61. }
  62. func port2port(port1 string, port2 string) {
  63. listen1 := start_server("0.0.0.0:" + port1)
  64. listen2 := start_server("0.0.0.0:" + port2)
  65. log.Println("[√]", "listen port:", port1, "and", port2, "success. waiting for client...")
  66. for {
  67. conn1 := accept(listen1)
  68. conn2 := accept(listen2)
  69. if conn1 == nil || conn2 == nil {
  70. log.Println("[x]", "accept client faild. retry in ", timeout, " seconds. ")
  71. time.Sleep(timeout * time.Second)
  72. continue
  73. }
  74. forward(conn1, conn2)
  75. }
  76. }
  77. func port2host(allowPort string, targetAddress string) {
  78. server := start_server("0.0.0.0:" + allowPort)
  79. for {
  80. conn := accept(server)
  81. if conn == nil {
  82. continue
  83. }
  84. //println(targetAddress)
  85. go func(targetAddress string) {
  86. log.Println("[+]", "start connect host:["+targetAddress+"]")
  87. target, err := net.Dial("tcp", targetAddress)
  88. if err != nil {
  89. // temporarily unavailable, don't use fatal.
  90. log.Println("[x]", "connect target address ["+targetAddress+"] faild. retry in ", timeout, "seconds. ")
  91. conn.Close()
  92. log.Println("[←]", "close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]")
  93. time.Sleep(timeout * time.Second)
  94. return
  95. }
  96. log.Println("[→]", "connect target address ["+targetAddress+"] success.")
  97. forward(target, conn)
  98. }(targetAddress)
  99. }
  100. }
  101. func host2host(address1, address2 string) {
  102. for {
  103. log.Println("[+]", "try to connect host:["+address1+"] and ["+address2+"]")
  104. var host1, host2 net.Conn
  105. var err error
  106. for {
  107. host1, err = net.Dial("tcp", address1)
  108. if err == nil {
  109. log.Println("[→]", "connect ["+address1+"] success.")
  110. break
  111. } else {
  112. log.Println("[x]", "connect target address ["+address1+"] faild. retry in ", timeout, " seconds. ")
  113. time.Sleep(timeout * time.Second)
  114. }
  115. }
  116. for {
  117. host2, err = net.Dial("tcp", address2)
  118. if err == nil {
  119. log.Println("[→]", "connect ["+address2+"] success.")
  120. break
  121. } else {
  122. log.Println("[x]", "connect target address ["+address2+"] faild. retry in ", timeout, " seconds. ")
  123. time.Sleep(timeout * time.Second)
  124. }
  125. }
  126. forward(host1, host2)
  127. }
  128. }
  129. func start_server(address string) net.Listener {
  130. log.Println("[+]", "try to start server on:["+address+"]")
  131. server, err := net.Listen("tcp", address)
  132. if err != nil {
  133. log.Fatalln("[x]", "listen address ["+address+"] faild.")
  134. }
  135. log.Println("[√]", "start listen at address:["+address+"]")
  136. return server
  137. }
  138. func accept(listener net.Listener) net.Conn {
  139. conn, err := listener.Accept()
  140. if err != nil {
  141. log.Println("[x]", "accept connect ["+conn.RemoteAddr().String()+"] faild.", err.Error())
  142. return nil
  143. }
  144. log.Println("[√]", "accept a new client. remote address:["+conn.RemoteAddr().String()+"], local address:["+conn.LocalAddr().String()+"]")
  145. return conn
  146. }
  147. func forward(conn1 net.Conn, conn2 net.Conn) {
  148. log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
  149. var wg sync.WaitGroup
  150. // wait tow goroutines
  151. wg.Add(2)
  152. go connCopy(conn1, conn2, &wg)
  153. go connCopy(conn2, conn1, &wg)
  154. //blocking when the wg is locked
  155. wg.Wait()
  156. }
  157. func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup) {
  158. //TODO:log, record the data from conn1 and conn2.
  159. logFile := openLog(conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
  160. if logFile != nil {
  161. w := io.MultiWriter(conn1, logFile)
  162. io.Copy(w, conn2)
  163. } else {
  164. io.Copy(conn1, conn2)
  165. }
  166. conn1.Close()
  167. log.Println("[←]", "close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]")
  168. //conn2.Close()
  169. //log.Println("[←]", "close the connect at local:["+conn2.LocalAddr().String()+"] and remote:["+conn2.RemoteAddr().String()+"]")
  170. wg.Done()
  171. }
  172. func openLog(address1, address2, address3, address4 string) *os.File {
  173. args := os.Args
  174. argc := len(os.Args)
  175. var logFileError error
  176. var logFile *os.File
  177. if argc > 5 && args[4] == "-log" {
  178. address1 = strings.Replace(address1, ":", "_", -1)
  179. address2 = strings.Replace(address2, ":", "_", -1)
  180. address3 = strings.Replace(address3, ":", "_", -1)
  181. address4 = strings.Replace(address4, ":", "_", -1)
  182. timeStr := time.Now().Format("2006_01_02_15_04_05") // "2006-01-02 15:04:05"
  183. logPath := args[5] + "/" + timeStr + args[1] + "-" + address1 + "_" + address2 + "-" + address3 + "_" + address4 + ".log"
  184. logPath = strings.Replace(logPath, `\`, "/", -1)
  185. logPath = strings.Replace(logPath, "//", "/", -1)
  186. logFile, logFileError = os.OpenFile(logPath, os.O_APPEND|os.O_CREATE, 0666)
  187. if logFileError != nil {
  188. log.Fatalln("[x]", "log file path error.", logFileError.Error())
  189. }
  190. log.Println("[√]", "open test log file success. path:", logPath)
  191. }
  192. return logFile
  193. }