Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Chào mọi người! Tên tôi là Dmitry Samsonov, tôi làm quản trị viên hệ thống hàng đầu tại Odnoklassniki. Chúng tôi có hơn 7 nghìn máy chủ vật lý, 11 nghìn container trên đám mây và 200 ứng dụng, với nhiều cấu hình khác nhau tạo thành 700 cụm khác nhau. Phần lớn các máy chủ chạy CentOS 7.
Ngày 14/2018/XNUMX thông tin về lỗ hổng FragmentSmack được công bố
(CVE-2018-5391) và SegmentSmack (CVE-2018-5390). Đây là những lỗ hổng có vectơ tấn công mạng và điểm số khá cao (7.5), đe dọa từ chối dịch vụ (DoS) do cạn kiệt tài nguyên (CPU). Bản sửa lỗi kernel cho FragmentSmack chưa được đề xuất vào thời điểm đó, hơn nữa, nó xuất hiện muộn hơn nhiều so với việc công bố thông tin về lỗ hổng. Để loại bỏ SegmentSmack, chúng tôi khuyên bạn nên cập nhật kernel. Bản thân gói cập nhật đã được phát hành cùng ngày, tất cả những gì còn lại là cài đặt nó.
Không, chúng tôi hoàn toàn không phản đối việc cập nhật kernel! Tuy nhiên, có những sắc thái...

Cách chúng tôi cập nhật kernel khi sản xuất

Nói chung, không có gì phức tạp:

  1. Tải xuống các gói;
  2. Cài đặt chúng trên một số máy chủ (bao gồm cả máy chủ lưu trữ đám mây của chúng tôi);
  3. Hãy chắc chắn rằng không có gì bị hỏng;
  4. Đảm bảo rằng tất cả cài đặt kernel tiêu chuẩn được áp dụng mà không có lỗi;
  5. Đợi vài ngày;
  6. Kiểm tra hiệu suất máy chủ;
  7. Chuyển triển khai máy chủ mới sang kernel mới;
  8. Cập nhật tất cả các máy chủ theo trung tâm dữ liệu (mỗi lần một trung tâm dữ liệu để giảm thiểu ảnh hưởng đến người dùng trong trường hợp có sự cố);
  9. Khởi động lại tất cả các máy chủ.

Lặp lại cho tất cả các nhánh của hạt nhân mà chúng ta có. Tại thời điểm này là:

  • Stock CentOS 7 3.10 - dành cho hầu hết các máy chủ thông thường;
  • Vanilla 4.19 - cho chúng tôi đám mây một đám, bởi vì chúng tôi cần BFQ, BBR, v.v.;
  • Elrepo kernel-ml 5.2 - dành cho nhà phân phối tải cao, bởi vì phiên bản 4.19 từng hoạt động không ổn định nhưng vẫn cần có các tính năng tương tự.

Như bạn có thể đoán, việc khởi động lại hàng nghìn máy chủ mất nhiều thời gian nhất. Vì không phải tất cả các lỗ hổng đều nghiêm trọng đối với tất cả các máy chủ nên chúng tôi chỉ khởi động lại những lỗ hổng có thể truy cập trực tiếp từ Internet. Trong đám mây, để không hạn chế tính linh hoạt, chúng tôi không liên kết các vùng chứa có thể truy cập bên ngoài với các máy chủ riêng lẻ bằng hạt nhân mới mà khởi động lại tất cả các máy chủ mà không có ngoại lệ. May mắn thay, quy trình ở đó đơn giản hơn so với các máy chủ thông thường. Ví dụ: các vùng chứa không trạng thái có thể chỉ cần di chuyển sang máy chủ khác trong quá trình khởi động lại.

Tuy nhiên, vẫn còn rất nhiều việc phải làm và có thể mất vài tuần, còn nếu có vấn đề gì với phiên bản mới thì lên đến vài tháng. Những kẻ tấn công hiểu rất rõ điều này nên chúng cần có kế hoạch B.

FragmentSmack/SegmentSmack. Cách giải quyết

May mắn thay, đối với một số lỗ hổng, kế hoạch B tồn tại và nó được gọi là Giải pháp thay thế. Thông thường, đây là một thay đổi trong cài đặt kernel/ứng dụng có thể giảm thiểu tác động có thể xảy ra hoặc loại bỏ hoàn toàn việc khai thác lỗ hổng.

Trong trường hợp FragmentSmack/SegmentSmack đã được đề xuất Cách giải quyết này:

«Bạn có thể thay đổi giá trị mặc định 4MB và 3MB trong net.ipv4.ipfrag_high_thresh và net.ipv4.ipfrag_low_thresh (và các giá trị tương ứng của chúng cho ipv6 net.ipv6.ipfrag_high_thresh và net.ipv6.ipfrag_low_thresh) thành 256 kB và 192 kB tương ứng hoặc thấp hơn. Các thử nghiệm cho thấy mức sử dụng CPU giảm từ nhỏ đến đáng kể trong một cuộc tấn công, tùy thuộc vào phần cứng, cài đặt và điều kiện. Tuy nhiên, có thể có một số tác động về hiệu suất do ipfrag_high_thresh=262144 byte, vì mỗi lần chỉ có hai đoạn 64K có thể vừa với hàng đợi tập hợp lại. Ví dụ: có nguy cơ các ứng dụng hoạt động với các gói UDP lớn sẽ bị hỏng'.

Bản thân các thông số trong tài liệu hạt nhân được mô tả như sau:

ipfrag_high_thresh - LONG INTEGER
    Maximum memory used to reassemble IP fragments.

ipfrag_low_thresh - LONG INTEGER
    Maximum memory used to reassemble IP fragments before the kernel
    begins to remove incomplete fragment queues to free up resources.
    The kernel still accepts new fragments for defragmentation.

Chúng tôi không có UDP lớn cho các dịch vụ sản xuất. Không có lưu lượng bị phân mảnh trên mạng LAN; có lưu lượng bị phân mảnh trên WAN, nhưng không đáng kể. Không có dấu hiệu nào - bạn có thể triển khai Giải pháp thay thế!

FragmentSmack/SegmentSmack. Dòng máu đầu tiên

Vấn đề đầu tiên chúng tôi gặp phải là các vùng chứa đám mây đôi khi chỉ áp dụng một phần cài đặt mới (chỉ ipfrag_low_thresh) và đôi khi hoàn toàn không áp dụng chúng - chúng chỉ bị lỗi khi bắt đầu. Không thể tái tạo sự cố một cách ổn định (tất cả các cài đặt đều được áp dụng thủ công mà không gặp bất kỳ khó khăn nào). Việc hiểu lý do tại sao container gặp sự cố khi bắt đầu cũng không dễ dàng như vậy: không tìm thấy lỗi nào. Một điều chắc chắn là: khôi phục cài đặt sẽ giải quyết được sự cố với vùng chứa.

Tại sao áp dụng Sysctl trên máy chủ là không đủ? Vùng chứa tồn tại trong Không gian tên mạng chuyên dụng của riêng nó, vì vậy ít nhất một phần của các tham số Sysctl mạng trong thùng chứa có thể khác với máy chủ.

Cài đặt Sysctl được áp dụng chính xác như thế nào trong vùng chứa? Vì vùng chứa của chúng tôi không có đặc quyền nên bạn sẽ không thể thay đổi bất kỳ cài đặt Sysctl nào bằng cách đi vào chính vùng chứa đó - đơn giản là bạn không có đủ quyền. Để chạy các container, đám mây của chúng tôi lúc đó đã sử dụng Docker (bây giờ podman). Các tham số của vùng chứa mới đã được chuyển đến Docker thông qua API, bao gồm các cài đặt Sysctl cần thiết.
Khi tìm kiếm qua các phiên bản, hóa ra API Docker không trả về tất cả các lỗi (ít nhất là trong phiên bản 1.10). Khi chúng tôi cố gắng khởi động vùng chứa thông qua "docker run", cuối cùng chúng tôi đã thấy ít nhất một điều:

write /proc/sys/net/ipv4/ipfrag_high_thresh: invalid argument docker: Error response from daemon: Cannot start container <...>: [9] System error: could not synchronise with container process.

Giá trị tham số không hợp lệ. Nhưng tại sao? Và tại sao đôi khi nó không hợp lệ? Hóa ra Docker không đảm bảo thứ tự áp dụng các tham số Sysctl (phiên bản thử nghiệm mới nhất là 1.13.1), vì vậy đôi khi ipfrag_high_thresh đã cố gắng đặt thành 256K khi ipfrag_low_thresh vẫn là 3M, tức là giới hạn trên thấp hơn hơn giới hạn dưới, dẫn đến sai số.

Vào thời điểm đó, chúng tôi đã sử dụng cơ chế riêng của mình để cấu hình lại vùng chứa sau khi bắt đầu (đóng băng vùng chứa sau tủ đông nhóm và thực thi các lệnh trong không gian tên của vùng chứa thông qua mạng ip) và chúng tôi cũng đã thêm các thông số ghi Sysctl vào phần này. Các vấn đề đã được giải quyết.

FragmentSmack/SegmentSmack. Máu đầu tiên 2

Trước khi chúng tôi có thời gian tìm hiểu cách sử dụng Giải pháp thay thế trên đám mây, những lời phàn nàn hiếm hoi đầu tiên từ người dùng đã bắt đầu xuất hiện. Vào thời điểm đó, đã vài tuần trôi qua kể từ khi bắt đầu sử dụng Giải pháp thay thế trên các máy chủ đầu tiên. Cuộc điều tra ban đầu cho thấy rằng đã nhận được khiếu nại đối với các dịch vụ riêng lẻ chứ không phải tất cả máy chủ của các dịch vụ này. Vấn đề một lần nữa trở nên cực kỳ không chắc chắn.

Tất nhiên, trước hết, chúng tôi đã cố gắng khôi phục cài đặt Sysctl, nhưng điều này không có tác dụng gì. Nhiều thao tác khác nhau với cài đặt máy chủ và ứng dụng cũng không giúp ích được gì. Khởi động lại đã giúp. Việc khởi động lại Linux là điều không tự nhiên như chuyện bình thường đối với Windows ngày xưa. Tuy nhiên, điều đó đã giúp ích và chúng tôi cho rằng đó là "trục trặc hạt nhân" khi áp dụng các cài đặt mới trong Sysctl. Nó thật phù phiếm làm sao...

Ba tuần sau vấn đề lại tái diễn. Cấu hình của các máy chủ này khá đơn giản: Nginx ở chế độ proxy/cân bằng. Không có nhiều lưu lượng truy cập. Lưu ý giới thiệu mới: số lượng lỗi 504 trên máy khách đang tăng lên mỗi ngày (Cổng Timeout). Biểu đồ hiển thị số lượng lỗi 504 mỗi ngày đối với dịch vụ này:

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Tất cả các lỗi đều liên quan đến cùng một phần phụ trợ - về phần phụ trợ trên đám mây. Biểu đồ mức tiêu thụ bộ nhớ cho các đoạn gói trên phần phụ trợ này trông như thế này:

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Đây là một trong những biểu hiện rõ ràng nhất của vấn đề trong đồ thị của hệ điều hành. Đồng thời, trên đám mây, một sự cố mạng khác với cài đặt QoS (Kiểm soát lưu lượng) đã được khắc phục. Trên biểu đồ mức tiêu thụ bộ nhớ cho các phân đoạn gói, nó trông giống hệt nhau:

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Giả định rất đơn giản: nếu chúng trông giống nhau trên biểu đồ thì chúng có cùng lý do. Hơn nữa, bất kỳ vấn đề nào xảy ra với loại bộ nhớ này là cực kỳ hiếm.

Bản chất của vấn đề đã được khắc phục là chúng tôi đã sử dụng bộ lập lịch gói fq với cài đặt mặc định trong QoS. Theo mặc định, đối với một kết nối, nó cho phép bạn thêm 100 gói vào hàng đợi và một số kết nối, trong trường hợp thiếu kênh, bắt đầu làm tắc nghẽn hàng đợi đến dung lượng. Trong trường hợp này, các gói bị loại bỏ. Trong thống kê tc (tc -s qdisc) có thể thấy như thế này:

qdisc fq 2c6c: parent 1:2c6c limit 10000p flow_limit 100p buckets 1024 orphan_mask 1023 quantum 3028 initial_quantum 15140 refill_delay 40.0ms
 Sent 454701676345 bytes 491683359 pkt (dropped 464545, overlimits 0 requeues 0)
 backlog 0b 0p requeues 0
  1024 flows (1021 inactive, 0 throttled)
  0 gc, 0 highprio, 0 throttled, 464545 flows_plimit

“464545flow_plimit” là các gói bị rớt do vượt quá giới hạn hàng đợi của một kết nối và “dropped 464545” là tổng của tất cả các gói bị rớt của bộ lập lịch này. Sau khi tăng độ dài hàng đợi lên 1 nghìn và khởi động lại vùng chứa, sự cố đã ngừng xảy ra. Bạn có thể ngồi lại và uống một ly sinh tố.

FragmentSmack/SegmentSmack. Máu cuối cùng

Đầu tiên, vài tháng sau khi thông báo về các lỗ hổng trong kernel, bản sửa lỗi cho FragmentSmack cuối cùng đã xuất hiện (để tôi nhắc bạn rằng cùng với thông báo vào tháng 7.5, bản sửa lỗi chỉ dành cho SegmentSmack đã được phát hành), điều này đã cho chúng tôi cơ hội từ bỏ Giải pháp thay thế, điều đó đã gây cho chúng tôi khá nhiều rắc rối. Trong thời gian này, chúng tôi đã cố gắng chuyển một số máy chủ sang kernel mới và bây giờ chúng tôi phải bắt đầu lại từ đầu. Tại sao chúng tôi cập nhật kernel mà không đợi bản sửa lỗi FragmentSmack? Thực tế là quá trình bảo vệ khỏi các lỗ hổng này trùng khớp (và hợp nhất) với quá trình cập nhật CentOS (thậm chí còn mất nhiều thời gian hơn so với việc chỉ cập nhật kernel). Ngoài ra, SegmentSmack là một lỗ hổng nguy hiểm hơn và bản sửa lỗi đã xuất hiện ngay lập tức, vì vậy dù sao thì điều này cũng có lý. Tuy nhiên, chúng tôi không thể chỉ cập nhật kernel trên CentOS vì lỗ hổng FragmentSmack xuất hiện trong CentOS 7.6 chỉ được sửa trong phiên bản 7.5, vì vậy chúng tôi phải dừng cập nhật lên 7.6 và bắt đầu lại từ đầu với bản cập nhật lên XNUMX. Và điều này cũng xảy ra.

Thứ hai, những lời phàn nàn hiếm hoi của người dùng về các vấn đề đã quay trở lại với chúng tôi. Bây giờ chúng tôi đã biết chắc chắn rằng tất cả chúng đều liên quan đến việc tải tệp từ máy khách lên một số máy chủ của chúng tôi. Hơn nữa, một số lượng rất nhỏ các lượt tải lên trong tổng số lượt tải lên đã đi qua các máy chủ này.

Như chúng ta nhớ từ câu chuyện trên, việc khôi phục Sysctl không giúp ích được gì. Khởi động lại đã giúp, nhưng chỉ tạm thời.
Những nghi ngờ liên quan đến Sysctl vẫn chưa được xóa bỏ, nhưng lần này cần phải thu thập càng nhiều thông tin càng tốt. Ngoài ra còn thiếu rất nhiều khả năng tái tạo sự cố tải lên trên máy khách để nghiên cứu chính xác hơn những gì đang xảy ra.

Phân tích tất cả số liệu thống kê và nhật ký có sẵn không giúp chúng tôi hiểu rõ hơn điều gì đang xảy ra. Thiếu trầm trọng khả năng tái hiện vấn đề để “cảm nhận” một mối liên hệ cụ thể. Cuối cùng, các nhà phát triển, bằng cách sử dụng phiên bản đặc biệt của ứng dụng, đã cố gắng tái tạo ổn định các sự cố trên thiết bị thử nghiệm khi kết nối qua Wi-Fi. Đây là một bước đột phá trong cuộc điều tra. Máy khách đã kết nối với Nginx, được ủy quyền cho phần phụ trợ, vốn là ứng dụng Java của chúng tôi.

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Cuộc đối thoại về các vấn đề giống như thế này (đã được sửa ở phía proxy Nginx):

  1. Client: yêu cầu nhận thông tin về việc tải file.
  2. Máy chủ Java: phản hồi.
  3. Khách hàng: POST bằng tệp.
  4. Máy chủ Java: lỗi.

Đồng thời, máy chủ Java ghi vào nhật ký rằng 0 byte dữ liệu đã được nhận từ máy khách và proxy Nginx ghi rằng yêu cầu mất hơn 30 giây (30 giây là thời gian chờ của ứng dụng khách). Tại sao thời gian chờ và tại sao 0 byte? Từ góc độ HTTP, mọi thứ đều hoạt động như bình thường, nhưng POST với tệp dường như biến mất khỏi mạng. Hơn nữa, nó biến mất giữa máy khách và Nginx. Đã đến lúc trang bị cho mình Tcpdump! Nhưng trước tiên bạn cần hiểu cấu hình mạng. Proxy Nginx đứng sau bộ cân bằng L3 Phần mềm NF. Đường hầm được sử dụng để phân phối các gói từ bộ cân bằng L3 đến máy chủ, máy chủ này sẽ thêm các tiêu đề của nó vào các gói:

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Trong trường hợp này, mạng đến máy chủ này dưới dạng lưu lượng được gắn thẻ Vlan, mạng này cũng thêm các trường riêng của nó vào các gói:

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Và lưu lượng truy cập này cũng có thể bị phân mảnh (cùng một tỷ lệ nhỏ lưu lượng truy cập bị phân mảnh đến mà chúng ta đã nói đến khi đánh giá rủi ro từ Giải pháp thay thế), điều này cũng làm thay đổi nội dung của tiêu đề:

Cảnh giác với các lỗ hổng mang lại vòng làm việc. Phần 1: FragmentSmack/SegmentSmack

Một lần nữa: các gói được đóng gói bằng thẻ Vlan, được đóng gói bằng một đường hầm, bị phân mảnh. Để hiểu rõ hơn điều này xảy ra như thế nào, hãy theo dõi lộ trình gói từ máy khách đến proxy Nginx.

  1. Gói đạt đến bộ cân bằng L3. Để định tuyến chính xác trong trung tâm dữ liệu, gói được gói gọn trong một đường hầm và gửi tới card mạng.
  2. Do tiêu đề gói + đường hầm không vừa với MTU nên gói sẽ bị cắt thành nhiều đoạn và gửi tới mạng.
  3. Công tắc sau bộ cân bằng L3, khi nhận được gói, sẽ thêm thẻ Vlan vào đó và gửi đi.
  4. Công tắc phía trước proxy Nginx sẽ thấy (dựa trên cài đặt cổng) rằng máy chủ đang mong đợi một gói được đóng gói bằng Vlan, do đó, nó sẽ gửi gói đó như cũ mà không xóa thẻ Vlan.
  5. Linux lấy các mảnh của gói riêng lẻ và hợp nhất chúng thành một gói lớn.
  6. Tiếp theo, gói đến giao diện Vlan, nơi lớp đầu tiên được loại bỏ khỏi nó - đóng gói Vlan.
  7. Sau đó, Linux gửi nó đến giao diện Đường hầm, nơi một lớp khác được loại bỏ khỏi nó - Đóng gói đường hầm.

Khó khăn là chuyển tất cả những thứ này dưới dạng tham số cho tcpdump.
Hãy bắt đầu từ cuối: có các gói IP sạch (không có tiêu đề không cần thiết) từ máy khách, đã loại bỏ tính năng đóng gói vlan và đường hầm không?

tcpdump host <ip клиента>

Không, không có gói nào như vậy trên máy chủ. Vì vậy, vấn đề phải có sớm hơn. Có gói nào chỉ bị loại bỏ đóng gói Vlan không?

tcpdump ip[32:4]=0xx390x2xx

0xx390x2xx là địa chỉ IP của máy khách ở định dạng hex.
32:4 — địa chỉ và độ dài của trường trong đó IP SCR được ghi trong gói Đường hầm.

Địa chỉ trường phải được chọn một cách thô bạo, vì trên Internet họ viết khoảng 40, 44, 50, 54, nhưng không có địa chỉ IP ở đó. Bạn cũng có thể xem một trong các gói ở dạng hex (tham số -xx hoặc -XX trong tcpdump) và tính địa chỉ IP mà bạn biết.

Có những phân đoạn gói nào chưa được loại bỏ tính năng đóng gói Vlan và Tunnel không?

tcpdump ((ip[6:2] > 0) and (not ip[6] = 64))

Phép thuật này sẽ cho chúng ta thấy tất cả các mảnh vỡ, kể cả mảnh cuối cùng. Có lẽ, điều tương tự có thể được lọc theo IP, nhưng tôi đã không thử, vì không có nhiều gói như vậy và những gói tôi cần có thể dễ dàng tìm thấy trong luồng chung. Họ đây rồi:

14:02:58.471063 In 00:de:ff:1a:94:11 ethertype IPv4 (0x0800), length 1516: (tos 0x0, ttl 63, id 53652, offset 0, flags [+], proto IPIP (4), length 1500)
    11.11.11.11 > 22.22.22.22: truncated-ip - 20 bytes missing! (tos 0x0, ttl 50, id 57750, offset 0, flags [DF], proto TCP (6), length 1500)
    33.33.33.33.33333 > 44.44.44.44.80: Flags [.], seq 0:1448, ack 1, win 343, options [nop,nop,TS val 11660691 ecr 2998165860], length 1448
        0x0000: 0000 0001 0006 00de fb1a 9441 0000 0800 ...........A....
        0x0010: 4500 05dc d194 2000 3f09 d5fb 0a66 387d E.......?....f8}
        0x0020: 1x67 7899 4500 06xx e198 4000 3206 6xx4 [email protected].
        0x0030: b291 x9xx x345 2541 83b9 0050 9740 0x04 .......A...P.@..
        0x0040: 6444 4939 8010 0257 8c3c 0000 0101 080x dDI9...W.......
        0x0050: 00b1 ed93 b2b4 6964 xxd8 ffe1 006a 4578 ......ad.....jEx
        0x0060: 6966 0000 4x4d 002a 0500 0008 0004 0100 if..MM.*........

14:02:58.471103 In 00:de:ff:1a:94:11 ethertype IPv4 (0x0800), length 62: (tos 0x0, ttl 63, id 53652, offset 1480, flags [none], proto IPIP (4), length 40)
    11.11.11.11 > 22.22.22.22: ip-proto-4
        0x0000: 0000 0001 0006 00de fb1a 9441 0000 0800 ...........A....
        0x0010: 4500 0028 d194 00b9 3f04 faf6 2x76 385x E..(....?....f8}
        0x0020: 1x76 6545 xxxx 1x11 2d2c 0c21 8016 8e43 .faE...D-,.!...C
        0x0030: x978 e91d x9b0 d608 0000 0000 0000 7c31 .x............|Q
        0x0040: 881d c4b6 0000 0000 0000 0000 0000 ..............

Đây là hai mảnh của một gói (cùng ID 53652) có ảnh (chữ Exif hiển thị trong gói đầu tiên). Do thực tế là có các gói ở cấp độ này, nhưng không ở dạng hợp nhất trong các bãi chứa, nên vấn đề rõ ràng là ở việc lắp ráp. Cuối cùng cũng có bằng chứng tài liệu về điều này!

Bộ giải mã gói không tiết lộ bất kỳ vấn đề nào có thể ngăn cản quá trình xây dựng. Đã thử nó ở đây: hpd.gasmi.net. Lúc đầu, khi bạn cố nhét thứ gì đó vào đó, bộ giải mã không thích định dạng gói. Hóa ra có thêm hai octet giữa Srcmac và Ethertype (không liên quan đến thông tin phân đoạn). Sau khi loại bỏ chúng, bộ giải mã bắt đầu hoạt động. Tuy nhiên, nó không có vấn đề gì.
Dù người ta có thể nói gì, không có gì khác được tìm thấy ngoại trừ những Sysctl đó. Tất cả những gì còn lại là tìm cách xác định các máy chủ có vấn đề để hiểu quy mô và quyết định các hành động tiếp theo. Bộ đếm cần thiết đã được tìm thấy đủ nhanh:

netstat -s | grep "packet reassembles failed”

Nó cũng ở dạng snmpd trong OID=1.3.6.1.2.1.4.31.1.1.16.1 (ipSystemStatsReasmFails).

“Số lỗi được phát hiện bởi thuật toán lắp ráp lại IP (vì bất kỳ lý do gì: hết thời gian chờ, lỗi, v.v.).”

Trong số nhóm máy chủ mà sự cố được nghiên cứu, trên hai máy chủ, bộ đếm này tăng nhanh hơn, trên hai máy chủ chậm hơn và trên hai máy chủ khác thì nó không tăng chút nào. So sánh động lực học của bộ đếm này với động lực học của các lỗi HTTP trên máy chủ Java cho thấy mối tương quan. Nghĩa là, đồng hồ có thể được theo dõi.

Việc có một chỉ báo đáng tin cậy về các vấn đề là rất quan trọng để bạn có thể xác định chính xác liệu việc khôi phục Sysctl có giúp ích hay không, vì từ câu chuyện trước, chúng ta biết rằng điều này không thể hiểu ngay được từ ứng dụng. Chỉ báo này sẽ cho phép chúng tôi xác định tất cả các vấn đề trong quá trình sản xuất trước khi người dùng phát hiện ra.
Sau khi khôi phục Sysctl, các lỗi giám sát đã dừng lại, do đó nguyên nhân của sự cố đã được chứng minh, cũng như thực tế là việc khôi phục đã giúp ích.

Chúng tôi đã khôi phục cài đặt phân mảnh trên các máy chủ khác, nơi tính năng giám sát mới được triển khai và ở đâu đó, chúng tôi đã phân bổ nhiều bộ nhớ hơn cho các phân đoạn so với mặc định trước đây (đây là số liệu thống kê UDP, việc mất một phần không đáng chú ý so với nền tảng chung) .

Những câu hỏi quan trọng nhất

Tại sao các gói bị phân mảnh trên bộ cân bằng L3 của chúng tôi? Hầu hết các gói đến từ người dùng đến bộ cân bằng là SYN và ACK. Kích thước của các gói này là nhỏ. Nhưng vì tỷ lệ của các gói như vậy là rất lớn nên so với nền tảng của chúng, chúng tôi không nhận thấy sự hiện diện của các gói lớn bắt đầu phân mảnh.

Lý do là tập lệnh cấu hình bị hỏng lời khuyên trên các máy chủ có giao diện Vlan (có rất ít máy chủ có lưu lượng được gắn thẻ đang được sản xuất tại thời điểm đó). Advmss cho phép chúng tôi truyền tải tới khách hàng thông tin rằng các gói theo hướng của chúng tôi phải có kích thước nhỏ hơn để sau khi gắn các tiêu đề đường hầm vào chúng, chúng không bị phân mảnh.

Tại sao việc khôi phục Sysctl không giúp ích được gì nhưng việc khởi động lại thì có? Khôi phục Sysctl đã thay đổi dung lượng bộ nhớ có sẵn để hợp nhất các gói. Đồng thời, rõ ràng thực tế tràn bộ nhớ đối với các phân đoạn đã dẫn đến kết nối chậm lại, dẫn đến các phân đoạn bị trì hoãn trong một thời gian dài trong hàng đợi. Tức là quá trình này diễn ra theo chu kỳ.
Việc khởi động lại đã xóa bộ nhớ và mọi thứ trở lại trật tự.

Có thể thực hiện được mà không cần Giải pháp thay thế không? Có, nhưng có nguy cơ cao khiến người dùng không có dịch vụ trong trường hợp bị tấn công. Tất nhiên, việc sử dụng Giải pháp thay thế đã dẫn đến nhiều vấn đề khác nhau, bao gồm cả việc làm chậm một trong các dịch vụ dành cho người dùng, tuy nhiên, chúng tôi tin rằng hành động đó là hợp lý.

Rất cám ơn Andrey Timofeev (atimofeyev) để được hỗ trợ tiến hành điều tra, cũng như Alexey Krenev (thiết bịx) - dành cho công việc quan trọng là cập nhật Centos và hạt nhân trên máy chủ. Một quá trình trong trường hợp này phải được bắt đầu lại từ đầu nhiều lần, đó là lý do tại sao nó kéo dài trong nhiều tháng.

Nguồn: www.habr.com

Thêm một lời nhận xét