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  }