github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/tproxy/tcp.go (about) 1 package tproxy 2 3 import ( 4 "context" 5 "fmt" 6 "net" 7 "syscall" 8 9 "github.com/Asutorufa/yuhaiin/pkg/log" 10 "github.com/Asutorufa/yuhaiin/pkg/net/dialer" 11 "github.com/Asutorufa/yuhaiin/pkg/net/netapi" 12 "github.com/Asutorufa/yuhaiin/pkg/protos/statistic" 13 ) 14 15 func init() { 16 dialer.DefaultMarkSymbol = func(socket int32) bool { 17 return dialer.LinuxMarkSymbol(socket, 0xff) == nil 18 } 19 } 20 21 func controlTCP(c syscall.RawConn) error { 22 var fn = func(s uintptr) { 23 err := syscall.SetsockoptInt(int(s), syscall.SOL_IP, syscall.IP_TRANSPARENT, 1) 24 if err != nil { 25 log.Warn("set socket with SOL_IP,IP_TRANSPARENT failed", "err", err) 26 } 27 28 v, err := syscall.GetsockoptInt(int(s), syscall.SOL_IP, syscall.IP_TRANSPARENT) 29 if err != nil { 30 log.Warn("get socket with SOL_IP, IP_TRANSPARENT failed", "err", err) 31 } else { 32 log.Debug("value of IP_TRANSPARENT", "options", int(v)) 33 } 34 } 35 36 if err := c.Control(fn); err != nil { 37 return err 38 } 39 40 return nil 41 } 42 43 func (t *Tproxy) handleTCP(c net.Conn) error { 44 target, err := netapi.ParseSysAddr(c.LocalAddr()) 45 if err != nil { 46 return fmt.Errorf("parse local addr failed: %w", err) 47 } 48 49 if ip, err := target.IP(context.TODO()); err == nil && ip.Equal(t.lisAddr.IP) && target.Port().Port() == uint16(t.lisAddr.Port) { 50 return fmt.Errorf("local addr and remote addr are same") 51 } 52 53 return t.SendStream(&netapi.StreamMeta{ 54 Source: c.RemoteAddr(), 55 Destination: c.LocalAddr(), 56 Inbound: netapi.ParseIPAddrPort(statistic.Type_tcp, t.lisAddr.IP, t.lisAddr.Port), 57 Src: c, 58 Address: target, 59 }) 60 } 61 62 func (t *Tproxy) newTCP() error { 63 lis, err := t.lis.Stream(t.Context()) 64 if err != nil { 65 return err 66 } 67 68 tcpLis, ok := lis.(*net.TCPListener) 69 if !ok { 70 lis.Close() 71 return fmt.Errorf("listen is not tcp listener") 72 } 73 74 f, err := tcpLis.SyscallConn() 75 if err != nil { 76 lis.Close() 77 return err 78 } 79 80 err = controlTCP(f) 81 if err != nil { 82 lis.Close() 83 return err 84 } 85 86 log.Info("new tproxy tcp server", "host", lis.Addr()) 87 88 t.lisAddr = lis.Addr().(*net.TCPAddr) 89 90 go func() { 91 for { 92 conn, err := lis.Accept() 93 if err != nil { 94 log.Error("tcp server accept failed", "err", err) 95 break 96 } 97 98 go func() { 99 if err := t.handleTCP(conn); err != nil { 100 log.Error("tcp server handle failed", "err", err) 101 } 102 }() 103 } 104 }() 105 106 return nil 107 }