github.com/xraypb/xray-core@v1.6.6/proxy/vless/encoding/encoding.go (about) 1 package encoding 2 3 //go:generate go run github.com/xraypb/xray-core/common/errors/errorgen 4 5 import ( 6 "bytes" 7 "context" 8 "crypto/rand" 9 "fmt" 10 "io" 11 "math/big" 12 "runtime" 13 "strconv" 14 "syscall" 15 "time" 16 17 "github.com/xraypb/xray-core/common/buf" 18 "github.com/xraypb/xray-core/common/errors" 19 "github.com/xraypb/xray-core/common/net" 20 "github.com/xraypb/xray-core/common/protocol" 21 "github.com/xraypb/xray-core/common/session" 22 "github.com/xraypb/xray-core/common/signal" 23 "github.com/xraypb/xray-core/features/stats" 24 "github.com/xraypb/xray-core/proxy/vless" 25 "github.com/xraypb/xray-core/transport/internet/stat" 26 "github.com/xraypb/xray-core/transport/internet/tls" 27 "github.com/xraypb/xray-core/transport/internet/xtls" 28 ) 29 30 const ( 31 Version = byte(0) 32 ) 33 34 var tls13SupportedVersions = []byte{0x00, 0x2b, 0x00, 0x02, 0x03, 0x04} 35 var tlsClientHandShakeStart = []byte{0x16, 0x03} 36 var tlsServerHandShakeStart = []byte{0x16, 0x03, 0x03} 37 var tlsApplicationDataStart = []byte{0x17, 0x03, 0x03} 38 39 var addrParser = protocol.NewAddressParser( 40 protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv4), net.AddressFamilyIPv4), 41 protocol.AddressFamilyByte(byte(protocol.AddressTypeDomain), net.AddressFamilyDomain), 42 protocol.AddressFamilyByte(byte(protocol.AddressTypeIPv6), net.AddressFamilyIPv6), 43 protocol.PortThenAddress(), 44 ) 45 46 // EncodeRequestHeader writes encoded request header into the given writer. 47 func EncodeRequestHeader(writer io.Writer, request *protocol.RequestHeader, requestAddons *Addons) error { 48 buffer := buf.StackNew() 49 defer buffer.Release() 50 51 if err := buffer.WriteByte(request.Version); err != nil { 52 return newError("failed to write request version").Base(err) 53 } 54 55 if _, err := buffer.Write(request.User.Account.(*vless.MemoryAccount).ID.Bytes()); err != nil { 56 return newError("failed to write request user id").Base(err) 57 } 58 59 if err := EncodeHeaderAddons(&buffer, requestAddons); err != nil { 60 return newError("failed to encode request header addons").Base(err) 61 } 62 63 if err := buffer.WriteByte(byte(request.Command)); err != nil { 64 return newError("failed to write request command").Base(err) 65 } 66 67 if request.Command != protocol.RequestCommandMux { 68 if err := addrParser.WriteAddressPort(&buffer, request.Address, request.Port); err != nil { 69 return newError("failed to write request address and port").Base(err) 70 } 71 } 72 73 if _, err := writer.Write(buffer.Bytes()); err != nil { 74 return newError("failed to write request header").Base(err) 75 } 76 77 return nil 78 } 79 80 // DecodeRequestHeader decodes and returns (if successful) a RequestHeader from an input stream. 81 func DecodeRequestHeader(isfb bool, first *buf.Buffer, reader io.Reader, validator *vless.Validator) (*protocol.RequestHeader, *Addons, bool, error) { 82 buffer := buf.StackNew() 83 defer buffer.Release() 84 85 request := new(protocol.RequestHeader) 86 87 if isfb { 88 request.Version = first.Byte(0) 89 } else { 90 if _, err := buffer.ReadFullFrom(reader, 1); err != nil { 91 return nil, nil, false, newError("failed to read request version").Base(err) 92 } 93 request.Version = buffer.Byte(0) 94 } 95 96 switch request.Version { 97 case 0: 98 99 var id [16]byte 100 101 if isfb { 102 copy(id[:], first.BytesRange(1, 17)) 103 } else { 104 buffer.Clear() 105 if _, err := buffer.ReadFullFrom(reader, 16); err != nil { 106 return nil, nil, false, newError("failed to read request user id").Base(err) 107 } 108 copy(id[:], buffer.Bytes()) 109 } 110 111 if request.User = validator.Get(id); request.User == nil { 112 return nil, nil, isfb, newError("invalid request user id") 113 } 114 115 if isfb { 116 first.Advance(17) 117 } 118 119 requestAddons, err := DecodeHeaderAddons(&buffer, reader) 120 if err != nil { 121 return nil, nil, false, newError("failed to decode request header addons").Base(err) 122 } 123 124 buffer.Clear() 125 if _, err := buffer.ReadFullFrom(reader, 1); err != nil { 126 return nil, nil, false, newError("failed to read request command").Base(err) 127 } 128 129 request.Command = protocol.RequestCommand(buffer.Byte(0)) 130 switch request.Command { 131 case protocol.RequestCommandMux: 132 request.Address = net.DomainAddress("v1.mux.cool") 133 request.Port = 0 134 case protocol.RequestCommandTCP, protocol.RequestCommandUDP: 135 if addr, port, err := addrParser.ReadAddressPort(&buffer, reader); err == nil { 136 request.Address = addr 137 request.Port = port 138 } 139 } 140 if request.Address == nil { 141 return nil, nil, false, newError("invalid request address") 142 } 143 return request, requestAddons, false, nil 144 default: 145 return nil, nil, isfb, newError("invalid request version") 146 } 147 } 148 149 // EncodeResponseHeader writes encoded response header into the given writer. 150 func EncodeResponseHeader(writer io.Writer, request *protocol.RequestHeader, responseAddons *Addons) error { 151 buffer := buf.StackNew() 152 defer buffer.Release() 153 154 if err := buffer.WriteByte(request.Version); err != nil { 155 return newError("failed to write response version").Base(err) 156 } 157 158 if err := EncodeHeaderAddons(&buffer, responseAddons); err != nil { 159 return newError("failed to encode response header addons").Base(err) 160 } 161 162 if _, err := writer.Write(buffer.Bytes()); err != nil { 163 return newError("failed to write response header").Base(err) 164 } 165 166 return nil 167 } 168 169 // DecodeResponseHeader decodes and returns (if successful) a ResponseHeader from an input stream. 170 func DecodeResponseHeader(reader io.Reader, request *protocol.RequestHeader) (*Addons, error) { 171 buffer := buf.StackNew() 172 defer buffer.Release() 173 174 if _, err := buffer.ReadFullFrom(reader, 1); err != nil { 175 return nil, newError("failed to read response version").Base(err) 176 } 177 178 if buffer.Byte(0) != request.Version { 179 return nil, newError("unexpected response version. Expecting ", int(request.Version), " but actually ", int(buffer.Byte(0))) 180 } 181 182 responseAddons, err := DecodeHeaderAddons(&buffer, reader) 183 if err != nil { 184 return nil, newError("failed to decode response header addons").Base(err) 185 } 186 187 return responseAddons, nil 188 } 189 190 func ReadV(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn *xtls.Conn, rawConn syscall.RawConn, counter stats.Counter, ctx context.Context) error { 191 err := func() error { 192 var ct stats.Counter 193 for { 194 if conn.DirectIn { 195 conn.DirectIn = false 196 if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil { 197 iConn := inbound.Conn 198 statConn, ok := iConn.(*stat.CounterConnection) 199 if ok { 200 iConn = statConn.Connection 201 } 202 if xc, ok := iConn.(*xtls.Conn); ok { 203 iConn = xc.NetConn() 204 } 205 if tc, ok := iConn.(*net.TCPConn); ok { 206 if conn.SHOW { 207 fmt.Println(conn.MARK, "Splice") 208 } 209 runtime.Gosched() // necessary 210 w, err := tc.ReadFrom(conn.NetConn()) 211 if counter != nil { 212 counter.Add(w) 213 } 214 if statConn != nil && statConn.WriteCounter != nil { 215 statConn.WriteCounter.Add(w) 216 } 217 return err 218 } else { 219 panic("XTLS Splice: not TCP inbound") 220 } 221 } 222 reader = buf.NewReadVReader(conn.NetConn(), rawConn, nil) 223 ct = counter 224 if conn.SHOW { 225 fmt.Println(conn.MARK, "ReadV") 226 } 227 } 228 buffer, err := reader.ReadMultiBuffer() 229 if !buffer.IsEmpty() { 230 if ct != nil { 231 ct.Add(int64(buffer.Len())) 232 } 233 timer.Update() 234 if werr := writer.WriteMultiBuffer(buffer); werr != nil { 235 return werr 236 } 237 } 238 if err != nil { 239 return err 240 } 241 } 242 }() 243 if err != nil && errors.Cause(err) != io.EOF { 244 return err 245 } 246 return nil 247 } 248 249 // XtlsRead filter and read xtls protocol 250 func XtlsRead(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, rawConn syscall.RawConn, 251 counter stats.Counter, ctx context.Context, userUUID []byte, numberOfPacketToFilter *int, enableXtls *bool, 252 isTLS12orAbove *bool, isTLS *bool, cipher *uint16, remainingServerHello *int32) error { 253 err := func() error { 254 var ct stats.Counter 255 filterUUID := true 256 shouldSwitchToDirectCopy := false 257 var remainingContent int32 = -1 258 var remainingPadding int32 = -1 259 currentCommand := 0 260 for { 261 if shouldSwitchToDirectCopy { 262 shouldSwitchToDirectCopy = false 263 if runtime.GOOS == "linux" || runtime.GOOS == "android" { 264 if inbound := session.InboundFromContext(ctx); inbound != nil && inbound.Conn != nil { 265 iConn := inbound.Conn 266 statConn, ok := iConn.(*stat.CounterConnection) 267 if ok { 268 iConn = statConn.Connection 269 } 270 if xc, ok := iConn.(*tls.Conn); ok { 271 iConn = xc.NetConn() 272 } 273 if tc, ok := iConn.(*net.TCPConn); ok { 274 newError("XtlsRead splice").WriteToLog(session.ExportIDToError(ctx)) 275 runtime.Gosched() // necessary 276 w, err := tc.ReadFrom(conn) 277 if counter != nil { 278 counter.Add(w) 279 } 280 if statConn != nil && statConn.WriteCounter != nil { 281 statConn.WriteCounter.Add(w) 282 } 283 return err 284 } else { 285 panic("XTLS Splice: not TCP inbound") 286 } 287 } else { 288 // panic("XTLS Splice: nil inbound or nil inbound.Conn") 289 } 290 } 291 reader = buf.NewReadVReader(conn, rawConn, nil) 292 ct = counter 293 newError("XtlsRead readV").WriteToLog(session.ExportIDToError(ctx)) 294 } 295 buffer, err := reader.ReadMultiBuffer() 296 if !buffer.IsEmpty() { 297 if filterUUID && (*isTLS || *numberOfPacketToFilter > 0) { 298 buffer = XtlsUnpadding(ctx, buffer, userUUID, &remainingContent, &remainingPadding, ¤tCommand) 299 if remainingContent == 0 && remainingPadding == 0 { 300 if currentCommand == 1 { 301 filterUUID = false 302 } else if currentCommand == 2 { 303 filterUUID = false 304 shouldSwitchToDirectCopy = true 305 } else if currentCommand != 0 { 306 newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 307 } 308 } 309 } 310 if *numberOfPacketToFilter > 0 { 311 XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx) 312 } 313 if ct != nil { 314 ct.Add(int64(buffer.Len())) 315 } 316 timer.Update() 317 if werr := writer.WriteMultiBuffer(buffer); werr != nil { 318 return werr 319 } 320 } 321 if err != nil { 322 return err 323 } 324 } 325 }() 326 if err != nil && errors.Cause(err) != io.EOF { 327 return err 328 } 329 return nil 330 } 331 332 // XtlsWrite filter and write xtls protocol 333 func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter, 334 ctx context.Context, userUUID *[]byte, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool, 335 cipher *uint16, remainingServerHello *int32) error { 336 err := func() error { 337 var ct stats.Counter 338 filterTlsApplicationData := true 339 shouldSwitchToDirectCopy := false 340 for { 341 buffer, err := reader.ReadMultiBuffer() 342 if !buffer.IsEmpty() { 343 if *numberOfPacketToFilter > 0 { 344 XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx) 345 } 346 if filterTlsApplicationData && *isTLS { 347 buffer = ReshapeMultiBuffer(ctx, buffer) 348 var xtlsSpecIndex int 349 for i, b := range buffer { 350 if b.Len() >= 6 && bytes.Equal(tlsApplicationDataStart, b.BytesTo(3)) { 351 var command byte = 0x01 352 if *enableXtls { 353 shouldSwitchToDirectCopy = true 354 xtlsSpecIndex = i 355 command = 0x02 356 } 357 filterTlsApplicationData = false 358 buffer[i] = XtlsPadding(b, command, userUUID, ctx) 359 break 360 } else if !*isTLS12orAbove && *numberOfPacketToFilter <= 0 { 361 //maybe tls 1.1 or 1.0 362 filterTlsApplicationData = false 363 buffer[i] = XtlsPadding(b, 0x01, userUUID, ctx) 364 break 365 } 366 buffer[i] = XtlsPadding(b, 0x00, userUUID, ctx) 367 } 368 if shouldSwitchToDirectCopy { 369 encryptBuffer, directBuffer := buf.SplitMulti(buffer, xtlsSpecIndex+1) 370 length := encryptBuffer.Len() 371 if !encryptBuffer.IsEmpty() { 372 timer.Update() 373 if werr := writer.WriteMultiBuffer(encryptBuffer); werr != nil { 374 return werr 375 } 376 } 377 buffer = directBuffer 378 writer = buf.NewWriter(conn) 379 ct = counter 380 newError("XtlsWrite writeV ", xtlsSpecIndex, " ", length, " ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 381 time.Sleep(5 * time.Millisecond) // for some device, the first xtls direct packet fails without this delay 382 } 383 } 384 if !buffer.IsEmpty() { 385 if ct != nil { 386 ct.Add(int64(buffer.Len())) 387 } 388 timer.Update() 389 if werr := writer.WriteMultiBuffer(buffer); werr != nil { 390 return werr 391 } 392 } 393 } 394 if err != nil { 395 return err 396 } 397 } 398 }() 399 if err != nil && errors.Cause(err) != io.EOF { 400 return err 401 } 402 return nil 403 } 404 405 // XtlsFilterTls filter and recognize tls 1.3 and other info 406 func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool, 407 cipher *uint16, remainingServerHello *int32, ctx context.Context) { 408 for _, b := range buffer { 409 *numberOfPacketToFilter-- 410 if b.Len() >= 6 { 411 startsBytes := b.BytesTo(6) 412 if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == 0x02 { 413 *remainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5 414 *isTLS12orAbove = true 415 *isTLS = true 416 if b.Len() >= 79 && *remainingServerHello >= 79 { 417 sessionIdLen := int32(b.Byte(43)) 418 cipherSuite := b.BytesRange(43+sessionIdLen+1, 43+sessionIdLen+3) 419 *cipher = uint16(cipherSuite[0])<<8 | uint16(cipherSuite[1]) 420 } else { 421 newError("XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx)) 422 } 423 } else if bytes.Equal(tlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == 0x01 { 424 *isTLS = true 425 newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 426 } 427 } 428 if *remainingServerHello > 0 { 429 end := *remainingServerHello 430 if end > b.Len() { 431 end = b.Len() 432 } 433 *remainingServerHello -= b.Len() 434 if bytes.Contains(b.BytesTo(end), tls13SupportedVersions) { 435 v, ok := Tls13CipherSuiteDic[*cipher] 436 if !ok { 437 v = "Old cipher: " + strconv.FormatUint(uint64(*cipher), 16) 438 } else if v != "TLS_AES_128_CCM_8_SHA256" { 439 *enableXtls = true 440 } 441 newError("XtlsFilterTls found tls 1.3! ", b.Len(), " ", v).WriteToLog(session.ExportIDToError(ctx)) 442 *numberOfPacketToFilter = 0 443 return 444 } else if *remainingServerHello <= 0 { 445 newError("XtlsFilterTls found tls 1.2! ", b.Len()).WriteToLog(session.ExportIDToError(ctx)) 446 *numberOfPacketToFilter = 0 447 return 448 } 449 newError("XtlsFilterTls inclusive server hello ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx)) 450 } 451 if *numberOfPacketToFilter <= 0 { 452 newError("XtlsFilterTls stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 453 } 454 } 455 } 456 457 // ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes) 458 func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer { 459 needReshape := false 460 for _, b := range buffer { 461 if b.Len() >= buf.Size-21 { 462 needReshape = true 463 } 464 } 465 if !needReshape { 466 return buffer 467 } 468 mb2 := make(buf.MultiBuffer, 0, len(buffer)) 469 print := "" 470 for _, b := range buffer { 471 if b.Len() >= buf.Size-21 { 472 index := int32(bytes.LastIndex(b.Bytes(), tlsApplicationDataStart)) 473 if index <= 0 { 474 index = buf.Size / 2 475 } 476 buffer1 := buf.New() 477 buffer2 := buf.New() 478 buffer1.Write(b.BytesTo(index)) 479 buffer2.Write(b.BytesFrom(index)) 480 mb2 = append(mb2, buffer1, buffer2) 481 print += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len())) 482 } else { 483 newbuffer := buf.New() 484 newbuffer.Write(b.Bytes()) 485 mb2 = append(mb2, newbuffer) 486 print += " " + strconv.Itoa(int(b.Len())) 487 } 488 } 489 buf.ReleaseMulti(buffer) 490 newError("ReshapeMultiBuffer ", print).WriteToLog(session.ExportIDToError(ctx)) 491 return mb2 492 } 493 494 // XtlsPadding add padding to eliminate length siganature during tls handshake 495 func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, ctx context.Context) *buf.Buffer { 496 var length int32 = 0 497 if b.Len() < 900 { 498 l, err := rand.Int(rand.Reader, big.NewInt(500)) 499 if err != nil { 500 newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx)) 501 } 502 length = int32(l.Int64()) + 900 - b.Len() 503 } 504 newbuffer := buf.New() 505 if userUUID != nil { 506 newbuffer.Write(*userUUID) 507 *userUUID = nil 508 } 509 newbuffer.Write([]byte{command, byte(b.Len() >> 8), byte(b.Len()), byte(length >> 8), byte(length)}) 510 newbuffer.Write(b.Bytes()) 511 newbuffer.Extend(length) 512 newError("XtlsPadding ", b.Len(), " ", length, " ", command).WriteToLog(session.ExportIDToError(ctx)) 513 b.Release() 514 b = nil 515 return newbuffer 516 } 517 518 // XtlsUnpadding remove padding and parse command 519 func XtlsUnpadding(ctx context.Context, buffer buf.MultiBuffer, userUUID []byte, remainingContent *int32, remainingPadding *int32, currentCommand *int) buf.MultiBuffer { 520 posindex := 0 521 var posByte int32 = 0 522 if *remainingContent == -1 && *remainingPadding == -1 { 523 for i, b := range buffer { 524 if b.Len() >= 21 && bytes.Equal(userUUID, b.BytesTo(16)) { 525 posindex = i 526 posByte = 16 527 *remainingContent = 0 528 *remainingPadding = 0 529 break 530 } 531 } 532 } 533 if *remainingContent == -1 && *remainingPadding == -1 { 534 return buffer 535 } 536 mb2 := make(buf.MultiBuffer, 0, len(buffer)) 537 for i := 0; i < posindex; i++ { 538 newbuffer := buf.New() 539 newbuffer.Write(buffer[i].Bytes()) 540 mb2 = append(mb2, newbuffer) 541 } 542 for i := posindex; i < len(buffer); i++ { 543 b := buffer[i] 544 for posByte < b.Len() { 545 if *remainingContent <= 0 && *remainingPadding <= 0 { 546 if *currentCommand == 1 { // possible buffer after padding, no need to worry about xtls (command 2) 547 len := b.Len() - posByte 548 newbuffer := buf.New() 549 newbuffer.Write(b.BytesRange(posByte, posByte+len)) 550 mb2 = append(mb2, newbuffer) 551 posByte += len 552 } else { 553 paddingInfo := b.BytesRange(posByte, posByte+5) 554 *currentCommand = int(paddingInfo[0]) 555 *remainingContent = int32(paddingInfo[1])<<8 | int32(paddingInfo[2]) 556 *remainingPadding = int32(paddingInfo[3])<<8 | int32(paddingInfo[4]) 557 newError("Xtls Unpadding new block", i, " ", posByte, " content ", *remainingContent, " padding ", *remainingPadding, " ", paddingInfo[0]).WriteToLog(session.ExportIDToError(ctx)) 558 posByte += 5 559 } 560 } else if *remainingContent > 0 { 561 len := *remainingContent 562 if b.Len() < posByte+*remainingContent { 563 len = b.Len() - posByte 564 } 565 newbuffer := buf.New() 566 newbuffer.Write(b.BytesRange(posByte, posByte+len)) 567 mb2 = append(mb2, newbuffer) 568 *remainingContent -= len 569 posByte += len 570 } else { // remainingPadding > 0 571 len := *remainingPadding 572 if b.Len() < posByte+*remainingPadding { 573 len = b.Len() - posByte 574 } 575 *remainingPadding -= len 576 posByte += len 577 } 578 if posByte == b.Len() { 579 posByte = 0 580 break 581 } 582 } 583 } 584 buf.ReleaseMulti(buffer) 585 return mb2 586 } 587 588 var Tls13CipherSuiteDic = map[uint16]string{ 589 0x1301: "TLS_AES_128_GCM_SHA256", 590 0x1302: "TLS_AES_256_GCM_SHA384", 591 0x1303: "TLS_CHACHA20_POLY1305_SHA256", 592 0x1304: "TLS_AES_128_CCM_SHA256", 593 0x1305: "TLS_AES_128_CCM_8_SHA256", 594 }