1. Introduction

In server administration, understanding the traffic that flows through our server running on Linux is akin to having a roadmap in an unfamiliar city. It guides us to optimize performance, bolster security, and enhance the overall user experience.

Among the various techniques at our disposal, dumping HTTP requests is a particularly insightful method to achieve this understanding. As server administrators, this technique allows us to capture and analyze the HTTP headers and payloads sent to our server, offering a granular view of client-server interactions.

In this tutorial, we’ll explore the built-in functionalities of Apache, the widely used web server software, and third-party tools that enable us to efficiently dump and analyze HTTP requests. Whether we’re seasoned server administrators or developers looking to understand more about the traffic our application receives, our journey will take us from tweaking Apache configurations to leveraging sophisticated network monitoring tools. Let’s get started!

2. The Need for HTTP Request Dumping

Dumping HTTP requests serves multiple purposes, from debugging application issues to enhancing security by monitoring for malicious requests. At its core, it’s about visibility.

As server administrators, having a detailed log of incoming requests can be invaluable when understanding how clients interact with our applications. Whether we’re troubleshooting a tricky bug, conducting a security audit, or simply optimizing our server’s response times, the insights gained from these dumps can guide our decision-making process.

However, the distinction between application-level and network-level capturing is crucial here.

2.1. Application-Level Logging

Application-level logging, such as that provided by Apache, focuses on the traffic that reaches the application, offering insights into how the application processes requests.

As developers and server administrators, we must learn how web applications process and respond to client requests. This type of logging captures detailed information about the interactions within the application, including the sequence of events, errors, and transaction times.

Also, it aids in debugging by pinpointing the exact location of errors within the codebase, optimizing application performance by identifying slow processes or queries, and enhancing security by detecting anomalous behavior indicative of potential threats.

Furthermore, we can use application logs to understand user behavior, providing valuable feedback for improving user experience and developing new features.

In short, application-level logging is indispensable for maintaining, securing, and enhancing our web applications.

2.2. Network-Level Monitoring

On the flip side, network-level monitoring offers a bird’s-eye view of all the traffic passing through the network interface, capturing data packets regardless of their destination within the server or adherence to application protocols. This method is essential for identifying and mitigating external threats before they reach the application layer.

Additionally, network-level monitoring allows administrators to detect unusual traffic patterns, potential security breaches, and protocol anomalies, serving as an early warning system against attacks. It also plays a vital role in network performance analysis, capacity planning, and compliance with regulatory standards by providing comprehensive data on incoming and outgoing traffic.

In essence, network-level monitoring complements application-level logging by securing the perimeter and ensuring the integrity of the server’s network traffic. However, each method discussed has its place in a comprehensive monitoring strategy.

Application-level logging is often more straightforward to set up and interpret for application-specific troubleshooting and optimization. Network-level capturing provides a broader view, ideal for security monitoring and identifying issues outside the application’s direct handling of requests.

3. Using mod_dumpio: A Built-In Apache Solution

Apache, one of the most popular web servers in the world, comes equipped with robust logging capabilities for dumping HTTP requests that can be tailored to suit various needs.

It offers a straightforward approach through its configuration files. This flexibility allows administrators to adjust the level of detail logged, making it possible to capture everything from basic request headers to the full payload of data sent in a request.

3.1. Enabling mod_dumpio for Detailed Logging

One of Apache’s lesser-known modules, mod_dumpio, is particularly useful for dumping HTTP requests and responses. This module allows for logging all I/O to and from Apache, providing a detailed view of the data the server is exchanging.

Enabling mod_dumpio is a simple process, but one that can significantly increase the verbosity of our logs. So, we best use it in a development or troubleshooting scenario where detailed information is more critical than log brevity.

To enable mod_dumpio on our Apache server, we’ll need to load the module and then configure it to capture the data we’re interested in.

First, we’ll load the mod_dumpio module by using any text editor like nano, vi, or gedit to edit our Apache configuration file (/etc/httpd/conf/httpd.conf for CentOS/RHEL-based distributions or /etc/apache2/apache2.conf for Debian/Ubuntu-based distributions):

$ sudo vi /etc/httpd/conf/httpd.conf
# OR
$ sudo vi /etc/apache2/apache2.conf

Then, inside the configuration file, we’ll add the line to load the mod_dumpio module:

# File httpd.conf or apache2.conf
LoadModule dump_io_module modules/mod_dumpio.so

This loads the mod_dumpio module.

3.2. Setting the Logging Level

After loading the module, we continue configuring our Apache server within the same configuration file.

Now, we’ll configure Apache to start dumping HTTP requests and responses by setting the logging level with these directives:

# File httpd.conf or apache2.conf
LoadModule dump_io_module modules/mod_dumpio.so
LogLevel dumpio:trace7
DumpIOInput On
DumpIOOutput On
DumpIOLogLevel debug

Let’s understand our configuration:

  • LogLevel dumpio:trace7 – sets the logging level to one of the most lengthy levels (trace7) provided by Apache
  • DumpIOInput On – enables logging of input data (HTTP requests)
  • DumpIOOutput On – enables logging of output data (HTTP responses)
  • DumpIOLogLevel debug – sets the log level to debug (required to log the input/output data)

The trace log levels are part of an extended logging level system in Apache that goes from trace1 (least verbose) to trace8 (most verbose). trace7 provides detailed trace logging, showing the flow of data and decisions within the server without being as overwhelmingly detailed as trace8.

However, this level of logging (trace7) can generate a large amount of log data. So, suppose computing or storage resources are a concern, especially if we run a busy server. In that case, we should typically use them temporarily during troubleshooting sessions rather than as a permanent setting in a production environment.

3.3. Restarting Apache

After we’re done modifying the configuration file, we should save our changes to the file and restart Apache with systemctl for the changes to take effect:

$ sudo systemctl restart httpd
# OR
$ sudo systemctl restart apache2

With this, Apache restarts and starts dumping HTTP requests with mod_dumpio.

3.4. Sample Log

After we enable mod_dumpio and configure it on our Apache server from our previous interactions, it begins to log detailed information about the HTTP traffic it handles.

Typically, it writes this information to the server’s error log file at /var/log/apache2/error.log on Debian-based systems or /var/log/httpd/error_log on Red Hat-based systems. This might initially seem counterintuitive. However, because mod_dumpio is primarily used for debugging purposes, the error log is considered the appropriate place for this level of detailed output.

Basically, the output includes the complete HTTP headers and body (if present) for both requests and responses. This can be immensely valuable when we’re trying to debug complex issues related to request processing or when we need to ensure the secure transmission of sensitive data.

For real-time monitoring of the error log as requests are being processed, we can use the tail command with the -f option. This displays the most recent log entries and updates in real time.

Let’s see a sample error log for a simple HTTP request:

$ sudo tail -f /var/log/apache2/error.log

[Tue Feb 23 20:10:22.123456 2024] [dumpio:trace7] [pid 12345] mod_dumpio.c(100): [client] mod_dumpio: dumpio_in (data-HEAP):  GET / HTTP/1.1
[Tue Feb 23 20:10:22.123456 2024] [dumpio:trace7] [pid 12345] mod_dumpio.c(103): [client] mod_dumpio: dumpio_in (data-HEAP): Host: www.example.com

Here, this output captures the essence of the HTTP request, the request line, and headers as the server receives them. If the request includes a body, such as a POST request with form data, mod_dumpio will log that as well, providing a comprehensive view of the incoming request.

Notably, this command will continue to run in our terminal, displaying new log entries as they are written to the error log. When we see entries starting with [dumpio:trace7] (or whatever trace level we have set), those are the detailed dumps of HTTP requests and responses generated by mod_dumpio.

To exit the tail command, we can press Ctrl+C.

4. Using tcpdump for Network-Level Monitoring

While mod_dumpio, Apache’s built-in tool, offers insight into the traffic our server handles, sometimes we need to capture data at a lower level or look for a more user-friendly way to analyze the captured data. This is where third-party tools like tcpdump come into play.

tcpdump is a powerful command-line packet analyzer that allows us to capture packets flowing into and out of our server. Typically, it’s useful for capturing all HTTP requests, not just those Apache handles, providing a comprehensive view of incoming traffic.

4.1. Sample Capture

For instance, let’s use tcpdump to capture all traffic destined for port 80 (the default HTTP port) on our sample server:

$ sudo tcpdump -s 0 -X 'tcp dst port 80'
14:22:03.611278 IP > server.example.com.http: Flags [P.], seq 1:83, ack 1, win 229, options [nop,nop,TS val 239482020 ecr 123456789], length 82
        0x0000:  4500 0072 0000 4000 4006 aaaa c0a8 0105  E..r..@.@.......
        0x0010:  c0a8 01f4 ca3e 0050 0000 0001 0000 0001  .....>.P........
        0x0020:  8018 00e5 3072 0000 0101 080a 0e4d 2f4c  ....0r.......M/L
        0x0030:  075b cd15 4745 5420 2f20 4854 5450 2f31  .[..GET./.HTTP/1
        0x0040:  2e31 0d0a 486f 7374 3a20 6578 616d 706c  .1..Host:.exampl
        0x0050:  652e 636f 6d0d 0a55 7365 722d 4167 656e  e.com..User-Agen
        0x0060:  743a 2043 7572 6c2f 372e 3634 2e30 0d0a  t:.Curl/7.64.0..
        0x0070:  0d0a                                     ..

In our command to run tcpdump with administrative privileges (sudo):

  • -s 0 – sets the snap length (the maximum amount of data to be captured from each packet) to its maximum, meaning it will capture the entire packet regardless of its size
  • -X – tells tcpdump to print each packet in Hex and ASCII, which is useful for reading the contents of the HTTP requests
  • ‘tcp dst port 80’ – a filter expression that tells tcpdump to capture only Transmission Control Protocol (TCP) packets destined for port 80

This command captures the entire packet and prints the header and the payload in Hexadecimal and ASCII filtered to show only traffic destined for port 80.

4.2. Explanation

As we can see in our output, the first line provides a summary of the packet, i.e., the timestamp (14:22:03.611278), source IP address and port (, destination IP and port (server.example.com.http or server.example.com.80), along with TCP flags and sequence information.

Afterward, the packet’s data is shown in Hexadecimal (0x0000: 4500 0072…) and ASCII (GET / HTTP/1.1…). In this example, we can see part of an HTTP GET request, including the method (GET), the requested resource (/), and the HTTP version (HTTP/1.1), followed by the host header and the beginning of the User-Agent header.

In several scenarios, our output can be extremely useful for debugging issues with HTTP traffic, understanding the behavior of our web applications, or monitoring suspicious activity.

4.3. Dumping the Data to a File

For more user-friendly analysis, we can consider saving the tcpdump output to a file with the -w option:

$ sudo tcpdump -s 0 -w http_traffic.pcap 'tcp dst port 80'

With our -w option here, we won’t see the live packet data on our terminal as we did with the -X option. The capturing process will continue until we terminate it by pressing Ctrl+C.

However, with -w http_traffic.pcap, we specify that the output should be written to a file http_traffic.pcap. The .pcap extension indicates the file format for packet capture data, which most packet analyzing tools like Wireshark recognize.

For packet captures, Wireshark provides powerful filters and analysis tools we can use to delve into the details of each request. We can use this method of capturing and analyzing traffic for deep-dive troubleshooting, security analysis, and learning more about network protocols and their behaviors.

For Apache logs, tools like goaccess or awk scripts can help summarize and visualize the data.

5. Simplifying Packet Captures With tcpflow

tcpflow is a user-friendly alternative to more complex packet capture tools like tcpdump. It simplifies monitoring HTTP traffic by automatically separating the data streams into individual files, making it significantly easier to analyze the traffic between a client and a server.

Thus, unlike tcpdump, which requires us to manually sift through packets and reconstruct the session streams, tcpflow does this heavy lifting for us, presenting the data in a more accessible format.

5.1. Sample Capture

For instance, let’s use tcpflow to capture HTTP requests:

$ tcpflow -p -c port 80 GET /index.html HTTP/1.1
Host: example.com
User-Agent: curl/7.58.0
Accept: */* HTTP/1.1 200 OK
Date: Sun, 07 Feb 2024 12:34:56 GMT
Server: Apache
Last-Modified: Wed, 05 Feb 2024 12:18:22 GMT
Content-Type: text/html
Content-Length: 178
Connection: close

<h1>Hello, World!</h1>

In our command, the -p flag tells tcpflow not to put the interface into promiscuous mode. This is often unnecessary unless we want to capture all traffic passing through the network, including traffic not destined for our machine.

Then, the -c option writes the captured data to the console (standard output) instead of saving it to files. This is useful for real-time monitoring or when we’re only interested in a quick overview rather than a detailed analysis.

5.2. Explanation

As we can see in our output, the first line shows a request from a client IP ( and port (51762) to a server IP ( on port 80 (00080), requesting /index.html via the HTTP GET method. Then, we can see the HTTP headers sent by the client, including the Host, User-Agent, and Accept headers.

Afterward, tcpflow shows the response from the server, starting with the response line (HTTP/1.1 200 OK), followed by the server’s response headers (Date, Server, etc.). Finally, we can see the actual content of the response, in this case, a simple HTML document.

Essentially, tcpflow is particularly useful for us as system administrators and developers looking for a straightforward way to monitor HTTP traffic without requiring extensive packet analysis skills. Its output format makes it straightforward to understand the HTTP conversation between the client and the server. It displays each continuously, so there’s no need to manually reconstruct the session from separate packets as we would with tcpdump.

However, its simplicity doesn’t compromise its effectiveness, making it a valuable tool in our network monitoring and packet dumping toolkit.

6. HTTP Request Inspection With ngrep

ngrep is a versatile tool that combines the functionality of grep with the network packet-capturing capabilities of tcpdump. It searches for specific patterns in the payload of packets, making it exceptionally useful for inspecting HTTP requests for certain keywords, headers, or values.

For example, let’s filter a sample HTTP GET request to port 80:

$ ngrep -q '^GET .* HTTP/1.[01]' port 80
interface: eth0 (
filter: (ip or ip6) and ( port 80 )
match: ^GET .* HTTP/1.[01]

T -> [AP]
GET /index.html HTTP/1.1.
Host: www.example.com
User-Agent: curl/7.58.0
Accept: */*


In our command, the q flag (quiet mode) reduces the amount of information printed on the screen. It suppresses the packet summary lines that ngrep normally outputs, showing only the packet payloads that match the expression.

From our output, the first few lines provide information about the network interface ngrep is listening on (eth0), the IP range for that interface, and the filter conditions applied (traffic on port 80 matching the regular expression).

As we can see, ngrep is especially handy when we need to quickly check for the presence of specific data in HTTP requests without setting up more complex packet capture and analysis environments. Whether we’re debugging an application, performing a security audit, or simply curious about the traffic our server handles, ngrep provides a powerful yet user-friendly way to inspect our HTTP requests.

7. Conclusion

In this article, we explored how to dump HTTP requests using Apache’s built-in functionalities and various third-party tools. We started with an overview of why we might want to capture HTTP requests, touching on scenarios ranging from debugging and security auditing to performance optimization.

Then, we delved into the specifics of leveraging Apache’s mod_dumpio module for detailed request logging, providing step-by-step instructions to enable and configure this powerful feature.

Finally, we touched on the analysis and utilization of captured data, emphasizing the importance of identifying patterns and extracting actionable insights from the information HTTP request dumps can provide. Whether through manual analysis or using tools designed to parse and visualize the data, the ultimate goal is to enhance our understanding of server-client interactions, leading to improved application performance, tightened security, and a better user experience.

Comments are open for 30 days after publishing a post. For any issues past this date, use the Contact form on the site.