github.com/metacubex/mihomo@v1.18.5/listener/tproxy/tproxy.go (about) 1 package tproxy 2 3 import ( 4 "net" 5 6 "github.com/metacubex/mihomo/adapter/inbound" 7 N "github.com/metacubex/mihomo/common/net" 8 C "github.com/metacubex/mihomo/constant" 9 "github.com/metacubex/mihomo/transport/socks5" 10 ) 11 12 type Listener struct { 13 listener net.Listener 14 addr string 15 closed bool 16 } 17 18 // RawAddress implements C.Listener 19 func (l *Listener) RawAddress() string { 20 return l.addr 21 } 22 23 // Address implements C.Listener 24 func (l *Listener) Address() string { 25 return l.listener.Addr().String() 26 } 27 28 // Close implements C.Listener 29 func (l *Listener) Close() error { 30 l.closed = true 31 return l.listener.Close() 32 } 33 34 func (l *Listener) handleTProxy(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { 35 target := socks5.ParseAddrToSocksAddr(conn.LocalAddr()) 36 N.TCPKeepAlive(conn) 37 // TProxy's conn.LocalAddr() is target address, so we set from l.listener 38 additions = append([]inbound.Addition{inbound.WithInAddr(l.listener.Addr())}, additions...) 39 tunnel.HandleTCPConn(inbound.NewSocket(target, conn, C.TPROXY, additions...)) 40 } 41 42 func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { 43 if len(additions) == 0 { 44 additions = []inbound.Addition{ 45 inbound.WithInName("DEFAULT-TPROXY"), 46 inbound.WithSpecialRules(""), 47 } 48 } 49 l, err := net.Listen("tcp", addr) 50 if err != nil { 51 return nil, err 52 } 53 54 tl := l.(*net.TCPListener) 55 rc, err := tl.SyscallConn() 56 if err != nil { 57 return nil, err 58 } 59 60 err = setsockopt(rc, addr) 61 if err != nil { 62 return nil, err 63 } 64 65 rl := &Listener{ 66 listener: l, 67 addr: addr, 68 } 69 70 go func() { 71 for { 72 c, err := l.Accept() 73 if err != nil { 74 if rl.closed { 75 break 76 } 77 continue 78 } 79 go rl.handleTProxy(c, tunnel, additions...) 80 } 81 }() 82 83 return rl, nil 84 }