Computing Checksum from UDP Header in AWS with tcpdump: In order to compute the checksum properly using tcpdump you may need to disable the hardware offloading of the checksum computation. If the hardware is doing the checksum computation, then when transmitting a udp segment tcpdump will intercept the udp segment BEFORE the segment's checksum is computed by the network interface card hardware. You can check if this is happening with this command: sudo ethtool -k lo | grep checksumming Here we are asking what the status of checksum offloading is for the "lo" or loopback/localhost interface. You'll see output that looks like this: rx-checksumming: on [fixed] tx-checksumming: on In this case checksum offloading turned on. Unfortunately, recent version of AWS do not allow you to turn off checksum offloading... SO that means that the udp checksum field displayed by tcpdump will be incorrect. Keep this in mind when you are computing your udp checksum. Use the project at: http://web.stonehill.edu/compsci/cs390/udpclientserver.tar Use this command to capture udp segments sent from client -> server: sudo tcpdump -X -vvv -nn -i eth0 udp port 8800 Thanks to the following url for info on this process: https://sokratisg.net/2012/04/01/udp-tcp-checksum-errors-from-tcpdump-nic-hardware-offloading/ The output will look like this (assuming client/server on same machine). NOTE this output is from an earlier AWS machine that allowed me to turn off checksum offloading so the checksum value is correct. tcpdump: listening on eth0, link-type EN10MB (Ethernet), capture size 65535 bytes 21:24:05.391990 IP (tos 0x0, ttl 64, id 0, offset 0, flags [DF], proto UDP (17), length 33) 172.31.4.207.47509 > 52.36.117.95.8800: [udp sum ok] UDP, length 5 0x0000: 4500 0021 0000 4000 4011 e05a ac1f 04cf E..!..@.@..Z.... 0x0010: 3424 755f b995 2260 000d 859a 6865 6c6c 4$u_.."`....hell 0x0020: 6f o 21:24:05.392180 IP (tos 0x0, ttl 63, id 0, offset 0, flags [DF], proto UDP (17), length 33) 52.36.117.95.47509 > 172.31.4.207.8800: [udp sum ok] UDP, length 5 0x0000: 4500 0021 0000 4000 3f11 e15a 3424 755f E..!..@.?..Z4$u_ 0x0010: ac1f 04cf b995 2260 000d 859a 6865 6c6c ......"`....hell 0x0020: 6f o Let's break the first UDP segment down into it's components and see if the checksum is correct, the UDP segment is inside of the payload of an IPv4 packet, and that's what tcpdump has captured: IPv4 Header +-----------------------------------+-----------------------------------+ | | | | | | | | | |Version |IHL |Type of Service |Total Length | |4x |5x |00x |0021x | +-----------------------------------+-----------------------------------+ |Identification |Flg|Fragment Offset | |0000x |010b|0000x | +-----------------------------------+-----------------------------------+ |Time to Live |Protocol |Header Checksum | |40x |11x |e05ax | +-----------------------------------+-----------------------------------+ |Source Address | |ac1f 04cfx (172.31.4.207) | +-----------------------------------+-----------------------------------+ |Destination Address | |3424 755fx (52.36.117.95) | +-----------------------------------+-----------------------------------+ Because the IHL is 5, that means IPv4 header length is 5 32 bit words so there is no IP Option. Next up is the UDP Header & data +-----------------------------------+-----------------------------------+ | | | | | | | | | | Source Port | Destination Port | |b995x | 2260x | |-----------------------------------+-----------------------------------+ |Length | Checksum | |000dx | 859ax | +-----------------------------------+-----------------------------------+ |Data | |6865 6c6cx | +-----------------------------------------------------------------------+ |6fx | +-----------------------------------------------------------------------+ Now the UDP pseudo-header (this doesn't exist but we construct it to compute the checksum): +-----------------------------------+-----------------------------------+ | | | | | | | | | |Source Address | |ac1f 04cfx | +-----------------------------------+-----------------------------------+ |Destination Address | |3424 755fx | +-----------------------------------+-----------------------------------+ |Reserved |Protocol |UDP Length | |00x |11x |00dx | +-----------------------------------+-----------------------------------+ UDP pseudo-header with UDP in 16 bit words to compute checksum: ac 1f 1010 1100 0001 1111 04 cf 0000 0100 1100 1111 34 24 0011 0100 0010 0100 75 5f 0111 0101 0101 1111 00 11 0000 0000 0001 0001 00 0d 0000 0000 0000 1101 b9 95 1100 1001 1001 0011 22 60 0010 0010 0110 0000 00 0d 0000 0000 0000 1101 00 00 <- set checksum to 0 0000 0000 0000 0000 68 65 0110 1000 0110 0101 6c 6c 0110 1100 0110 1100 6f 00 <- pad xtra byte 0110 1111 0000 0000 Now do the addition in pairs showing the carry, we can do this by adding up individual binary numbers, or we can add the hexadecimal numbers in a spreadsheet, take the final sum and strip off anything higher than 16 bits and add this to the beginning of the final sum. If there is an overflow again, repeat the process until there's no overflow: ------------ Data Sum ------------ ac1f AC1F 04cf B0EE 3424 E512 755f 15A71 0011 15A82 000d 15A8F b995 21424 2260 23684 000d 23691 0000 23691 6865 29EF6 6c6c 30B62 6f00 37A62 7a65 <- overflow add (+3 to beginning of sum) FFFF -7a65 <- subtract from FFFF to get complement ---- 859A <- computed checksum this is the checksum computed by the UDP transport layer segment intercepted by tcpdump