TCP/UDP 端口转发(Google Voice 可用)
2020-11-26 21:03:34
Art
自己写的tcp/udp 转发工具,附部分源码。原先使用haproxy转发流量,提供的功能很强大,性能也很好,后来用Google Volce的时候发现用不了,不支持udp流量转发,于是自己动手写一个简易转发工具,自测可用。
1.TCP部分源码
func handle(client net.Conn, server string, output string) { if client == nil { return } log.Println("TCP handle new connection.") defer client.Close() destConn, err := net.DialTimeout("tcp", server+output, time.Second*3) if err != nil { log.Println(err) return } defer destConn.Close() //将客户端的请求转发至服务端,将服务端的响应转发给客户端。io.Copy为阻塞函数,文件描述符不关闭就不停止 relay(client, destConn) log.Println("TCP handle close connection.") } // relay copies between left and right bidirectionally func relay(left, right net.Conn) error { var err, err1 error var wg sync.WaitGroup var wait = 5 * time.Second wg.Add(1) go func() { defer wg.Done() _, err1 = io.Copy(right, left) right.SetReadDeadline(time.Now().Add(wait)) // unblock read on right }() _, err = io.Copy(left, right) left.SetReadDeadline(time.Now().Add(wait)) // unblock read on left wg.Wait() if err1 != nil && !errors.Is(err1, os.ErrDeadlineExceeded) { // requires Go 1.15+ return err1 } if err != nil && !errors.Is(err, os.ErrDeadlineExceeded) { return err } return nil }
2.UDP部分源码
type UDPCap struct { ClientAddr *net.UDPAddr // Address of the client ServerConn *net.UDPConn // UDP connection to server } type UDPCapsLock struct { UDPCaps map[string]*UDPCap Lock sync.Mutex } // Generate a new connection by opening a UDP connection to the server func NewConnection(srvAddr, cliAddr *net.UDPAddr) *UDPCap { conn := new(UDPCap) conn.ClientAddr = cliAddr srvudp, err := net.DialUDP("udp", nil, srvAddr) if checkreport(1, err) { return nil } conn.ServerConn = srvudp return conn } func setup(hostport string, port int) { // Set up Proxy saddr, err := net.ResolveUDPAddr("udp", fmt.Sprintf(":%d", port)) if checkreport(1, err) { } localConn, err := net.ListenUDP("udp", saddr) if checkreport(1, err) { } logf("UDP Proxy serving on port %d\n", port) // Get server address ServerAddr, err := net.ResolveUDPAddr("udp", hostport) if checkreport(1, err) { } logf("UDP Connected to server at %s\n", hostport) RunProxy(localConn, ServerAddr) } // Go routine which manages connection from server to single client func RunConnection(conn *UDPCap, udpcapsLock UDPCapsLock, localConn *net.UDPConn) { var buffer [1500]byte for { // Read from server conn.ServerConn.SetReadDeadline(time.Now().Add(time.Minute * 5)) n, err := conn.ServerConn.Read(buffer[0:]) if checkreport2(1, err) == 1 { //删除 log.Println("udp delete timeout router") udpcapsLock.Lock.Lock() conn.ServerConn.Close() delete(udpcapsLock.UDPCaps, conn.ClientAddr.String()) udpcapsLock.Lock.Unlock() break } // Relay it to client _, err = localConn.WriteToUDP(buffer[0:n], conn.ClientAddr) } } // Routine to handle inputs to Proxy port func RunProxy(localConn *net.UDPConn, ServerAddr *net.UDPAddr) { var buffer [1500]byte log.Println("UDP start") var uncapsLock UDPCapsLock uncapsLock.UDPCaps = map[string]*UDPCap{} for { n, cliaddr, err := localConn.ReadFromUDP(buffer[0:]) if checkreport(1, err) { continue } //Vlogf(3, "UDP Read sth. from client %s, routers length %d \n", cliaddr.String(), len(uncapsLock.UDPCaps)) saddr := cliaddr.String() udpcap, found := uncapsLock.UDPCaps[saddr] if !found { udpcap = NewConnection(ServerAddr, cliaddr) if udpcap == nil { continue } uncapsLock.Lock.Lock() uncapsLock.UDPCaps[saddr] = udpcap uncapsLock.Lock.Unlock() logf("UDP Created new connection for client %s routers length %d \n", saddr, len(uncapsLock.UDPCaps)) // Fire up routine to manage new connection go RunConnection(udpcap, uncapsLock, localConn) } // Relay to server _, err = udpcap.ServerConn.Write(buffer[0:n]) if checkreport(1, err) { continue } } }
3.forward工具下载
提取码: zus5 复制这段内容后打开百度网盘手机App,操作更方便哦
4.configs.json
[ { "inport": 13531, "outport": 13531, "server": "127.0.0.1" }, { "inport": 13532, "outport": 13532, "server": "127.0.0.1" }, { "inport": 13533, "outport": 13533, "server": "127.0.0.1" } ]
5.打开方式
./forward ./configs.json &