NGINX Traffic Capture
This guide shows you how to use Qtap to capture HTTP traffic flowing through NGINX, one of the most popular web servers and reverse proxies. You'll learn how to observe both incoming client requests and outgoing upstream connections, all without proxies or code changes.
What You'll Learn
Capture NGINX ingress traffic (client requests coming in)
Capture NGINX egress traffic (upstream service requests going out)
Monitor both sides of a reverse proxy simultaneously
Apply conditional capture rules for specific endpoints
Set up NGINX + Qtap in Docker for testing
Deploy production-ready configurations with S3 storage
Use Cases
Why capture NGINX traffic?
Reverse Proxy Visibility: See both client requests and upstream responses in one place
Performance Analysis: Measure latency between client→nginx and nginx→upstream
API Gateway Monitoring: Track all API calls flowing through your gateway
Security Auditing: Detect malicious requests or data exfiltration attempts
Troubleshooting: Debug issues with request/response transformations
Compliance: Audit all traffic for regulatory requirements
Load Balancer Analytics: Understand traffic distribution patterns
Prerequisites
Linux system with kernel 5.10+ and eBPF support
Docker installed (for this guide's examples)
Root/sudo access
Basic understanding of NGINX configuration
Part 1: Simple NGINX Web Server
Let's start with a basic NGINX setup serving static content and reverse proxying to an upstream service.
Step 1: Create NGINX Configuration
Create a directory for our demo:
Create nginx.conf:
Step 2: Create Qtap Configuration
Create qtap.yaml:
Key Configuration Points:
direction: all- Captures both incoming (client→nginx) AND outgoing (nginx→upstream) trafficignore_loopback: false- Important! NGINX often communicates via localhostlevel: full- Captures complete requests/responses including bodies
Step 3: Create Docker Compose Setup
Create docker-compose.yaml:
Part 2: Running and Testing
Step 1: Start the Services
Step 2: Generate Test Traffic
Step 3: View Captured Traffic
What you should see:
Key indicators that it's working:
✅
"exe": "/usr/sbin/nginx"- NGINX process identified✅
Direction: INGRESS- Client to NGINX✅
Direction: EGRESS- NGINX to upstream✅ Two transactions for proxied requests (one ingress, one egress)
✅ Custom headers visible (
X-Custom-Header,X-Real-IP)✅ Full request/response bodies captured
✅ Latency tracked for both hops
Part 3: Advanced Configurations
Configuration 1: Capture Only Errors
Reduce volume by capturing only failed requests (4xx/5xx status codes):
Test it:
Configuration 2: Separate Ingress and Egress Stacks
Apply different capture levels to ingress vs. egress traffic:
Configuration 3: Filter by API Endpoint
Capture only specific API paths using Rulekit:
Configuration 4: Production Setup with S3
For production, store sensitive data in your own S3 bucket:
Update docker-compose.yaml to pass S3 credentials:
See Storage Configuration for complete S3 setup.
Part 4: Real-World Use Cases
Use Case 1: API Gateway Monitoring
Monitor all API traffic flowing through NGINX as an API gateway:
Use Case 2: Debugging Reverse Proxy Issues
Capture both sides of a reverse proxy to debug transformation issues:
This configuration lets you compare:
What the client sent to NGINX (ingress)
What NGINX forwarded to the upstream (egress)
What the upstream returned (egress response)
What NGINX sent back to the client (ingress response)
Use Case 3: Load Balancer Analytics
Track traffic distribution across multiple upstreams:
nginx.conf (simplified):
qtap.yaml:
Analyze the logs to see which backend server received each request.
Understanding the Output
Dual Capture for Reverse Proxy
When NGINX proxies a request, Qtap captures two separate HTTP transactions:
Transaction 1: INGRESS (Client → NGINX)
Transaction 2: EGRESS (NGINX → Upstream)
This dual capture lets you:
Measure end-to-end latency vs. upstream latency
See how NGINX transforms requests (headers, paths, bodies)
Debug issues on either side of the proxy
Capture Levels Explained
none: No capture (use with rules for conditional capture)summary: Basic metadata (method, URL, status, duration) - no headers/bodiesdetails: Includes headers - no bodiesfull: Everything (headers + bodies)
For high-traffic NGINX servers, start with summary or details to control volume.
Troubleshooting
Not Seeing NGINX Traffic?
Check 1: Is Qtap running before you made requests?
Check 2: Is ignore_loopback set correctly?
Check 3: Is NGINX actually processing requests?
Check 4: Verify Qtap is hooking NGINX
Seeing "l7Protocol": "other"?
"l7Protocol": "other"?This means Qtap captured the connection but couldn't parse HTTP:
NGINX might be using HTTPS internally (check TLS configuration)
Traffic might not be HTTP
Qtap may not have fully initialized (wait 6+ seconds after starting)
Too Much Traffic Captured?
Option 1: Use conditional rules
Option 2: Filter specific paths
Option 3: Capture summary only
Duplicate Transactions?
If you see the same request captured multiple times, this is expected for reverse proxies:
One INGRESS capture (client → nginx)
One EGRESS capture (nginx → upstream)
To capture only one direction:
Performance Considerations
NGINX + Qtap Performance Impact
Qtap operates out-of-band using eBPF, with minimal impact:
CPU overhead: ~1-3% for typical HTTP traffic
Memory: ~50-200MB depending on traffic volume
Latency: No additional latency (passive observation)
Best practices for high-traffic NGINX:
Use
level: summaryordetails(avoidfullwith large bodies)Apply conditional rules to reduce captured volume
Filter out health checks and monitoring endpoints
Send data to S3 in batches (use Fluent Bit for buffering)
Set TTL policies on storage (90 days recommended)
Scaling Recommendations
Traffic Volume
Recommended Level
Storage
< 100 req/sec
full
stdout or S3
100-1000 req/sec
details
S3 with batching
1000-10000 req/sec
summary
S3 + Fluent Bit
> 10000 req/sec
conditional rules
S3 + Fluent Bit + aggressive filtering
Next Steps
Learn More About Qtap:
Traffic Capture Settings - Complete
tapconfigurationTraffic Processing with Plugins - All plugin options
Complete Guide - Progressive tutorial covering all features
Production Deployment:
Storage Configuration - S3 setup guide
Capturing All HTTP Traffic with Fluent Bit - Batching and buffering
Kubernetes Manifest - Deploy in K8s
Related Guides:
Ingress Traffic Capture with Python - Similar concepts for other servers
HTTPS Header Capture Without Proxies - TLS inspection details
Alternative: Cloud Management:
Qplane - Manage Qtap with visual dashboards
POC Kick Off Guide - Quick start with cloud control plane
Cleanup
This guide uses validated configurations. All examples are tested and guaranteed to work with NGINX and Qtap.
Last updated