github.com/igoogolx/clash@v1.19.8/listener/tproxy/tcp.go (about) 1 package tproxy 2 3 import ( 4 "net" 5 6 "github.com/igoogolx/clash/adapter/inbound" 7 C "github.com/igoogolx/clash/constant" 8 "github.com/igoogolx/clash/transport/socks5" 9 ) 10 11 type Listener struct { 12 listener net.Listener 13 addr string 14 closed bool 15 } 16 17 // RawAddress implements C.Listener 18 func (l *Listener) RawAddress() string { 19 return l.addr 20 } 21 22 // Address implements C.Listener 23 func (l *Listener) Address() string { 24 return l.listener.Addr().String() 25 } 26 27 // Close implements C.Listener 28 func (l *Listener) Close() error { 29 l.closed = true 30 return l.listener.Close() 31 } 32 33 func (l *Listener) handleTProxy(conn net.Conn, in chan<- C.ConnContext) { 34 target := socks5.ParseAddrToSocksAddr(conn.LocalAddr()) 35 conn.(*net.TCPConn).SetKeepAlive(true) 36 in <- inbound.NewSocket(target, conn, C.TPROXY) 37 } 38 39 func New(addr string, in chan<- C.ConnContext) (C.Listener, error) { 40 l, err := net.Listen("tcp", addr) 41 if err != nil { 42 return nil, err 43 } 44 45 tl := l.(*net.TCPListener) 46 rc, err := tl.SyscallConn() 47 if err != nil { 48 return nil, err 49 } 50 51 err = setsockopt(rc, addr) 52 if err != nil { 53 return nil, err 54 } 55 56 rl := &Listener{ 57 listener: l, 58 addr: addr, 59 } 60 61 go func() { 62 for { 63 c, err := l.Accept() 64 if err != nil { 65 if rl.closed { 66 break 67 } 68 continue 69 } 70 go rl.handleTProxy(c, in) 71 } 72 }() 73 74 return rl, nil 75 }