From 5ac95d987a71d81bea135ed05f09b278f8ec8198 Mon Sep 17 00:00:00 2001 From: Toby Date: Tue, 27 Apr 2021 20:14:43 -0700 Subject: [PATCH] Use core.Transport --- cmd/client.go | 23 ++++++++------ cmd/server.go | 4 +-- pkg/acl/engine.go | 2 +- pkg/core/server_client.go | 12 +++---- pkg/core/transport.go | 67 +++++++++++++++++++++++++++++++++++---- pkg/http/server.go | 4 +-- pkg/relay/tcp.go | 8 +++-- pkg/relay/udp.go | 8 +++-- pkg/socks5/server.go | 19 ++++++----- pkg/tproxy/tcp_linux.go | 11 ++++--- pkg/tproxy/udp_linux.go | 11 ++++--- 11 files changed, 120 insertions(+), 49 deletions(-) diff --git a/cmd/client.go b/cmd/client.go index 8d3dfe1..c33fa6d 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -75,7 +75,7 @@ func client(config *clientConfig) { var aclEngine *acl.Engine if len(config.ACL) > 0 { var err error - aclEngine, err = acl.LoadFromFile(config.ACL) + aclEngine, err = acl.LoadFromFile(config.ACL, core.DefaultTransport) if err != nil { logrus.WithFields(logrus.Fields{ "error": err, @@ -84,7 +84,7 @@ func client(config *clientConfig) { } } // Client - client, err := core.NewClient(config.Server, auth, tlsConfig, quicConfig, + client, err := core.NewClient(config.Server, auth, tlsConfig, quicConfig, core.DefaultTransport, uint64(config.UpMbps)*mbpsToBps, uint64(config.DownMbps)*mbpsToBps, func(refBPS uint64) congestion.CongestionControl { return hyCongestion.NewBrutalSender(congestion.ByteCount(refBPS)) @@ -105,7 +105,7 @@ func client(config *clientConfig) { return config.SOCKS5.User == user && config.SOCKS5.Password == password } } - socks5server, err := socks5.NewServer(client, config.SOCKS5.Listen, authFunc, + socks5server, err := socks5.NewServer(client, core.DefaultTransport, config.SOCKS5.Listen, authFunc, time.Duration(config.SOCKS5.Timeout)*time.Second, aclEngine, config.SOCKS5.DisableUDP, func(addr net.Addr, reqAddr string, action acl.Action, arg string) { logrus.WithFields(logrus.Fields{ @@ -161,7 +161,8 @@ func client(config *clientConfig) { return config.HTTP.User == user && config.HTTP.Password == password } } - proxy, err := hyHTTP.NewProxyHTTPServer(client, time.Duration(config.HTTP.Timeout)*time.Second, aclEngine, + proxy, err := hyHTTP.NewProxyHTTPServer(client, core.DefaultTransport, + time.Duration(config.HTTP.Timeout)*time.Second, aclEngine, func(reqAddr string, action acl.Action, arg string) { logrus.WithFields(logrus.Fields{ "action": actionToString(action, arg), @@ -184,7 +185,8 @@ func client(config *clientConfig) { if len(config.TCPRelay.Listen) > 0 { go func() { - rl, err := relay.NewTCPRelay(client, config.TCPRelay.Listen, config.TCPRelay.Remote, + rl, err := relay.NewTCPRelay(client, core.DefaultTransport, + config.TCPRelay.Listen, config.TCPRelay.Remote, time.Duration(config.TCPRelay.Timeout)*time.Second, func(addr net.Addr) { logrus.WithFields(logrus.Fields{ @@ -213,7 +215,8 @@ func client(config *clientConfig) { if len(config.UDPRelay.Listen) > 0 { go func() { - rl, err := relay.NewUDPRelay(client, config.UDPRelay.Listen, config.UDPRelay.Remote, + rl, err := relay.NewUDPRelay(client, core.DefaultTransport, + config.UDPRelay.Listen, config.UDPRelay.Remote, time.Duration(config.UDPRelay.Timeout)*time.Second, func(addr net.Addr) { logrus.WithFields(logrus.Fields{ @@ -242,8 +245,8 @@ func client(config *clientConfig) { if len(config.TCPTProxy.Listen) > 0 { go func() { - rl, err := tproxy.NewTCPTProxy(client, config.TCPTProxy.Listen, - time.Duration(config.TCPTProxy.Timeout)*time.Second, aclEngine, + rl, err := tproxy.NewTCPTProxy(client, core.DefaultTransport, + config.TCPTProxy.Listen, time.Duration(config.TCPTProxy.Timeout)*time.Second, aclEngine, func(addr, reqAddr net.Addr, action acl.Action, arg string) { logrus.WithFields(logrus.Fields{ "action": actionToString(action, arg), @@ -275,8 +278,8 @@ func client(config *clientConfig) { if len(config.UDPTProxy.Listen) > 0 { go func() { - rl, err := tproxy.NewUDPTProxy(client, config.UDPTProxy.Listen, - time.Duration(config.UDPTProxy.Timeout)*time.Second, aclEngine, + rl, err := tproxy.NewUDPTProxy(client, core.DefaultTransport, + config.UDPTProxy.Listen, time.Duration(config.UDPTProxy.Timeout)*time.Second, aclEngine, func(addr net.Addr) { logrus.WithFields(logrus.Fields{ "src": addr.String(), diff --git a/cmd/server.go b/cmd/server.go index 95ab1ad..f62521f 100644 --- a/cmd/server.go +++ b/cmd/server.go @@ -104,7 +104,7 @@ func server(config *serverConfig) { // ACL var aclEngine *acl.Engine if len(config.ACL) > 0 { - aclEngine, err = acl.LoadFromFile(config.ACL) + aclEngine, err = acl.LoadFromFile(config.ACL, core.DefaultTransport) if err != nil { logrus.WithFields(logrus.Fields{ "error": err, @@ -123,7 +123,7 @@ func server(config *serverConfig) { logrus.WithField("error", err).Fatal("Prometheus HTTP server error") }() } - server, err := core.NewServer(config.Listen, tlsConfig, quicConfig, + server, err := core.NewServer(config.Listen, tlsConfig, quicConfig, core.DefaultTransport, uint64(config.UpMbps)*mbpsToBps, uint64(config.DownMbps)*mbpsToBps, func(refBPS uint64) congestion.CongestionControl { return hyCongestion.NewBrutalSender(congestion.ByteCount(refBPS)) diff --git a/pkg/acl/engine.go b/pkg/acl/engine.go index b62bd58..c843570 100644 --- a/pkg/acl/engine.go +++ b/pkg/acl/engine.go @@ -59,7 +59,7 @@ func (e *Engine) ResolveAndMatch(host string) (Action, string, *net.IPAddr, erro ip, zone := parseIPZone(host) if ip == nil { // Domain - ipAddr, err := e.Transport.OutResolveIPAddr(host) + ipAddr, err := e.Transport.LocalResolveIPAddr(host) if v, ok := e.Cache.Get(host); ok { // Cache hit ce := v.(cacheEntry) diff --git a/pkg/core/server_client.go b/pkg/core/server_client.go index 094d5f7..79de6cc 100644 --- a/pkg/core/server_client.go +++ b/pkg/core/server_client.go @@ -120,7 +120,7 @@ func (c *serverClient) handleMessage(msg []byte) { if c.ACLEngine != nil { action, arg, ipAddr, err = c.ACLEngine.ResolveAndMatch(udpMsg.Host) } else { - ipAddr, err = c.Transport.OutResolveIPAddr(udpMsg.Host) + ipAddr, err = c.Transport.LocalResolveIPAddr(udpMsg.Host) } if err != nil { return @@ -139,7 +139,7 @@ func (c *serverClient) handleMessage(msg []byte) { // Do nothing case acl.ActionHijack: hijackAddr := net.JoinHostPort(arg, strconv.Itoa(int(udpMsg.Port))) - addr, err := c.Transport.OutResolveUDPAddr(hijackAddr) + addr, err := c.Transport.LocalResolveUDPAddr(hijackAddr) if err == nil { _, _ = conn.WriteToUDP(udpMsg.Data, addr) if c.UpCounter != nil { @@ -160,7 +160,7 @@ func (c *serverClient) handleTCP(stream quic.Stream, host string, port uint16) { if c.ACLEngine != nil { action, arg, ipAddr, err = c.ACLEngine.ResolveAndMatch(host) } else { - ipAddr, err = c.Transport.OutResolveIPAddr(host) + ipAddr, err = c.Transport.LocalResolveIPAddr(host) } if err != nil { _ = struc.Pack(stream, &serverResponse{ @@ -175,7 +175,7 @@ func (c *serverClient) handleTCP(stream quic.Stream, host string, port uint16) { var conn net.Conn // Connection to be piped switch action { case acl.ActionDirect, acl.ActionProxy: // Treat proxy as direct on server side - conn, err = c.Transport.OutDialTCP(nil, &net.TCPAddr{ + conn, err = c.Transport.LocalDialTCP(nil, &net.TCPAddr{ IP: ipAddr.IP, Port: int(port), Zone: ipAddr.Zone, @@ -196,7 +196,7 @@ func (c *serverClient) handleTCP(stream quic.Stream, host string, port uint16) { return case acl.ActionHijack: hijackAddr := net.JoinHostPort(arg, strconv.Itoa(int(port))) - conn, err = c.Transport.OutDial("tcp", hijackAddr) + conn, err = c.Transport.LocalDial("tcp", hijackAddr) if err != nil { _ = struc.Pack(stream, &serverResponse{ OK: false, @@ -236,7 +236,7 @@ func (c *serverClient) handleTCP(stream quic.Stream, host string, port uint16) { func (c *serverClient) handleUDP(stream quic.Stream) { // Like in SOCKS5, the stream here is only used to maintain the UDP session. No need to read anything from it - conn, err := c.Transport.OutListenUDP(nil) + conn, err := c.Transport.LocalListenUDP(nil) if err != nil { _ = struc.Pack(stream, &serverResponse{ OK: false, diff --git a/pkg/core/transport.go b/pkg/core/transport.go index f1c242c..337f35a 100644 --- a/pkg/core/transport.go +++ b/pkg/core/transport.go @@ -1,14 +1,69 @@ package core -import "net" +import ( + "net" + "time" +) type Transport interface { QUICResolveUDPAddr(address string) (*net.UDPAddr, error) QUICListenUDP(laddr *net.UDPAddr) (*net.UDPConn, error) - OutResolveIPAddr(address string) (*net.IPAddr, error) - OutResolveUDPAddr(address string) (*net.UDPAddr, error) - OutDial(network, address string) (net.Conn, error) - OutDialTCP(laddr, raddr *net.TCPAddr) (*net.TCPConn, error) - OutListenUDP(laddr *net.UDPAddr) (*net.UDPConn, error) + LocalResolveIPAddr(address string) (*net.IPAddr, error) + LocalResolveTCPAddr(address string) (*net.TCPAddr, error) + LocalResolveUDPAddr(address string) (*net.UDPAddr, error) + LocalDial(network, address string) (net.Conn, error) + LocalDialTCP(laddr, raddr *net.TCPAddr) (*net.TCPConn, error) + LocalListenTCP(laddr *net.TCPAddr) (*net.TCPListener, error) + LocalListenUDP(laddr *net.UDPAddr) (*net.UDPConn, error) +} + +var DefaultTransport Transport = &defaultTransport{ + Timeout: 8 * time.Second, +} + +type defaultTransport struct { + Timeout time.Duration +} + +func (t *defaultTransport) QUICResolveUDPAddr(address string) (*net.UDPAddr, error) { + return net.ResolveUDPAddr("udp", address) +} + +func (t *defaultTransport) QUICListenUDP(laddr *net.UDPAddr) (*net.UDPConn, error) { + return net.ListenUDP("udp", laddr) +} + +func (t *defaultTransport) LocalResolveIPAddr(address string) (*net.IPAddr, error) { + return net.ResolveIPAddr("ip", address) +} + +func (t *defaultTransport) LocalResolveTCPAddr(address string) (*net.TCPAddr, error) { + return net.ResolveTCPAddr("tcp", address) +} + +func (t *defaultTransport) LocalResolveUDPAddr(address string) (*net.UDPAddr, error) { + return net.ResolveUDPAddr("udp", address) +} + +func (t *defaultTransport) LocalDial(network, address string) (net.Conn, error) { + dialer := &net.Dialer{Timeout: t.Timeout} + return dialer.Dial(network, address) +} + +func (t *defaultTransport) LocalDialTCP(laddr, raddr *net.TCPAddr) (*net.TCPConn, error) { + dialer := &net.Dialer{Timeout: t.Timeout, LocalAddr: laddr} + conn, err := dialer.Dial("tcp", raddr.String()) + if err != nil { + return nil, err + } + return conn.(*net.TCPConn), nil +} + +func (t *defaultTransport) LocalListenTCP(laddr *net.TCPAddr) (*net.TCPListener, error) { + return net.ListenTCP("tcp", laddr) +} + +func (t *defaultTransport) LocalListenUDP(laddr *net.UDPAddr) (*net.UDPConn, error) { + return net.ListenUDP("udp", laddr) } diff --git a/pkg/http/server.go b/pkg/http/server.go index 6c68085..070e5b0 100644 --- a/pkg/http/server.go +++ b/pkg/http/server.go @@ -44,7 +44,7 @@ func NewProxyHTTPServer(hyClient *core.Client, transport core.Transport, idleTim if resErr != nil { return nil, resErr } - return transport.OutDialTCP(nil, &net.TCPAddr{ + return transport.LocalDialTCP(nil, &net.TCPAddr{ IP: ipAddr.IP, Port: int(port), Zone: ipAddr.Zone, @@ -54,7 +54,7 @@ func NewProxyHTTPServer(hyClient *core.Client, transport core.Transport, idleTim case acl.ActionBlock: return nil, errors.New("blocked by ACL") case acl.ActionHijack: - return transport.OutDial(network, net.JoinHostPort(arg, strconv.Itoa(int(port)))) + return transport.LocalDial(network, net.JoinHostPort(arg, strconv.Itoa(int(port)))) default: return nil, fmt.Errorf("unknown action %d", action) } diff --git a/pkg/relay/tcp.go b/pkg/relay/tcp.go index 9e16349..c79105c 100644 --- a/pkg/relay/tcp.go +++ b/pkg/relay/tcp.go @@ -9,6 +9,7 @@ import ( type TCPRelay struct { HyClient *core.Client + Transport core.Transport ListenAddr *net.TCPAddr Remote string Timeout time.Duration @@ -17,14 +18,15 @@ type TCPRelay struct { ErrorFunc func(addr net.Addr, err error) } -func NewTCPRelay(hyClient *core.Client, listen, remote string, timeout time.Duration, +func NewTCPRelay(hyClient *core.Client, transport core.Transport, listen, remote string, timeout time.Duration, connFunc func(addr net.Addr), errorFunc func(addr net.Addr, err error)) (*TCPRelay, error) { - tAddr, err := net.ResolveTCPAddr("tcp", listen) + tAddr, err := transport.LocalResolveTCPAddr(listen) if err != nil { return nil, err } r := &TCPRelay{ HyClient: hyClient, + Transport: transport, ListenAddr: tAddr, Remote: remote, Timeout: timeout, @@ -35,7 +37,7 @@ func NewTCPRelay(hyClient *core.Client, listen, remote string, timeout time.Dura } func (r *TCPRelay) ListenAndServe() error { - listener, err := net.ListenTCP("tcp", r.ListenAddr) + listener, err := r.Transport.LocalListenTCP(r.ListenAddr) if err != nil { return err } diff --git a/pkg/relay/udp.go b/pkg/relay/udp.go index c1181d7..d132018 100644 --- a/pkg/relay/udp.go +++ b/pkg/relay/udp.go @@ -15,6 +15,7 @@ var ErrTimeout = errors.New("inactivity timeout") type UDPRelay struct { HyClient *core.Client + Transport core.Transport ListenAddr *net.UDPAddr Remote string Timeout time.Duration @@ -23,14 +24,15 @@ type UDPRelay struct { ErrorFunc func(addr net.Addr, err error) } -func NewUDPRelay(hyClient *core.Client, listen, remote string, timeout time.Duration, +func NewUDPRelay(hyClient *core.Client, transport core.Transport, listen, remote string, timeout time.Duration, connFunc func(addr net.Addr), errorFunc func(addr net.Addr, err error)) (*UDPRelay, error) { - uAddr, err := net.ResolveUDPAddr("udp", listen) + uAddr, err := transport.LocalResolveUDPAddr(listen) if err != nil { return nil, err } r := &UDPRelay{ HyClient: hyClient, + Transport: transport, ListenAddr: uAddr, Remote: remote, Timeout: timeout, @@ -49,7 +51,7 @@ type connEntry struct { } func (r *UDPRelay) ListenAndServe() error { - conn, err := net.ListenUDP("udp", r.ListenAddr) + conn, err := r.Transport.LocalListenUDP(r.ListenAddr) if err != nil { return err } diff --git a/pkg/socks5/server.go b/pkg/socks5/server.go index 996bfae..91f29a9 100644 --- a/pkg/socks5/server.go +++ b/pkg/socks5/server.go @@ -25,6 +25,7 @@ var ( type Server struct { HyClient *core.Client + Transport core.Transport AuthFunc func(username, password string) bool Method byte TCPAddr *net.TCPAddr @@ -40,12 +41,13 @@ type Server struct { tcpListener *net.TCPListener } -func NewServer(hyClient *core.Client, addr string, authFunc func(username, password string) bool, tcpTimeout time.Duration, +func NewServer(hyClient *core.Client, transport core.Transport, addr string, + authFunc func(username, password string) bool, tcpTimeout time.Duration, aclEngine *acl.Engine, disableUDP bool, tcpReqFunc func(addr net.Addr, reqAddr string, action acl.Action, arg string), tcpErrorFunc func(addr net.Addr, reqAddr string, err error), udpAssocFunc func(addr net.Addr), udpErrorFunc func(addr net.Addr, err error)) (*Server, error) { - tAddr, err := net.ResolveTCPAddr("tcp", addr) + tAddr, err := transport.LocalResolveTCPAddr(addr) if err != nil { return nil, err } @@ -55,6 +57,7 @@ func NewServer(hyClient *core.Client, addr string, authFunc func(username, passw } s := &Server{ HyClient: hyClient, + Transport: transport, AuthFunc: authFunc, Method: m, TCPAddr: tAddr, @@ -114,7 +117,7 @@ func (s *Server) negotiate(c *net.TCPConn) error { func (s *Server) ListenAndServe() error { var err error - s.tcpListener, err = net.ListenTCP("tcp", s.TCPAddr) + s.tcpListener, err = s.Transport.LocalListenTCP(s.TCPAddr) if err != nil { return err } @@ -183,7 +186,7 @@ func (s *Server) handleTCP(c *net.TCPConn, r *socks5.Request) error { closeErr = resErr return resErr } - rc, err := net.DialTCP("tcp", nil, &net.TCPAddr{ + rc, err := s.Transport.LocalDialTCP(nil, &net.TCPAddr{ IP: ipAddr.IP, Port: int(port), Zone: ipAddr.Zone, @@ -213,7 +216,7 @@ func (s *Server) handleTCP(c *net.TCPConn, r *socks5.Request) error { closeErr = errors.New("blocked in ACL") return nil case acl.ActionHijack: - rc, err := net.Dial("tcp", net.JoinHostPort(arg, strconv.Itoa(int(port)))) + rc, err := s.Transport.LocalDial("tcp", net.JoinHostPort(arg, strconv.Itoa(int(port)))) if err != nil { _ = sendReply(c, socks5.RepHostUnreachable) closeErr = err @@ -237,7 +240,7 @@ func (s *Server) handleUDP(c *net.TCPConn, r *socks5.Request) error { s.UDPErrorFunc(c.RemoteAddr(), closeErr) }() // Start local UDP server - udpConn, err := net.ListenUDP("udp", &net.UDPAddr{ + udpConn, err := s.Transport.LocalListenUDP(&net.UDPAddr{ IP: s.TCPAddr.IP, Zone: s.TCPAddr.Zone, }) @@ -250,7 +253,7 @@ func (s *Server) handleUDP(c *net.TCPConn, r *socks5.Request) error { // Local UDP relay conn for ACL Direct var localRelayConn *net.UDPConn if s.ACLEngine != nil { - localRelayConn, err = net.ListenUDP("udp", nil) + localRelayConn, err = s.Transport.LocalListenUDP(nil) if err != nil { _ = sendReply(c, socks5.RepServerFailure) closeErr = err @@ -371,7 +374,7 @@ func (s *Server) udpServer(clientConn *net.UDPConn, localRelayConn *net.UDPConn, // Do nothing case acl.ActionHijack: hijackAddr := net.JoinHostPort(arg, strconv.Itoa(int(port))) - rAddr, err := net.ResolveUDPAddr("udp", hijackAddr) + rAddr, err := s.Transport.LocalResolveUDPAddr(hijackAddr) if err == nil { _, _ = localRelayConn.WriteToUDP(d.Data, rAddr) } diff --git a/pkg/tproxy/tcp_linux.go b/pkg/tproxy/tcp_linux.go index b89f3de..b3ff346 100644 --- a/pkg/tproxy/tcp_linux.go +++ b/pkg/tproxy/tcp_linux.go @@ -14,6 +14,7 @@ import ( type TCPTProxy struct { HyClient *core.Client + Transport core.Transport ListenAddr *net.TCPAddr Timeout time.Duration ACLEngine *acl.Engine @@ -22,15 +23,17 @@ type TCPTProxy struct { ErrorFunc func(addr, reqAddr net.Addr, err error) } -func NewTCPTProxy(hyClient *core.Client, listen string, timeout time.Duration, aclEngine *acl.Engine, +func NewTCPTProxy(hyClient *core.Client, transport core.Transport, listen string, timeout time.Duration, + aclEngine *acl.Engine, connFunc func(addr, reqAddr net.Addr, action acl.Action, arg string), errorFunc func(addr, reqAddr net.Addr, err error)) (*TCPTProxy, error) { - tAddr, err := net.ResolveTCPAddr("tcp", listen) + tAddr, err := transport.LocalResolveTCPAddr(listen) if err != nil { return nil, err } r := &TCPTProxy{ HyClient: hyClient, + Transport: transport, ListenAddr: tAddr, Timeout: timeout, ACLEngine: aclEngine, @@ -79,7 +82,7 @@ func (r *TCPTProxy) ListenAndServe() error { closeErr = resErr return } - rc, err := net.DialTCP("tcp", nil, &net.TCPAddr{ + rc, err := r.Transport.LocalDialTCP(nil, &net.TCPAddr{ IP: ipAddr.IP, Port: int(port), Zone: ipAddr.Zone, @@ -104,7 +107,7 @@ func (r *TCPTProxy) ListenAndServe() error { closeErr = errors.New("blocked in ACL") return case acl.ActionHijack: - rc, err := net.Dial("tcp", net.JoinHostPort(arg, strconv.Itoa(int(port)))) + rc, err := r.Transport.LocalDial("tcp", net.JoinHostPort(arg, strconv.Itoa(int(port)))) if err != nil { closeErr = err return diff --git a/pkg/tproxy/udp_linux.go b/pkg/tproxy/udp_linux.go index c2b5ce8..fcf9304 100644 --- a/pkg/tproxy/udp_linux.go +++ b/pkg/tproxy/udp_linux.go @@ -19,6 +19,7 @@ var ErrTimeout = errors.New("inactivity timeout") type UDPTProxy struct { HyClient *core.Client + Transport core.Transport ListenAddr *net.UDPAddr Timeout time.Duration ACLEngine *acl.Engine @@ -27,14 +28,16 @@ type UDPTProxy struct { ErrorFunc func(addr net.Addr, err error) } -func NewUDPTProxy(hyClient *core.Client, listen string, timeout time.Duration, aclEngine *acl.Engine, +func NewUDPTProxy(hyClient *core.Client, transport core.Transport, listen string, timeout time.Duration, + aclEngine *acl.Engine, connFunc func(addr net.Addr), errorFunc func(addr net.Addr, err error)) (*UDPTProxy, error) { - uAddr, err := net.ResolveUDPAddr("udp", listen) + uAddr, err := transport.LocalResolveUDPAddr(listen) if err != nil { return nil, err } r := &UDPTProxy{ HyClient: hyClient, + Transport: transport, ListenAddr: uAddr, Timeout: timeout, ACLEngine: aclEngine, @@ -84,7 +87,7 @@ func (r *UDPTProxy) sendPacket(entry *connEntry, dstAddr *net.UDPAddr, data []by return nil case acl.ActionHijack: hijackAddr := net.JoinHostPort(arg, strconv.Itoa(int(port))) - rAddr, err := net.ResolveUDPAddr("udp", hijackAddr) + rAddr, err := r.Transport.LocalResolveUDPAddr(hijackAddr) if err != nil { return err } @@ -126,7 +129,7 @@ func (r *UDPTProxy) ListenAndServe() error { } var localConn *net.UDPConn if r.ACLEngine != nil { - localConn, err = net.ListenUDP("udp", nil) + localConn, err = r.Transport.LocalListenUDP(nil) if err != nil { r.ErrorFunc(srcAddr, err) continue