github.com/metacubex/mihomo@v1.18.5/transport/tuic/v5/protocol.go (about) 1 package v5 2 3 import ( 4 "encoding/binary" 5 "fmt" 6 "io" 7 "net" 8 "net/netip" 9 "strconv" 10 11 "github.com/metacubex/mihomo/common/utils" 12 C "github.com/metacubex/mihomo/constant" 13 "github.com/metacubex/mihomo/transport/socks5" 14 15 "github.com/metacubex/quic-go" 16 ) 17 18 type BufferedReader interface { 19 io.Reader 20 io.ByteReader 21 } 22 23 type BufferedWriter interface { 24 io.Writer 25 io.ByteWriter 26 } 27 28 type CommandType byte 29 30 const ( 31 AuthenticateType = CommandType(0x00) 32 ConnectType = CommandType(0x01) 33 PacketType = CommandType(0x02) 34 DissociateType = CommandType(0x03) 35 HeartbeatType = CommandType(0x04) 36 ) 37 38 const VER byte = 0x05 39 40 func (c CommandType) String() string { 41 switch c { 42 case AuthenticateType: 43 return "Authenticate" 44 case ConnectType: 45 return "Connect" 46 case PacketType: 47 return "Packet" 48 case DissociateType: 49 return "Dissociate" 50 case HeartbeatType: 51 return "Heartbeat" 52 default: 53 return fmt.Sprintf("UnknowCommand: %#x", byte(c)) 54 } 55 } 56 57 func (c CommandType) BytesLen() int { 58 return 1 59 } 60 61 type CommandHead struct { 62 VER byte 63 TYPE CommandType 64 } 65 66 func NewCommandHead(TYPE CommandType) CommandHead { 67 return CommandHead{ 68 VER: VER, 69 TYPE: TYPE, 70 } 71 } 72 73 func ReadCommandHead(reader BufferedReader) (c CommandHead, err error) { 74 c.VER, err = reader.ReadByte() 75 if err != nil { 76 return 77 } 78 TYPE, err := reader.ReadByte() 79 if err != nil { 80 return 81 } 82 c.TYPE = CommandType(TYPE) 83 return 84 } 85 86 func (c CommandHead) WriteTo(writer BufferedWriter) (err error) { 87 err = writer.WriteByte(c.VER) 88 if err != nil { 89 return 90 } 91 err = writer.WriteByte(byte(c.TYPE)) 92 if err != nil { 93 return 94 } 95 return 96 } 97 98 func (c CommandHead) BytesLen() int { 99 return 1 + c.TYPE.BytesLen() 100 } 101 102 type Authenticate struct { 103 CommandHead 104 UUID [16]byte 105 TOKEN [32]byte 106 } 107 108 func NewAuthenticate(UUID [16]byte, TOKEN [32]byte) Authenticate { 109 return Authenticate{ 110 CommandHead: NewCommandHead(AuthenticateType), 111 UUID: UUID, 112 TOKEN: TOKEN, 113 } 114 } 115 116 func ReadAuthenticateWithHead(head CommandHead, reader BufferedReader) (c Authenticate, err error) { 117 c.CommandHead = head 118 if c.CommandHead.TYPE != AuthenticateType { 119 err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE) 120 return 121 } 122 _, err = io.ReadFull(reader, c.UUID[:]) 123 if err != nil { 124 return 125 } 126 _, err = io.ReadFull(reader, c.TOKEN[:]) 127 if err != nil { 128 return 129 } 130 return 131 } 132 133 func ReadAuthenticate(reader BufferedReader) (c Authenticate, err error) { 134 head, err := ReadCommandHead(reader) 135 if err != nil { 136 return 137 } 138 return ReadAuthenticateWithHead(head, reader) 139 } 140 141 func GenToken(state quic.ConnectionState, uuid [16]byte, password string) (token [32]byte, err error) { 142 var tokenBytes []byte 143 tokenBytes, err = state.TLS.ExportKeyingMaterial(utils.StringFromImmutableBytes(uuid[:]), utils.ImmutableBytesFromString(password), 32) 144 if err != nil { 145 return 146 } 147 copy(token[:], tokenBytes) 148 return 149 } 150 151 func (c Authenticate) WriteTo(writer BufferedWriter) (err error) { 152 err = c.CommandHead.WriteTo(writer) 153 if err != nil { 154 return 155 } 156 _, err = writer.Write(c.UUID[:]) 157 if err != nil { 158 return 159 } 160 _, err = writer.Write(c.TOKEN[:]) 161 if err != nil { 162 return 163 } 164 return 165 } 166 167 func (c Authenticate) BytesLen() int { 168 return c.CommandHead.BytesLen() + 16 + 32 169 } 170 171 type Connect struct { 172 CommandHead 173 ADDR Address 174 } 175 176 func NewConnect(ADDR Address) Connect { 177 return Connect{ 178 CommandHead: NewCommandHead(ConnectType), 179 ADDR: ADDR, 180 } 181 } 182 183 func ReadConnectWithHead(head CommandHead, reader BufferedReader) (c Connect, err error) { 184 c.CommandHead = head 185 if c.CommandHead.TYPE != ConnectType { 186 err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE) 187 return 188 } 189 c.ADDR, err = ReadAddress(reader) 190 if err != nil { 191 return 192 } 193 return 194 } 195 196 func ReadConnect(reader BufferedReader) (c Connect, err error) { 197 head, err := ReadCommandHead(reader) 198 if err != nil { 199 return 200 } 201 return ReadConnectWithHead(head, reader) 202 } 203 204 func (c Connect) WriteTo(writer BufferedWriter) (err error) { 205 err = c.CommandHead.WriteTo(writer) 206 if err != nil { 207 return 208 } 209 err = c.ADDR.WriteTo(writer) 210 if err != nil { 211 return 212 } 213 return 214 } 215 216 func (c Connect) BytesLen() int { 217 return c.CommandHead.BytesLen() + c.ADDR.BytesLen() 218 } 219 220 type Packet struct { 221 CommandHead 222 ASSOC_ID uint16 223 PKT_ID uint16 224 FRAG_TOTAL uint8 225 FRAG_ID uint8 226 SIZE uint16 227 ADDR Address 228 DATA []byte 229 } 230 231 func NewPacket(ASSOC_ID uint16, PKT_ID uint16, FRGA_TOTAL uint8, FRAG_ID uint8, SIZE uint16, ADDR Address, DATA []byte) Packet { 232 return Packet{ 233 CommandHead: NewCommandHead(PacketType), 234 ASSOC_ID: ASSOC_ID, 235 PKT_ID: PKT_ID, 236 FRAG_ID: FRAG_ID, 237 FRAG_TOTAL: FRGA_TOTAL, 238 SIZE: SIZE, 239 ADDR: ADDR, 240 DATA: DATA, 241 } 242 } 243 244 func ReadPacketWithHead(head CommandHead, reader BufferedReader) (c Packet, err error) { 245 c.CommandHead = head 246 if c.CommandHead.TYPE != PacketType { 247 err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE) 248 return 249 } 250 err = binary.Read(reader, binary.BigEndian, &c.ASSOC_ID) 251 if err != nil { 252 return 253 } 254 err = binary.Read(reader, binary.BigEndian, &c.PKT_ID) 255 if err != nil { 256 return 257 } 258 err = binary.Read(reader, binary.BigEndian, &c.FRAG_TOTAL) 259 if err != nil { 260 return 261 } 262 err = binary.Read(reader, binary.BigEndian, &c.FRAG_ID) 263 if err != nil { 264 return 265 } 266 err = binary.Read(reader, binary.BigEndian, &c.SIZE) 267 if err != nil { 268 return 269 } 270 c.ADDR, err = ReadAddress(reader) 271 if err != nil { 272 return 273 } 274 c.DATA = make([]byte, c.SIZE) 275 _, err = io.ReadFull(reader, c.DATA) 276 if err != nil { 277 return 278 } 279 return 280 } 281 282 func ReadPacket(reader BufferedReader) (c Packet, err error) { 283 head, err := ReadCommandHead(reader) 284 if err != nil { 285 return 286 } 287 return ReadPacketWithHead(head, reader) 288 } 289 290 func (c Packet) WriteTo(writer BufferedWriter) (err error) { 291 err = c.CommandHead.WriteTo(writer) 292 if err != nil { 293 return 294 } 295 err = binary.Write(writer, binary.BigEndian, c.ASSOC_ID) 296 if err != nil { 297 return 298 } 299 err = binary.Write(writer, binary.BigEndian, c.PKT_ID) 300 if err != nil { 301 return 302 } 303 err = binary.Write(writer, binary.BigEndian, c.FRAG_TOTAL) 304 if err != nil { 305 return 306 } 307 err = binary.Write(writer, binary.BigEndian, c.FRAG_ID) 308 if err != nil { 309 return 310 } 311 err = binary.Write(writer, binary.BigEndian, c.SIZE) 312 if err != nil { 313 return 314 } 315 err = c.ADDR.WriteTo(writer) 316 if err != nil { 317 return 318 } 319 _, err = writer.Write(c.DATA) 320 if err != nil { 321 return 322 } 323 return 324 } 325 326 func (c Packet) BytesLen() int { 327 return c.CommandHead.BytesLen() + 4 + 2 + c.ADDR.BytesLen() + len(c.DATA) 328 } 329 330 var PacketOverHead = NewPacket(0, 0, 0, 0, 0, NewAddressAddrPort(netip.AddrPortFrom(netip.IPv6Unspecified(), 0)), nil).BytesLen() 331 332 type Dissociate struct { 333 CommandHead 334 ASSOC_ID uint16 335 } 336 337 func NewDissociate(ASSOC_ID uint16) Dissociate { 338 return Dissociate{ 339 CommandHead: NewCommandHead(DissociateType), 340 ASSOC_ID: ASSOC_ID, 341 } 342 } 343 344 func ReadDissociateWithHead(head CommandHead, reader BufferedReader) (c Dissociate, err error) { 345 c.CommandHead = head 346 if c.CommandHead.TYPE != DissociateType { 347 err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE) 348 return 349 } 350 err = binary.Read(reader, binary.BigEndian, &c.ASSOC_ID) 351 if err != nil { 352 return 353 } 354 return 355 } 356 357 func ReadDissociate(reader BufferedReader) (c Dissociate, err error) { 358 head, err := ReadCommandHead(reader) 359 if err != nil { 360 return 361 } 362 return ReadDissociateWithHead(head, reader) 363 } 364 365 func (c Dissociate) WriteTo(writer BufferedWriter) (err error) { 366 err = c.CommandHead.WriteTo(writer) 367 if err != nil { 368 return 369 } 370 err = binary.Write(writer, binary.BigEndian, c.ASSOC_ID) 371 if err != nil { 372 return 373 } 374 return 375 } 376 377 func (c Dissociate) BytesLen() int { 378 return c.CommandHead.BytesLen() + 4 379 } 380 381 type Heartbeat struct { 382 CommandHead 383 } 384 385 func NewHeartbeat() Heartbeat { 386 return Heartbeat{ 387 CommandHead: NewCommandHead(HeartbeatType), 388 } 389 } 390 391 func ReadHeartbeatWithHead(head CommandHead, reader BufferedReader) (c Heartbeat, err error) { 392 c.CommandHead = head 393 if c.CommandHead.TYPE != HeartbeatType { 394 err = fmt.Errorf("error command type: %s", c.CommandHead.TYPE) 395 return 396 } 397 return 398 } 399 400 func ReadHeartbeat(reader BufferedReader) (c Heartbeat, err error) { 401 head, err := ReadCommandHead(reader) 402 if err != nil { 403 return 404 } 405 return ReadHeartbeatWithHead(head, reader) 406 } 407 408 // Addr types 409 const ( 410 AtypDomainName byte = 0 411 AtypIPv4 byte = 1 412 AtypIPv6 byte = 2 413 AtypNone byte = 255 // Address type None is used in Packet commands that is not the first fragment of a UDP packet. 414 ) 415 416 type Address struct { 417 TYPE byte 418 ADDR []byte 419 PORT uint16 420 } 421 422 func NewAddress(metadata *C.Metadata) Address { 423 var addrType byte 424 var addr []byte 425 switch metadata.AddrType() { 426 case socks5.AtypIPv4: 427 addrType = AtypIPv4 428 addr = metadata.DstIP.AsSlice() 429 case socks5.AtypIPv6: 430 addrType = AtypIPv6 431 addr = metadata.DstIP.AsSlice() 432 case socks5.AtypDomainName: 433 addrType = AtypDomainName 434 addr = make([]byte, len(metadata.Host)+1) 435 addr[0] = byte(len(metadata.Host)) 436 copy(addr[1:], metadata.Host) 437 } 438 439 return Address{ 440 TYPE: addrType, 441 ADDR: addr, 442 PORT: metadata.DstPort, 443 } 444 } 445 446 func NewAddressNetAddr(addr net.Addr) (Address, error) { 447 if addr, ok := addr.(interface{ AddrPort() netip.AddrPort }); ok { 448 if addrPort := addr.AddrPort(); addrPort.IsValid() { // sing's M.Socksaddr maybe return an invalid AddrPort if it's a DomainName 449 return NewAddressAddrPort(addrPort), nil 450 } 451 } 452 addrStr := addr.String() 453 if addrPort, err := netip.ParseAddrPort(addrStr); err == nil { 454 return NewAddressAddrPort(addrPort), nil 455 } 456 metadata := &C.Metadata{} 457 if err := metadata.SetRemoteAddress(addrStr); err != nil { 458 return Address{}, err 459 } 460 return NewAddress(metadata), nil 461 } 462 463 func NewAddressAddrPort(addrPort netip.AddrPort) Address { 464 var addrType byte 465 port := addrPort.Port() 466 addr := addrPort.Addr().Unmap() 467 if addr.Is4() { 468 addrType = AtypIPv4 469 } else { 470 addrType = AtypIPv6 471 } 472 return Address{ 473 TYPE: addrType, 474 ADDR: addr.AsSlice(), 475 PORT: port, 476 } 477 } 478 479 func ReadAddress(reader BufferedReader) (c Address, err error) { 480 c.TYPE, err = reader.ReadByte() 481 if err != nil { 482 return 483 } 484 switch c.TYPE { 485 case AtypIPv4: 486 c.ADDR = make([]byte, net.IPv4len) 487 _, err = io.ReadFull(reader, c.ADDR) 488 if err != nil { 489 return 490 } 491 case AtypIPv6: 492 c.ADDR = make([]byte, net.IPv6len) 493 _, err = io.ReadFull(reader, c.ADDR) 494 if err != nil { 495 return 496 } 497 case AtypDomainName: 498 var addrLen byte 499 addrLen, err = reader.ReadByte() 500 if err != nil { 501 return 502 } 503 c.ADDR = make([]byte, addrLen+1) 504 c.ADDR[0] = addrLen 505 _, err = io.ReadFull(reader, c.ADDR[1:]) 506 if err != nil { 507 return 508 } 509 } 510 511 if c.TYPE == AtypNone { 512 return 513 } 514 err = binary.Read(reader, binary.BigEndian, &c.PORT) 515 if err != nil { 516 return 517 } 518 return 519 } 520 521 func (c Address) WriteTo(writer BufferedWriter) (err error) { 522 err = writer.WriteByte(c.TYPE) 523 if err != nil { 524 return 525 } 526 if c.TYPE == AtypNone { 527 return 528 } 529 _, err = writer.Write(c.ADDR[:]) 530 if err != nil { 531 return 532 } 533 err = binary.Write(writer, binary.BigEndian, c.PORT) 534 if err != nil { 535 return 536 } 537 return 538 } 539 540 func (c Address) String() string { 541 switch c.TYPE { 542 case AtypDomainName: 543 return net.JoinHostPort(string(c.ADDR[1:]), strconv.Itoa(int(c.PORT))) 544 default: 545 addr, _ := netip.AddrFromSlice(c.ADDR) 546 addrPort := netip.AddrPortFrom(addr, c.PORT) 547 return addrPort.String() 548 } 549 } 550 551 func (c Address) SocksAddr() socks5.Addr { 552 addr := make([]byte, 1+len(c.ADDR)+2) 553 switch c.TYPE { 554 case AtypIPv4: 555 addr[0] = socks5.AtypIPv4 556 case AtypIPv6: 557 addr[0] = socks5.AtypIPv6 558 case AtypDomainName: 559 addr[0] = socks5.AtypDomainName 560 } 561 copy(addr[1:], c.ADDR) 562 binary.BigEndian.PutUint16(addr[len(addr)-2:], c.PORT) 563 return addr 564 } 565 566 func (c Address) UDPAddr() *net.UDPAddr { 567 return &net.UDPAddr{ 568 IP: c.ADDR, 569 Port: int(c.PORT), 570 Zone: "", 571 } 572 } 573 574 func (c Address) BytesLen() int { 575 return 1 + len(c.ADDR) + 2 576 } 577 578 const ( 579 ProtocolError = quic.ApplicationErrorCode(0xfffffff0) 580 AuthenticationFailed = quic.ApplicationErrorCode(0xfffffff1) 581 AuthenticationTimeout = quic.ApplicationErrorCode(0xfffffff2) 582 BadCommand = quic.ApplicationErrorCode(0xfffffff3) 583 )