func (p *Proxy) proxyUDPStream(ctx context.Context, src *net.UDPConn) { srcRemoteAddr := src.RemoteAddr().(*net.UDPAddr) srcLocalAddr := src.LocalAddr().(*net.UDPAddr) route := p.routes.GetTable().Lookup(protocols.UDP, srcRemoteAddr.IP, srcLocalAddr.IP, uint16(srcRemoteAddr.Port), uint16(srcLocalAddr.Port)) if route == nil { src.Close() return } go func() { dstAddr := net.UDPAddr{ IP: route.Outbound.DstIP, Port: int(route.Outbound.DstPort), } dst, err := net.DialUDP("udp", nil, &dstAddr) if err != nil { src.Close() return } dst.SetKeepAlivePeriod(10 * time.Second) src.SetKeepAlivePeriod(10 * time.Second) go func() { <-ctx.Done() src.Close() dst.Close() }() go func() { defer dst.CloseWrite() defer src.CloseRead() io.Copy(dst, src) }() go func() { defer src.CloseWrite() defer dst.CloseRead() io.Copy(src, dst) }() }() }