package app import ( "git.makemake.in/test/mycommon/mylog" "io" "math/rand" "net" "sync" "time" ) func Run() { rand.Seed(time.Now().UnixNano()) for name, item := range ProxyMap { go listenTcp(name, item) } select {} } func listenTcp(name string, item ProxyItem) { listen, err := net.Listen("tcp", item.LocalAddr) if err != nil { mylog.Errorf("[%s] listen err: %s", name, err) return } mylog.Infof("[%s] listen %s", name, item.LocalAddr) for { localConn, err := listen.Accept() if err != nil { mylog.Errorf("conn accept err: %s", item.LocalAddr, err) return } go proxyTcp(localConn, item) } } func proxyTcp(localConn net.Conn, item ProxyItem) { randRemoteAddr := item.RemoteAddr[rand.Intn(len(item.RemoteAddr))] remoteConn, err := net.DialTimeout("tcp", randRemoteAddr, time.Second*3) if err != nil { localConn.Close() mylog.Errorf("connect remote err: %s", err) return } mylog.Infof("start proxy %s -> %s", localConn.RemoteAddr(), randRemoteAddr) wg0 := &sync.WaitGroup{} wg0.Add(2) go copyConn(wg0, localConn, remoteConn) go copyConn(wg0, remoteConn, localConn) wg0.Wait() mylog.Infof("stop proxy %s -> %s", localConn.RemoteAddr(), randRemoteAddr) } func copyConn(wg0 *sync.WaitGroup, localConn, remoteConn net.Conn) { defer func() { wg0.Done() localConn.Close() remoteConn.Close() }() _, err := io.Copy(remoteConn, localConn) if err != nil { mylog.Error(err) } }