Wireshark-dev: [Wireshark-dev] Possible bug in udpdump TLVs header parsing
From: Jeff Walter <jeff@xxxxxxxxxx>
Date: Thu, 7 Mar 2024 19:19:29 -0600
Hello, I’m running the g3-proxy from bytedance and am streaming their udpdump to Wireshark for debugging. In Wireshark, both the exported_pdu src and dest ips are being reported as 127.0.0.1. I wrote a little script to decode the exported_pdu data and am seeing the real ips in my code. Here is their github repo: https://github.com/bytedance/g3/blob/master/g3proxy/README.md Here is their doc for setting up the udpdump in Wireshark: https://github.com/bytedance/g3/blob/master/g3proxy/doc/protocol/setup/wireshark_udpdump.rst I’m pretty convinced this is a bug in the Wireshark exported_pdu dissector code, but I’m not setup to really debug it: https://github.com/wireshark/wireshark/blob/master/epan/dissectors/packet-exported_pdu.c Please let me know if/how I can make the issue clearer for you guys. Thanks, P.S. Here are some screenshots to illustrate what I’m seeing: Here’s a Wireshark screenshot: Here’s a screenshot of my script: Here’s my hacky code (in Go) that produced the above output: package main import ( "encoding/binary" "fmt" "log" "net" "strings" "github.com/google/gopacket" "github.com/google/gopacket/layers" "github.com/google/gopacket/pcap" ) const ( EXP_PDU_TAG_END_OF_OPT = 0 EXP_PDU_TAG_DISSECTOR_NAME = 12 EXP_PDU_TAG_DISSECTOR_TABLE_NAME = 14 EXP_PDU_TAG_IPV4_SRC = 20 EXP_PDU_TAG_IPV4_DST = 21 EXP_PDU_TAG_PORT_TYPE = 24 EXP_PDU_TAG_SRC_PORT = 25 EXP_PDU_TAG_DST_PORT = 26 EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL = 32 EXP_PDU_TAG_TCP_INFO_DATA = 34 EXP_PDU_TAG_USER_DATA_PDU = 37 ) // TCPInfo represents the structure of the TCP info data as described. type TCPInfo struct { Version uint16 Seq uint32 Nxtseq uint32 Lastackseq uint32 IsReassembled uint8 Flags uint16 UrgentPointer uint16 } // decodeTCPInfoData takes a byte slice and attempts to decode it into a TCPInfo struct. func decodeTCPInfoData(data []byte) (*TCPInfo, error) { // Ensure the data slice contains enough bytes to decode the complete structure. if len(data) < 17 { // 2 + 4 + 4 + 4 + 1 + 2 + 2 = 17 bytes return nil, fmt.Errorf("data slice is too short to contain TCP info data") } tcpInfo := &TCPInfo{ Version: binary.BigEndian.Uint16(data[:2]), Seq: binary.BigEndian.Uint32(data[2:6]), Nxtseq: binary.BigEndian.Uint32(data[6:10]), Lastackseq: binary.BigEndian.Uint32(data[10:14]), IsReassembled: data[14], Flags: binary.BigEndian.Uint16(data[15:17]), UrgentPointer: binary.BigEndian.Uint16(data[17:19]), } return tcpInfo, nil } func hexToASCII(data []byte) string { var ascii strings.Builder for _, b := range data { if b >= 32 && b <= 126 { // printable ASCII range ascii.WriteByte(b) } else if b == 0 { continue // skip null bytes } else { ascii.WriteString(fmt.Sprintf("\\x%02x", b)) } } return ascii.String() } func toIP(data []byte) string { if len(data) == 4 { return net.IP(data).String() } return "" } // portTypeToString maps the integer port type value to its corresponding string representation. func portTypeToString(portType int) string { switch portType { case 0: return "None" case 1: return "SCTP" case 2: return "TCP" case 3: return "UDP" case 4: return "DCCP" case 5: return "IPX" case 6: return "NCP" case 7: return "EXCHG" case 8: return "DDP" case 9: return "SBCCS" case 10: return "IDP" case 11: return "TIPC" case 12: return "USB" case 13: return "I2C" case 14: return "IBQP" case 15: return "BLUETOOTH" case 16: return "TDMOP" case 17: return "IWARP_MPA" case 18: return "MCTP" default: return "Unknown" } } func main() { device := "lo0" snapshotLen := int32(1024) promiscuous := true timeout := pcap.BlockForever handle, err := pcap.OpenLive(device, snapshotLen, promiscuous, timeout) if err != nil { log.Fatal(err) } defer handle.Close() if err := handle.SetBPFFilter("udp and port 5555"); err != nil { log.Fatal(err) } packetSource := gopacket.NewPacketSource(handle, handle.LinkType()) for { endOfOptions := false Loop: for packet := range packetSource.Packets() { udpLayer := packet.Layer(layers.LayerTypeUDP) if udpLayer != nil { udp, _ := udpLayer.(*layers.UDP) payload := udp.Payload cursor := 0 for cursor < len(payload) { if cursor+4 > len(payload) { fmt.Println("Malformed packet or insufficient data for TLV length") break Loop } tlvType := binary.BigEndian.Uint16(payload[cursor : cursor+2]) tlvLength := binary.BigEndian.Uint16(payload[cursor+2 : cursor+4]) cursor += 4 if cursor+int(tlvLength) > len(payload) { fmt.Println("Malformed packet or insufficient data for TLV length") break Loop } tlvValue := payload[cursor : cursor+int(tlvLength)] cursor += int(tlvLength) if endOfOptions { // fmt.Printf("Data: %s\n", payload[cursor:]) continue } switch tlvType { case EXP_PDU_TAG_END_OF_OPT: fmt.Println("***** End of options *****") endOfOptions = true // Exit loop at the end of options TLV case EXP_PDU_TAG_DISSECTOR_NAME: fmt.Printf("Protocol: %s\n", tlvValue) case EXP_PDU_TAG_DISSECTOR_TABLE_NAME: fmt.Printf("Dissector Table Name: %s\n", tlvValue) case EXP_PDU_TAG_IPV4_SRC: fmt.Printf("Source IP Address: %s\n", toIP(tlvValue)) case EXP_PDU_TAG_IPV4_DST: fmt.Printf("Destination IP Address: %s\n", toIP(tlvValue)) case EXP_PDU_TAG_PORT_TYPE: portType := int(binary.BigEndian.Uint32(tlvValue)) fmt.Printf("Port Type: %s\n", portTypeToString(portType)) case EXP_PDU_TAG_SRC_PORT: fmt.Printf("Source Port: %d\n", binary.BigEndian.Uint32(tlvValue)) case EXP_PDU_TAG_DST_PORT: fmt.Printf("Destination Port: %d\n", binary.BigEndian.Uint32(tlvValue)) case EXP_PDU_TAG_DISSECTOR_TABLE_NAME_NUM_VAL: fmt.Printf("Dissector Table Name Num Val: %s\n", hexToASCII(tlvValue)) case EXP_PDU_TAG_TCP_INFO_DATA: tcpInfo, err := decodeTCPInfoData(tlvValue) if err != nil { fmt.Println("Error decoding TCP info data:", err) break Loop } fmt.Println("TCP Info Data:") fmt.Printf("Version: %d\n", tcpInfo.Version) fmt.Printf("Seq: %d\n", tcpInfo.Seq) fmt.Printf("Nxtseq: %d\n", tcpInfo.Nxtseq) fmt.Printf("Lastackseq: %d\n", tcpInfo.Lastackseq) fmt.Printf("IsReassembled: %d\n", tcpInfo.IsReassembled) fmt.Printf("Flags: %d\n", tcpInfo.Flags) fmt.Printf("UrgentPointer: %d\n", tcpInfo.UrgentPointer) case EXP_PDU_TAG_USER_DATA_PDU: fmt.Printf("Data: %s\n", hexToASCII(tlvValue)) default: fmt.Printf("Unknown TLV Type %d, ASCII Value: %s\n", tlvType, hexToASCII(tlvValue)) } } } } } } |
- Next by Date: [Wireshark-dev] Running test_tls13_rfc8446 manually
- Next by thread: [Wireshark-dev] Running test_tls13_rfc8446 manually
- Index(es):