udp.go 3.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123
  1. package packetparse
  2. import (
  3. "github.com/google/gopacket"
  4. "github.com/google/gopacket/layers"
  5. "github.com/v2fly/v2ray-core/v5/common/net"
  6. )
  7. var (
  8. errNotIPPacket = newError("not an IP packet")
  9. errNotUDPPacket = newError("not a UDP packet")
  10. )
  11. var nullDestination = net.UnixDestination(net.DomainAddress("null"))
  12. func TryParseAsUDPPacket(packet []byte) (src, dst net.Destination, data []byte, err error) {
  13. parsedPacket := gopacket.NewPacket(packet, layers.LayerTypeIPv4, gopacket.DecodeOptions{
  14. Lazy: true,
  15. NoCopy: false,
  16. SkipDecodeRecovery: false,
  17. DecodeStreamsAsDatagrams: false,
  18. })
  19. var srcIP net.Address
  20. var dstIP net.Address
  21. ipv4Layer := parsedPacket.Layer(layers.LayerTypeIPv4)
  22. if ipv4Layer == nil {
  23. parsedPacketAsIPv6 := gopacket.NewPacket(packet, layers.LayerTypeIPv6, gopacket.DecodeOptions{
  24. Lazy: true,
  25. NoCopy: false,
  26. SkipDecodeRecovery: false,
  27. DecodeStreamsAsDatagrams: false,
  28. })
  29. ipv6Layer := parsedPacketAsIPv6.Layer(layers.LayerTypeIPv6)
  30. if ipv6Layer == nil {
  31. return nullDestination, nullDestination, nil, errNotIPPacket
  32. }
  33. ipv6 := ipv6Layer.(*layers.IPv6)
  34. srcIP = net.IPAddress(ipv6.SrcIP)
  35. dstIP = net.IPAddress(ipv6.DstIP)
  36. parsedPacket = parsedPacketAsIPv6
  37. } else {
  38. ipv4 := ipv4Layer.(*layers.IPv4)
  39. srcIP = net.IPAddress(ipv4.SrcIP)
  40. dstIP = net.IPAddress(ipv4.DstIP)
  41. }
  42. udpLayer := parsedPacket.Layer(layers.LayerTypeUDP)
  43. if udpLayer == nil {
  44. return nullDestination, nullDestination, nil, errNotUDPPacket
  45. }
  46. udp := udpLayer.(*layers.UDP)
  47. srcPort := net.Port(udp.SrcPort)
  48. dstPort := net.Port(udp.DstPort)
  49. src = net.UDPDestination(srcIP, srcPort)
  50. dst = net.UDPDestination(dstIP, dstPort)
  51. data = udp.Payload
  52. return // nolint: nakedret
  53. }
  54. func TryConstructUDPPacket(src, dst net.Destination, data []byte) ([]byte, error) {
  55. if src.Address.Family().IsIPv4() && dst.Address.Family().IsIPv4() {
  56. return constructIPv4UDPPacket(src, dst, data)
  57. }
  58. if src.Address.Family().IsIPv6() && dst.Address.Family().IsIPv6() {
  59. return constructIPv6UDPPacket(src, dst, data)
  60. }
  61. return nil, newError("not supported")
  62. }
  63. func constructIPv4UDPPacket(src, dst net.Destination, data []byte) ([]byte, error) {
  64. ipv4 := &layers.IPv4{
  65. Version: 4,
  66. Protocol: layers.IPProtocolUDP,
  67. SrcIP: src.Address.IP(),
  68. DstIP: dst.Address.IP(),
  69. }
  70. udp := &layers.UDP{
  71. SrcPort: layers.UDPPort(src.Port),
  72. DstPort: layers.UDPPort(dst.Port),
  73. }
  74. err := udp.SetNetworkLayerForChecksum(ipv4)
  75. if err != nil {
  76. return nil, err
  77. }
  78. buffer := gopacket.NewSerializeBuffer()
  79. if err := gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{
  80. FixLengths: true,
  81. ComputeChecksums: true,
  82. }, ipv4, udp, gopacket.Payload(data)); err != nil {
  83. return nil, err
  84. }
  85. return buffer.Bytes(), nil
  86. }
  87. func constructIPv6UDPPacket(src, dst net.Destination, data []byte) ([]byte, error) {
  88. ipv6 := &layers.IPv6{
  89. Version: 6,
  90. NextHeader: layers.IPProtocolUDP,
  91. SrcIP: src.Address.IP(),
  92. DstIP: dst.Address.IP(),
  93. }
  94. udp := &layers.UDP{
  95. SrcPort: layers.UDPPort(src.Port),
  96. DstPort: layers.UDPPort(dst.Port),
  97. }
  98. err := udp.SetNetworkLayerForChecksum(ipv6)
  99. if err != nil {
  100. return nil, err
  101. }
  102. buffer := gopacket.NewSerializeBuffer()
  103. if err := gopacket.SerializeLayers(buffer, gopacket.SerializeOptions{
  104. FixLengths: true,
  105. ComputeChecksums: true,
  106. }, ipv6, udp, gopacket.Payload(data)); err != nil {
  107. return nil, err
  108. }
  109. return buffer.Bytes(), nil
  110. }