How to Log and Debug Suspicious HTTP Requests in Nginx (0.7.65) with Request Dumping


2 views

When running nginx 0.7.65 on Ubuntu 10.04.2, you might encounter suspicious HTTP requests that need investigation. The challenge is to capture these requests without logging all normal traffic.

Since you can identify bogus requests by a specific GET parameter (like 'foo'), we can use nginx's conditional logging:

server {
    # ... other server config ...
    
    set $logme 0;
    if ($arg_foo) {
        set $logme 1;
    }

    access_log /var/log/nginx/suspicious.log combined if=$logme;
}

If you prefer packet-level inspection, this tcpdump command captures only requests containing 'foo' parameter:

sudo tcpdump -i eth0 -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and tcp[((tcp[12]&0xf0)>>2)+4:4] = 0x666f6f3d'

For deeper inspection, you can proxy suspicious requests to a simple HTTP server that logs everything:

location / {
    if ($arg_foo) {
        proxy_pass http://127.0.0.1:8080;
        break;
    }
    # ... normal handling ...
}

Then run a simple Python debug server:

python -m SimpleHTTPServer 8080 2>&1 | tee debug.log

ngrep can efficiently capture requests with specific patterns:

ngrep -q -d eth0 'GET.*foo=' 'port 80'

Or for POST requests with the parameter:

ngrep -q -d eth0 'POST.*\r\n\r\n.*foo=' 'port 80'

For more detailed request logging, add this to your nginx config:

log_format debug '$remote_addr - $remote_user [$time_local] '
                 '"$request" $status $body_bytes_sent '
                 '"$http_referer" "$http_user_agent" '
                 'Request Headers: "$http_headers" '
                 'Request Body: "$request_body"';

server {
    # ... other config ...
    access_log /var/log/nginx/debug.log debug if=$logme;
}

When dealing with suspicious HTTP traffic in Nginx (particularly version 0.7.65 on Ubuntu 10.04.2), we often need to inspect complete request data - including both headers and body - without capturing all production traffic. The ideal solution should:

  • Filter requests based on specific patterns (like a "foo" parameter in GET queries)
  • Capture only the anomalous traffic
  • Operate without additional proxy servers
  • Avoid performance-impacting packet captures

For Nginx 0.7.65, we have several practical approaches:

# Method 1: Conditional logging with $request_body
http {
    log_format debug_request '$remote_addr - $remote_user [$time_local] '
                           '"$request" $status $body_bytes_sent '
                           '"$http_referer" "$http_user_agent" '
                           'Request Body: "$request_body"';

    server {
        set $log_request 0;
        
        if ($arg_foo) {
            set $log_request 1;
        }
        
        access_log /var/log/nginx/debug.log debug_request if=$log_request;
    }
}

For POST requests, you'll need to add:

location / {
    client_body_in_file_only on;
    client_body_temp_path /tmp/nginx_debug;
}

When dealing with complex filtering needs (beyond simple query parameters), consider these alternatives:

# Using Lua with Nginx (requires ngx_lua module)
location / {
    access_by_lua '
        if ngx.var.arg_foo then
            ngx.req.read_body()
            local file = io.open("/tmp/nginx_debug.log", "a")
            file:write(ngx.var.request_uri, "\\n", ngx.req.get_body_data(), "\\n\\n")
            file:close()
        end
    ';
}

When Nginx logging isn't sufficient, these system tools can help:

# ngrep example for specific GET parameter
sudo ngrep -d eth0 -W byline 'foo=[^&]*' port 80

# tcpdump with advanced filtering
sudo tcpdump -i eth0 -A -s 0 'tcp port 80 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0) and (tcp[((tcp[12]&0xf0)>>2)+4:4] = 0x666f6f3d)'

When implementing these solutions:

  • Rotate debug logs regularly (logrotate with size-based triggers)
  • Consider memory buffers (like memcached) for high-traffic environments
  • For POST requests, be mindful of client_body_buffer_size limitations
  • In modern Nginx versions (1.7+), consider the error_log with debug_connection