Format yang dapat dibaca manusia untuk tajuk http dengan tcpdump


69

Saya ingin melihat header HTTP yang dikirim dari Apache (mendengarkan pada port 80) ke Tomcat (pada port 4080) di mesin Linux.

Menurut Wikipedia ,

Field header adalah pasangan nilai-nilai yang dipisahkan oleh usus besar dalam format string teks yang jelas.

Saya sudah mencoba beberapa variasi dari tcpdumpperintah berikut :

$ sudo tcpdump -lnX dst port 4080 -c 10

11:29:28.605894 IP SOME_IP.33273 > SOME_IP.4080: P 0:49(49) ack 1 win 23 <nop,nop,timestamp 1191760962 509391143>
    0x0000:  4500 0065 3a9f 4000 3f06 0084 628a 9ec4  E..e:.@.?...b...
    0x0010:  628a 9c97 81f9 0ff0 9e87 eee0 144b 90e1  b............K..
    0x0020:  8018 0017 fb43 0000 0101 080a 4708 d442  .....C......G..B
    0x0030:  1e5c b127 4845 4144 202f 6461 7070 6572  .\.'HEAD./dapper
    0x0040:  5f73 6572 7669 6e67 2f41 644d 6f6e 6b65  _serving/AdMonke
    0x0050:  793f                                     y?

Hasilnya selalu sama - campuran aneh kata-kata omong kosong dan bahasa Inggris (misalnya HEAD).

Bagaimana saya bisa melihat header dalam format yang bisa dibaca manusia?


Tcpdump menunjukkan seluruh paket. Ini termasuk IP, dan header TCP. AFAIK, Anda tidak dapat menampilkan hanya muatan TCP.
Zoredache

Jawaban:


93

Berikut ini adalah satu-baris yang saya buat untuk menampilkan permintaan dan tanggapan menggunakan HTTP header tcpdump(yang seharusnya bisa digunakan untuk kasus Anda):

sudo tcpdump -A -s 10240 'tcp port 4080 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)' | egrep --line-buffered "^........(GET |HTTP\/|POST |HEAD )|^[A-Za-z0-9-]+: " | sed -r 's/^........(GET |HTTP\/|POST |HEAD )/\n\1/g'

Ini membatasi pemotongan paket pada 10Kb dan hanya tahu perintah GET, POST, dan HEAD, tetapi itu sudah cukup di sebagian besar kasus.

EDIT : memodifikasinya untuk menghilangkan buffer di setiap langkah agar lebih responsif. Perlu Perl dan stdbuf sekarang, jadi gunakan versi aslinya jika Anda tidak memilikinya: EDIT : Target port skrip yang diubah dari 80 menjadi 4080, untuk benar-benar mendengarkan lalu lintas yang melewati apache, alih-alih lalu lintas langsung keluar langsung ke port 80:

sudo stdbuf -oL -eL /usr/sbin/tcpdump -A -s 10240 "tcp port 4080 and (((ip[2:2] - ((ip[0]&0xf)<<2)) - ((tcp[12]&0xf0)>>2)) != 0)" | egrep -a --line-buffered ".+(GET |HTTP\/|POST )|^[A-Za-z0-9-]+: " | perl -nle 'BEGIN{$|=1} { s/.*?(GET |HTTP\/[0-9.]* |POST )/\n$1/g; print }'

Beberapa penjelasan:

  • sudo stdbuf -oL -eL membuat tcpdump menjalankan line-buffered
  • filter ajaib tcpdump dijelaskan secara rinci di sini: https://stackoverflow.com/questions/11757477/understanding-tcpdump-filter-bit-masking
  • grep mencari baris apa pun dengan GET, HTTP / atau POST; atau garis apa pun yang terlihat seperti tajuk (huruf dan angka diikuti dengan titik dua)
  • BEGIN {$ | = 1} menyebabkan perl menjalankan line-buffered
  • s /.*? (DAPATKAN | HTTP / [0-9.] * | POST) / \ n $ 1 / g menambahkan baris baru sebelum awal setiap permintaan atau respons baru

1
Bagus sekali. Bisakah Anda menambahkan rincian lebih lanjut tentang bagaimana ekspresi tcpdump itu bekerja?
Vivek Thomas

1
bagian 'ip' di parens dijelaskan di sini, misalnya: stackoverflow.com/questions/11757477/…
Kibber

Anda baru saja menyelamatkan saya dari sakit kepala. Sayang saya hanya bisa +1.
Aaron Dobbing

19

Anda dapat mendekati sesuatu yang Anda inginkan dengan menggunakan -A, mis

E....c@.@...
.....Ng.d.P..Ch.).....s.......
.A...u.BHEAD / HTTP/1.1
User-Agent: curl/7.29.0
Host: www.google.com
Accept: */*

Jangan lupa gunakan -s 0untuk memastikan Anda mendapatkan seluruh paket.

Atau Anda dapat menggunakan wiresharkuntuk melihat header secara interaktif.


1
Mencoba -Adan -s 0, mendapat hasil yang sama.
Adam Matan

2
Coba tanpa -X.
Flup

tcpdump -s 0 -A dst port 4080memberi E..e..@.?.$bb...b....:......w........Q.....G..1.b..HEAD /dapper_serving/AdMonkey?ping=1 HTTP/1.0.
Adam Matan

... yang merupakan sesuatu yang dekat dengan apa yang Anda inginkan. Baca dari 'KEPALA' - ini adalah muatan HTTP. Jika Anda sudah pasti menggunakan -s 0dan tidak ada hasilnya HTTP/1.0, tidak ada tajuk HTTP dalam permintaan.
Flup

Terima kasih. Apakah ada cara untuk mencetak hanya header teks, tanpa muatan biner?
Adam Matan

Dengan menggunakan situs kami, Anda mengakui telah membaca dan memahami Kebijakan Cookie dan Kebijakan Privasi kami.
Licensed under cc by-sa 3.0 with attribution required.