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