In our application, we are using apache tomcat webserver running in 8081.
We observed one behavior where HTTP POST Requests from clients are getting fragmented whereas HTTP Response "200 OK" is not getting fragmented. This we observed by collecting iptraces.
Our ETH MTU value is 1500 Bytes.
Sample POST Request which is fragmented:
===( 331 bytes received on interface en0 )==== 13:50:01.040393849
ETHERNET packet : [ 00:26:cb:eb:df:7f -> 00:1a:64:47:3c:02 ] type 800 (IP)
IP header breakdown:
< SRC = 172.30.17.142 >
< DST = 10.16.0.72 > (un51sv01_if0)
ip_v=4, ip_hl=20, ip_tos=0, ip_len=317, ip_id=57225, ip_off=0 DF
ip_ttl=62, ip_sum=942d, ip_p = 6 (TCP)
TCP header breakdown:
<source port=43795, destination port=8081 >
th_seq=2849969884, th_ack=3790782429
th_off=5, flags<PUSH | ACK>
th_win=49680, th_sum=ba63, th_urp=0
00000000 504f5354 202f6973 61736f61 702f656e |POST /isasoap/en|
00000010 64706f69 6e742f49 6e766f6b 65417070 |dpoint/InvokeApp|
00000020 53657276 69636549 46204854 54502f31 |ServiceIF HTTP/1|
00000030 2e310d0a 436f6e74 656e742d 54797065 |.1..Content-Type|
00000040 3a207465 78742f78 6d6c3b20 63686172 |: text/xml; char|
00000050 7365743d 7574662d 380d0a41 63636570 |set=utf-8..Accep|
00000060 743a2074 6578742f 786d6c2c 20746578 |t: text/xml, tex|
00000070 742f6874 6d6c2c20 696d6167 652f6769 |t/html, image/gi|
00000080 662c2069 6d616765 2f6a7065 672c202a |f, image/jpeg, *|
00000090 3b20713d 2e322c20 2a2f2a3b 20713d2e |; q=.2, */*; q=.|
000000a0 320d0a53 4f415041 6374696f 6e3a2022 |2..SOAPAction: "|
000000b0 220d0a55 7365722d 4167656e 743a204a |"..User-Agent: J|
000000c0 6176612f 312e362e 305f3831 0d0a486f |ava/1.6.0_81..Ho|
000000d0 73743a20 31302e31 362e302e 37323a38 |st: 10.16.0.72:8|
000000e0 3038310d 0a436f6e 6e656374 696f6e3a |081..Connection:|
000000f0 206b6565 702d616c 6976650d 0a436f6e | keep-alive..Con|
00000100 74656e74 2d4c656e 6774683a 20333634 |tent-Length: 364|
00000110 390d0a0d 0a |9.... |
Now the fragmented second packet start:
====( 1434 bytes received on interface en0 )==== 13:50:01.040697474
ETHERNET packet : [ 00:26:cb:eb:df:7f -> 00:1a:64:47:3c:02 ] type 800 (IP)
IP header breakdown:
< SRC = 172.30.17.142 >
< DST = 10.16.0.72 > (un51sv01_if0)
ip_v=4, ip_hl=20, ip_tos=0, ip_len=1420, ip_id=57227, ip_off=0 DF
ip_ttl=62, ip_sum=8fdc, ip_p = 6 (TCP)
TCP header breakdown:
<source port=43795, destination port=8081 >
th_seq=2849970161, th_ack=3790782429
th_off=5, flags<ACK>
th_win=49680, th_sum=f8e9, th_urp=0
00000000 3c3f786d 6c207665 7273696f 6e3d2231 |<?xml version="1|
00000010 2e302220 656e636f 64696e67 3d225554 |.0" encoding="UT|
00000020 462d3822 3f3e0a3c 656e763a 456e7665 |F-8"?>.<env:Enve|
00000030 6c6f7065 20786d6c 6e733a65 6e763d22 |lope xmlns:env="|
00000040 68747470 3a2f2f73 6368656d 61732e78 |http://schemas.x|
00000050 6d6c736f 61702e6f 72672f73 6f61702f |mlsoap.org/soap/|
00000060 656e7665 6c6f7065 2f222078 6d6c6e73 |envelope/" xmlns|
00000070 3a787364 3d226874 74703a2f 2f777777 |:xsd="http://www|
00000080 2e77332e 6f72672f 32303031 2f584d4c |.w3.org/2001/XML|
00000090 53636865 6d612220 786d6c6e 733a7873 |Schema" xmlns:xs|
Similar to above, there is another packet.
Now the Final packet of ~950 Octets:
====( 943 bytes received on interface en0 )==== 13:50:01.040713619
ETHERNET packet : [ 00:26:cb:eb:df:7f -> 00:1a:64:47:3c:02 ] type 800 (IP)
IP header breakdown:
< SRC = 172.30.17.142 >
< DST = 10.16.0.72 > (un51sv01_if0)
ip_v=4, ip_hl=20, ip_tos=0, ip_len=929, ip_id=57229, ip_off=0 DF
ip_ttl=62, ip_sum=91c5, ip_p = 6 (TCP)
TCP header breakdown:
<source port=43795, destination port=8081 >
th_seq=2849972921, th_ack=3790782429
th_off=5, flags<PUSH | ACK>
th_win=49680, th_sum=32ac, th_urp=0
00000000 74612069 643d2249 44313122 20787369 |ta id="ID11" xsi|
00000010 3a747970 653d226e 73313a49 6e766f6b |:type="ns1:Invok|
00000020 65417070 44617461 223e3c64 61746154 |eAppData"><dataT|
.....
After some internal processing by our application, we send 200 OK and HTTP Response.
HTTP 200 OK Response
====( 3209 bytes transmitted on interface en0 )==== 13:50:01.041804849
ETHERNET packet : [ 00:1a:64:47:3c:02 -> 00:00:0c:07:ac:32 ] type 800 (IP)
IP header breakdown:
< SRC = 10.16.0.72 > (un51sv01_if0)
< DST = 172.30.17.142 >
ip_v=4, ip_hl=20, ip_tos=0, ip_len=3195, ip_id=60324, ip_off=0
ip_ttl=60, ip_sum=ffff, ip_p = 6 (TCP)
TCP header breakdown:
<source port=8081, destination port=43574 >
th_seq=3486085705, th_ack=3771812741
th_off=5, flags<PUSH | ACK>
th_win=65535, th_sum=564, th_urp=0
00000000 48545450 2f312e31 20323030 204f4b0d |HTTP/1.1 200 OK.|
00000010 0a416363 6570743a 20746578 742f786d |.Accept: text/xm|
00000020 6c2c2074 6578742f 68746d6c 2c20696d |l, text/html, im|
00000030 6167652f 6769662c 20696d61 67652f6a |age/gif, image/j|
00000040 7065672c 202a3b20 713d2e32 2c202a2f |peg, *; q=.2, */|
00000050 2a3b2071 3d2e320d 0a436f6e 74656e74 |*; q=.2..Content|
Please note from above that the length of packet received on en0 is "3209" for 200 OK HTTP Response which is actually the entire Response. But it is exceeding MTU of ethernet...
Our MTU value is default - 1500 bytes
un51sv01# lsattr -El en0 |grep mtu
mtu 1500 Maximum IP Packet Size for This Device True
Can somebody throw light into why it is happening this way?
Change / Show Characteristics of an Ethernet Adapter
Type or select values in entry fields.
Press Enter AFTER making all desired changes.
[Entry Fields]
Ethernet Adapter ent0
Description Logical Host Ethernet Port (lp-hea)
Status Available
Location
Request Transmit and Receive Jumbo Frames no +
Enable hardware Transmit TCP segmentation yes +
Enable receive TCP segment aggregation yes +
Enable hardware Transmit checksum yes +
Enable hardware Receive checksum yes +
Requested media speed Auto_Negotiation +
Enable ALTERNATE ETHERNET address no +
ALTERNATE ETHERNET address [0x000000000000] +
Apply change to DATABASE only no +
The above indicate Jumbo Frames are not enabled.
Thanks,
Sashi
Related
I'm trying to send a udp packet with scapy to the all the devices in my network with raw data: (hello everyone)
The packet looks like this:
packet = Ether(dst="ff:ff:ff:ff:ff:ff") / IP(dst="255.255.255.0") / UDP(sport=8118) / "hello everyone"
packet.show()
###[ Ethernet ]###
dst = ff:ff:ff:ff:ff:ff
src = (my mac address)
type = IPv4
###[ IP ]###
version = 4
ihl = None
tos = 0x0
len = None
id = 1
flags =
frag = 0
ttl = 64
proto = udp
chksum = None
src = 192.168.0.105
dst = 255.255.255.0
\options \
###[ UDP ]###
sport = 8118
dport = domain
len = None
chksum = None
###[ Raw ]###
load = 'hello everyone'
When I send the packet (sendp(packet)), wireshark says this is a malformed DNS packet:
What is the problem?
I believe you're confusing Wireshark, due to you not specifying the destination port. If you don't specify a dport for UDP, it defaults to 53:
class UDP(Packet):
name = "UDP"
fields_desc = [ShortEnumField("sport", 53, UDP_SERVICES),
ShortEnumField("dport", 53, UDP_SERVICES),
ShortField("len", None),
XShortField("chksum", None), ]
Both ports actually do. 53 is for DNS though, so Wireshark is attempting to interpret your payload as DNS based on the port number.
Specify both sport and dport to ensure that your packet isn't misinterpreted as a DNS packet.
I am trying to do a handshake with a server I downloaded from the internet. But when the client receives [SYN, ACK] it sends back a [RST]. Have no idea what is happening. Already checked the acknowledge and sequence number but everything seems ok.
In wireshark I got this:
Here is the handshake client source code:
from scapy.all import *
src_ip = "192.168.43.34"
dst_ip = "192.168.43.115"
src_port = random.randint(1024, 65535)
dst_port = 502
seq_nr = random.randint(444, 8765432)
ack_nr = 0
# Create SYN packet
ip = IP (src = src_ip, dst = dst_ip)
syn = TCP(sport = src_port, dport = dst_port, flags='S', seq = seq_nr, ack = ack_nr)
pkt_syn = ip / syn
pkt_syn.show()
# send SYN packet and receive SYN/ACK packet
print('Sending SYN')
pkt_syn_ack = sr1(pkt_syn)
print('ACK received')
pkt_syn_ack.show()
# Create the ACK packet
ack_nr = pkt_syn_ack.seq + 1
seq_nr = seq_nr + 1
ack = TCP(sport = src_port, dport = dst_port, flags = 'A', seq = seq_nr, ack = ack_nr)
send(ip / ack)
...
The problem is that your OS is receiving the SYN-ACK packet, has no idea why it was sent (as the OS itself didn't start a handshake) and reset the connection.
You can find some solutions here (for Linux)-
Unwanted RST TCP packet with Scapy
Another option is to use a different IP than the OS's, or in Windows turn off the IP stack of the used interface (only if this is the only thing that you use this interface for!)
I am using the gopacket package and every time I have a TCP packet I want to check if the payload contains an HTTP request. Is there an easy way to do that instead of writing my own parser? There is also a function (see: func ReadRequest(b *bufio.Reader)) which returns a Request struct but I do not know what kind of input I should use. tcp.Payload is the byte[] array that seems to have the information I need to parse (see the following example):
// Get the TCP layer from this packet
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
fmt.Printf("TCP ")
// Get actual TCP data from this layer
tcp, _ := tcpLayer.(*layers.TCP)
srcPort = tcp.SrcPort
dstPort = tcp.DstPort
if tcp.SYN {
fmt.Print("[SYN] ")
}
if tcp.ACK {
fmt.Print("[ACK] ")
}
if tcp.FIN {
fmt.Print("[FIN] ")
}
fmt.Printf("%s:%d > %s:%d ", srcIP, srcPort, dstIP, dstPort)
fmt.Println(string(tcp.Payload))
}
After sending an HTTP request I get the following output:
PKT [001] TCP [SYN] 192.168.2.6:59095 > 192.168.3.5:80
PKT [002] TCP [SYN] [ACK] 192.168.3.5:80 > 192.168.2.6:59095
PKT [003] TCP [ACK] 192.168.2.6:59095 > 192.168.3.5:80
PKT [004] TCP [ACK] 192.168.2.6:59095 > 192.168.3.5:80 GET /certificates/test.pdf HTTP/1.1
User-Agent: Wget/1.15 (linux-gnu)
Accept: */*
Host: 192.168.3.5
Connection: Keep-Alive
Any suggestions are welcome...
With help from this question: How to parse http headers in Go the following attempt with http.ReadRequest() works...
if tcpLayer := packet.Layer(layers.LayerTypeTCP); tcpLayer != nil {
tcp, _ := tcpLayer.(*layers.TCP)
if len(tcp.Payload) != 0 {
reader := bufio.NewReader(bytes.NewReader(tcp.Payload))
httpReq, err := http.ReadRequest(reader)
...
}
}
I started to write an application which will read RTP/H.264 video packets from an existing .pcap file, I need to read the packet size.
I tried to use packet->len or header->len, but it never displays the right number of bytes for packets (I'm using wireshark to verify packet size - under Length column). How to do it?
This is part of my code:
while (packet = pcap_next(handle,&header)) {
u_char *pkt_ptr = (u_char *)packet;
struct ip *ip_hdr = (struct ip *)pkt_ptr; //point to an IP header structure
struct pcap_pkthdr *pkt_hdr =(struct pcap_pkthdr *)packet;
unsigned int packet_length = pkt_hdr->len;
unsigned int ip_length = ntohs(ip_hdr->ip_len);
printf("Packet # %i IP Header length: %d bytes, Packet length: %d bytes\n",pkt_counter,ip_length,packet_length);
Packet # 0 IP Header length: 180 bytes, Packet length: 104857664 bytes
Packet # 1 IP Header length: 52 bytes, Packet length: 104857600 bytes
Packet # 2 IP Header length: 100 bytes, Packet length: 104857600 bytes
Packet # 3 IP Header length: 100 bytes, Packet length: 104857664 bytes
Packet # 4 IP Header length: 52 bytes, Packet length: 104857600 bytes
Packet # 5 IP Header length: 100 bytes, Packet length: 104857600 bytes
Another option I tried is to use:
pkt_ptr-> I get:
read_pcapfile.c:67:43: error: request for member ‘len’ in something not a structure or union
while (packet = pcap_next(handle,&header)) {
u_char *pkt_ptr = (u_char *)packet;
Don't do that; you're throwing away the const, and you really should NOT be modifying what the return value of pcap_next() points to.
struct ip *ip_hdr = (struct ip *)pkt_ptr; //point to an IP header structure
That will point to an IP header structure ONLY if pcap_datalink(handle) returns DLT_RAW, which it probably will NOT do on most devices.
If, for example, pcap_datalink(handle) returns DLT_EN10MB, packet will point to an Ethernet header (the 10MB is historical - it's used for all Ethernet speeds other than the ancient historical 3MB experimental Ethernet at Xerox, which had a different header type).
See the list of link-layer header type values for a list of the possible DLT_ types.
struct pcap_pkthdr *pkt_hdr =(struct pcap_pkthdr *)packet;
That won't work, either. The struct pcap_pkthdr for the packet is in header.
unsigned int packet_length = pkt_hdr->len;
As per my earlier comment, that won't work. Use header.len instead.
(And bear in mind that, if a "snapshot length" shorter than the maximum packet size was specified in the pcap_open_live() call, or specified in a pcap_set_snaplen() call between the pcap_create() and pcap_activate() calls, header.caplen could be less than header.len, and only header.caplen bytes of the packet data will actually be available.)
unsigned int ip_length = ntohs(ip_hdr->ip_len);
And, as per my earlier comment, that probably won't work, either.
You should be using header.len.
unsigned int packet_length = header.len;
I need to send a bunch of IP packets that I'm sure will trigger an ICMP TTL-expired error message. How exactly can I associate each error message with the packet that generated it? What field in the ICMP header is used for this?
Should I rather use some custom ID number in the original IP header, so that I can tell which error message corresponds to which packet? If so, which field is most suitable for this?
The body of ICMP TTL Expired messages must include the IP header of the original packet (which includes the source-port / destination-port) and 64 bits beyond the original header.
Based on timing and that header information, you can derive which packet triggered the TTL-expired message.
I am including a sample triggered by an NTP packet below...
See RFC 792 (Page 5) for more details.
ICMP TTL-Expired Message
Ethernet II, Src: JuniperN_c3:a0:00 (b0:c6:9a:c3:a0:00), Dst: 78:2b:cb:37:4c:7a (78:2b:cb:37:4c:7a)
Destination: 78:2b:cb:37:4c:7a (78:2b:cb:37:4c:7a)
Address: 78:2b:cb:37:4c:7a (78:2b:cb:37:4c:7a)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
Source: JuniperN_c3:a0:00 (b0:c6:9a:c3:a0:00)
Address: JuniperN_c3:a0:00 (b0:c6:9a:c3:a0:00)
.... ...0 .... .... .... .... = IG bit: Individual address (unicast)
.... ..0. .... .... .... .... = LG bit: Globally unique address (factory default)
Type: IP (0x0800)
Internet Protocol, Src: 172.25.116.254 (172.25.116.254), Dst: 172.25.116.10 (172.25.116.10)
Version: 4
Header length: 20 bytes
Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
0000 00.. = Differentiated Services Codepoint: Default (0x00)
.... ..0. = ECN-Capable Transport (ECT): 0
.... ...0 = ECN-CE: 0
Total Length: 56
Identification: 0x86d7 (34519)
Flags: 0x02 (Don't Fragment)
0.. = Reserved bit: Not Set
.1. = Don't fragment: Set
..0 = More fragments: Not Set
Fragment offset: 0
Time to live: 255
Protocol: ICMP (0x01)
Header checksum: 0xb3b1 [correct]
[Good: True]
[Bad : False]
Source: 172.25.116.254 (172.25.116.254)
Destination: 172.25.116.10 (172.25.116.10)
Internet Control Message Protocol
Type: 11 (Time-to-live exceeded)
Code: 0 (Time to live exceeded in transit)
Checksum: 0x4613 [correct]
Internet Protocol, Src: 172.25.116.10 (172.25.116.10), Dst: 172.25.0.11 (172.25.0.11)
Version: 4
Header length: 20 bytes
Differentiated Services Field: 0x00 (DSCP 0x00: Default; ECN: 0x00)
0000 00.. = Differentiated Services Codepoint: Default (0x00)
.... ..0. = ECN-Capable Transport (ECT): 0
.... ...0 = ECN-CE: 0
Total Length: 36
Identification: 0x0001 (1)
Flags: 0x00
0.. = Reserved bit: Not Set
.0. = Don't fragment: Not Set
..0 = More fragments: Not Set
Fragment offset: 0
Time to live: 0
[Expert Info (Note/Sequence): "Time To Live" only 0]
[Message: "Time To Live" only 0]
[Severity level: Note]
[Group: Sequence]
Protocol: UDP (0x11)
Header checksum: 0xee80 [correct]
[Good: True]
[Bad : False]
Source: 172.25.116.10 (172.25.116.10)
Destination: 172.25.0.11 (172.25.0.11)
User Datagram Protocol, Src Port: telindus (1728), Dst Port: ntp (123)
Source port: telindus (1728)
Destination port: ntp (123)
Length: 16
Checksum: 0xa7a1 [unchecked, not all data available]
[Good Checksum: False]
[Bad Checksum: False]