Bir sunucu neden bir SYN paketine yanıt olarak bir SYN / ACK paketi göndermiyor?


46

Son zamanlarda, web sitelerimize göz atan mac ve Linux kullanıcıları ile sınırlı olan bir TCP bağlantı sorununun farkında olduk.

Kullanıcı bakış açısından, web sitelerimizle (> 11 saniye) çok uzun bir bağlantı süresi sunuyor.

Bu sorunun teknik imzasını bulmayı başardık, ancak neden olduğunu veya nasıl düzeltileceğini çözemedik.

Temel olarak, olan şey, müşterinin makinesinin TCP bağlantısını kurmak için SYN paketini gönderiyor olması ve web sunucusunun bunu alması, ancak SYN / ACK paketiyle yanıt vermemesidir. İstemci birçok SYN paketi gönderdikten sonra, sunucu sonunda bir SYN / ACK paketi ile yanıt verir ve bağlantının kalanı için her şey yolundadır.

Ve elbette, soruna yol açan: aralıklı ve her zaman gerçekleşmiyor (her zaman% 10-30 arasında olmasına rağmen)

Fedora 12 Linux'u işletim sistemi olarak ve Nginx'i web sunucusu olarak kullanıyoruz.

Wireshark analizinin ekran görüntüsü

Wireshark analizinin ekran görüntüsü

Güncelleme:

İstemcide pencere ölçeklendirmeyi kapatmak, sorunun olmasını engelledi. Şimdi bir sunucu tarafı çözünürlüğüne ihtiyacım var (tüm istemcilerin bunu yapmasını sağlayamıyoruz) :)

Son Güncelleme:

Çözüm, sunucularımızda hem halka açık olan hem de TCP pencere ölçeklendirmeyi ve TCP zaman damgalarını kapatmaktı .


1
Bunun biraz tcpdump olduğunu görmemiz gerekecek.
coredump

Ters DNS tabanlı herhangi bir işlem veya kuralınız var mı? Daha sonra yalnızca istemci ile sunucu arasındaki bağlantıya bakmanız gerekebilir. Belki bir DNS araması zaman aşımına uğradı?
Zoredache

@coredump: Buradaki konu gösterileri olduğunu Wireshark analizi bir ekran görüntüsü var i.imgur.com/Bnzrm.png (sadece akışı olarak nasıl dışa çözemedim ....)
codemonkey

@Zoredache: hayır, ters DNS'e dayalı herhangi bir işlem veya kural yok. Bu halka açık bir web sunucusu ve herkesin erişimine izin
veriyoruz

Sadece bir ipucu, ancak sunucuda herhangi bir gelen bağlantı oranını sınırlandırıyor musunuz? Diyelim ki, iptables ile?
Steven Pazartesi,

Yanıtlar:


15

Bu aynı sorunu yaşadık. Sadece TCP zaman damgalarını devre dışı bırakmak sorunu çözdü.

sysctl -w net.ipv4.tcp_timestamps=0

Bu değişikliği kalıcı yapmak için giriş yapın /etc/sysctl.conf.

TCP Pencere Ölçeği seçeneğini devre dışı bırakma konusunda çok dikkatli olun. Bu seçenek internet üzerinden maksimum performans sağlamak için önemlidir . 10 megabit / sn bağlantısı olan bir kişi, gidiş dönüş süresi (temelde ping ile aynı) 55 ms'den daha fazla ise, alt-transfer aktarımına sahip olacaktır .

Aynı NAT'ın arkasında birden fazla cihaz varken bu sorunu gerçekten fark ettik. Sunucunun, zaman damgası alanlarına tamamen farklı değerler koyduğundan, Android cihazlardan ve OSX makinelerinden gelen zaman damgalarını aynı anda görmekle karıştırıldığından şüpheleniyorum.


4
Burada başka birinin aşağı indiğim tavşan deliğinden geçmesi durumunda: Yüksek trafik bağlantısında ciddi performans sonuçlarına neden olabilecek TCP zaman damgalarını veya pencere ölçeklendirmesini kapatmadan önce, tcp_tw_recycle'ın sizin sorununuz olup olmadığını kontrol edin: stackoverflow .com / sorular / 8893888 /…
nefte

12

Benim durumumda aşağıdaki komut Linux sunucusundan eksik SYN / ACK cevaplarıyla sorunu düzeltti:

sysctl -w net.ipv4.tcp_tw_recycle=0

TCP zaman damgalarını devre dışı bırakmaktan daha doğru olduğunu düşünüyorum, çünkü TCP zaman damgaları yüksek performans için yararlıdır (PAWS, pencere ölçeklendirmesi vb.).

tcp_tw_recycleAçıkça belgelenmesi, birçok NAT yönlendiricisinin zaman damgalarını koruduğu ve aynı IP’nin zaman damgaları tutarlı olmadığı için PAWS’ın başladığı için etkinleştirilmesinin önerilmediğini açıkça belirtir.

   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.

1
Burada iyi bir açıklama: vincent.bernat.im/tr/blog/2014-tcp-time-wait-state-linux Sunucu tarafında, asla NAT aygıtınız olmadığından emin olmadığınız sürece net.ipv4.tcp_tw_recycle işlevini etkinleştirmeyin Karışımda.
Gnought

1
Benim durumumda, net.ipv4.tcp_tw_recyclegerçek sebep budur. Teşekkürler.
bluearrow

Son çekirdekte tcp_tw_recycle kaldırıldı. Benzer başka bir çözüm var mı? @nephtes, zaman damgasının performansının zarar görmesini engellemek anlamına gelir.
MappaM

Tcp_tw_recycle kaldırıldığı için sorun, yalnızca varsayılan olmayan bir tcp_tw_recycle değeriyle olduğu gibi tekrar oluşmamalıdır.
lav

5

Merak ediyorum, ama neden SYN paketi için (çerçeve # 539; kabul edilen), WS ve TSV alanları "Bilgi" sütununda eksik?

WS, TCP Pencere Ölçeklemesi ve TSV, Zaman Damgası Değeridir . Her ikisi de tcp.options alanı altında bulunur ve Wireshark hala varsa bunları göstermelidir. Belki de İstemci TCP / IP yığını, 8. girişimde farklı SYN paketlerini yeniden göndermiştir ve neden aniden onaylanmasının nedeni budur?

Bize çerçeve 539 iç değerleri verebilir misiniz? SYN / ACK, her zaman WS'nin etkin olmadığı bir SYN paketi için mi geliyor?


@Ansis: işte 539 numaralı çerçeve için bazı ekran görüntüleri (iki bölüm halinde yapmak zorunda kaldı): i.imgur.com/D84GC.png & i.imgur.com/4riq3.png
codemonkey

@codemonkey: 8. SYN paketiniz ilk yedi SYN paketinden farklı görünüyor. Sunucu, SYN / ACK ile istemcinin SYN'sine, yalnızca tcp.options alanı 8 bayt olduğunda yanıt veriyor mu (İlk yedi SYN paketinde muhtemelen 20 bayt boyutunda tcp.options var.)? Sorunun çözülüp çözülmediğini görmek için istemci tarafında TCP pencere ölçeklendirmesini devre dışı bırakabilir misiniz? Sunucu tarafında TCP / IP yığınıyla ilgili bir sorun veya bir yerde yanlış yapılandırılmış güvenlik duvarı gibi görünüyor ...
Hans Solo

@Ansis: Evet, onu işaret ettiğinden beri bakıyorum ve diğer tüm SYN paketleri 24 bayt. İstemcide pencere ölçeklendirmeyi devre dışı bırakmayı deneyeceğim ve sonuçları sabah tekrar kontrol edeceğim.
codemonkey

@Ansis: istemcide ölçeklendirme pencerelerini kapatmak, sorunun olmasını engelledi. Teşekkürler! Ancak, şimdi bunu sunucu tarafında nasıl çözeceğimi çözmem gerekiyor (tüm müşterilerimizi pencereleri ölçeklendirmeyi devre dışı bırakamıyoruz) :) :) Söz konusu sunucuda net.ipv4.tcp_windows_scaling = 1
codemonkey

@Codemonkey: WS'yi tüm istemcilerde devre dışı bırakmanın bir çözüm olmadığını kabul ediyorum, ancak sorunu en azından WS / Paket Boyutu sorunlarıyla takip ettik. Nedenini daha fazla bulmak için güvenlik duvarınızın nasıl yapılandırıldığına bakmalıyız. WS ile farklı TCP portlarına TCP bağlantısı kurabilir misiniz? Farklı kaynak IP'lerinden mi?
Hans Solo

4

Biz de aynı problemle karşılaştık (senkronizasyon göndermemek için sunucuya sabitlemek biraz zaman aldı).

"Çözüm, tcp pencerelerini ölçeklendirmeyi ve sunucularımızda halka açık olan tcp zaman damgalarını kapatmaktı."


2

Ansis'in söylediklerini sürdürmek için, güvenlik duvarı TCP Windows Ölçeklendirmeyi desteklemediğinde böyle sorunlar gördüm. Bu iki ana bilgisayar arasında hangi marka / model güvenlik duvarı var?


Güvenlik duvarı, iptables kullanan bir Fedora 13 kutusudur. net.ipv4.tcp_windows_scaling bu makinede de 1 olarak ayarlanmıştır
codemonkey

2

Eksik SYN / ACK, güvenlik duvarındaki SYNFLOOD korumanızın çok düşük limitlerinden kaynaklanabilir. Sunucu kullanıcınıza kaç tane bağlantı kurduğuna bağlıdır. Spdy kullanmak bağlantı sayısını azaltacaktır ve net.ipv4.tcp_timestampskapatmanın işe yaramadığı durumlarda yardımcı olabilir.


1

Bu, bekleme süresi dolduğunda, dinleyen bir TCP soketinin davranışıdır.

Ngnix, backlog argümanının yapılandırmada ayarlanmasına izin verir: http://wiki.nginx.org/HttpCoreModule#listen

dinle 80 backlog = num

Num değerini varsayılan değerden daha büyük bir şeye ayarlamayı deneyin, 1024 gibi.

Tam bir dinleme sırasının gerçekte senin sorunun olduğuna dair hiçbir garanti veremem, ama bu kontrol edilmesi gereken ilk şey.


Bahşiş için teşekkürler. Ben deneyeceğim. Biriktirme işlemini OS düzeyinde belirledik, ancak Nginx config'te açıkça değil. Sonuç ile güncelleyeceğim.
codemonkey

davranışını hiç değiştirmedi. Tahmin et sorun değil mi? ya da tek sorun ...
codemonkey

1
uygulama seviyesi backlog parametresi, tamamlanmış tcp bağlantıları için kuyruk boyutunu kontrol eder, yani 3 yollu el sıkışma tamamlandı, yani syn-ack aldı - bu yüzden OP durumu ile
eşleşmiyor

1

Linux TCP istemcilerinin 3 denemeden sonra SYN paketlerini değiştirdiklerini ve Pencere Ölçeklendirme seçeneğini kaldırdıklarını keşfettim. Sanırım çekirdek geliştiriciler bunun internetteki bağlantı başarısızlığının ortak bir nedeni olduğunu düşünüyorlardı.

Bu istemcilerin neden 11 saniye sonra bağlantı kurmayı başardıklarını açıklıyor (penceresiz TCP SYN, varsayılan ayarlarla kısa testimde 9 saniye sonra oluyor)


0

Benzer bir problemim vardı, ama benim durumumda yanlış hesaplanan TCP sağlama toplamıydı. Müşteri bir veth arkasındaydı ve çalışan ethtool -K veth0 rx kapalı tx off yaptı.

Sitemizi kullandığınızda şunları okuyup anladığınızı kabul etmiş olursunuz: Çerez Politikası ve Gizlilik Politikası.
Licensed under cc by-sa 3.0 with attribution required.