|
748 | 748 | "\n", |
749 | 749 | "Examining this structure, we discern that the first 8 bits represent the type, followed by the subsequent 8 bits housing the ICMP code. Notably, the originating IP header of the message that triggered the response is encapsulated within the ICMP message, presenting an opportunity for validation.\n", |
750 | 750 | "\n", |
751 | | - "### Integration of ICMP Decoding\n", |
| 751 | + "#### Integration of ICMP Decoding\n", |
752 | 752 | "\n", |
753 | 753 | "Now, let's seamlessly integrate the decoding of ICMP packets into our existing packet-sniffing framework. The augmentation of our sniffer encompasses the implementation of an ICMP structure beneath the established IP structure. The following code snippet imports necessary modules and initializes the ICMP structure to facilitate the decoding process when ICMP packets are detected.\n", |
754 | 754 | "\n", |
|
1009 | 1009 | "\n", |
1010 | 1010 | "In conclusion, broadening our decoding capabilities beyond ICMP to encompass TCP and UDP marks a pivotal step in comprehending the diverse landscape of network protocols. Each protocol brings its own set of challenges and nuances, and by expanding our analysis toolkit, we empower ourselves to gain a holistic understanding of the complex communication patterns shaping the digital world." |
1011 | 1011 | ] |
| 1012 | + }, |
| 1013 | + { |
| 1014 | + "cell_type": "markdown", |
| 1015 | + "id": "7972e4b1-813d-45bd-bd9a-f741db2d9482", |
| 1016 | + "metadata": {}, |
| 1017 | + "source": [ |
| 1018 | + "### 1.6 Decoding TCP packets\n", |
| 1019 | + "\n", |
| 1020 | + "Decoding TCP packets involves understanding the complexities of the [**Transmission Control Protocol (TCP)**](https://en.wikipedia.org/wiki/Transmission_Control_Protocol), a fundamental protocol in the transport layer of the [**Internet Protocol Suite**](https://en.wikipedia.org/wiki/Internet_protocol_suite). Unlike [**ICMP**](https://en.wikipedia.org/wiki/Internet_Control_Message_Protocol), which is connectionless, TCP provides a reliable, connection-oriented communication channel. Understanding the structure of TCP packets entails parsing the various fields within the TCP header, each conveying essential information about the communication session.\n", |
| 1021 | + "\n", |
| 1022 | + "The TCP header includes crucial components such as the source and destination port numbers, which identify the endpoints of the communication. The sequence and acknowledgment numbers play a pivotal role in ensuring the ordered and reliable delivery of data. Flags within the TCP header signify the nature of the packet, indicating whether it is a data segment, a connection request (SYN), an acknowledgment (ACK), or other control messages. By decoding these flags, we gain insights into the state of the TCP connection and the ongoing communication process.\n", |
| 1023 | + "\n", |
| 1024 | + "> 3.1. Header Format\n", |
| 1025 | + "> \n", |
| 1026 | + "> TCP segments are sent as internet datagrams. The Internet Protocol\n", |
| 1027 | + "> header carries several information fields, including the source and\n", |
| 1028 | + "> destination host addresses [2]. A TCP header follows the internet\n", |
| 1029 | + "> header, supplying information specific to the TCP protocol. This\n", |
| 1030 | + "> division allows for the existence of host level protocols other than\n", |
| 1031 | + "> TCP.\n", |
| 1032 | + "> \n", |
| 1033 | + "> TCP Header Format\n", |
| 1034 | + " \n", |
| 1035 | + " 0 1 2 3 \n", |
| 1036 | + " 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 2 3 4 5 6 7 8 9 0 1 \n", |
| 1037 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1038 | + " | Source Port | Destination Port |\n", |
| 1039 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1040 | + " | Sequence Number |\n", |
| 1041 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1042 | + " | Acknowledgment Number |\n", |
| 1043 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1044 | + " | Data | |U|A|P|R|S|F| |\n", |
| 1045 | + " | Offset| Reserved |R|C|S|S|Y|I| Window |\n", |
| 1046 | + " | | |G|K|H|T|N|N| |\n", |
| 1047 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1048 | + " | Checksum | Urgent Pointer |\n", |
| 1049 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1050 | + " | Options | Padding |\n", |
| 1051 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1052 | + " | data |\n", |
| 1053 | + " +-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+-+\n", |
| 1054 | + "\n", |
| 1055 | + "> TCP Header Format\n", |
| 1056 | + ">\n", |
| 1057 | + "> Note that one tick mark represents one bit position.\n", |
| 1058 | + ">\n", |
| 1059 | + "> Figure 3.\n", |
| 1060 | + ">\n", |
| 1061 | + "> Source Port: 16 bits\n", |
| 1062 | + ">\n", |
| 1063 | + "> The source port number.\n", |
| 1064 | + ">\n", |
| 1065 | + "> Destination Port: 16 bits\n", |
| 1066 | + ">\n", |
| 1067 | + "> The destination port number.\n", |
| 1068 | + ">\n", |
| 1069 | + ">\n", |
| 1070 | + ">\n", |
| 1071 | + ">\n", |
| 1072 | + "> [Page 15]\n", |
| 1073 | + "\n", |
| 1074 | + "[**Excerpt from rfc793 Page 15**](https://www.ietf.org/rfc/rfc793.txt)\n", |
| 1075 | + "\n", |
| 1076 | + "Furthermore, the decoding process extends to examining optional fields within the TCP header, such as the Window Size and Urgent Pointer. The Window Size reflects the amount of data a sender can transmit before expecting an acknowledgment, contributing to flow control. The Urgent Pointer, when utilized, points to urgent data within the packet, enabling timely processing by the receiver. Understanding these optional fields enhances the comprehension of the nuanced behaviors and optimizations implemented within the TCP protocol.\n", |
| 1077 | + "\n", |
| 1078 | + "Deciphering TCP packets provides valuable insights into various applications that heavily rely on TCP, including web browsing, file transfers (via protocols like FTP), and email (via protocols like SMTP). By analyzing the content of TCP packets, one can uncover patterns in data transmission, detect anomalies, and troubleshoot network-related issues. This in-depth analysis of TCP communication contributes to a holistic understanding of the diverse and interconnected aspects of networking protocols.\n", |
| 1079 | + "\n", |
| 1080 | + "Now, let's decode TCP packets using the **`socket2`** crate in Rust which involves establishing a raw socket connection, capturing packets, and dissecting the TCP headers. As we have previously learned, the `socket2` crate provides low-level access to socket functionality, allowing for fine-grained control over network communication. Below is a simplified example illustrating the basic steps for decoding TCP packets using `socket2`:\n", |
| 1081 | + "\n", |
| 1082 | + "```rust\n", |
| 1083 | + "use std::mem::MaybeUninit;\n", |
| 1084 | + "use std::net::SocketAddr;\n", |
| 1085 | + "use std::net::{IpAddr, Ipv4Addr};\n", |
| 1086 | + "\n", |
| 1087 | + "// Constants for TCP and IP headers size\n", |
| 1088 | + "const TCP_HEADER_SIZE: usize = 20;\n", |
| 1089 | + "const IPV4_HEADER_SIZE: usize = 20;\n", |
| 1090 | + "\n", |
| 1091 | + "struct TCP {\n", |
| 1092 | + " source_port: u16,\n", |
| 1093 | + " destination_port: u16,\n", |
| 1094 | + " sequence_number: u32,\n", |
| 1095 | + " acknowledgment_number: u32,\n", |
| 1096 | + " data_offset: u8,\n", |
| 1097 | + " reserved: u8,\n", |
| 1098 | + " flags: u16,\n", |
| 1099 | + " window_size: u16,\n", |
| 1100 | + " checksum: u16,\n", |
| 1101 | + " urgent_pointer: u16,\n", |
| 1102 | + "}\n", |
| 1103 | + "\n", |
| 1104 | + "impl TCP {\n", |
| 1105 | + " fn new(buffer: &[u8]) -> Self {\n", |
| 1106 | + " // Parse the TCP header fields from the buffer\n", |
| 1107 | + " let source_port = u16::from_be_bytes([buffer[0], buffer[1]]);\n", |
| 1108 | + " let destination_port = u16::from_be_bytes([buffer[2], buffer[3]]);\n", |
| 1109 | + " let sequence_number = u32::from_be_bytes([buffer[4], buffer[5], buffer[6], buffer[7]]);\n", |
| 1110 | + " let acknowledgment_number =\n", |
| 1111 | + " u32::from_be_bytes([buffer[8], buffer[9], buffer[10], buffer[11]]);\n", |
| 1112 | + " let data_offset = (buffer[12] >> 4) * 4; // The top 4 bits represent the data offset\n", |
| 1113 | + " let reserved = buffer[12] & 0b00001111;\n", |
| 1114 | + " let flags = u16::from_be_bytes([buffer[13], buffer[14]]);\n", |
| 1115 | + " let window_size = u16::from_be_bytes([buffer[15], buffer[16]]);\n", |
| 1116 | + " let checksum = u16::from_be_bytes([buffer[17], buffer[18]]);\n", |
| 1117 | + " let urgent_pointer = u16::from_be_bytes([buffer[19], buffer[20]]);\n", |
| 1118 | + "\n", |
| 1119 | + " TCP {\n", |
| 1120 | + " source_port,\n", |
| 1121 | + " destination_port,\n", |
| 1122 | + " sequence_number,\n", |
| 1123 | + " acknowledgment_number,\n", |
| 1124 | + " data_offset,\n", |
| 1125 | + " reserved,\n", |
| 1126 | + " flags,\n", |
| 1127 | + " window_size,\n", |
| 1128 | + " checksum,\n", |
| 1129 | + " urgent_pointer,\n", |
| 1130 | + " }\n", |
| 1131 | + " }\n", |
| 1132 | + "}\n", |
| 1133 | + "\n", |
| 1134 | + "fn sniff(address: SocketAddr) {\n", |
| 1135 | + " let socket_protocol = if cfg!(target_os = \"windows\") {\n", |
| 1136 | + " 0\n", |
| 1137 | + " } else {\n", |
| 1138 | + " 6 // TCP\n", |
| 1139 | + " };\n", |
| 1140 | + "\n", |
| 1141 | + " let sniffer = socket2::Socket::new(\n", |
| 1142 | + " socket2::Domain::IPV4,\n", |
| 1143 | + " socket2::Type::RAW,\n", |
| 1144 | + " Some(socket2::Protocol::from(socket_protocol)),\n", |
| 1145 | + " )\n", |
| 1146 | + " .unwrap();\n", |
| 1147 | + "\n", |
| 1148 | + " sniffer.bind(&address.into()).unwrap();\n", |
| 1149 | + "\n", |
| 1150 | + " let mut buffer: [MaybeUninit<u8>; 65535] = unsafe { MaybeUninit::uninit().assume_init() };\n", |
| 1151 | + " loop {\n", |
| 1152 | + " // Receive a TCP packet\n", |
| 1153 | + " let _length = sniffer.recv_from(&mut buffer).unwrap();\n", |
| 1154 | + " let raw_buffer: &[u8] =\n", |
| 1155 | + " unsafe { std::slice::from_raw_parts(buffer.as_ptr() as *const u8, buffer.len()) };\n", |
| 1156 | + "\n", |
| 1157 | + " // Process the TCP packet\n", |
| 1158 | + " if size >= IPV4_HEADER_SIZE + TCP_HEADER_SIZE {\n", |
| 1159 | + " let tcp_header =\n", |
| 1160 | + " TCP::new(&raw_buffer[IPV4_HEADER_SIZE..IPV4_HEADER_SIZE + TCP_HEADER_SIZE + 1]);\n", |
| 1161 | + " // Print or process TCP header information\n", |
| 1162 | + " println!(\"Source Port: {}\", tcp_header.source_port);\n", |
| 1163 | + " println!(\"Destination Port: {}\", tcp_header.destination_port);\n", |
| 1164 | + " println!(\"Sequence Number: {}\", tcp_header.sequence_number);\n", |
| 1165 | + " println!(\n", |
| 1166 | + " \"Acknowledgment Number: {}\",\n", |
| 1167 | + " tcp_header.acknowledgment_number\n", |
| 1168 | + " );\n", |
| 1169 | + " println!(\"Data Offset: {}\", tcp_header.data_offset);\n", |
| 1170 | + " println!(\"Reserved: {}\", tcp_header.reserved);\n", |
| 1171 | + " println!(\"Flags: {}\", tcp_header.flags);\n", |
| 1172 | + " println!(\"Window Size: {}\", tcp_header.window_size);\n", |
| 1173 | + " println!(\"Checksum: {}\", tcp_header.checksum);\n", |
| 1174 | + " println!(\"Urgent Pointer: {}\", tcp_header.urgent_pointer);\n", |
| 1175 | + " }\n", |
| 1176 | + " }\n", |
| 1177 | + "}\n", |
| 1178 | + "\n", |
| 1179 | + "fn main() {\n", |
| 1180 | + " let socket = SocketAddr::new(IpAddr::V4(Ipv4Addr::new(127, 0, 0, 1)), 12345);\n", |
| 1181 | + "\n", |
| 1182 | + " sniff(socket);\n", |
| 1183 | + "}\n", |
| 1184 | + "```\n", |
| 1185 | + "\n", |
| 1186 | + "This example sets up a raw socket, binds it to a local address (in this case, the loopback address), and enters a loop to continuously capture and process TCP packets. The `TCP` struct encapsulates the relevant fields from the TCP header, and the `sniff_tcp_packets` function initializes the socket and processes incoming TCP packets. Keep in mind that decoding TCP packets often involves additional considerations, such as handling variable-length options within the TCP header." |
| 1187 | + ] |
| 1188 | + }, |
| 1189 | + { |
| 1190 | + "cell_type": "code", |
| 1191 | + "execution_count": 3, |
| 1192 | + "id": "027eeef8-a33b-42e7-a388-9987b99aab7e", |
| 1193 | + "metadata": {}, |
| 1194 | + "outputs": [ |
| 1195 | + { |
| 1196 | + "name": "stderr", |
| 1197 | + "output_type": "stream", |
| 1198 | + "text": [ |
| 1199 | + " Compiling decoding-tcp-packets v0.1.0 (/home/mahmoud/Desktop/Rust Book Dark/dark-web-rust/chapter-1/decoding-tcp-packets)\n", |
| 1200 | + " Finished dev [unoptimized + debuginfo] target(s) in 0.26s\n" |
| 1201 | + ] |
| 1202 | + }, |
| 1203 | + { |
| 1204 | + "name": "stdout", |
| 1205 | + "output_type": "stream", |
| 1206 | + "text": [ |
| 1207 | + "\n", |
| 1208 | + "Protocol: TCP 52.200.215.80 -> 192.168.1.8\n", |
| 1209 | + "Version: 69\n", |
| 1210 | + "Header Length: 52 TTL: 60\n", |
| 1211 | + "Source Port: 443\n", |
| 1212 | + "Destination Port: 42436\n", |
| 1213 | + "Sequence Number: 3205079071\n", |
| 1214 | + "Acknowledgment Number: 1443482503\n", |
| 1215 | + "Data Offset: 32\n", |
| 1216 | + "Reserved: 0\n", |
| 1217 | + "Flags: 4097\n", |
| 1218 | + "Window Size: 63162\n", |
| 1219 | + "Checksum: 24832\n", |
| 1220 | + "Urgent Pointer: 1\n" |
| 1221 | + ] |
| 1222 | + }, |
| 1223 | + { |
| 1224 | + "data": { |
| 1225 | + "text/plain": [ |
| 1226 | + "()" |
| 1227 | + ] |
| 1228 | + }, |
| 1229 | + "execution_count": 3, |
| 1230 | + "metadata": {}, |
| 1231 | + "output_type": "execute_result" |
| 1232 | + } |
| 1233 | + ], |
| 1234 | + "source": [ |
| 1235 | + "// The following command will execute the sniffer.\n", |
| 1236 | + "// Set your sudo password below by replacing 'your-passowrd' accordingly\n", |
| 1237 | + "\n", |
| 1238 | + "let command = \"cd decoding-tcp-packets && cargo build && echo 'your-passowrd' | sudo -S sudo setcap cap_net_raw+ep target/debug/decoding-tcp-packets && target/debug/decoding-tcp-packets\";\n", |
| 1239 | + "\n", |
| 1240 | + "if let Err(err) = execute_command(command) {\n", |
| 1241 | + " eprintln!(\"Error executing command: {}\", err);\n", |
| 1242 | + "}\n", |
| 1243 | + "\n", |
| 1244 | + "// Just open your web browser and surf the internet" |
| 1245 | + ] |
| 1246 | + }, |
| 1247 | + { |
| 1248 | + "cell_type": "markdown", |
| 1249 | + "id": "9e338373-00d9-4c60-9c29-e4ac6d60fdac", |
| 1250 | + "metadata": {}, |
| 1251 | + "source": [ |
| 1252 | + "The decoded information from the captured TCP packet reveals a communication exchange involving the IP address **52.200.215.80**, which is attributed to Amazon Web Services (AWS) Elastic Compute Cloud (EC2). [**AWS EC2**](https://en.wikipedia.org/wiki/Amazon_Elastic_Compute_Cloud) is a scalable cloud computing service that provides virtual servers in the cloud, allowing users to run applications and host various types of workloads. The presence of a TCP packet suggests a data transfer or communication event between the AWS EC2 instance, acting as the source (**52.200.215.80**), and our local machine with the destination IP address **192.168.1.8**.\n", |
| 1253 | + "\n", |
| 1254 | + "The identification of the TCP protocol in the \"**Protocol: TCP**\" field signifies that the communication adheres to the principles of Transmission Control Protocol, a foundational aspect of reliable data transmission over networks. The source port **443** and destination port **42436** provide insight into the specific application layer protocols in use. Port 443 is commonly associated with HTTPS, the secure variant of the HTTP protocol used for secure communication over the internet. The arbitrary destination port 42436 suggests that the communication may involve a dynamically assigned port for the client-side of the connection, our local machine.\n", |
| 1255 | + "\n", |
| 1256 | + "Examining the TCP flags, the value **4097** (binary 1000000000001) indicates that this is an **ACK** (Acknowledgment) packet. ACK packets are crucial for ensuring reliable data transfer and confirming the receipt of previously sent packets. The sequence and acknowledgment numbers, 3205079071 and 1443482503, respectively, reveal the progression of the data exchange. The data offset of 32, when multiplied by 4, yields a header length of 128 bytes, providing an extensive structure for encapsulating the TCP information. The window size of 63162 signifies the amount of data (in bytes) that can be sent before an acknowledgment is expected, contributing to the flow control mechanisms in TCP.\n", |
| 1257 | + "\n", |
| 1258 | + "Now that we have successfully decoded both ICMP and TCP packets, the subsequent phase in our network analysis efforts involves the complex process of decoding UDP (User Datagram Protocol) packets. [**UDP**](https://en.wikipedia.org/wiki/User_Datagram_Protocol), unlike TCP, operates as a connectionless and stateless protocol, prioritizing speed and simplicity over the robust reliability mechanisms inherent in TCP. As we delve into UDP packet decoding, we encounter a different set of challenges and nuances. UDP packets lack the elaborate handshaking and acknowledgment mechanisms found in TCP, making their decoding a more direct and, in some ways, more challenging task.\n", |
| 1259 | + "\n", |
| 1260 | + "The UDP decoding process necessitates a sharp understanding of the UDP header structure, including crucial fields such as source and destination ports, length, and checksum. The source and destination ports denote the application processes communicating over UDP, providing insight into the specific services involved in the data exchange. The length field specifies the total length of the UDP packet, aiding in proper segmentation and reassembly. The checksum field serves as a verification mechanism to ensure the integrity of the UDP packet during transmission.\n", |
| 1261 | + "\n", |
| 1262 | + "In our decoding journey, we must meticulously extract and interpret these UDP header fields, considering the contextual relevance of each piece of information within the broader network communication. The absence of a formal connection setup and teardown process in UDP introduces unique challenges, as deciphering the intent and context of UDP packets relies heavily on the payload data and its interpretation within the specific application layer protocol.\n", |
| 1263 | + "\n", |
| 1264 | + "As we extend our decoding capabilities to encompass UDP packets, we aim to uncover the underlying dynamics of real-time and efficient data communication. UDP is frequently employed in scenarios where low latency and rapid data transmission are paramount, such as in multimedia streaming, online gaming, and other time-sensitive applications. Therefore, our UDP decoding endeavors not only contribute to a comprehensive understanding of network traffic but also enable us to distinguish the diverse applications and services thriving within the network ecosystem. In navigating the intricacies of UDP packet decoding, we embark on a journey to unravel the rich tapestry of communication protocols that form the backbone of modern networking, further enhancing our ability to comprehend and analyze the multifaceted landscape of data transmission in diverse network environments." |
| 1265 | + ] |
| 1266 | + }, |
| 1267 | + { |
| 1268 | + "cell_type": "code", |
| 1269 | + "execution_count": null, |
| 1270 | + "id": "f3229384-bc07-47ac-b644-cbb95c61e097", |
| 1271 | + "metadata": {}, |
| 1272 | + "outputs": [], |
| 1273 | + "source": [] |
1012 | 1274 | } |
1013 | 1275 | ], |
1014 | 1276 | "metadata": { |
|
0 commit comments