From 6eb49eef12a12331739bc8cc8ec0d2cc9e4ac95c Mon Sep 17 00:00:00 2001 From: Toby Date: Wed, 24 Nov 2021 23:04:34 -0800 Subject: [PATCH] feat: remove ACL from TPROXY & TUN --- cmd/client.go | 19 ++--- pkg/tproxy/tcp_linux.go | 74 ++--------------- pkg/tproxy/tcp_stub.go | 4 +- pkg/tproxy/udp_linux.go | 95 ++-------------------- pkg/tproxy/udp_stub.go | 2 - pkg/tun/server.go | 4 +- pkg/tun/{server_fake.go => server_stub.go} | 8 +- pkg/tun/tcp.go | 54 ++---------- pkg/tun/udp.go | 75 +---------------- 9 files changed, 40 insertions(+), 295 deletions(-) rename pkg/tun/{server_fake.go => server_stub.go} (71%) diff --git a/cmd/client.go b/cmd/client.go index c9b9484..b8cdf1c 100644 --- a/cmd/client.go +++ b/cmd/client.go @@ -204,12 +204,10 @@ func client(config *clientConfig) { if err != nil { logrus.WithField("error", err).Fatal("Failed to initialize TUN server") } - tunServer.ACLEngine = aclEngine - tunServer.RequestFunc = func(addr net.Addr, reqAddr string, action acl.Action, arg string) { + tunServer.RequestFunc = func(addr net.Addr, reqAddr string) { logrus.WithFields(logrus.Fields{ - "action": actionToString(action, arg), - "src": addr.String(), - "dst": reqAddr, + "src": addr.String(), + "dst": reqAddr, }).Debugf("TUN %s request", strings.ToUpper(addr.Network())) } tunServer.ErrorFunc = func(addr net.Addr, reqAddr string, err error) { @@ -305,12 +303,11 @@ func client(config *clientConfig) { if len(config.TCPTProxy.Listen) > 0 { go func() { rl, err := tproxy.NewTCPTProxy(client, transport.DefaultTransport, - config.TCPTProxy.Listen, time.Duration(config.TCPTProxy.Timeout)*time.Second, aclEngine, - func(addr, reqAddr net.Addr, action acl.Action, arg string) { + config.TCPTProxy.Listen, time.Duration(config.TCPTProxy.Timeout)*time.Second, + func(addr, reqAddr net.Addr) { logrus.WithFields(logrus.Fields{ - "action": actionToString(action, arg), - "src": addr.String(), - "dst": reqAddr.String(), + "src": addr.String(), + "dst": reqAddr.String(), }).Debug("TCP TProxy request") }, func(addr, reqAddr net.Addr, err error) { @@ -338,7 +335,7 @@ func client(config *clientConfig) { if len(config.UDPTProxy.Listen) > 0 { go func() { rl, err := tproxy.NewUDPTProxy(client, transport.DefaultTransport, - config.UDPTProxy.Listen, time.Duration(config.UDPTProxy.Timeout)*time.Second, aclEngine, + config.UDPTProxy.Listen, time.Duration(config.UDPTProxy.Timeout)*time.Second, func(addr net.Addr) { logrus.WithFields(logrus.Fields{ "src": addr.String(), diff --git a/pkg/tproxy/tcp_linux.go b/pkg/tproxy/tcp_linux.go index 2690577..556f60e 100644 --- a/pkg/tproxy/tcp_linux.go +++ b/pkg/tproxy/tcp_linux.go @@ -1,15 +1,11 @@ package tproxy import ( - "errors" - "fmt" "github.com/LiamHaworth/go-tproxy" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/core" "github.com/tobyxdd/hysteria/pkg/transport" "github.com/tobyxdd/hysteria/pkg/utils" "net" - "strconv" "time" ) @@ -18,15 +14,13 @@ type TCPTProxy struct { Transport transport.Transport ListenAddr *net.TCPAddr Timeout time.Duration - ACLEngine *acl.Engine - ConnFunc func(addr, reqAddr net.Addr, action acl.Action, arg string) + ConnFunc func(addr, reqAddr net.Addr) ErrorFunc func(addr, reqAddr net.Addr, err error) } func NewTCPTProxy(hyClient *core.Client, transport transport.Transport, listen string, timeout time.Duration, - aclEngine *acl.Engine, - connFunc func(addr, reqAddr net.Addr, action acl.Action, arg string), + connFunc func(addr, reqAddr net.Addr), errorFunc func(addr, reqAddr net.Addr, err error)) (*TCPTProxy, error) { tAddr, err := transport.LocalResolveTCPAddr(listen) if err != nil { @@ -37,7 +31,6 @@ func NewTCPTProxy(hyClient *core.Client, transport transport.Transport, listen s Transport: transport, ListenAddr: tAddr, Timeout: timeout, - ACLEngine: aclEngine, ConnFunc: connFunc, ErrorFunc: errorFunc, } @@ -60,66 +53,15 @@ func (r *TCPTProxy) ListenAndServe() error { // Under TPROXY mode, we are effectively acting as the remote server // So our LocalAddr is actually the target to which the user is trying to connect // and our RemoteAddr is the local address where the user initiates the connection - host, port, err := utils.SplitHostPort(c.LocalAddr().String()) + r.ConnFunc(c.RemoteAddr(), c.LocalAddr()) + rc, err := r.HyClient.DialTCP(c.LocalAddr().String()) if err != nil { + r.ErrorFunc(c.RemoteAddr(), c.LocalAddr(), err) return } - action, arg := acl.ActionProxy, "" - var ipAddr *net.IPAddr - var resErr error - if r.ACLEngine != nil { - action, arg, ipAddr, resErr = r.ACLEngine.ResolveAndMatch(host) - // Doesn't always matter if the resolution fails, as we may send it through HyClient - } - r.ConnFunc(c.RemoteAddr(), c.LocalAddr(), action, arg) - var closeErr error - defer func() { - r.ErrorFunc(c.RemoteAddr(), c.LocalAddr(), closeErr) - }() - // Handle according to the action - switch action { - case acl.ActionDirect: - if resErr != nil { - closeErr = resErr - return - } - rc, err := r.Transport.LocalDialTCP(nil, &net.TCPAddr{ - IP: ipAddr.IP, - Port: int(port), - Zone: ipAddr.Zone, - }) - if err != nil { - closeErr = err - return - } - defer rc.Close() - closeErr = utils.PipePairWithTimeout(c, rc, r.Timeout) - return - case acl.ActionProxy: - rc, err := r.HyClient.DialTCP(c.LocalAddr().String()) - if err != nil { - closeErr = err - return - } - defer rc.Close() - closeErr = utils.PipePairWithTimeout(c, rc, r.Timeout) - return - case acl.ActionBlock: - closeErr = errors.New("blocked in ACL") - return - case acl.ActionHijack: - rc, err := r.Transport.LocalDial("tcp", net.JoinHostPort(arg, strconv.Itoa(int(port)))) - if err != nil { - closeErr = err - return - } - defer rc.Close() - closeErr = utils.PipePairWithTimeout(c, rc, r.Timeout) - return - default: - closeErr = fmt.Errorf("unknown action %d", action) - return - } + defer rc.Close() + err = utils.PipePairWithTimeout(c, rc, r.Timeout) + r.ErrorFunc(c.RemoteAddr(), c.LocalAddr(), err) }() } } diff --git a/pkg/tproxy/tcp_stub.go b/pkg/tproxy/tcp_stub.go index 0e1a326..302c487 100644 --- a/pkg/tproxy/tcp_stub.go +++ b/pkg/tproxy/tcp_stub.go @@ -4,7 +4,6 @@ package tproxy import ( "errors" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/core" "github.com/tobyxdd/hysteria/pkg/transport" "net" @@ -14,8 +13,7 @@ import ( type TCPTProxy struct{} func NewTCPTProxy(hyClient *core.Client, transport transport.Transport, listen string, timeout time.Duration, - aclEngine *acl.Engine, - connFunc func(addr, reqAddr net.Addr, action acl.Action, arg string), + connFunc func(addr, reqAddr net.Addr), errorFunc func(addr, reqAddr net.Addr, err error)) (*TCPTProxy, error) { return nil, errors.New("not supported on the current system") } diff --git a/pkg/tproxy/udp_linux.go b/pkg/tproxy/udp_linux.go index cfd525e..155d86c 100644 --- a/pkg/tproxy/udp_linux.go +++ b/pkg/tproxy/udp_linux.go @@ -3,12 +3,9 @@ package tproxy import ( "errors" "github.com/LiamHaworth/go-tproxy" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/core" "github.com/tobyxdd/hysteria/pkg/transport" - "github.com/tobyxdd/hysteria/pkg/utils" "net" - "strconv" "sync" "sync/atomic" "time" @@ -23,14 +20,12 @@ type UDPTProxy struct { Transport transport.Transport ListenAddr *net.UDPAddr Timeout time.Duration - ACLEngine *acl.Engine ConnFunc func(addr net.Addr) ErrorFunc func(addr net.Addr, err error) } func NewUDPTProxy(hyClient *core.Client, transport transport.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 := transport.LocalResolveUDPAddr(listen) if err != nil { @@ -41,7 +36,6 @@ func NewUDPTProxy(hyClient *core.Client, transport transport.Transport, listen s Transport: transport, ListenAddr: uAddr, Timeout: timeout, - ACLEngine: aclEngine, ConnFunc: connFunc, ErrorFunc: errorFunc, } @@ -52,53 +46,9 @@ func NewUDPTProxy(hyClient *core.Client, transport transport.Transport, listen s } type connEntry struct { - LocalConn *net.UDPConn - HyConn core.UDPConn - DirectConn *net.UDPConn - Deadline atomic.Value -} - -func (r *UDPTProxy) sendPacket(entry *connEntry, dstAddr *net.UDPAddr, data []byte) error { - entry.Deadline.Store(time.Now().Add(r.Timeout)) - host, port, err := utils.SplitHostPort(dstAddr.String()) - if err != nil { - return err - } - action, arg := acl.ActionProxy, "" - var ipAddr *net.IPAddr - var resErr error - if r.ACLEngine != nil && entry.DirectConn != nil { - action, arg, ipAddr, resErr = r.ACLEngine.ResolveAndMatch(host) - // Doesn't always matter if the resolution fails, as we may send it through HyClient - } - switch action { - case acl.ActionDirect: - if resErr != nil { - return resErr - } - _, err = entry.DirectConn.WriteToUDP(data, &net.UDPAddr{ - IP: ipAddr.IP, - Port: int(port), - Zone: ipAddr.Zone, - }) - return err - case acl.ActionProxy: - return entry.HyConn.WriteTo(data, dstAddr.String()) - case acl.ActionBlock: - // Do nothing - return nil - case acl.ActionHijack: - hijackAddr := net.JoinHostPort(arg, strconv.Itoa(int(port))) - rAddr, err := r.Transport.LocalResolveUDPAddr(hijackAddr) - if err != nil { - return err - } - _, err = entry.DirectConn.WriteToUDP(data, rAddr) - return err - default: - // Do nothing - return nil - } + LocalConn *net.UDPConn + HyConn core.UDPConn + Deadline atomic.Value } func (r *UDPTProxy) ListenAndServe() error { @@ -120,7 +70,8 @@ func (r *UDPTProxy) ListenAndServe() error { connMapMutex.RUnlock() if entry != nil { // Existing conn - _ = r.sendPacket(entry, dstAddr, buf[:n]) + entry.Deadline.Store(time.Now().Add(r.Timeout)) + _ = entry.HyConn.WriteTo(buf[:n], dstAddr.String()) } else { // New r.ConnFunc(srcAddr) @@ -136,23 +87,12 @@ func (r *UDPTProxy) ListenAndServe() error { _ = localConn.Close() continue } - var directConn *net.UDPConn - if r.ACLEngine != nil { - directConn, err = r.Transport.LocalListenUDP(nil) - if err != nil { - r.ErrorFunc(srcAddr, err) - _ = localConn.Close() - _ = hyConn.Close() - continue - } - } // Send entry := &connEntry{ - LocalConn: localConn, - HyConn: hyConn, - DirectConn: directConn, + LocalConn: localConn, + HyConn: hyConn, } - _ = r.sendPacket(entry, dstAddr, buf[:n]) + entry.Deadline.Store(time.Now().Add(r.Timeout)) // Add it to the map connMapMutex.Lock() connMap[srcAddr.String()] = entry @@ -168,21 +108,6 @@ func (r *UDPTProxy) ListenAndServe() error { _, _ = localConn.Write(bs) } }() - if directConn != nil { - go func() { - buf := make([]byte, udpBufferSize) - for { - n, _, err := directConn.ReadFrom(buf) - if n > 0 { - entry.Deadline.Store(time.Now().Add(r.Timeout)) - _, _ = localConn.Write(buf[:n]) - } - if err != nil { - break - } - } - }() - } // Timeout cleanup routine go func() { for { @@ -192,9 +117,6 @@ func (r *UDPTProxy) ListenAndServe() error { connMapMutex.Lock() _ = localConn.Close() _ = hyConn.Close() - if directConn != nil { - _ = directConn.Close() - } delete(connMap, srcAddr.String()) connMapMutex.Unlock() r.ErrorFunc(srcAddr, ErrTimeout) @@ -204,6 +126,7 @@ func (r *UDPTProxy) ListenAndServe() error { } } }() + _ = hyConn.WriteTo(buf[:n], dstAddr.String()) } } if err != nil { diff --git a/pkg/tproxy/udp_stub.go b/pkg/tproxy/udp_stub.go index 31ca612..a24a51d 100644 --- a/pkg/tproxy/udp_stub.go +++ b/pkg/tproxy/udp_stub.go @@ -4,7 +4,6 @@ package tproxy import ( "errors" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/core" "github.com/tobyxdd/hysteria/pkg/transport" "net" @@ -16,7 +15,6 @@ var ErrTimeout = errors.New("inactivity timeout") type UDPTProxy struct{} func NewUDPTProxy(hyClient *core.Client, transport transport.Transport, listen string, timeout time.Duration, - aclEngine *acl.Engine, connFunc func(addr net.Addr), errorFunc func(addr net.Addr, err error)) (*UDPTProxy, error) { return nil, errors.New("not supported on the current system") } diff --git a/pkg/tun/server.go b/pkg/tun/server.go index bced82b..8976a66 100644 --- a/pkg/tun/server.go +++ b/pkg/tun/server.go @@ -5,7 +5,6 @@ package tun import ( tun2socks "github.com/eycorsican/go-tun2socks/core" "github.com/eycorsican/go-tun2socks/tun" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/core" "github.com/tobyxdd/hysteria/pkg/transport" "io" @@ -19,9 +18,8 @@ type Server struct { Timeout time.Duration TunDev io.ReadWriteCloser Transport transport.Transport - ACLEngine *acl.Engine - RequestFunc func(addr net.Addr, reqAddr string, action acl.Action, arg string) + RequestFunc func(addr net.Addr, reqAddr string) ErrorFunc func(addr net.Addr, reqAddr string, err error) udpConnMap map[tun2socks.UDPConn]*udpConnInfo diff --git a/pkg/tun/server_fake.go b/pkg/tun/server_stub.go similarity index 71% rename from pkg/tun/server_fake.go rename to pkg/tun/server_stub.go index 86b493a..b5c0879 100644 --- a/pkg/tun/server_fake.go +++ b/pkg/tun/server_stub.go @@ -4,7 +4,6 @@ package tun import ( "errors" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/core" "github.com/tobyxdd/hysteria/pkg/transport" "io" @@ -17,9 +16,8 @@ type Server struct { Timeout time.Duration TunDev io.ReadWriteCloser Transport transport.Transport - ACLEngine *acl.Engine - RequestFunc func(addr net.Addr, reqAddr string, action acl.Action, arg string) + RequestFunc func(addr net.Addr, reqAddr string) ErrorFunc func(addr net.Addr, reqAddr string, err error) } @@ -30,13 +28,13 @@ const ( func NewServerWithTunDev(hyClient *core.Client, transport transport.Transport, timeout time.Duration, tunDev io.ReadWriteCloser) (*Server, error) { - return nil, errors.New("TUN mode is not available when build with CGO_ENABLED=0") + return nil, errors.New("TUN mode is not available in this build") } func NewServer(hyClient *core.Client, transport transport.Transport, timeout time.Duration, name, address, gateway, mask string, dnsServers []string, persist bool) (*Server, error) { - return nil, errors.New("TUN mode is not available when build with CGO_ENABLED=0") + return nil, errors.New("TUN mode is not available in this build") } func (s *Server) ListenAndServe() error { diff --git a/pkg/tun/tcp.go b/pkg/tun/tcp.go index 5ee9f6b..4e2fc86 100644 --- a/pkg/tun/tcp.go +++ b/pkg/tun/tcp.go @@ -3,23 +3,14 @@ package tun import ( - "errors" - "fmt" tun2socks "github.com/eycorsican/go-tun2socks/core" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/utils" "net" - "strconv" ) func (s *Server) Handle(conn net.Conn, target *net.TCPAddr) error { - action, arg := acl.ActionProxy, "" - var resErr error - if s.ACLEngine != nil { - action, arg, _, resErr = s.ACLEngine.ResolveAndMatch(target.IP.String()) - } if s.RequestFunc != nil { - s.RequestFunc(conn.LocalAddr(), target.String(), action, arg) + s.RequestFunc(conn.LocalAddr(), target.String()) } var closeErr error defer func() { @@ -27,44 +18,13 @@ func (s *Server) Handle(conn net.Conn, target *net.TCPAddr) error { s.ErrorFunc(conn.LocalAddr(), target.String(), closeErr) } }() - switch action { - case acl.ActionDirect: - if resErr != nil { - closeErr = resErr - return resErr - } - rc, err := s.Transport.LocalDialTCP(nil, target) - if err != nil { - closeErr = err - return err - } - go s.relayTCP(conn, rc) - return nil - case acl.ActionProxy: - rc, err := s.HyClient.DialTCP(target.String()) - if err != nil { - closeErr = err - return err - } - go s.relayTCP(conn, rc) - return nil - case acl.ActionBlock: - closeErr = errors.New("blocked in ACL") - // caller will abort the connection when err != nil - return closeErr - case acl.ActionHijack: - rc, err := s.Transport.LocalDial("tcp", net.JoinHostPort(arg, strconv.Itoa(target.Port))) - if err != nil { - closeErr = err - return err - } - go s.relayTCP(conn, rc) - return nil - default: - closeErr = fmt.Errorf("unknown action %d", action) - // caller will abort the connection when err != nil - return closeErr + rc, err := s.HyClient.DialTCP(target.String()) + if err != nil { + closeErr = err + return err } + go s.relayTCP(conn, rc) + return nil } func (s *Server) relayTCP(clientConn, relayConn net.Conn) { diff --git a/pkg/tun/udp.go b/pkg/tun/udp.go index 6053320..1cfd898 100644 --- a/pkg/tun/udp.go +++ b/pkg/tun/udp.go @@ -3,13 +3,9 @@ package tun import ( - "bytes" "errors" - "fmt" tun2socks "github.com/eycorsican/go-tun2socks/core" - "github.com/tobyxdd/hysteria/pkg/acl" "github.com/tobyxdd/hysteria/pkg/core" - "io" "net" "strconv" "sync/atomic" @@ -66,13 +62,8 @@ func (s *Server) fetchUDPInput(conn tun2socks.UDPConn, ci *udpConnInfo) { } func (s *Server) Connect(conn tun2socks.UDPConn, target *net.UDPAddr) error { - action, arg := acl.ActionProxy, "" - var resErr error - if s.ACLEngine != nil { - action, arg, _, resErr = s.ACLEngine.ResolveAndMatch(target.IP.String()) - } if s.RequestFunc != nil { - s.RequestFunc(conn.LocalAddr(), target.String(), action, arg) + s.RequestFunc(conn.LocalAddr(), target.String()) } var hyConn core.UDPConn var closeErr error @@ -81,43 +72,9 @@ func (s *Server) Connect(conn tun2socks.UDPConn, target *net.UDPAddr) error { s.ErrorFunc(conn.LocalAddr(), target.String(), closeErr) } }() - switch action { - case acl.ActionDirect: - if resErr != nil { - closeErr = resErr - return resErr - } - var relayConn net.Conn - relayConn, closeErr = s.Transport.LocalDial("udp", target.String()) - if closeErr != nil { - return closeErr - } - hyConn = &delegatedUDPConn{ - underlayConn: relayConn, - delegatedRemoteAddr: target.String(), - } - case acl.ActionProxy: - hyConn, closeErr = s.HyClient.DialUDP() - if closeErr != nil { - return closeErr - } - case acl.ActionBlock: - closeErr = errors.New("blocked in ACL") + hyConn, closeErr = s.HyClient.DialUDP() + if closeErr != nil { return closeErr - case acl.ActionHijack: - hijackAddr := net.JoinHostPort(arg, strconv.Itoa(target.Port)) - var relayConn net.Conn - relayConn, closeErr = s.Transport.LocalDial("udp", hijackAddr) - if closeErr != nil { - return closeErr - } - hyConn = &delegatedUDPConn{ - underlayConn: relayConn, - delegatedRemoteAddr: target.String(), - } - default: - closeErr = fmt.Errorf("unknown action %d", action) - return nil } ci := udpConnInfo{ hyConn: hyConn, @@ -154,29 +111,3 @@ func (s *Server) closeUDPConn(conn tun2socks.UDPConn) { delete(s.udpConnMap, conn) } } - -type delegatedUDPConn struct { - underlayConn net.Conn - delegatedRemoteAddr string -} - -func (c *delegatedUDPConn) ReadFrom() (bs []byte, addr string, err error) { - buf := make([]byte, udpBufferSize) - n, err := c.underlayConn.Read(buf) - if n > 0 { - bs = append(bs, buf[0:n]...) - } - if err != nil || err == io.EOF { - addr = c.delegatedRemoteAddr - } - return -} - -func (c *delegatedUDPConn) WriteTo(bs []byte, addr string) error { - _, err := io.Copy(c.underlayConn, bytes.NewReader(bs)) - return err -} - -func (c *delegatedUDPConn) Close() error { - return c.underlayConn.Close() -}