nginx: kết xuất các yêu cầu HTTP để gỡ lỗi


16
  • Ubuntu 10.04.2
  • nginx 0,7,65

Tôi thấy một số yêu cầu HTTP kỳ lạ đến máy chủ nginx của tôi.

Để hiểu rõ hơn những gì đang diễn ra, tôi muốn kết xuất toàn bộ dữ liệu yêu cầu HTTP cho các truy vấn đó. (Tức là bỏ tất cả các tiêu đề yêu cầu và cơ thể ở đâu đó tôi có thể đọc chúng.)

Tôi có thể làm điều này với nginx? Ngoài ra, có một số máy chủ HTTP cho phép tôi thực hiện việc này không, tôi có thể ủy quyền các yêu cầu này bằng nginx không?

Cập nhật: Lưu ý rằng hộp này có một loạt lưu lượng truy cập bình thường và tôi muốn tránh bắt tất cả lưu lượng ở mức thấp (giả sử với tcpdump) và lọc nó sau.

Tôi nghĩ rằng việc lọc lưu lượng tốt trước tiên sẽ dễ dàng hơn nhiều trong quy tắc viết lại (may mắn thay tôi có thể viết một lưu lượng khá dễ dàng trong trường hợp này), và sau đó chỉ xử lý lưu lượng truy cập không có thật.

Và tôi không muốn chuyển lưu lượng truy cập không có thật sang một hộp khác chỉ để có thể chụp nó ở đó với tcpdump.

Cập nhật 2: Để cung cấp thêm một chút chi tiết, yêu cầu không có thật có tham số có tên (giả sử) footrong truy vấn GET của họ (giá trị của tham số có thể khác nhau). Yêu cầu tốt được đảm bảo không có tham số này bao giờ.

Nếu tôi có thể lọc bằng cái này trong tcpdumphoặc ngrepbằng cách nào đó - không vấn đề gì, tôi sẽ sử dụng chúng.


Bạn có thể mô tả / phân loại các yêu cầu mà bạn cho là "lạ" không? Làm thế nào một người có thể đưa ra một quy tắc để giúp bạn nếu bạn không chia sẻ với chúng tôi điều gì là 'bình thường' và 'không có thật'?
hobodave

Tôi không yêu cầu một quy tắc - tôi có thể tự viết nó một cách dễ dàng. Tôi yêu cầu phương tiện để đổ dữ liệu yêu cầu HTTP.
Alexander Gladysh

@hobodave: nhưng dù sao, vì bạn đã hỏi, tôi đã thêm thông tin này vào câu hỏi.
Alexander Gladysh

Câu trả lời:


29

Điều chỉnh số lượng dòng trước / bài (-B và -A args) nếu cần:

tcpdump -n -S -s 0 -A 'tcp dst port 80' | grep -B3 -A10 "GET /url"

Điều này cho phép bạn nhận được các yêu cầu HTTP mà bạn muốn, trên hộp, mà không tạo tệp PCAP khổng lồ mà bạn phải giảm tải ở một nơi khác.

Hãy nhớ rằng bộ lọc BPF không bao giờ chính xác, nếu có một số lượng lớn các gói chảy qua bất kỳ hộp nào, BPF có thể và sẽ bỏ các gói.


5

Tôi không biết chính xác ý của bạn khi kết xuất yêu cầu nhưng bạn có thể sử dụng tcpdump và / hoặc wireshark để phân tích dữ liệu:

# tcpdump port 80 -s 0 -w capture.cap

Và bạn có thể sử dụng wireshark để mở tệp và xem cuộc hội thoại giữa các máy chủ.


Cảm ơn, nhưng tôi có khá nhiều lưu lượng truy cập trên máy chủ này (99% là tốt) và tôi nghĩ rằng thật khó để lọc ra đống dữ liệu cho cái giả mà tôi cần 1%.
Alexander Gladysh

... Nếu tôi chụp tất cả ở mức độ thấp như vậy. :-)
Alexander Gladysh

Tôi đã cập nhật câu hỏi để phản ánh điều đó.
Alexander Gladysh

Alexander - điều đó có nghĩa là cứ 100 yêu cầu thì sẽ có 1 tiêu đề kỳ lạ mà bạn đang tìm kiếm. Chạy một bản chụp trong một thời gian và sau đó tìm kiếm thông qua nhật ký kết quả để tìm kiếm các tiêu đề bạn muốn - đó chắc chắn không phải là một lượng công việc không thể chịu đựng được.
EEAA

Vấn đề không phải là công việc, mà là lượng dữ liệu cần xử lý. (Mặc dù có thể chịu được, nhưng, dù sao, tôi muốn xem một giải pháp thân thiện hơn.)
Alexander Gladysh

0

Nếu bạn ủy quyền các yêu cầu tới Apache với mod_php được cài đặt, bạn có thể sử dụng tập lệnh PHP sau để kết xuất các yêu cầu:

<?php
$pid = getmypid();
$now = date('M d H:i:s');
$fp = fopen('/tmp/intrusion.log', 'a');

if (!function_exists('getallheaders')) 
{ 
    function getallheaders() 
    { 
           $headers = ''; 
       foreach ($_SERVER as $name => $value) 
       { 
           if (substr($name, 0, 5) == 'HTTP_') 
           { 
               $headers[str_replace(' ', '-', ucwords(strtolower(str_replace('_', ' ', substr($name, 5)))))] = $value; 
           } 
       } 
       return $headers; 
    } 
} 

function ulog ($str) {
    global $pid, $now, $fp;
    fwrite($fp, "$now $pid {$_SERVER['REMOTE_ADDR']} $str\n");
}

foreach (getallheaders() as $h => $v) {
    ulog("H $h: $v");
}
foreach ($_GET as $h => $v) {
    ulog("G $h: $v");
}
foreach ($_POST as $h => $v) {
    ulog("P $h: $v");
}
fclose($fp);

Lưu ý rằng vì bạn đang sử dụng nginx nên $_SERVER['REMOTE_ADDR']có thể là vô nghĩa. Bạn sẽ phải chuyển IP thực cho Apache thông qua proxy_set_header X-Real-IP $remote_addr;và thay vào đó bạn có thể sử dụng IP đó (hoặc chỉ dựa vào nó được đăng nhập qua getallheaders()).


Cảm ơn bạn. Nhưng tôi không có PHP trên máy chủ của mình. Tuy nhiên, ý tưởng này là hợp lệ cho bất kỳ sự mơ hồ lập trình nhận biết http nào khác. :-)
Alexander Gladysh
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.