github.com/moqsien/xraycore@v1.8.5/proxy/vless/encoding/encoding.go (about) 1 package encoding 2 3 //go:generate go run github.com/moqsien/xraycore/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/moqsien/xraycore/common/buf" 17 "github.com/moqsien/xraycore/common/errors" 18 "github.com/moqsien/xraycore/common/net" 19 "github.com/moqsien/xraycore/common/protocol" 20 "github.com/moqsien/xraycore/common/session" 21 "github.com/moqsien/xraycore/common/signal" 22 "github.com/moqsien/xraycore/features/stats" 23 "github.com/moqsien/xraycore/proxy/vless" 24 "github.com/moqsien/xraycore/transport/internet/reality" 25 "github.com/moqsien/xraycore/transport/internet/stat" 26 "github.com/moqsien/xraycore/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 if rawConn != nil { 251 reader = buf.NewReadVReader(conn, rawConn, nil) 252 } else { 253 reader = buf.NewReader(conn) 254 } 255 ct = counter 256 newError("XtlsRead readV").WriteToLog(session.ExportIDToError(ctx)) 257 } 258 buffer, err := reader.ReadMultiBuffer() 259 if !buffer.IsEmpty() { 260 if withinPaddingBuffers || *numberOfPacketToFilter > 0 { 261 buffer = XtlsUnpadding(ctx, buffer, userUUID, &remainingContent, &remainingPadding, ¤tCommand) 262 if remainingContent == 0 && remainingPadding == 0 { 263 if currentCommand == 1 { 264 withinPaddingBuffers = false 265 remainingContent = -1 266 remainingPadding = -1 // set to initial state to parse the next padding 267 } else if currentCommand == 2 { 268 withinPaddingBuffers = false 269 shouldSwitchToDirectCopy = true 270 // XTLS Vision processes struct TLS Conn's input and rawInput 271 if inputBuffer, err := buf.ReadFrom(input); err == nil { 272 if !inputBuffer.IsEmpty() { 273 buffer, _ = buf.MergeMulti(buffer, inputBuffer) 274 } 275 } 276 if rawInputBuffer, err := buf.ReadFrom(rawInput); err == nil { 277 if !rawInputBuffer.IsEmpty() { 278 buffer, _ = buf.MergeMulti(buffer, rawInputBuffer) 279 } 280 } 281 } else if currentCommand == 0 { 282 withinPaddingBuffers = true 283 } else { 284 newError("XtlsRead unknown command ", currentCommand, buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 285 } 286 } else if remainingContent > 0 || remainingPadding > 0 { 287 withinPaddingBuffers = true 288 } else { 289 withinPaddingBuffers = false 290 } 291 } 292 if *numberOfPacketToFilter > 0 { 293 XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx) 294 } 295 if ct != nil { 296 ct.Add(int64(buffer.Len())) 297 } 298 timer.Update() 299 if werr := writer.WriteMultiBuffer(buffer); werr != nil { 300 return werr 301 } 302 } 303 if err != nil { 304 return err 305 } 306 } 307 }() 308 if err != nil && errors.Cause(err) != io.EOF { 309 return err 310 } 311 return nil 312 } 313 314 // XtlsWrite filter and write xtls protocol 315 func XtlsWrite(reader buf.Reader, writer buf.Writer, timer signal.ActivityUpdater, conn net.Conn, counter stats.Counter, 316 ctx context.Context, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool, 317 cipher *uint16, remainingServerHello *int32, 318 ) error { 319 err := func() error { 320 var ct stats.Counter 321 isPadding := true 322 shouldSwitchToDirectCopy := false 323 for { 324 buffer, err := reader.ReadMultiBuffer() 325 if !buffer.IsEmpty() { 326 if *numberOfPacketToFilter > 0 { 327 XtlsFilterTls(buffer, numberOfPacketToFilter, enableXtls, isTLS12orAbove, isTLS, cipher, remainingServerHello, ctx) 328 } 329 if isPadding { 330 buffer = ReshapeMultiBuffer(ctx, buffer) 331 var xtlsSpecIndex int 332 for i, b := range buffer { 333 if *isTLS && b.Len() >= 6 && bytes.Equal(tlsApplicationDataStart, b.BytesTo(3)) { 334 var command byte = CommandPaddingEnd 335 if *enableXtls { 336 shouldSwitchToDirectCopy = true 337 xtlsSpecIndex = i 338 command = CommandPaddingDirect 339 } 340 isPadding = false 341 buffer[i] = XtlsPadding(b, command, nil, *isTLS, ctx) 342 break 343 } else if !*isTLS12orAbove && *numberOfPacketToFilter <= 1 { // For compatibility with earlier vision receiver, we finish padding 1 packet early 344 isPadding = false 345 buffer[i] = XtlsPadding(b, CommandPaddingEnd, nil, *isTLS, ctx) 346 break 347 } 348 buffer[i] = XtlsPadding(b, CommandPaddingContinue, nil, *isTLS, ctx) 349 } 350 if shouldSwitchToDirectCopy { 351 encryptBuffer, directBuffer := buf.SplitMulti(buffer, xtlsSpecIndex+1) 352 length := encryptBuffer.Len() 353 if !encryptBuffer.IsEmpty() { 354 timer.Update() 355 if werr := writer.WriteMultiBuffer(encryptBuffer); werr != nil { 356 return werr 357 } 358 } 359 buffer = directBuffer 360 writer = buf.NewWriter(conn) 361 ct = counter 362 newError("XtlsWrite writeV ", xtlsSpecIndex, " ", length, " ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 363 time.Sleep(5 * time.Millisecond) // for some device, the first xtls direct packet fails without this delay 364 } 365 } 366 if !buffer.IsEmpty() { 367 if ct != nil { 368 ct.Add(int64(buffer.Len())) 369 } 370 timer.Update() 371 if werr := writer.WriteMultiBuffer(buffer); werr != nil { 372 return werr 373 } 374 } 375 } 376 if err != nil { 377 return err 378 } 379 } 380 }() 381 if err != nil && errors.Cause(err) != io.EOF { 382 return err 383 } 384 return nil 385 } 386 387 // XtlsFilterTls filter and recognize tls 1.3 and other info 388 func XtlsFilterTls(buffer buf.MultiBuffer, numberOfPacketToFilter *int, enableXtls *bool, isTLS12orAbove *bool, isTLS *bool, 389 cipher *uint16, remainingServerHello *int32, ctx context.Context, 390 ) { 391 for _, b := range buffer { 392 *numberOfPacketToFilter-- 393 if b.Len() >= 6 { 394 startsBytes := b.BytesTo(6) 395 if bytes.Equal(tlsServerHandShakeStart, startsBytes[:3]) && startsBytes[5] == tlsHandshakeTypeServerHello { 396 *remainingServerHello = (int32(startsBytes[3])<<8 | int32(startsBytes[4])) + 5 397 *isTLS12orAbove = true 398 *isTLS = true 399 if b.Len() >= 79 && *remainingServerHello >= 79 { 400 sessionIdLen := int32(b.Byte(43)) 401 cipherSuite := b.BytesRange(43+sessionIdLen+1, 43+sessionIdLen+3) 402 *cipher = uint16(cipherSuite[0])<<8 | uint16(cipherSuite[1]) 403 } else { 404 newError("XtlsFilterTls short server hello, tls 1.2 or older? ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx)) 405 } 406 } else if bytes.Equal(tlsClientHandShakeStart, startsBytes[:2]) && startsBytes[5] == tlsHandshakeTypeClientHello { 407 *isTLS = true 408 newError("XtlsFilterTls found tls client hello! ", buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 409 } 410 } 411 if *remainingServerHello > 0 { 412 end := *remainingServerHello 413 if end > b.Len() { 414 end = b.Len() 415 } 416 *remainingServerHello -= b.Len() 417 if bytes.Contains(b.BytesTo(end), tls13SupportedVersions) { 418 v, ok := Tls13CipherSuiteDic[*cipher] 419 if !ok { 420 v = "Old cipher: " + strconv.FormatUint(uint64(*cipher), 16) 421 } else if v != "TLS_AES_128_CCM_8_SHA256" { 422 *enableXtls = true 423 } 424 newError("XtlsFilterTls found tls 1.3! ", b.Len(), " ", v).WriteToLog(session.ExportIDToError(ctx)) 425 *numberOfPacketToFilter = 0 426 return 427 } else if *remainingServerHello <= 0 { 428 newError("XtlsFilterTls found tls 1.2! ", b.Len()).WriteToLog(session.ExportIDToError(ctx)) 429 *numberOfPacketToFilter = 0 430 return 431 } 432 newError("XtlsFilterTls inconclusive server hello ", b.Len(), " ", *remainingServerHello).WriteToLog(session.ExportIDToError(ctx)) 433 } 434 if *numberOfPacketToFilter <= 0 { 435 newError("XtlsFilterTls stop filtering", buffer.Len()).WriteToLog(session.ExportIDToError(ctx)) 436 } 437 } 438 } 439 440 // ReshapeMultiBuffer prepare multi buffer for padding stucture (max 21 bytes) 441 func ReshapeMultiBuffer(ctx context.Context, buffer buf.MultiBuffer) buf.MultiBuffer { 442 needReshape := 0 443 for _, b := range buffer { 444 if b.Len() >= buf.Size-21 { 445 needReshape += 1 446 } 447 } 448 if needReshape == 0 { 449 return buffer 450 } 451 mb2 := make(buf.MultiBuffer, 0, len(buffer)+needReshape) 452 toPrint := "" 453 for i, buffer1 := range buffer { 454 if buffer1.Len() >= buf.Size-21 { 455 index := int32(bytes.LastIndex(buffer1.Bytes(), tlsApplicationDataStart)) 456 if index <= 0 || index > buf.Size-21 { 457 index = buf.Size / 2 458 } 459 buffer2 := buf.New() 460 buffer2.Write(buffer1.BytesFrom(index)) 461 buffer1.Resize(0, index) 462 mb2 = append(mb2, buffer1, buffer2) 463 toPrint += " " + strconv.Itoa(int(buffer1.Len())) + " " + strconv.Itoa(int(buffer2.Len())) 464 } else { 465 mb2 = append(mb2, buffer1) 466 toPrint += " " + strconv.Itoa(int(buffer1.Len())) 467 } 468 buffer[i] = nil 469 } 470 buffer = buffer[:0] 471 newError("ReshapeMultiBuffer ", toPrint).WriteToLog(session.ExportIDToError(ctx)) 472 return mb2 473 } 474 475 // XtlsPadding add padding to eliminate length siganature during tls handshake 476 func XtlsPadding(b *buf.Buffer, command byte, userUUID *[]byte, longPadding bool, ctx context.Context) *buf.Buffer { 477 var contentLen int32 = 0 478 var paddingLen int32 = 0 479 if b != nil { 480 contentLen = b.Len() 481 } 482 if contentLen < 900 && longPadding { 483 l, err := rand.Int(rand.Reader, big.NewInt(500)) 484 if err != nil { 485 newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx)) 486 } 487 paddingLen = int32(l.Int64()) + 900 - contentLen 488 } else { 489 l, err := rand.Int(rand.Reader, big.NewInt(256)) 490 if err != nil { 491 newError("failed to generate padding").Base(err).WriteToLog(session.ExportIDToError(ctx)) 492 } 493 paddingLen = int32(l.Int64()) 494 } 495 if paddingLen > buf.Size-21-contentLen { 496 paddingLen = buf.Size - 21 - contentLen 497 } 498 newbuffer := buf.New() 499 if userUUID != nil { 500 newbuffer.Write(*userUUID) 501 *userUUID = nil 502 } 503 newbuffer.Write([]byte{command, byte(contentLen >> 8), byte(contentLen), byte(paddingLen >> 8), byte(paddingLen)}) 504 if b != nil { 505 newbuffer.Write(b.Bytes()) 506 b.Release() 507 b = nil 508 } 509 newbuffer.Extend(paddingLen) 510 newError("XtlsPadding ", contentLen, " ", paddingLen, " ", command).WriteToLog(session.ExportIDToError(ctx)) 511 return newbuffer 512 } 513 514 // XtlsUnpadding remove padding and parse command 515 func XtlsUnpadding(ctx context.Context, buffer buf.MultiBuffer, userUUID []byte, remainingContent *int32, remainingPadding *int32, currentCommand *int) buf.MultiBuffer { 516 posindex := 0 517 var posByte int32 = 0 518 if *remainingContent == -1 && *remainingPadding == -1 { 519 for i, b := range buffer { 520 if b.Len() >= 21 && bytes.Equal(userUUID, b.BytesTo(16)) { 521 posindex = i 522 posByte = 16 523 *remainingContent = 0 524 *remainingPadding = 0 525 *currentCommand = 0 526 break 527 } 528 } 529 } 530 if *remainingContent == -1 && *remainingPadding == -1 { 531 return buffer 532 } 533 mb2 := make(buf.MultiBuffer, 0, len(buffer)) 534 for i := 0; i < posindex; i++ { 535 newbuffer := buf.New() 536 newbuffer.Write(buffer[i].Bytes()) 537 mb2 = append(mb2, newbuffer) 538 } 539 for i := posindex; i < len(buffer); i++ { 540 b := buffer[i] 541 for posByte < b.Len() { 542 if *remainingContent <= 0 && *remainingPadding <= 0 { 543 if *currentCommand == 1 { // possible buffer after padding, no need to worry about xtls (command 2) 544 len := b.Len() - posByte 545 newbuffer := buf.New() 546 newbuffer.Write(b.BytesRange(posByte, posByte+len)) 547 mb2 = append(mb2, newbuffer) 548 posByte += len 549 } else { 550 paddingInfo := b.BytesRange(posByte, posByte+5) 551 *currentCommand = int(paddingInfo[0]) 552 *remainingContent = int32(paddingInfo[1])<<8 | int32(paddingInfo[2]) 553 *remainingPadding = int32(paddingInfo[3])<<8 | int32(paddingInfo[4]) 554 newError("Xtls Unpadding new block", i, " ", posByte, " content ", *remainingContent, " padding ", *remainingPadding, " ", paddingInfo[0]).WriteToLog(session.ExportIDToError(ctx)) 555 posByte += 5 556 } 557 } else if *remainingContent > 0 { 558 len := *remainingContent 559 if b.Len() < posByte+*remainingContent { 560 len = b.Len() - posByte 561 } 562 newbuffer := buf.New() 563 newbuffer.Write(b.BytesRange(posByte, posByte+len)) 564 mb2 = append(mb2, newbuffer) 565 *remainingContent -= len 566 posByte += len 567 } else { // remainingPadding > 0 568 len := *remainingPadding 569 if b.Len() < posByte+*remainingPadding { 570 len = b.Len() - posByte 571 } 572 *remainingPadding -= len 573 posByte += len 574 } 575 if posByte == b.Len() { 576 posByte = 0 577 break 578 } 579 } 580 } 581 buf.ReleaseMulti(buffer) 582 return mb2 583 }