github.com/Asutorufa/yuhaiin@v0.3.6-0.20240502055049-7984da7023a0/pkg/net/proxy/socks5/server.go (about) 1 package socks5 2 3 import ( 4 "crypto/subtle" 5 "errors" 6 "fmt" 7 "io" 8 "net" 9 10 "github.com/Asutorufa/yuhaiin/pkg/log" 11 "github.com/Asutorufa/yuhaiin/pkg/net/netapi" 12 "github.com/Asutorufa/yuhaiin/pkg/net/proxy/socks5/tools" 13 "github.com/Asutorufa/yuhaiin/pkg/net/proxy/yuubinsya" 14 "github.com/Asutorufa/yuhaiin/pkg/protos/config/listener" 15 "github.com/Asutorufa/yuhaiin/pkg/protos/statistic" 16 "github.com/Asutorufa/yuhaiin/pkg/utils/pool" 17 "github.com/Asutorufa/yuhaiin/pkg/utils/relay" 18 ) 19 20 func (s *Server) startUDPServer() error { 21 packet, err := s.lis.Packet(s.Context()) 22 if err != nil { 23 return err 24 } 25 26 go func() { 27 defer packet.Close() 28 yuubinsya.StartUDPServer(packet, s.SendPacket, nil, true) 29 }() 30 31 return nil 32 } 33 34 func (s *Server) startTCPServer() error { 35 lis, err := s.lis.Stream(s.Context()) 36 if err != nil { 37 return err 38 } 39 go func() { 40 defer s.Close() 41 defer lis.Close() 42 43 for { 44 conn, err := lis.Accept() 45 if err != nil { 46 log.Error("socks5 accept failed", "err", err) 47 48 if ne, ok := err.(net.Error); ok && ne.Temporary() { 49 continue 50 } 51 return 52 } 53 54 go func() { 55 if err := s.Handle(conn); err != nil { 56 if errors.Is(err, netapi.ErrBlocked) { 57 log.Debug(err.Error()) 58 } else { 59 log.Error("socks5 server handle failed", "err", err) 60 } 61 } 62 }() 63 64 } 65 }() 66 67 return nil 68 } 69 70 func (s *Server) Handle(client net.Conn) (err error) { 71 b := pool.GetBytes(pool.DefaultSize) 72 defer pool.PutBytes(b) 73 74 err = s.handshake1(client, b) 75 if err != nil { 76 return fmt.Errorf("first hand failed: %w", err) 77 } 78 79 if err = s.handshake2(client, b); err != nil { 80 return fmt.Errorf("second hand failed: %w", err) 81 } 82 83 return 84 } 85 86 func (s *Server) handshake1(client net.Conn, buf []byte) error { 87 //socks5 first handshake 88 if _, err := io.ReadFull(client, buf[:2]); err != nil { 89 return fmt.Errorf("read first handshake failed: %w", err) 90 } 91 92 if buf[0] != 0x05 { // ver 93 err := writeHandshake1(client, tools.NoAcceptableMethods) 94 return fmt.Errorf("no acceptable method: %d, resp err: %w", buf[0], err) 95 } 96 97 nMethods := int(buf[1]) 98 99 if nMethods > len(buf) { 100 err := writeHandshake1(client, tools.NoAcceptableMethods) 101 return fmt.Errorf("nMethods length of methods out of buf, resp err: %w", err) 102 } 103 104 if _, err := io.ReadFull(client, buf[:nMethods]); err != nil { 105 return fmt.Errorf("read methods failed: %w", err) 106 } 107 108 noNeedVerify := s.username == "" && s.password == "" 109 userAndPasswordSupport := false 110 111 for _, v := range buf[:nMethods] { // range all supported methods 112 if v == tools.NoAuthenticationRequired && noNeedVerify { 113 return writeHandshake1(client, tools.NoAuthenticationRequired) 114 } 115 116 if v == tools.UserAndPassword { 117 userAndPasswordSupport = true 118 } 119 } 120 121 if userAndPasswordSupport { 122 return verifyUserPass(client, s.username, s.password) 123 } 124 125 err := writeHandshake1(client, tools.NoAcceptableMethods) 126 127 return fmt.Errorf("no acceptable authentication methods: [length: %d, method:%v], response err: %w", nMethods, buf[:nMethods], err) 128 } 129 130 func verifyUserPass(client net.Conn, user, key string) error { 131 if err := writeHandshake1(client, tools.UserAndPassword); err != nil { 132 return err 133 } 134 135 b := pool.GetBytes(pool.DefaultSize) 136 defer pool.PutBytes(b) 137 138 if _, err := io.ReadFull(client, b[:2]); err != nil { 139 return fmt.Errorf("read ver and user name length failed: %w", err) 140 } 141 142 // if b[0] != 0x01 { 143 // return fmt.Errorf("unknown ver: %d", b[0]) 144 // } 145 146 usernameLength := int(b[1]) 147 148 if _, err := io.ReadFull(client, b[2:2+usernameLength]); err != nil { 149 return fmt.Errorf("read username failed: %w", err) 150 } 151 152 username := b[2 : 2+usernameLength] 153 154 if _, err := io.ReadFull(client, b[2+usernameLength:2+usernameLength+1]); err != nil { 155 return fmt.Errorf("read password length failed: %w", err) 156 } 157 158 passwordLength := int(b[2+usernameLength]) 159 160 if _, err := io.ReadFull(client, b[2+usernameLength+1:2+usernameLength+1+passwordLength]); err != nil { 161 return fmt.Errorf("read password failed: %w", err) 162 } 163 164 password := b[2+usernameLength+1 : 2+usernameLength+1+passwordLength] 165 166 if (len(user) > 0 && subtle.ConstantTimeCompare([]byte(user), username) != 1) || 167 (len(key) > 0 && subtle.ConstantTimeCompare([]byte(key), password) != 1) { 168 _, err := client.Write([]byte{1, 1}) 169 return fmt.Errorf("verify username and password failed, resp err: %w", err) 170 } 171 172 _, err := client.Write([]byte{1, 0}) 173 return err 174 } 175 176 func (s *Server) handshake2(client net.Conn, buf []byte) error { 177 // socks5 second handshake 178 if _, err := io.ReadFull(client, buf[:3]); err != nil { 179 return fmt.Errorf("read second handshake failed: %w", err) 180 } 181 182 if buf[0] != 0x05 { // ver 183 err := writeHandshake2(client, tools.NoAcceptableMethods, netapi.EmptyAddr) 184 return fmt.Errorf("no acceptable method: %d, resp err: %w", buf[0], err) 185 } 186 187 var err error 188 189 switch tools.CMD(buf[1]) { // mode 190 case tools.Connect: 191 var adr *tools.Addr 192 adr, err = tools.ResolveAddr(client) 193 if err != nil { 194 return fmt.Errorf("resolve addr failed: %w", err) 195 } 196 defer adr.Free() 197 198 addr := adr.Address(statistic.Type_tcp) 199 200 caddr, err := netapi.ParseSysAddr(client.LocalAddr()) 201 if err != nil { 202 return fmt.Errorf("parse local addr failed: %w", err) 203 } 204 err = writeHandshake2(client, tools.Succeeded, caddr) // response to connect successful 205 if err != nil { 206 return err 207 } 208 209 return s.SendStream(&netapi.StreamMeta{ 210 Source: client.RemoteAddr(), 211 Destination: addr, 212 Inbound: client.LocalAddr(), 213 Src: client, 214 Address: addr, 215 }) 216 217 case tools.Udp: // udp 218 if s.udp { 219 err = handleUDP(client) 220 break 221 } 222 fallthrough 223 224 case tools.Bind: // bind request 225 fallthrough 226 227 default: 228 err := writeHandshake2(client, tools.CommandNotSupport, netapi.EmptyAddr) 229 return fmt.Errorf("not Support Method %d, resp err: %w", buf[1], err) 230 } 231 232 if err != nil { 233 _ = writeHandshake2(client, tools.HostUnreachable, netapi.EmptyAddr) 234 } 235 return err 236 } 237 238 func handleUDP(client net.Conn) error { 239 laddr, err := netapi.ParseSysAddr(client.LocalAddr()) 240 if err != nil { 241 return fmt.Errorf("parse sys addr failed: %w", err) 242 } 243 err = writeHandshake2(client, tools.Succeeded, netapi.ParseAddressPort(statistic.Type_tcp, "0.0.0.0", laddr.Port())) 244 if err != nil { 245 return err 246 } 247 _, _ = relay.Copy(io.Discard, client) 248 return nil 249 } 250 251 func writeHandshake1(conn net.Conn, errREP byte) error { 252 _, err := conn.Write([]byte{0x05, errREP}) 253 return err 254 } 255 256 func writeHandshake2(conn net.Conn, errREP byte, addr netapi.Address) error { 257 adr := tools.ParseAddr(addr) 258 defer adr.Free() 259 _, err := conn.Write(append([]byte{0x05, errREP, 0x00}, adr.Bytes.Bytes()...)) 260 return err 261 } 262 263 type Server struct { 264 udp bool 265 lis netapi.Listener 266 username string 267 password string 268 269 *netapi.ChannelServer 270 } 271 272 func (s *Server) Close() error { 273 s.ChannelServer.Close() 274 return s.lis.Close() 275 } 276 277 func init() { 278 listener.RegisterProtocol(NewServer) 279 } 280 281 func NewServer(o *listener.Inbound_Socks5) func(netapi.Listener) (netapi.Accepter, error) { 282 return func(ii netapi.Listener) (netapi.Accepter, error) { 283 s := &Server{ 284 udp: o.Socks5.Udp, 285 username: o.Socks5.Username, 286 password: o.Socks5.Password, 287 lis: ii, 288 ChannelServer: netapi.NewChannelServer(), 289 } 290 291 if s.udp { 292 if err := s.startUDPServer(); err != nil { 293 return nil, err 294 } 295 } 296 297 if err := s.startTCPServer(); err != nil { 298 s.Close() 299 return nil, err 300 } 301 302 return s, nil 303 } 304 }