github.com/metacubex/mihomo@v1.18.5/listener/socks/tcp.go (about) 1 package socks 2 3 import ( 4 "io" 5 "net" 6 7 "github.com/metacubex/mihomo/adapter/inbound" 8 N "github.com/metacubex/mihomo/common/net" 9 C "github.com/metacubex/mihomo/constant" 10 authStore "github.com/metacubex/mihomo/listener/auth" 11 "github.com/metacubex/mihomo/transport/socks4" 12 "github.com/metacubex/mihomo/transport/socks5" 13 ) 14 15 type Listener struct { 16 listener net.Listener 17 addr string 18 closed bool 19 } 20 21 // RawAddress implements C.Listener 22 func (l *Listener) RawAddress() string { 23 return l.addr 24 } 25 26 // Address implements C.Listener 27 func (l *Listener) Address() string { 28 return l.listener.Addr().String() 29 } 30 31 // Close implements C.Listener 32 func (l *Listener) Close() error { 33 l.closed = true 34 return l.listener.Close() 35 } 36 37 func New(addr string, tunnel C.Tunnel, additions ...inbound.Addition) (*Listener, error) { 38 isDefault := false 39 if len(additions) == 0 { 40 isDefault = true 41 additions = []inbound.Addition{ 42 inbound.WithInName("DEFAULT-SOCKS"), 43 inbound.WithSpecialRules(""), 44 } 45 } 46 l, err := inbound.Listen("tcp", addr) 47 if err != nil { 48 return nil, err 49 } 50 51 sl := &Listener{ 52 listener: l, 53 addr: addr, 54 } 55 go func() { 56 for { 57 c, err := l.Accept() 58 if err != nil { 59 if sl.closed { 60 break 61 } 62 continue 63 } 64 if isDefault { // only apply on default listener 65 if !inbound.IsRemoteAddrDisAllowed(c.RemoteAddr()) { 66 _ = c.Close() 67 continue 68 } 69 } 70 go handleSocks(c, tunnel, additions...) 71 } 72 }() 73 74 return sl, nil 75 } 76 77 func handleSocks(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { 78 N.TCPKeepAlive(conn) 79 bufConn := N.NewBufferedConn(conn) 80 head, err := bufConn.Peek(1) 81 if err != nil { 82 conn.Close() 83 return 84 } 85 86 switch head[0] { 87 case socks4.Version: 88 HandleSocks4(bufConn, tunnel, additions...) 89 case socks5.Version: 90 HandleSocks5(bufConn, tunnel, additions...) 91 default: 92 conn.Close() 93 } 94 } 95 96 func HandleSocks4(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { 97 authenticator := authStore.Authenticator() 98 if inbound.SkipAuthRemoteAddr(conn.RemoteAddr()) { 99 authenticator = nil 100 } 101 addr, _, user, err := socks4.ServerHandshake(conn, authenticator) 102 if err != nil { 103 conn.Close() 104 return 105 } 106 additions = append(additions, inbound.WithInUser(user)) 107 tunnel.HandleTCPConn(inbound.NewSocket(socks5.ParseAddr(addr), conn, C.SOCKS4, additions...)) 108 } 109 110 func HandleSocks5(conn net.Conn, tunnel C.Tunnel, additions ...inbound.Addition) { 111 authenticator := authStore.Authenticator() 112 if inbound.SkipAuthRemoteAddr(conn.RemoteAddr()) { 113 authenticator = nil 114 } 115 target, command, user, err := socks5.ServerHandshake(conn, authenticator) 116 if err != nil { 117 conn.Close() 118 return 119 } 120 if command == socks5.CmdUDPAssociate { 121 defer conn.Close() 122 io.Copy(io.Discard, conn) 123 return 124 } 125 additions = append(additions, inbound.WithInUser(user)) 126 tunnel.HandleTCPConn(inbound.NewSocket(target, conn, C.SOCKS5, additions...)) 127 }