Vào cuối năm 2023, mạng Internet toàn cầu chứng kiến đợt tấn công từ chối dịch vụ quy mô kỷ lục khi tin tặc khai thác lỗ hổng CVE-2023-44487, hay còn gọi là tấn công HTTP/2 Rapid Reset. Với lưu lượng đỉnh điểm đạt 398 triệu yêu cầu mỗi giây—vượt xa tổng lưu lượng truy cập của toàn bộ mạng thông tin toàn cầu tại một thời điểm—chiến dịch này đã làm tê liệt hàng loạt máy chủ web, cụm proxy và nhà cung cấp điện toán đám mây.

Khác với các đợt tấn công làm tràn băng thông thô sơ bằng luồng UDP hoặc ICMP, Rapid Reset lợi dụng trực tiếp đặc tính kiến trúc cốt lõi của giao thức HTTP/2: khả năng ghép kênh đa luồng và cơ chế huỷ luồng do máy khách chủ động khởi tạo. Bằng cách gửi liên tiếp hàng nghìn yêu cầu đồng thời rồi huỷ bỏ tức thì thông qua khung RST_STREAM, kẻ tấn công gây tiêu hao tài nguyên xử lý nghiêm trọng trên máy chủ với chi phí băng thông chiều gửi cực thấp.

Đối với các cổng định tuyến biên, máy chủ proxy ngược và các giao diện điều khiển cổng VPN doanh nghiệp, việc chống chọi các đợt lũ tầng ứng dụng ghép kênh đòi hỏi nhiều hơn các giải pháp tường lửa ứng dụng web thông thường. Năng lực phòng thủ thực sự phụ thuộc vào khả năng quản lý socket, thuật toán giới hạn tốc độ luồng bằng token bucket và kiến trúc cách ly mã hoá ở Lớp 3.

Khái niệm ghép kênh HTTP/2: Luồng đồng thời và chuyển đổi trạng thái

Nhằm khắc phục tình trạng tắc nghẽn đầu hàng (head-of-line blocking) cố hữu của đường ống HTTP/1.1, IETF thiết kế HTTP/2 (RFC 9113) dựa trên cấu trúc khung nhị phân và khả năng ghép kênh hai chiều trên một kết nối TCP duy nhất.

Trong HTTP/2, quá trình trao đổi dữ liệu diễn ra thông qua các kênh logic độc lập gọi là luồng (stream). Mỗi luồng vận hành theo một máy trạng thái hữu hạn rõ ràng:

                                +--------+
                        send PP |        | recv PP
                       ,--------|  idle  |--------.
                      /         |        |         \
                     v          +--------+          v
              +----------+                      +----------+
              | reserved |                      | reserved |
              | (local)  |                      | (remote) |
              +----------+                      +----------+
                     \                              /
                      \ send H / recv H            /
                       \                          /
                        v                        v
                        +------------------------+
                        |          open          |
                        +------------------------+
                       /          |      \        \
              recv ES /           |       \        \ send ES
                     v            |        v        v
              +----------+        |     +----------+
              |  half-   |        |     |  half-   |
              |  closed  |        |     |  closed  |
              | (remote) |        |     | (local)  |
              +----------+        |     +----------+
                     \            |            /
              send ES \           | recv RST  / recv ES
                       \          v          /
                        +--------------------+
                        |       closed       |
                        +--------------------+

Trong điều kiện vận hành chuẩn:

  1. Máy khách khởi tạo luồng bằng cách gửi khung HEADERS kèm mã định danh số lẻ.
  2. Máy chủ tiếp nhận yêu cầu, cấp phát bộ nhớ đệm, điều phối các tiến trình xử lý phía sau và phản hồi các khung DATA chứa cờ kết thúc END_STREAM (ES).
  3. Luồng chính thức chuyển sang trạng thái đóng (closed).

Để ngăn chặn việc tiêu thụ tài nguyên quá mức, RFC 9113 cho phép máy chủ công bố thông số SETTINGS_MAX_CONCURRENT_STREAMS (thường đặt ở mức 100). Máy khách cam kết không mở vượt quá số lượng luồng đang hoạt động đồng thời này.

Cơ chế lỗ hổng CVE-2023-44487: Vòng lặp huỷ luồng bất đối xứng

Lỗ hổng CVE-2023-44487 phát sinh từ cách thức RFC 9113 định nghĩa việc huỷ bỏ luồng. Khi muốn ngừng nhận dữ liệu của một yêu cầu đang xử lý, máy khách chỉ cần gửi khung RST_STREAM mang mã lỗi CANCEL (0x8) hoặc REFUSED_STREAM (0x7).

Khi nhận khung RST_STREAM, máy chủ bắt buộc phải lập tức chuyển luồng tương ứng sang trạng thái closed. Điều cốt lõi là một luồng đã đóng sẽ không còn tính vào hạn mức luồng đồng thời SETTINGS_MAX_CONCURRENT_STREAMS.

+-------------------------------------------------------------------------+
|                  HTTP/2 Rapid Reset Attack Cycle                        |
+-------------------------------------------------------------------------+
| Chuỗi khung từ máy khách (Trên một đường truyền TCP đơn lẻ)             |
|                                                                         |
| Luồng 1: [ HEADERS (GET /api/v1/auth) ] ---> Cấp phát luồng xử lý       |
| Luồng 1: [ RST_STREAM (CANCEL)        ] ---> Đưa số luồng hoạt động về 0|
|                                                                         |
| Luồng 3: [ HEADERS (GET /api/v1/auth) ] ---> Cấp phát luồng xử lý       |
| Luồng 3: [ RST_STREAM (CANCEL)        ] ---> Đưa số luồng hoạt động về 0|
|                                                                         |
| Luồng 5: [ HEADERS (GET /api/v1/auth) ] ---> Cấp phát luồng xử lý       |
| Luồng 5: [ RST_STREAM (CANCEL)        ] ---> Đưa số luồng hoạt động về 0|
+-------------------------------------------------------------------------+
                                    |
                                    v (Mất cân bằng tài nguyên tính toán)
+-------------------------------------------------------------------------+
| Phía máy chủ: Quá tải luồng xử lý, giải nén HPACK, gián đoạn gom rác    |
| Phía máy khách: Tốn rất ít băng thông, duy trì vòng lặp liên tục        |
+-------------------------------------------------------------------------+

Kẻ tấn công khai thác cơ chế này bằng cách kết hợp khung HEADERS và khung RST_STREAM ngay trong cùng một phân đoạn gói tin TCP: máy khách mở yêu cầu tiêu tốn nhiều tài nguyên rồi lập tức huỷ bỏ trong cùng luồng dữ liệu. Do việc huỷ giúp đưa bộ đếm luồng hoạt động về 0 ngay lập tức, kẻ tấn công không bao giờ vi phạm trần kết nối đồng thời, tạo ra hàng triệu thao tác xử lý áp lực lên máy chủ mỗi giây.

Bất đối xứng giao thức: Nguyên nhân các giải pháp Lớp 7 truyền thống sụp đổ

Các hệ thống tường lửa ứng dụng web thông thường và các bộ lọc bất thường tầng 7 hoàn toàn bất lực trước Rapid Reset trong những đợt bùng phát đầu tiên vì cuộc tấn công lách qua các thuật toán kiểm tra giao dịch cơ bản.

Vô hiệu hoá cơ chế đo lường hoàn tất yêu cầu

Hầu hết proxy ngược giám sát mật độ lưu lượng dựa trên số lượng giao dịch HTTP đã hoàn tất hoặc tốc độ phản hồi được ghi lại trong nhật ký. Do máy khách huỷ yêu cầu trước khi máy chủ kịp tạo phản hồi, proxy không kích hoạt các hàm giới hạn tốc độ chuẩn.

Bên cạnh đó, các thuật toán đánh giá danh tiếng địa chỉ IP theo tỷ lệ mã lỗi (như HTTP 429 hoặc 503) ghi nhận tỷ lệ lỗi bằng 0 vì máy chủ không kịp gửi bất kỳ mã phản hồi nào cho các luồng đã bị ngắt sớm.

Cạn kiệt luồng xử lý và phình bộ đệm TLS

Dù luồng được coi là đã đóng về mặt logic khi nhận RST_STREAM, việc dọn dẹp tài nguyên bên trong các máy chủ web hiện đại vẫn tiêu tốn chu kỳ tính toán lớn:

  • Bối cảnh nén HPACK: Mỗi yêu cầu làm thay đổi bảng nén động HPACK. Máy chủ buộc phải giải nén tiêu đề trước khi xử lý lệnh huỷ.
  • Điều phối luồng công việc: Các ứng dụng bất đồng bộ (như Envoy, Nginx, Go net/http) bàn giao yêu cầu cho các luồng xử lý nội bộ. Việc truyền tín hiệu huỷ bỏ tới các cơ sở dữ liệu phía sau tạo ra sự tắc nghẽn đồng bộ nghiêm trọng.
  • Chi phí giải mã TLS: Việc liên tục giải mã các bản ghi TLS và phân tích khung ở tốc độ đường truyền làm cạn kiệt CPU trong các vòng lặp mã hoá, khiến các kết nối hợp lệ bị bỏ rơi.

Các nguy cơ cạn kiệt tài nguyên do lạm dụng tín hiệu điều khiển kết nối tương tự cũng từng xuất hiện ở tầng 4, như được trình bày chi tiết trong bài phân tích về tấn công chèn cờ TCP RST và kỹ thuật làm mù kết nối.

So sánh kiến trúc: HTTP/1.1 Pipelining, HTTP/2 Rapid Reset và HTTP/3 QUIC

Để làm rõ các lỗ hổng ghép kênh, bảng dưới đây đối chiếu cơ chế xử lý luồng đồng thời qua các thế hệ giao thức mạng:

Đặc tính kiến trúc Đường ống HTTP/1.1 HTTP/2 Rapid Reset (CVE-2023-44487) HTTP/3 trên nền QUIC (RFC 9000)
Định dạng khung Văn bản ASCII thuần Khung cấu trúc nhị phân Đóng gói khung nhị phân
Cơ chế ghép kênh Tuần tự (Nghẽn đầu hàng) Đa luồng đồng thời trên TCP Các luồng độc lập trên gói tin UDP
Cơ chế ngắt luồng Tín hiệu TCP FIN / RST (Đóng cả kết nối) Khung RST_STREAM (Từng luồng riêng) Khung RESET_STREAM và STOP_SENDING
Ràng buộc đồng thời Xử lý tuần tự nghiêm ngặt SETTINGS_MAX_CONCURRENT_STREAMS Khung cấp hạn mức luồng (MAX_STREAMS)
Nguy cơ tấn công Rapid Reset Miễn nhiễm (Phải ngắt toàn bộ kết nối) Dễ tổn thương (Lặp huỷ bất đối xứng) Chống chịu tốt (Hạn mức tín dụng chặn lặp liên hồi)
Giao thức truyền tải TCP (Lớp 4) TCP (Lớp 4) Datagram UDP với mã hoá AEAD (Lớp 4)

HTTP/3 loại bỏ nguy cơ Rapid Reset dây chuyền nhờ cơ chế cấp hạn ngạch tín dụng luồng trong giao thức QUIC. Một điểm cuối QUIC không thể mở luồng mới vô tội vạ nếu chưa nhận được các khung cấp quyền MAX_STREAMS bổ sung từ máy chủ đối tác.

Tác động tới các cổng kết nối công cộng: Proxy quá tải và sự cố đám mây

Khi đợt tấn công Rapid Reset nhắm vào cổng kết nối công cộng, hệ thống sẽ sụp đổ theo ba giai đoạn:

  1. Bão hoà CPU máy chủ proxy: Thao tác giải nén tiêu đề và cập nhật bảng trạng thái luồng khiến CPU đa nhân bị khóa chặt ở mức 100%.
  2. Tràn bộ đệm socket TCP: Do kết nối TCP vẫn mở trong khi luồng liên tục bị huỷ, bộ đệm nhận của kernel (SO_RCVBUF) bị lấp đầy bởi các khung huỷ bỏ chưa kịp đọc.
  3. Quá hạn phản hồi dây chuyền: Các dịch vụ xác thực và hệ thống nội bộ phía sau không thể nhận được dữ liệu, làm đứt gãy kết nối người dùng.

Các cổng quản trị và điểm xác thực công khai của cổng VPN doanh nghiệp là mục tiêu đặc biệt nguy hiểm. Nếu tin tặc làm tê liệt các cổng này bằng Rapid Reset, người dùng từ xa sẽ không thể khởi tạo kết nối hoặc xác thực chứng chỉ mạng.

Lá chắn cổng VPN Lớp 3: Đóng gói luồng điều khiển trong đường hầm mã hoá

Điểm yếu cốt tử của lỗ hổng CVE-2023-44487 là việc để lộ trực tiếp các điểm cuối HTTP/2 ra môi trường mạng công cộng. Khi các giao diện quản trị và API điều khiển vận hành trên dải IP mở, chúng luôn đối mặt với các nguy cơ bị tấn công ở tầng ứng dụng.

Việc triển khai kiến trúc VPN Lớp 3 tái cấu trúc hoàn toàn vành đai bảo mật này:

+------------------------------------------------------------------------+
|                     Mạng Internet công cộng nhiều rủi ro               |
|            Kẻ tấn công phát luồng HTTP/2 Rapid Reset qua cổng 443      |
+------------------------------------------------------------------------+
                                    |
                                    v (Cổng tiếp nhận biên kiên cố)
+------------------------------------------------------------------------+
|             Nút tiếp nhận biên: Giới hạn tốc độ bằng Token Bucket      |
|      Theo dõi tỷ lệ RST_STREAM/HEADERS: Ngắt kết nối TCP đáng ngờ      |
+------------------------------------------------------------------------+
                                    |
                                    v (Đường truyền Lớp 3 cách ly)
+------------------------------------------------------------------------+
|             Đóng gói đường hầm WireGuard / RiceGuard                   |
|   Mã hoá xác thực: ChaCha20-Poly1305 (RFC 7539 / RFC 5116)             |
|   API nội bộ và máy chủ điều khiển gắn chặt vào card rg0 (10.8.0.1)     |
+------------------------------------------------------------------------+
                                    |
                                    v (Lõi bảo vệ an toàn nội bộ)
+------------------------------------------------------------------------+
|               Dịch vụ ứng dụng và xác thực được bảo vệ nội bộ           |
|           Miễn nhiễm với các đợt lũ HTTP/2 Rapid Reset từ bên ngoài    |
+------------------------------------------------------------------------+

Bằng cách đóng gói toàn bộ lưu lượng quản trị và ứng dụng bên trong đường hầm Lớp 3 có xác thực:

  1. Các điểm cuối web nội bộ chỉ lắng nghe trên giao diện mạng ảo (như 10.8.0.1), hoàn toàn vô hình trước các công cụ quét mạng công cộng.
  2. Tin tặc bên ngoài không thể thiết lập bắt tay ba bước TCP với các máy chủ HTTP/2 phía sau.
  3. Mọi gói tin gửi đến đều phải được giải mã và kiểm tra thẻ xác thực ChaCha20-Poly1305 trước khi được nhân hệ điều hành chuyển tới ứng dụng.

Cơ chế phòng vệ vành đai tương tự cũng bảo vệ hạ tầng định tuyến trước các cuộc tấn công làm tràn băng thông, như được phân tích trong chuyên đề về phòng chống tấn công TCP SYN Flood và cơ chế cookie WireGuard.

Hệ thống phòng thủ RiceGuard: Gia cố hạ tầng cổng kết nối trước các đợt lũ

VPNRice ứng dụng giao thức RiceGuard cải tiến trên nền tảng WireGuard nhằm duy trì độ ổn định liên lạc trong các điều kiện mạng khắc nghiệt:

  1. Ràng buộc giao diện chặt chẽ ở cấp kernel: RiceGuard thực thi chính sách định tuyến cô lập các giao diện quản trị và dịch vụ DNS đằng sau card mạng ảo rg0. Lưu lượng công cộng trên card vật lý eth0 không thể xâm nhập vào tiến trình HTTP/2 nội bộ.
  2. Gói tin mã hoá kích thước cố định: WireGuard truyền dữ liệu qua UDP với cấu trúc tiêu đề định sẵn, loại bỏ hoàn toàn các máy trạng thái phức tạp của việc ghép kênh HTTP/2 ở lớp đóng gói bên ngoài.
  3. Kiến trúc cổng tàng hình: Các nút mạng RiceGuard chỉ phản hồi những gói tin có chữ ký mã hoá hợp lệ từ khóa công khai tạm thời. Các truy vấn thăm dò chưa xác thực sẽ không nhận được bất kỳ phản hồi ICMP hay bắt tay TCP nào, tước đoạt cơ hội khai thác của kẻ tấn công.

Quản trị viên và người dùng có thể kiểm tra tính toàn vẹn của kết nối định tuyến và trạng thái địa chỉ IP thông qua công cụ kiểm tra IP.

Thử nghiệm thực tế: Bão hoà CPU, độ trễ yêu cầu và tỷ lệ rớt luồng

Chúng tôi đã đánh giá khả năng chống chịu của hệ thống tại phòng thí nghiệm phần cứng độc lập. Thiết bị tấn công phát luồng HTTP/2 Rapid Reset nhắm vào ba cấu hình: máy chủ proxy ngược thông thường chưa vá lỗi, proxy biên được trang bị bộ giới hạn khung huỷ và hệ thống bảo vệ đằng sau đường hầm mã hoá RiceGuard.

Đợt tấn công bơm 2.500.000 yêu cầu huỷ luồng mỗi giây trên 128 kết nối TCP đồng thời.

Tiêu chí đánh giá Proxy HTTP/2 chưa vá Proxy biên gia cố Cổng bảo vệ RiceGuard
Mức tiêu thụ CPU biên 99.4% (Tắc nghẽn hoàn toàn) 28.6% (Tải định mức) 4.2% (Chuyển tiếp mã hoá)
Gia tăng bộ nhớ RAM +3.4 GB (Tràn bộ đệm) +140 MB (Giới hạn kiểm soát) +12 MB (Không cấp phát luồng)
Độ trễ yêu cầu hợp lệ Hết thời gian chờ (> 30.000 ms) 42 ms (Biến động +18 ms) 1.8 ms (Tốc độ đường truyền)
Kết nối TCP hợp lệ bị đứt 88.2% Bị ngắt 0.4% Bị ngắt 0% (Toàn bộ phiên an toàn)
Ngắt kết nối kẻ tấn công Không ngắt (Vòng lặp duy trì) Ngắt trong vòng 12 ms Chặn ngay tại bộ lọc đường hầm

Trên máy chủ proxy chưa vá, các khung huỷ luồng liên tiếp gây tràn bộ nhớ và nghẽn luồng xử lý, ngăn chặn hoàn toàn các truy cập hợp lệ.

Trong khi đó, với RiceGuard, do các tiến trình HTTP/2 được tách biệt hoàn toàn khỏi Internet công cộng, cổng mạng chuyển tiếp các gói tin mã hoá ở tốc độ tối đa với mức gia tăng độ trễ không đáng kể.

Hướng dẫn thực hành: Giới hạn tốc độ cổng, tinh chỉnh bộ đệm TCP và kiểm tra lưu lượng

Quản trị viên vận hành các dịch vụ HTTP/2 mở ra Internet có thể áp dụng các biện pháp phòng vệ đa lớp trên hệ thống proxy và nhân hệ điều hành.

Cấu hình ngưỡng khung huỷ luồng trên máy chủ proxy ngược

Trên hệ thống sử dụng Nginx, hãy áp dụng tỷ lệ giới hạn khung huỷ và thu hẹp số lượng luồng đồng thời:

# /etc/nginx/nginx.conf - Thiet lap gia co HTTP/2

http {
    # Gioi han so luong luong dong thoi tren moi ket noi TCP
    http2_max_concurrent_streams 64;

    # Ap dung han muc xu ly yeu cau
    limit_req_zone $binary_remote_addr zone = api_limit:20m rate=100r/s;

    server {
        listen 443 ssl http2;
        server_name api.enterprise-core.internal;

        keepalive_requests 1000;
        client_header_timeout 5s;
        client_body_timeout 5s;

        location / {
            limit_req zone = api_limit burst=200 nodelay;
            proxy_pass http://backend_cluster;
        }
    }
}

Đối với hạ tầng HAProxy, thiết lập giới hạn ghép kênh ở tầng tiếp nhận:

frontend https_in
    bind :443 ssl crt /etc/ssl/certs/gateway.pem alpn h2,http/1.1
    tune.h2.max-concurrent-streams 64
    tune.h2.initial-window-size 65535

Giám sát tỷ lệ khung HTTP/2 bằng công cụ phân tích mạng

Kiểm tra lưu lượng đi vào giao diện mạng để phát hiện các đợt đột biến khung RST_STREAM:

# Bat va dem so luong khung HTTP/2 RST_STREAM bang tshark
sudo tshark -i eth0 -f "tcp port 443" -Y "http2.type == 3" -T fields -e ip.src -e http2.streamid

# Kiem tra trang thai cap phat socket va bo nho dem TCP
ss -t -i -a | grep -E "ESTAB|wscale"

# Kiem tra hang doi ket noi bi tran tren card mang vat ly
netstat -s | grep -i "listen overflows"

Dù các giải pháp giới hạn ở tầng ứng dụng giúp giảm thiểu triệu chứng, việc loại trừ nguy cơ triệt để đòi hỏi phải cô lập các dịch vụ thiết yếu vào các miền định tuyến riêng tư. Khi người dùng thiết lập kết nối mã hoá bảo vệ qua ứng dụng VPNRice chính thức, mọi luồng dữ liệu đều được truyền an toàn trong đường hầm Lớp 3 với các chuẩn mật mã hiện đại.

Sự kết hợp giữa giám sát luồng tại cổng proxy và giải pháp cách ly mã hoá Lớp 3 là nền tảng vững chắc giúp hạ tầng mạng duy trì tính liên tục và an toàn trước các đợt tấn công huỷ luồng tần số cao.