Tại sao máy chủ không gửi gói SYN / ACK để phản hồi gói SYN


46

Gần đây, chúng tôi đã nhận ra vấn đề kết nối TCP chủ yếu giới hạn ở người dùng mac và Linux duyệt trang web của chúng tôi.

Từ góc độ người dùng, nó thể hiện thời gian kết nối thực sự dài với các trang web của chúng tôi (> 11 giây).

Chúng tôi đã cố gắng theo dõi chữ ký kỹ thuật của vấn đề này, nhưng không thể hiểu tại sao nó lại xảy ra hoặc cách khắc phục nó.

Về cơ bản, điều đang xảy ra là máy của khách hàng đang gửi gói SYN để thiết lập kết nối TCP và máy chủ web nhận được nó, nhưng không phản hồi với gói SYN / ACK. Sau khi máy khách đã gửi nhiều gói SYN, cuối cùng máy chủ sẽ phản hồi với gói SYN / ACK và mọi thứ đều ổn cho phần còn lại của kết nối.

Và, tất nhiên, tác nhân gây ra vấn đề: nó không liên tục và không xảy ra mọi lúc (mặc dù nó xảy ra trong khoảng 10-30% thời gian)

Chúng tôi đang sử dụng Fedora 12 Linux làm HĐH và Nginx làm máy chủ web.

Ảnh chụp màn hình phân tích wireshark

Ảnh chụp màn hình phân tích wireshark

Cập nhật:

Tắt tỷ lệ cửa sổ trên máy khách đã ngăn sự cố xảy ra. Bây giờ tôi chỉ cần một độ phân giải phía máy chủ (chúng tôi không thể khiến tất cả khách hàng làm điều này) :)

Cập nhật cuối cùng:

Giải pháp là tắt cả hai cửa sổ TCP dấu thời gian TCP trên các máy chủ của chúng tôi có thể truy cập công khai.


1
Tôi nghĩ rằng chúng ta sẽ cần phải thấy một số tcpdump của nó xảy ra.
coredump

Bạn có bất kỳ acls hoặc quy tắc dựa trên DNS ngược? Bạn có thể cần xem xét nhiều hơn sau đó chỉ là kết nối giữa máy khách và máy chủ. Có lẽ một tra cứu DNS đã hết thời gian?
Zoredache

@coredump: đây là ảnh chụp màn hình phân tích wireshark cho thấy vấn đề i.imgur.com/Bnzrm.png (không thể tìm ra cách xuất chỉ luồng ....)
codemonkey 15/211

@Zoredache: không, chúng tôi không có bất kỳ quy tắc hoặc quy tắc nào dựa trên DNS ngược. Đây là một máy chủ web đối mặt công khai và chúng tôi cho phép mọi người truy cập nó
codemonkey

Chỉ là linh cảm, nhưng bạn có đang thực hiện bất kỳ loại giới hạn tốc độ kết nối đến nào trên máy chủ không? Nói, với iptables?
Steven Thứ Hai

Câu trả lời:


15

Chúng tôi đã có chính xác vấn đề này. Chỉ cần vô hiệu hóa dấu thời gian TCP đã giải quyết vấn đề.

sysctl -w net.ipv4.tcp_timestamps=0

Để thực hiện thay đổi này vĩnh viễn, hãy thực hiện một mục /etc/sysctl.conf.

Hãy cẩn thận về việc tắt tùy chọn TCP Window Scale. Đây tùy chọn là rất quan trọng trong việc cung cấp hiệu suất tối đa qua internet. Ai đó có kết nối 10 megabit / giây sẽ có chuyển khoản dưới mức tối đa nếu thời gian khứ hồi (về cơ bản giống như ping) là hơn 55 ms.

Chúng tôi thực sự nhận thấy vấn đề này khi có nhiều thiết bị đằng sau cùng một NAT. Tôi nghi ngờ rằng máy chủ có thể đã nhầm lẫn khi nhìn thấy dấu thời gian từ các thiết bị Android và máy OSX cùng một lúc vì chúng đặt các giá trị hoàn toàn khác nhau trong các trường dấu thời gian.


4
Trong trường hợp có người khác kết thúc ở đây thông qua cùng một lỗ thỏ mà tôi vừa đi xuống: Trước khi tắt dấu thời gian TCP hoặc chia tỷ lệ cửa sổ, điều này có thể gây hậu quả nghiêm trọng đối với liên kết lưu lượng truy cập cao, hãy kiểm tra xem liệu tcp_tw_recycle có phải là vấn đề của bạn không: stackoverflow .com / câu hỏi / 8893888 /
Hoài

12

Trong trường hợp của tôi, lệnh sau đã khắc phục sự cố với các câu trả lời SYN / ACK bị thiếu từ máy chủ Linux:

sysctl -w net.ipv4.tcp_tw_recycle=0

Tôi nghĩ nó đúng hơn là vô hiệu hóa dấu thời gian TCP, vì dấu thời gian TCP rất hữu ích cho hiệu suất cao (PAWS, chia tỷ lệ cửa sổ, v.v.).

Tài liệu về các tcp_tw_recycletrạng thái rõ ràng không khuyến khích kích hoạt nó, vì nhiều bộ định tuyến NAT bảo toàn dấu thời gian và do đó PAWS khởi động, vì dấu thời gian từ cùng một IP không nhất quán.

   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
giải thích tốt tại đây: vincent.bernat.im/en/blog/2014-tcp-time-wait-state-linux Về phía máy chủ, không kích hoạt net.ipv4.tcp_tw_recycle trừ khi bạn khá chắc chắn rằng bạn sẽ không bao giờ có thiết bị NAT trong hỗn hợp.
Gniber

1
Trong trường hợp của tôi, net.ipv4.tcp_tw_recyclelà lý do thực sự. Cảm ơn.
bluearrow

tcp_tw_recycle đã bị xóa trong các nhân gần đây. Có một giải pháp khác như nhau? @nephtes ngụ ý vô hiệu hóa dấu thời gian làm tổn hại đến hiệu suất.
MappaM

Vì tcp_tw_recycle đã bị xóa, nên sự cố không xảy ra nữa vì nó chỉ xảy ra với giá trị không mặc định là tcp_tw_recycle.
lav

5

Chỉ cần tự hỏi, nhưng tại sao đối với gói SYN (khung # 539; khung được chấp nhận), các trường WS và TSV bị thiếu trong cột "Thông tin"?

WS là TCP Window Scale và TSV là Dấu thời gian Giá trị . Cả hai đều được tìm thấy trong trường tcp.options và Wireshark vẫn sẽ hiển thị chúng nếu chúng có mặt. Có thể ngăn xếp TCP / IP của máy khách phẫn nộ gói SYN khác nhau trong lần thử thứ 8 và đó là lý do tại sao nó đột nhiên được thừa nhận?

Bạn có thể cung cấp cho chúng tôi khung 539 giá trị nội bộ không? Có phải SYN / ACK luôn đi kèm với gói SYN không kích hoạt WS không?


@Ansis: đây là một số ảnh chụp màn hình để khung 539 chi tiết (phải làm điều đó trong hai phần): i.imgur.com/D84GC.png & i.imgur.com/4riq3.png
codemonkey

@codemonkey: Gói SYN thứ 8 của bạn dường như khác với bảy gói SYN đầu tiên. Có phải máy chủ chỉ phản hồi với SYN / ACK với SYN của máy khách khi trường tcp.options có kích thước 8 byte (Bảy gói SYN đầu tiên có thể có tcp.options có kích thước 20 byte.)? Bạn có thể tắt tính năng mở rộng cửa sổ TCP ở phía máy khách để xem sự cố có biến mất không? Có vẻ như có vấn đề với ngăn xếp TCP / IP ở phía máy chủ hoặc tường lửa bị định cấu hình sai ở đâu đó ...
Hans Solo

@Ansis: yeah, tôi đã xem xét điều đó vì bạn đã chỉ ra và tất cả các gói SYN khác là 24 byte. Tôi sẽ thử vô hiệu hóa tỷ lệ cửa sổ trên máy khách và kiểm tra lại với kết quả vào buổi sáng.
codemonkey

@Ansis: tắt quy mô cửa sổ trên máy khách đã ngăn sự cố xảy ra. Cảm ơn! Tuy nhiên, bây giờ tôi cần tìm ra cách khắc phục vấn đề này ở phía máy chủ (vì chúng tôi không thể làm cho tất cả các máy khách của mình vô hiệu hóa tỷ lệ cửa sổ) :) Máy chủ được đề cập có net.ipv4.tcp_windows_scaling = 1
codemonkey

@Codemonkey: Tôi đồng ý rằng việc tắt WS trên tất cả các máy khách không phải là một giải pháp, nhưng ít nhất chúng tôi đã theo dõi vấn đề đối với các vấn đề về Kích thước WS / Gói. Để tìm hiểu thêm nguyên nhân, chúng ta nên xem xét cách cấu hình tường lửa của bạn. Bạn có thể thiết lập kết nối TCP với WS tới các cổng TCP khác nhau không? Từ các IP nguồn khác nhau?
Hans Solo

4

Chúng tôi vừa gặp vấn đề chính xác (thực sự mất khá nhiều thời gian để ghim nó vào máy chủ không gửi syn-ack).

"Giải pháp là tắt quy mô cửa sổ tcp và dấu thời gian tcp trên các máy chủ của chúng tôi có thể truy cập công khai."


2

Để thực hiện những gì Ansis đã nêu, tôi đã thấy các vấn đề như thế này khi tường lửa không hỗ trợ TCP Windows Scaling. Tường lửa tạo / mô hình nào nằm giữa hai máy chủ này?


Tường lửa là một hộp Fedora 13 sử dụng iptables. net.ipv4.tcp_windows_scaling cũng được đặt thành 1 trên máy này
codemonkey

2

Việc thiếu SYN / ACK có thể được gây ra bởi các giới hạn quá thấp của bảo vệ SYNFLOOD trên tường lửa. Nó phụ thuộc vào số lượng kết nối đến người dùng máy chủ của bạn tạo ra. Sử dụng spdy sẽ làm giảm số lượng kết nối và có thể giúp đỡ trong trường hợp net.ipv4.tcp_timestampstắt không giúp ích.


1

Đây là hành vi của một ổ cắm TCP lắng nghe khi tồn đọng của nó đầy.

Ngnix cho phép đối số tồn đọng nghe được thiết lập trong cấu hình: http://wiki.nginx.org/HttpCoreModule#listen

nghe 80 backlog = num

Hãy thử đặt num thành một cái gì đó lớn hơn mặc định, như 1024.

Tôi không đảm bảo rằng một hàng đợi nghe đầy đủ thực sự là vấn đề của bạn, nhưng đây là điều đầu tiên tốt để kiểm tra.


cảm ơn vì tiền hỗ trợ. Tôi sẽ thử nó. Chúng tôi đã đặt tồn đọng ở cấp HĐH, nhưng không rõ ràng trong cấu hình Nginx. Tôi sẽ cập nhật với kết quả.
codemonkey

nó đã không thay đổi hành vi. Đoán xem, đó không phải là vấn đề? hoặc vấn đề duy nhất ...
codemonkey

1
Tham số tồn đọng ở mức ứng dụng kiểm soát kích thước của hàng đợi cho các kết nối tcp đã hoàn thành, tức là bắt tay 3 bước, tức là đã nhận được syn-ack - vì vậy nó không khớp với tình huống OP
ygrek

1

Tôi mới phát hiện ra rằng các máy khách TCP TCP thay đổi gói SYN của chúng sau 3 lần thử và loại bỏ tùy chọn Thu nhỏ cửa sổ. Tôi đoán các nhà phát triển kernel đã hiểu rằng đây là nguyên nhân phổ biến gây ra lỗi kết nối trên Internet

Nó giải thích lý do tại sao các máy khách này quản lý để kết nối sau 11 giây (TCP SYN không có cửa sổ xảy ra sau 9 giây trong thử nghiệm ngắn gọn của tôi với cài đặt mặc định)


0

Tôi đã có một vấn đề tương tự, nhưng trong trường hợp của tôi, đó là tổng kiểm tra TCP đã được tính toán sai. Khách hàng đứng sau một veth và chạy ethtool -K veth0 rx tắt tx tắt đã lừa.

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.