Mengapa server tidak mengirim paket SYN / ACK sebagai tanggapan terhadap paket SYN

46

Akhir-akhir ini, kami menyadari masalah koneksi TCP yang sebagian besar terbatas pada pengguna mac dan Linux yang menelusuri situs web kami.

Dari perspektif pengguna, ini menghadirkan dirinya sebagai waktu koneksi yang sangat lama ke situs web kami (> 11 detik).

Kami telah berhasil melacak tanda tangan teknis masalah ini, tetapi tidak dapat mengetahui mengapa itu terjadi atau bagaimana cara memperbaikinya.

Pada dasarnya, apa yang terjadi adalah bahwa mesin klien mengirimkan paket SYN untuk membuat koneksi TCP dan server web menerimanya, tetapi tidak merespons dengan paket SYN / ACK. Setelah klien mengirim banyak paket SYN, server akhirnya merespons dengan paket SYN / ACK dan semuanya baik-baik saja selama sisa koneksi.

Dan, tentu saja, kicker untuk masalah: itu berselang dan tidak terjadi setiap saat (meskipun itu terjadi antara 10-30% dari waktu)

Kami menggunakan Fedora 12 Linux sebagai OS dan Nginx sebagai server web.

Cuplikan layar analisis wireshark

Cuplikan layar analisis wireshark

Memperbarui:

Mematikan penskalaan jendela pada klien menghentikan masalah terjadi. Sekarang saya hanya perlu resolusi sisi server (kami tidak dapat membuat semua klien melakukan ini) :)

Pembaruan Terakhir:

Solusinya adalah mematikan penskalaan jendela TCP dan cap waktu TCP pada server kami yang dapat diakses oleh publik.

codemonkey
sumber
1
Saya pikir kita perlu melihat beberapa hal terjadi.
coredump
Apakah Anda memiliki ACL atau aturan berdasarkan DNS terbalik? Anda mungkin perlu melihat lebih dari sekadar koneksi antara klien dan server. Mungkin pencarian DNS sedang kehabisan waktu?
Zoredache
@coredump: inilah cuplikan layar analisis wireshark yang menunjukkan masalah i.imgur.com/Bnzrm.png (tidak dapat menemukan cara mengekspor hanya aliran ....)
codemonkey
@Zoredache: tidak, kami tidak memiliki ACL atau aturan apa pun berdasarkan DNS terbalik. Ini adalah server web yang menghadap publik dan kami mengizinkan semua orang untuk mengaksesnya
codemonkey
Hanya firasat, tetapi apakah Anda melakukan segala jenis pembatasan koneksi masuk pada server? Katakan, dengan iptables?
Steven Monday

Jawaban:

15

Kami memiliki masalah yang sama persis ini. Hanya menonaktifkan cap waktu TCP memecahkan masalah.

sysctl -w net.ipv4.tcp_timestamps=0

Untuk membuat perubahan ini permanen, buat entri di /etc/sysctl.conf.

Berhati-hatilah untuk menonaktifkan opsi Skala Jendela TCP. Ini pilihan adalah penting untuk memberikan performa yang maksimal melalui internet. Seseorang dengan koneksi 10 megabit / detik akan memiliki transfer suboptimal jika waktu pulang pergi (pada dasarnya sama dengan ping) lebih dari 55 ms.

Kami benar-benar memperhatikan masalah ini ketika ada beberapa perangkat di belakang NAT yang sama. Saya menduga bahwa server mungkin bingung melihat cap waktu dari perangkat Android dan mesin OSX pada saat yang sama karena mereka meletakkan nilai yang sama sekali berbeda di bidang cap waktu.

mcdizzle
sumber
4
Jika seseorang berakhir di sini melalui lubang kelinci yang sama dengan yang baru saja saya turun: Sebelum mematikan cap waktu TCP atau penskalaan jendela, yang mungkin memiliki konsekuensi kinerja yang parah pada tautan lalu lintas tinggi, periksa untuk melihat apakah tcp_tw_recycle adalah masalah Anda: stackoverflow .com / pertanyaan / 8893888 / ...
nephtes
12

Dalam kasus saya, perintah berikut memperbaiki masalah dengan tidak adanya balasan SYN / ACK dari server Linux:

sysctl -w net.ipv4.tcp_tw_recycle=0

Saya pikir itu lebih benar daripada menonaktifkan cap waktu TCP, karena cap waktu TCP berguna untuk kinerja tinggi (PAWS, skala jendela, dll).

Dokumentasi pada tcp_tw_recyclesecara eksplisit menyatakan bahwa tidak disarankan untuk mengaktifkannya, karena banyak router NAT menyimpan stempel waktu dan karenanya PAWS masuk, karena stempel waktu dari IP yang sama tidak konsisten.

   tcp_tw_recycle (Boolean; default: disabled; since Linux 2.4)
          Enable fast recycling of TIME_WAIT sockets.  Enabling this
          option is not recommended for devices communicating with the
          general Internet or using NAT (Network Address Translation).
          Since some NAT gateways pass through IP timestamp values, one
          IP can appear to have non-increasing timestamps.  See RFC 1323
          (PAWS), RFC 6191.
lav
sumber
1
penjelasan yang baik di sini: vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux Di sisi server, jangan aktifkan net.ipv4.tcp_tw_recycle kecuali Anda cukup yakin Anda tidak akan pernah memiliki perangkat NAT dalam campuran.
Gnought
1
Dalam kasus saya, net.ipv4.tcp_tw_recycleadalah alasan sebenarnya. Terima kasih.
bluearrow
tcp_tw_recycle telah dihapus di kernel baru-baru ini. Apakah ada solusi lain yang sama? @nephtes menyiratkan penonaktifan stempel waktu mengganggu kinerja.
MappaM
Karena tcp_tw_recycle telah dihapus, masalahnya tidak boleh terjadi lagi karena hanya terjadi dengan nilai tcp_tw_recycle yang tidak standar.
lav
5

Hanya ingin tahu, tetapi mengapa untuk paket SYN (frame # 539; yang diterima), bidang WS dan TSV hilang di kolom "Info"?

WS adalah TCP Window Scaling dan TSV adalah Nilai Timestamp . Keduanya ditemukan di bawah bidang tcp.options dan Wireshark masih harus menunjukkannya jika ada. Mungkin Client TCP / IP stack membenci paket SYN yang berbeda pada upaya ke-8 dan itulah alasan mengapa tiba-tiba diakui?

Bisakah Anda memberi kami nilai internal frame 539? Apakah SYN / ACK selalu datang untuk paket SYN yang tidak memiliki WS diaktifkan?

Hans Solo
sumber
@Ansis: inilah beberapa cuplikan layar untuk detail bingkai 539 (harus melakukannya dalam dua bagian): i.imgur.com/D84GC.png & i.imgur.com/4riq3.png
codemonkey
@codemonkey: Paket SYN ke-8 Anda tampaknya berbeda dari tujuh paket SYN pertama. Apakah server merespons dengan SYN / ACK ke SYN klien hanya ketika bidang tcp.options berukuran 8 byte (Tujuh paket SYN pertama mungkin memiliki tcp.pilihan ukuran 20 byte.)? Bisakah Anda menonaktifkan penskalaan jendela TCP di sisi klien untuk melihat apakah masalahnya hilang? Sepertinya ada masalah dengan TCP / IP stack di sisi server atau firewall yang salah konfigurasi di suatu tempat ...
Hans Solo
@Ansis: yeah, saya telah melihat itu sejak Anda menunjukkannya dan semua paket SYN lainnya adalah 24 byte. Saya akan mencoba menonaktifkan penskalaan jendela pada klien dan memeriksa kembali hasilnya di pagi hari.
codemonkey
@Ansis: mematikan penskalaan windows pada klien menghentikan masalah terjadi. Terima kasih! Namun, sekarang saya perlu mencari cara untuk memperbaikinya di sisi server (karena kami tidak dapat membuat semua klien kami menonaktifkan penskalaan windows) :) Server yang dimaksud memang memiliki net.ipv4.tcp_windows_scaling = 1
codemonkey
@Codemonkey: Saya setuju bahwa menonaktifkan WS pada semua klien bukanlah solusi, tetapi kami setidaknya telah melacak masalah ini ke masalah WS / Packet Size. Untuk mengetahui penyebabnya lebih lanjut, kita harus melihat bagaimana firewall Anda dikonfigurasi. Bisakah Anda membuat koneksi TCP dengan WS ke berbagai port TCP? Dari IP sumber yang berbeda?
Hans Solo
4

Kami hanya mengalami masalah yang sama persis (butuh waktu cukup lama untuk menyematkannya ke server tidak mengirim syn-ack).

"Solusinya adalah mematikan penskalaan jendela tcp dan stempel waktu tcp di server kami yang dapat diakses oleh publik."

Alex Li
sumber
2

Untuk menjalankan apa yang telah dinyatakan Ansis, saya telah melihat masalah seperti ini ketika firewall tidak mendukung TCP Windows Scaling. Apa yang membuat / model firewall antara dua host ini?

joeqwerty
sumber
Firewall adalah kotak Fedora 13 menggunakan iptables. net.ipv4.tcp_windows_scaling diatur ke 1 di mesin ini juga
codemonkey
2

SYN / ACK yang hilang dapat disebabkan oleh batas perlindungan SYNFLOOD Anda yang terlalu rendah pada firewall. Itu tergantung pada berapa banyak koneksi ke pengguna server Anda buat. Menggunakan spdy akan mengurangi jumlah koneksi dan dapat membantu dalam situasi di mana mematikan net.ipv4.tcp_timestampstidak membantu.

brablc
sumber
1

Ini adalah perilaku soket TCP yang mendengarkan ketika tumpukannya penuh.

Ngnix memungkinkan argumen backlog untuk mendengarkan diatur dalam konfigurasi: http://wiki.nginx.org/HttpCoreModule#listen

dengarkan 80 backlog = num

Coba atur num ke sesuatu yang lebih besar dari standar, seperti 1024.

Saya tidak memberikan jaminan bahwa mendengarkan penuh antrian sebenarnya adalah masalah Anda, tetapi ini adalah hal pertama yang baik untuk diperiksa.

akramer
sumber
terima kasih atas tipnya. Saya akan mencobanya. Kami telah mengatur backlog pada level OS, tetapi tidak secara eksplisit dalam konfigurasi Nginx. Saya akan memperbarui dengan hasilnya.
codemonkey
itu tidak mengubah perilaku sama sekali. Tebak, bukan itu masalahnya? atau satu-satunya masalah ...
codemonkey
1
parameter backlog level aplikasi mengontrol ukuran antrian untuk koneksi tcp yang sudah selesai yaitu jabat tangan 3 arah selesai, yaitu syn-ack diterima - sehingga tidak cocok dengan situasi OP
ygrek
1

Saya baru saja menemukan bahwa klien Linux TCP mengubah paket SYN mereka setelah 3 kali mencoba, dan menghapus opsi Window Scaling. Saya kira para pengembang kernel menemukan bahwa ini adalah penyebab umum dari kegagalan koneksi di Internet

Ini menjelaskan mengapa klien ini berhasil terhubung setelah 11 detik (TCP SYN tanpa jendela terjadi setelah 9 detik dalam pengujian singkat saya dengan pengaturan default)

Jeroen van Bemmel
sumber
0

Saya memiliki masalah yang sama, tetapi dalam kasus saya itu adalah checksum TCP yang salah dihitung. Klien berada di belakang veth dan menjalankan ethtool -K veth0 rx off tx off melakukan trik.

Baroudi Safwen
sumber