github.com/yaling888/clash@v1.53.0/adapter/outbound/vless.go (about) 1 package outbound 2 3 import ( 4 "context" 5 "crypto/tls" 6 "encoding/binary" 7 "errors" 8 "fmt" 9 "io" 10 "net" 11 "net/http" 12 "strconv" 13 "sync" 14 15 "golang.org/x/net/http2" 16 17 "github.com/yaling888/clash/common/convert" 18 "github.com/yaling888/clash/common/pool" 19 "github.com/yaling888/clash/component/dialer" 20 "github.com/yaling888/clash/component/resolver" 21 C "github.com/yaling888/clash/constant" 22 "github.com/yaling888/clash/transport/crypto" 23 "github.com/yaling888/clash/transport/gun" 24 "github.com/yaling888/clash/transport/h1" 25 "github.com/yaling888/clash/transport/h2" 26 "github.com/yaling888/clash/transport/header" 27 "github.com/yaling888/clash/transport/quic" 28 "github.com/yaling888/clash/transport/socks5" 29 tls2 "github.com/yaling888/clash/transport/tls" 30 "github.com/yaling888/clash/transport/vless" 31 "github.com/yaling888/clash/transport/vmess" 32 ) 33 34 const ( 35 // max packet length 36 maxLength = 1024 << 4 37 ) 38 39 var _ C.ProxyAdapter = (*Vless)(nil) 40 41 type Vless struct { 42 *Base 43 client *vless.Client 44 option *VlessOption 45 46 // for gun mux 47 gunTLSConfig *tls.Config 48 gunConfig *gun.Config 49 transport *http2.Transport 50 51 quicAEAD *crypto.AEAD 52 } 53 54 type VlessOption struct { 55 BasicOption 56 Name string `proxy:"name"` 57 Server string `proxy:"server"` 58 Port int `proxy:"port"` 59 UUID string `proxy:"uuid"` 60 UDP bool `proxy:"udp,omitempty"` 61 Network string `proxy:"network,omitempty"` 62 TLS bool `proxy:"tls,omitempty"` 63 SkipCertVerify bool `proxy:"skip-cert-verify,omitempty"` 64 ALPN []string `proxy:"alpn,omitempty"` 65 ServerName string `proxy:"servername,omitempty"` 66 HTTPOpts HTTPOptions `proxy:"http-opts,omitempty"` 67 HTTP2Opts HTTP2Options `proxy:"h2-opts,omitempty"` 68 GrpcOpts GrpcOptions `proxy:"grpc-opts,omitempty"` 69 WSOpts WSOptions `proxy:"ws-opts,omitempty"` 70 QUICOpts QUICOptions `proxy:"quic-opts,omitempty"` 71 AEADOpts crypto.AEADOption `proxy:"aead-opts,omitempty"` 72 RandomHost bool `proxy:"rand-host,omitempty"` 73 RemoteDnsResolve bool `proxy:"remote-dns-resolve,omitempty"` 74 } 75 76 // StreamConn implements C.ProxyAdapter 77 func (v *Vless) StreamConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { 78 var err error 79 switch v.option.Network { 80 case "ws": 81 host, port, _ := net.SplitHostPort(v.addr) 82 wsOpts := &vmess.WebsocketConfig{ 83 Host: host, 84 Port: port, 85 Headers: http.Header{}, 86 Path: v.option.WSOpts.Path, 87 MaxEarlyData: v.option.WSOpts.MaxEarlyData, 88 EarlyDataHeaderName: v.option.WSOpts.EarlyDataHeaderName, 89 } 90 91 if len(v.option.WSOpts.Headers) != 0 { 92 for key, value := range v.option.WSOpts.Headers { 93 wsOpts.Headers.Add(key, value) 94 } 95 } 96 97 if v.option.TLS { 98 wsOpts.TLS = true 99 wsOpts.TLSConfig = &tls.Config{ 100 ServerName: host, 101 InsecureSkipVerify: v.option.SkipCertVerify, 102 NextProtos: []string{"http/1.1"}, 103 } 104 if v.option.ServerName != "" { 105 wsOpts.TLSConfig.ServerName = v.option.ServerName 106 wsOpts.Host = v.option.ServerName 107 } else if host1 := wsOpts.Headers.Get("Host"); host1 != "" { 108 wsOpts.TLSConfig.ServerName = host1 109 wsOpts.Host = host1 110 } 111 } else if v.option.RandomHost || wsOpts.Headers.Get("Host") == "" { 112 wsOpts.Headers.Set("Host", convert.RandHost()) 113 } 114 115 if wsOpts.Headers.Get("User-Agent") == "" { 116 wsOpts.Headers.Set("User-Agent", convert.RandUserAgent()) 117 } 118 c, err = vmess.StreamWebsocketConn(c, wsOpts) 119 case "http": 120 host := v.option.Server 121 // readability first, so just copy default TLS logic 122 if v.option.TLS { 123 tlsOpts := &tls2.Config{ 124 Host: host, 125 SkipCertVerify: v.option.SkipCertVerify, 126 } 127 128 if v.option.ServerName != "" { 129 tlsOpts.Host = v.option.ServerName 130 } 131 132 c, err = tls2.StreamTLSConn(c, tlsOpts) 133 if err != nil { 134 return nil, err 135 } 136 } 137 138 httpOpts := &h1.HTTPConfig{ 139 Host: host, 140 Method: v.option.HTTPOpts.Method, 141 Path: v.option.HTTPOpts.Path, 142 Headers: make(map[string][]string), 143 } 144 145 if len(v.option.HTTPOpts.Headers) != 0 { 146 for key, value := range v.option.HTTPOpts.Headers { 147 httpOpts.Headers[key] = value 148 } 149 } 150 151 if !v.option.TLS && (v.option.RandomHost || len(v.option.HTTPOpts.Headers["Host"]) == 0) { 152 httpOpts.Headers["Host"] = []string{convert.RandHost()} 153 } 154 155 if len(v.option.HTTPOpts.Headers["User-Agent"]) == 0 { 156 httpOpts.Headers["User-Agent"] = []string{convert.RandUserAgent()} 157 } 158 c = h1.StreamHTTPConn(c, httpOpts) 159 case "h2": 160 tlsOpts := tls2.Config{ 161 Host: v.option.Server, 162 SkipCertVerify: v.option.SkipCertVerify, 163 NextProtos: []string{"h2"}, 164 } 165 166 if v.option.ServerName != "" { 167 tlsOpts.Host = v.option.ServerName 168 } 169 170 c, err = tls2.StreamTLSConn(c, &tlsOpts) 171 if err != nil { 172 return nil, err 173 } 174 175 h2Opts := &h2.Config{ 176 Hosts: v.option.HTTP2Opts.Host, 177 Path: v.option.HTTP2Opts.Path, 178 Headers: http.Header{}, 179 } 180 181 if len(v.option.HTTP2Opts.Headers) != 0 { 182 for key, value := range v.option.HTTP2Opts.Headers { 183 h2Opts.Headers.Add(key, value) 184 } 185 } 186 187 if h2Opts.Headers.Get("User-Agent") == "" { 188 h2Opts.Headers.Set("User-Agent", convert.RandUserAgent()) 189 } 190 191 c, err = h2.StreamH2Conn(c, h2Opts) 192 case "grpc": 193 c, err = gun.StreamGunWithConn(c, v.gunTLSConfig, v.gunConfig) 194 case "quic": 195 quicOpts := &quic.Config{ 196 Host: v.option.Server, 197 Port: v.option.Port, 198 ALPN: v.option.ALPN, 199 ServerName: v.option.Server, 200 SkipCertVerify: v.option.SkipCertVerify, 201 Header: v.option.QUICOpts.Header, 202 AEAD: v.quicAEAD, 203 } 204 205 if v.option.ServerName != "" { 206 quicOpts.ServerName = v.option.ServerName 207 } 208 209 c, err = quic.StreamQUICConn(c, quicOpts) 210 default: 211 // handle TLS 212 if v.option.TLS { 213 host, _, _ := net.SplitHostPort(v.addr) 214 tlsOpts := &tls2.Config{ 215 Host: host, 216 SkipCertVerify: v.option.SkipCertVerify, 217 } 218 219 if v.option.ServerName != "" { 220 tlsOpts.Host = v.option.ServerName 221 } 222 223 c, err = tls2.StreamTLSConn(c, tlsOpts) 224 } 225 } 226 227 if err != nil { 228 return nil, err 229 } 230 231 c, err = crypto.StreamAEADConnOrNot(c, v.option.AEADOpts) 232 if err != nil { 233 return nil, err 234 } 235 236 return v.client.StreamConn(c, parseVlessAddr(metadata)) 237 } 238 239 // StreamPacketConn implements C.ProxyAdapter 240 func (v *Vless) StreamPacketConn(c net.Conn, metadata *C.Metadata) (net.Conn, error) { 241 // vless use stream-oriented udp with a special address, so we need a net.UDPAddr 242 if !metadata.Resolved() { 243 rAddrs, err := resolver.LookupIP(context.Background(), metadata.Host) 244 if err != nil { 245 return c, fmt.Errorf("can't resolve ip, %w", err) 246 } 247 metadata.DstIP = rAddrs[0] 248 } 249 250 var err error 251 c, err = v.StreamConn(c, metadata) 252 if err != nil { 253 return c, fmt.Errorf("new vless client error: %w", err) 254 } 255 256 return WrapConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}), nil 257 } 258 259 // DialContext implements C.ProxyAdapter 260 func (v *Vless) DialContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.Conn, err error) { 261 // gun transport 262 if v.transport != nil && len(opts) == 0 { 263 c, err := gun.StreamGunWithTransport(v.transport, v.gunConfig) 264 if err != nil { 265 return nil, err 266 } 267 defer func(cc net.Conn, e error) { 268 safeConnClose(cc, e) 269 }(c, err) 270 271 c, err = v.client.StreamConn(c, parseVlessAddr(metadata)) 272 if err != nil { 273 return nil, err 274 } 275 276 return NewConn(c, v), nil 277 } 278 279 c, err := v.dialContext(ctx, opts...) 280 if err != nil { 281 return nil, err 282 } 283 tcpKeepAlive(c) 284 defer func(cc net.Conn, e error) { 285 safeConnClose(cc, e) 286 }(c, err) 287 288 c, err = v.StreamConn(c, metadata) 289 return NewConn(c, v), err 290 } 291 292 // ListenPacketContext implements C.ProxyAdapter 293 func (v *Vless) ListenPacketContext(ctx context.Context, metadata *C.Metadata, opts ...dialer.Option) (_ C.PacketConn, err error) { 294 var c net.Conn 295 // gun transport 296 if v.transport != nil && len(opts) == 0 { 297 // vless use stream-oriented udp with a special address, so we need a net.UDPAddr 298 if !metadata.Resolved() { 299 rAddrs, err := resolver.LookupIP(context.Background(), metadata.Host) 300 if err != nil { 301 return nil, fmt.Errorf("can't resolve ip, %w", err) 302 } 303 metadata.DstIP = rAddrs[0] 304 } 305 306 c, err = gun.StreamGunWithTransport(v.transport, v.gunConfig) 307 if err != nil { 308 return nil, err 309 } 310 defer func(cc net.Conn, e error) { 311 safeConnClose(cc, e) 312 }(c, err) 313 314 c, err = v.client.StreamConn(c, parseVlessAddr(metadata)) 315 if err != nil { 316 return nil, fmt.Errorf("new vless client error: %w", err) 317 } 318 319 return NewPacketConn(&vlessPacketConn{Conn: c, rAddr: metadata.UDPAddr()}, v), nil 320 } 321 322 c, err = v.dialContext(ctx, opts...) 323 if err != nil { 324 return nil, err 325 } 326 327 tcpKeepAlive(c) 328 defer func(cc net.Conn, e error) { 329 safeConnClose(cc, e) 330 }(c, err) 331 332 c, err = v.StreamPacketConn(c, metadata) 333 if err != nil { 334 return nil, fmt.Errorf("new vless client error: %w", err) 335 } 336 337 return NewPacketConn(c.(net.PacketConn), v), nil 338 } 339 340 func (v *Vless) dialContext(ctx context.Context, opts ...dialer.Option) (net.Conn, error) { 341 switch v.option.Network { 342 case "quic": 343 c, err := dialer.ListenPacket(ctx, "udp", "", v.Base.DialOptions(opts...)...) 344 if err != nil { 345 return nil, fmt.Errorf("%s connect error: %w", v.addr, err) 346 } 347 return c.(*net.UDPConn), nil 348 } 349 350 c, err := dialer.DialContext(ctx, "tcp", v.addr, v.Base.DialOptions(opts...)...) 351 if err != nil { 352 return nil, fmt.Errorf("%s connect error: %w", v.addr, err) 353 } 354 return c, nil 355 } 356 357 func parseVlessAddr(metadata *C.Metadata) *vless.DstAddr { 358 var addrType byte 359 var addr []byte 360 switch metadata.AddrType() { 361 case socks5.AtypIPv4: 362 addrType = vless.AtypIPv4 363 addr = make([]byte, net.IPv4len) 364 copy(addr[:], metadata.DstIP.AsSlice()) 365 case socks5.AtypIPv6: 366 addrType = vless.AtypIPv6 367 addr = make([]byte, net.IPv6len) 368 copy(addr[:], metadata.DstIP.AsSlice()) 369 case socks5.AtypDomainName: 370 addrType = vless.AtypDomainName 371 addr = make([]byte, len(metadata.Host)+1) 372 addr[0] = byte(len(metadata.Host)) 373 copy(addr[1:], metadata.Host) 374 } 375 376 return &vless.DstAddr{ 377 UDP: metadata.NetWork == C.UDP, 378 AddrType: addrType, 379 Addr: addr, 380 Port: uint(metadata.DstPort), 381 } 382 } 383 384 type vlessPacketConn struct { 385 net.Conn 386 rAddr net.Addr 387 remain int 388 mux sync.Mutex 389 } 390 391 func (vc *vlessPacketConn) WriteTo(b []byte, addr net.Addr) (int, error) { 392 realAddr := vc.rAddr.(*net.UDPAddr) 393 destAddr := addr.(*net.UDPAddr) 394 if !realAddr.IP.Equal(destAddr.IP) || realAddr.Port != destAddr.Port { 395 return 0, errors.New("udp packet dropped due to mismatched remote address") 396 } 397 398 total := len(b) 399 if total == 0 { 400 return 0, nil 401 } 402 if total <= maxLength { 403 return writePacket(vc.Conn, b) 404 } 405 406 offset := 0 407 for { 408 cursor := min(offset+maxLength, total) 409 410 n, err := writePacket(vc.Conn, b[offset:cursor]) 411 if err != nil { 412 return offset + n, err 413 } 414 415 offset = cursor 416 if offset == total { 417 break 418 } 419 } 420 421 return total, nil 422 } 423 424 func (vc *vlessPacketConn) ReadFrom(b []byte) (int, net.Addr, error) { 425 vc.mux.Lock() 426 defer vc.mux.Unlock() 427 428 if vc.remain > 0 { 429 length := min(len(b), vc.remain) 430 431 n, err := vc.Conn.Read(b[:length]) 432 if err != nil { 433 return n, vc.rAddr, err 434 } 435 436 vc.remain -= n 437 438 return n, vc.rAddr, nil 439 } 440 441 if n, err := io.ReadFull(vc.Conn, b[:2]); err != nil { 442 return n, vc.rAddr, fmt.Errorf("read length error: %w", err) 443 } 444 445 total := int(binary.BigEndian.Uint16(b[:2])) 446 if total == 0 || total > maxLength { 447 return 0, vc.rAddr, fmt.Errorf("invalid packet length: %d", total) 448 } 449 450 length := min(len(b), total) 451 452 if n, err := io.ReadFull(vc.Conn, b[:length]); err != nil { 453 return n, vc.rAddr, fmt.Errorf("read packet error: %w", err) 454 } 455 456 vc.remain = total - length 457 458 return length, vc.rAddr, nil 459 } 460 461 func writePacket(w io.Writer, b []byte) (n int, err error) { 462 bufP := pool.GetNetBuf() 463 defer pool.PutNetBuf(bufP) 464 465 binary.BigEndian.PutUint16(*bufP, uint16(len(b))) 466 n = copy((*bufP)[2:], b) 467 _, err = w.Write((*bufP)[:2+n]) 468 return 469 } 470 471 func NewVless(option VlessOption) (*Vless, error) { 472 if option.Network != "ws" && !option.TLS { 473 return nil, errors.New("TLS must be true with tcp/http/h2/grpc/quic network") 474 } 475 476 if _, err := crypto.VerifyAEADOption(option.AEADOpts, true); err != nil { 477 return nil, err 478 } 479 480 client, err := vless.NewClient(option.UUID) 481 if err != nil { 482 return nil, err 483 } 484 485 v := &Vless{ 486 Base: &Base{ 487 name: option.Name, 488 addr: net.JoinHostPort(option.Server, strconv.Itoa(option.Port)), 489 tp: C.Vless, 490 udp: option.UDP, 491 iface: option.Interface, 492 dns: option.RemoteDnsResolve, 493 }, 494 client: client, 495 option: &option, 496 } 497 498 host := option.Server 499 if option.ServerName != "" { 500 host = option.ServerName 501 } 502 503 switch option.Network { 504 case "h2": 505 if len(option.HTTP2Opts.Host) == 0 { 506 option.HTTP2Opts.Host = append(option.HTTP2Opts.Host, host) 507 } 508 case "grpc": 509 dialFn := func(network, addr string) (net.Conn, error) { 510 c, err := dialer.DialContext(context.Background(), "tcp", v.addr, v.Base.DialOptions()...) 511 if err != nil { 512 return nil, fmt.Errorf("%s connect error: %w", v.addr, err) 513 } 514 tcpKeepAlive(c) 515 return c, nil 516 } 517 518 gunConfig := &gun.Config{ 519 ServiceName: v.option.GrpcOpts.GrpcServiceName, 520 Host: v.option.ServerName, 521 } 522 tlsConfig := &tls.Config{ 523 InsecureSkipVerify: v.option.SkipCertVerify, 524 ServerName: v.option.ServerName, 525 } 526 527 if v.option.ServerName == "" { 528 host, _, _ := net.SplitHostPort(v.addr) 529 tlsConfig.ServerName = host 530 gunConfig.Host = host 531 } 532 533 v.gunTLSConfig = tlsConfig 534 v.gunConfig = gunConfig 535 v.transport = gun.NewHTTP2Client(dialFn, tlsConfig) 536 case "quic": 537 quicAEAD, err := crypto.NewAEAD(v.option.QUICOpts.Security, v.option.QUICOpts.Key, "v2ray-quic-salt") 538 if err != nil { 539 return nil, fmt.Errorf("invalid quic-opts: %w", err) 540 } 541 v.quicAEAD = quicAEAD 542 _, err = header.New(v.option.QUICOpts.Header) 543 if err != nil { 544 return nil, fmt.Errorf("invalid quic-opts: %w", err) 545 } 546 } 547 548 return v, nil 549 }