nbp(修正).go 9.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303
  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. const timeout = 5
  15. func main() {
  16. //log.SetFlags(log.Ldate | log.Lmicroseconds | log.Lshortfile)
  17. log.SetFlags(log.Ldate | log.Lmicroseconds)
  18. printWelcome()
  19. args := os.Args
  20. argc := len(os.Args)
  21. if argc <= 2 {
  22. printHelp()
  23. os.Exit(0)
  24. }
  25. //TODO:support UDP protocol
  26. /*var logFileError error
  27. if argc > 5 && args[4] == "-log" {
  28. logPath := args[5] + "/" + time.Now().Format("2006_01_02_15_04_05") // "2006-01-02 15:04:05"
  29. logPath += args[1] + "-" + strings.Replace(args[2], ":", "_", -1) + "-" + args[3] + ".log"
  30. logPath = strings.Replace(logPath, `\`, "/", -1)
  31. logPath = strings.Replace(logPath, "//", "/", -1)
  32. logFile, logFileError = os.OpenFile(logPath, os.O_APPEND|os.O_CREATE, 0666)
  33. if logFileError != nil {
  34. log.Fatalln("[x]", "log file path error.", logFileError.Error())
  35. }
  36. log.Println("[√]", "open test log file success. path:", logPath)
  37. }*/
  38. switch args[1] {
  39. case "-listen":
  40. if argc < 3 {
  41. log.Fatalln(`-listen need two arguments, like "nb -listen 1997 2017".`)
  42. }
  43. port1 := checkPort(args[2])
  44. port2 := checkPort(args[3])
  45. log.Println("[√]", "start to listen port:", port1, "and port:", port2)
  46. port2port(port1, port2)
  47. break
  48. case "-tran":
  49. if argc < 3 {
  50. log.Fatalln(`-tran need two arguments, like "nb -tran 1997 192.168.1.2:3389".`)
  51. }
  52. port := checkPort(args[2])
  53. var remoteAddress string
  54. if checkIp(args[3]) {
  55. remoteAddress = args[3]
  56. }
  57. split := strings.SplitN(remoteAddress, ":", 2)
  58. log.Println("[√]", "start to transmit address:", remoteAddress, "to address:", split[0]+":"+port)
  59. port2host(port, remoteAddress)
  60. break
  61. case "-slave":
  62. if argc < 3 {
  63. log.Fatalln(`-slave need two arguments, like "nb -slave 127.0.0.1:3389 8.8.8.8:1997".`)
  64. }
  65. var address1, address2 string
  66. checkIp(args[2])
  67. if checkIp(args[2]) {
  68. address1 = args[2]
  69. }
  70. checkIp(args[3])
  71. if checkIp(args[3]) {
  72. address2 = args[3]
  73. }
  74. log.Println("[√]", "start to connect address:", address1, "and address:", address2)
  75. host2host(address1, address2)
  76. break
  77. default:
  78. printHelp()
  79. }
  80. }
  81. func printWelcome() {
  82. fmt.Println("+----------------------------------------------------------------+")
  83. fmt.Println("| Welcome to use NATBypass Ver1.0.0 . |")
  84. fmt.Println("| Code by cw1997 at 2017-10-19 03:59:51 |")
  85. fmt.Println("| If you have some problem when you use the tool, |")
  86. fmt.Println("| please submit issue at : https://github.com/cw1997/NATBypass . |")
  87. fmt.Println("+----------------------------------------------------------------+")
  88. fmt.Println()
  89. // sleep one second because the fmt is not thread-safety.
  90. // if not to do this, fmt.Print will print after the log.Print.
  91. time.Sleep(time.Second)
  92. }
  93. func printHelp() {
  94. fmt.Println(`usage: "-listen port1 port2" example: "nb -listen 1997 2017" `)
  95. fmt.Println(` "-tran port1 ip:port2" example: "nb -tran 1997 192.168.1.2:3389" `)
  96. fmt.Println(` "-slave ip1:port1 ip2:port2" example: "nb -slave 127.0.0.1:3389 8.8.8.8:1997" `)
  97. fmt.Println(`============================================================`)
  98. fmt.Println(`optional argument: "-log logpath" . example: "nb -listen 1997 2017 -log d:/nb" `)
  99. fmt.Println(`log filename format: Y_m_d_H_i_s-agrs1-args2-args3.log`)
  100. fmt.Println(`============================================================`)
  101. fmt.Println(`if you want more help, please read "README.md". `)
  102. }
  103. func checkPort(port string) string {
  104. PortNum, err := strconv.Atoi(port)
  105. if err != nil {
  106. log.Fatalln("[x]", "port should be a number")
  107. }
  108. if PortNum < 1 || PortNum > 65535 {
  109. log.Fatalln("[x]", "port should be a number and the range is [1,65536)")
  110. }
  111. return port
  112. }
  113. func checkIp(address string) bool {
  114. ipAndPort := strings.Split(address, ":")
  115. if len(ipAndPort) != 2 {
  116. log.Fatalln("[x]", "address error. should be a string like [ip:port]. ")
  117. }
  118. ip := ipAndPort[0]
  119. port := ipAndPort[1]
  120. checkPort(port)
  121. 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])$`
  122. ok, err := regexp.MatchString(pattern, ip)
  123. if err != nil || !ok {
  124. log.Fatalln("[x]", "ip error. ")
  125. }
  126. return ok
  127. }
  128. func port2port(port1 string, port2 string) {
  129. listen1 := start_server("0.0.0.0:" + port1)
  130. listen2 := start_server("0.0.0.0:" + port2)
  131. log.Println("[√]", "listen port:", port1, "and", port2, "success. waiting for client...")
  132. for {
  133. err1 := listen1.Close();
  134. if err1 != nil {
  135. log.Println("[x]", "Close Listen1 Error:",err1)
  136. }else{
  137. listen1 = start_server("0.0.0.0:" + port1)
  138. }
  139. err2 := listen2.Close();
  140. if err2 != nil {
  141. log.Println("[x]", "Close Listen2 Error:",err2)
  142. }else{
  143. listen2 = start_server("0.0.0.0:" + port2)
  144. }
  145. conn1 := accept(listen1)
  146. conn2 := accept(listen2)
  147. if conn1 == nil || conn2 == nil {
  148. log.Println("[x]", "accept client faild. retry in ", timeout, " seconds. ")
  149. time.Sleep(timeout * time.Second)
  150. continue
  151. }
  152. forward(conn1, conn2)
  153. }
  154. }
  155. func port2host(allowPort string, targetAddress string) {
  156. server := start_server("0.0.0.0:" + allowPort)
  157. for {
  158. conn := accept(server)
  159. if conn == nil {
  160. continue
  161. }
  162. //println(targetAddress)
  163. go func(targetAddress string) {
  164. log.Println("[+]", "start connect host:["+targetAddress+"]")
  165. target, err := net.Dial("tcp", targetAddress)
  166. if err != nil {
  167. // temporarily unavailable, don't use fatal.
  168. log.Println("[x]", "connect target address ["+targetAddress+"] faild. retry in ", timeout, "seconds. ")
  169. conn.Close()
  170. log.Println("[←]", "close the connect at local:["+conn.LocalAddr().String()+"] and remote:["+conn.RemoteAddr().String()+"]")
  171. time.Sleep(timeout * time.Second)
  172. return
  173. }
  174. log.Println("[→]", "connect target address ["+targetAddress+"] success.")
  175. forward(target, conn)
  176. }(targetAddress)
  177. }
  178. }
  179. func host2host(address1, address2 string) {
  180. for {
  181. log.Println("[+]", "try to connect host:["+address1+"] and ["+address2+"]")
  182. var host1, host2 net.Conn
  183. var err error
  184. for {
  185. host1, err = net.Dial("tcp", address1)
  186. if err == nil {
  187. log.Println("[→]", "connect ["+address1+"] success.")
  188. break
  189. } else {
  190. log.Println("[x]", "connect target address ["+address1+"] faild. retry in ", timeout, " seconds. ")
  191. time.Sleep(timeout * time.Second)
  192. }
  193. }
  194. for {
  195. host2, err = net.Dial("tcp", address2)
  196. if err == nil {
  197. log.Println("[→]", "connect ["+address2+"] success.")
  198. break
  199. } else {
  200. log.Println("[x]", "connect target address ["+address2+"] faild. retry in ", timeout, " seconds. ")
  201. time.Sleep(timeout * time.Second)
  202. }
  203. }
  204. forward(host1, host2)
  205. }
  206. }
  207. func start_server(address string) net.Listener {
  208. log.Println("[+]", "try to start server on:["+address+"]")
  209. server, err := net.Listen("tcp", address)
  210. if err != nil {
  211. log.Fatalln("[x]", "listen address ["+address+"] faild.")
  212. }
  213. log.Println("[√]", "start listen at address:["+address+"]")
  214. return server
  215. /*defer server.Close()
  216. for {
  217. conn, err := server.Accept()
  218. log.Println("accept a new client. remote address:[" + conn.RemoteAddr().String() +
  219. "], local address:[" + conn.LocalAddr().String() + "]")
  220. if err != nil {
  221. log.Println("accept a new client faild.", err.Error())
  222. continue
  223. }
  224. //go recvConnMsg(conn)
  225. }*/
  226. }
  227. func accept(listener net.Listener) net.Conn {
  228. conn, err := listener.Accept()
  229. if err != nil {
  230. log.Println("[x]", "accept connect ["+conn.RemoteAddr().String()+"] faild.", err.Error())
  231. return nil
  232. }
  233. log.Println("[√]", "accept a new client. remote address:["+conn.RemoteAddr().String()+"], local address:["+conn.LocalAddr().String()+"]")
  234. return conn
  235. }
  236. func forward(conn1 net.Conn, conn2 net.Conn) {
  237. log.Printf("[+] start transmit. [%s],[%s] <-> [%s],[%s] \n", conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
  238. var wg sync.WaitGroup
  239. // wait tow goroutines
  240. wg.Add(2)
  241. go connCopy(conn1, conn2, &wg)
  242. go connCopy(conn2, conn1, &wg)
  243. //blocking when the wg is locked
  244. wg.Wait()
  245. }
  246. func connCopy(conn1 net.Conn, conn2 net.Conn, wg *sync.WaitGroup) {
  247. //TODO:log, record the data from conn1 and conn2.
  248. logFile := openLog(conn1.LocalAddr().String(), conn1.RemoteAddr().String(), conn2.LocalAddr().String(), conn2.RemoteAddr().String())
  249. if logFile != nil {
  250. w := io.MultiWriter(conn1, logFile)
  251. io.Copy(w, conn2)
  252. } else {
  253. io.Copy(conn1, conn2)
  254. }
  255. conn1.Close()
  256. log.Println("[←]", "close the connect at local:["+conn1.LocalAddr().String()+"] and remote:["+conn1.RemoteAddr().String()+"]")
  257. //conn2.Close()
  258. //log.Println("[←]", "close the connect at local:["+conn2.LocalAddr().String()+"] and remote:["+conn2.RemoteAddr().String()+"]")
  259. wg.Done()
  260. }
  261. func openLog(address1, address2, address3, address4 string) *os.File {
  262. args := os.Args
  263. argc := len(os.Args)
  264. var logFileError error
  265. var logFile *os.File
  266. if argc > 5 && args[4] == "-log" {
  267. address1 = strings.Replace(address1, ":", "_", -1)
  268. address2 = strings.Replace(address2, ":", "_", -1)
  269. address3 = strings.Replace(address3, ":", "_", -1)
  270. address4 = strings.Replace(address4, ":", "_", -1)
  271. timeStr := time.Now().Format("2006_01_02_15_04_05") // "2006-01-02 15:04:05"
  272. logPath := args[5] + "/" + timeStr + args[1] + "-" + address1 + "_" + address2 + "-" + address3 + "_" + address4 + ".log"
  273. logPath = strings.Replace(logPath, `\`, "/", -1)
  274. logPath = strings.Replace(logPath, "//", "/", -1)
  275. logFile, logFileError = os.OpenFile(logPath, os.O_APPEND|os.O_CREATE, 0666)
  276. if logFileError != nil {
  277. log.Fatalln("[x]", "log file path error.", logFileError.Error())
  278. }
  279. log.Println("[√]", "open test log file success. path:", logPath)
  280. }
  281. return logFile
  282. }