Triển khai Suricata IDS/IPS trên Linux: Phân tích lưu lượng thời gian thực và phòng thủ mạng

Networking tutorial - IT technology blog
Networking tutorial - IT technology blog

Sáu tháng trước, cổng gateway biên của chúng tôi bị nghẽn nghiêm trọng trên đường truyền uplink 10Gbps. Cụm Snort cũ đã làm rớt tới 12% số lượng gói tin gửi đến trong các đợt lưu lượng tăng đột biến vào buổi chiều. Lỗ hổng giám sát này ảnh hưởng trực tiếp đến trạng thái bảo mật của hệ thống ngay vào thời điểm chúng tôi cần khả năng quan sát mạng nhất. Việc chuyển đổi sang Suricata đã giải quyết triệt để nút thắt cổ chai này. Kiến trúc đa luồng gốc (native multi-threading) cùng cơ chế thu thập gói tin zero-copy qua AF_PACKET đã xử lý mượt mà các đợt bùng nổ lưu lượng tức thời (microbursts).

Dưới đây là hướng dẫn triển khai Suricata với cả hai vai trò: cảm biến thụ động (IDS) và tường lửa ngăn chặn chủ động (IPS) trên Ubuntu hoặc Debian, dựa trên dữ liệu thực tế sau sáu tháng vận hành trên hệ thống production.

Bắt đầu nhanh (5 phút)

Khởi tạo một hệ thống IDS cơ bản chỉ mất khoảng năm phút với kho lưu trữ chính thức và công cụ cập nhật rule tự động.

1. Cài đặt Suricata

Ubuntu có sẵn Suricata trong kho lưu trữ universe, nhưng phiên bản tại đây thường chậm hơn bản phát hành chính thức vài bản cập nhật nhỏ. Hãy sử dụng PPA chính thức từ Open Information Security Foundation (OISF) để nhận các bộ phân tích giao thức mới nhất, các bản sửa lỗi và cải thiện hiệu năng.

sudo add-apt-repository ppa:oisf/suricata-stable -y
sudo apt update
sudo apt install suricata jq ethtool -y

2. Cập nhật các rule từ Emerging Threats

Suricata đi kèm sẵn công cụ suricata-update. Tiện ích này giúp tải và hợp nhất các signature phát hiện mối đe dọa trực tiếp từ các nguồn uy tín như Emerging Threats (ET) Open, cập nhật hơn 45.000 quy tắc phát hiện đang hoạt động chỉ trong vài giây.

sudo suricata-update
sudo suricata -T -c /etc/suricata/suricata.yaml -v

Luôn kiểm tra tính hợp lệ của tệp cấu hình trước khi đưa vào hoạt động thực tế. Cờ -T thực hiện kiểm tra thử cú pháp của rule và các thiết lập YAML. Hãy đảm bảo bạn thấy dòng chữ Configuration provided was successfully tested ở cuối kết quả trả về.

3. Chạy Suricata ở chế độ IDS thụ động

Kiểm tra danh sách giao diện mạng bằng lệnh ip -br addr, sau đó khởi chạy Suricata gắn với giao diện mạng chính (ở đây là eth0):

sudo systemctl stop suricata
sudo suricata -c /etc/suricata/suricata.yaml -i eth0 --init-errors-fatal

Trên một cửa sổ terminal khác, theo dõi các cảnh báo bảo mật có cấu trúc theo thời gian thực bằng jq:

sudo tail -f /var/log/suricata/eve.json | jq 'select(.event_type=="alert")'

Đi sâu vào kỹ thuật

Suricata đảm nhận hai vai trò vận hành riêng biệt. Với vai trò IDS, nó giám sát thụ động các cổng SPAN hoặc lưu lượng mirrored mà không can thiệp vào luồng mạng. Với vai trò IPS, nó nằm trực tiếp trên đường đi của lưu lượng, đánh giá từng gói tin và đưa ra phán quyết hủy (drop) gói trước khi kernel kịp định tuyến chúng. Để duy trì thông lượng gigabit ổn định, mấu chốt nằm ở cách phân bổ luồng và quản lý vùng đệm (buffer).

Kiến trúc đa luồng

Các công cụ xử lý đơn luồng sẽ dễ dàng gặp hiện tượng nghẽn cổ chai trên một nhân CPU, dẫn đến tình trạng rớt gói tin khi băng thông tăng cao. Suricata chia nhỏ quá trình thu thập gói tin, giải mã giao thức, tái cấu trúc luồng (flow reassembly), kiểm tra signature và ghi log sang các luồng hoạt động độc lập.

  • Chế độ chạy “autofp” (Automatic Flow Pinning): Các luồng capture chuyên dụng sẽ tiếp nhận gói tin và tính toán giá trị băm (hash) dựa trên bộ 5-tuple (IP nguồn, IP đích, cổng nguồn, cổng đích và giao thức). Suricata sẽ ghim toàn bộ các gói tin thuộc cùng một phiên làm việc vào cùng một worker thread. Điều này giúp tận dụng tối đa bộ nhớ đệm CPU L2/L3 và ngăn chặn việc ghép nối gói tin bị sai thứ tự.
  • Chế độ chạy “workers”: Mỗi luồng sẽ xử lý toàn bộ vòng đời của gói tin—từ capture, giải mã, tái cấu trúc stream cho đến kiểm tra quy tắc—cho một hàng đợi hoặc interface được chỉ định. Hãy dùng chế độ này trên các thiết bị chuyên dụng để đạt được thông lượng tối đa theo tốc độ đường truyền (line-rate) mà không chịu chi phí điều phối giữa các luồng.

Tối ưu hóa AF_PACKET trong suricata.yaml

Trình điều khiển libpcap tiêu chuẩn phụ thuộc vào các lệnh gọi hệ thống (system call) để sao chép từng frame dữ liệu từ kernel memory sang không gian người dùng (user space). Dưới mức tải từ 1Gbps trở lên, việc sao chép vùng nhớ này tiêu tốn rất nhiều chu kỳ CPU và nhanh chóng gây rớt gói. Ring buffer AF_PACKET của Linux ánh xạ trực tiếp vùng nhớ kernel vào user space, loại bỏ hoàn toàn chi phí sao chép dữ liệu đó.

Mở tệp /etc/suricata/suricata.yaml và tinh chỉnh các thiết lập capture cho interface giám sát của bạn:

af-packet:
  - interface: eth0
    threads: auto
    cluster-id: 99
    cluster-type: cluster_flow
    defrag: yes
    use-mmap: yes
    mmap-locked: yes
    tpacket-v3: yes
    ring-size: 204800

Các số liệu thực tế đã chứng minh hiệu quả rõ rệt. Trước khi tối ưu, gateway của chúng tôi đánh rơi khoảng 7,4% lượng gói tin trong các đợt lưu lượng đạt đỉnh 6 Gbps vào giữa ngày. Sau khi cấp phát ring buffer tpacket-v3 ở mức 204.800 frame cho mỗi luồng, tỷ lệ rớt gói giảm mạnh xuống chỉ còn 0,001%. Tải CPU cũng được dàn đều trên toàn bộ 16 nhân của máy chủ thử nghiệm chạy chip Intel Xeon Silver.

Trích xuất tín hiệu cảnh báo từ eve.json

Suricata ghi lại mọi sự kiện—bao gồm cảnh báo, metadata HTTP, truy vấn DNS, chứng chỉ TLS và dữ liệu đo đạc flow thô—thành các bản ghi JSON riêng biệt trong /var/log/suricata/eve.json. Bạn có thể phân tích luồng log khổng lồ này bằng các công cụ dòng lệnh tiêu chuẩn mà không cần phải chờ hệ thống SIEM bên ngoài xử lý:

# Thống kê top 5 signature cảnh báo kích hoạt nhiều nhất trong 10.000 bản ghi gần nhất
tail -n 10000 /var/log/suricata/eve.json | \
  jq -r 'select(.event_type=="alert") | .alert.signature' | \
  sort | uniq -c | sort -nr | head -n 5

Sử dụng nâng cao

Các cảnh báo thụ động giúp bạn nắm bắt tình hình mạng, nhưng các mối đe dọa đang diễn ra lại đòi hỏi cơ chế xử lý tự động. Việc tích hợp Suricata vào các hàng đợi Netfilter (NFQ) sẽ biến hệ thống giám sát thụ động thành một tường lửa ngăn chặn xâm nhập inline.

Cấu hình IPS Inline với NFQueue

Trong chế độ NFQ, iptables sẽ điều hướng các gói tin thỏa mãn điều kiện vào hàng đợi ở không gian người dùng. Suricata sẽ kiểm tra payload của từng gói tin dựa trên các rule đang kích hoạt, sau đó đưa ra phán quyết: NF_ACCEPT để cho gói tin đi qua, hoặc NF_DROP để hủy gói tin.

Đầu tiên, hãy kiểm tra hoặc thêm khối cấu hình NFQ trong /etc/suricata/suricata.yaml:

nfq:
  mode: accept
  repeat-mark: 1
  repeat-mask: 1
  bypass-mark: 1
  bypass-mask: 1
  route-queue: 2

Tiếp theo, điều hướng lưu lượng đến hoặc lưu lượng được định tuyến vào hàng đợi 0 bằng iptables:

# Điều hướng lưu lượng định tuyến forwarding vào NFQueue 0
sudo iptables -I FORWARD -j NFQUEUE --queue-num 0 --queue-bypass

# Hoặc kiểm tra trực tiếp lưu lượng đến server trên các cổng web
sudo iptables -I INPUT -p tcp -m multiport --dports 80,443 -j NFQUEUE --queue-num 0 --queue-bypass

Cờ --queue-bypass là một cứu cánh cực kỳ quan trọng. Nếu Suricata khởi động lại, bị crash hoặc bị treo do thiếu bộ nhớ, kernel Linux sẽ tự động bỏ qua hàng đợi và cho các gói tin đi qua bình thường. Nếu không có cờ này, toàn bộ kết nối mạng của bạn sẽ bị gián đoạn ngay khi tiến trình Suricata dừng hoạt động.

Viết rule tùy chỉnh để chặn gói tin Inline

Suricata sử dụng các bộ đệm từ khóa nhận biết giao thức để kiểm tra payload của HTTP, TLS, DNS và SSH với mức tiêu tốn tài nguyên regex tối thiểu. Hãy đưa các signature tùy chỉnh của bạn vào tệp /var/lib/suricata/rules/local.rules:

# Chặn các đợt quét tự động nhắm vào endpoint đăng nhập WordPress
drop http any any -> $HOME_NET any (
    msg:"CHẶN BẢO MẬT - Phát hiện yêu cầu POST wp-login đáng ngờ";
    flow:established,to_server;
    http.method; content:"POST";
    http.uri; content:"/wp-login.php";
    threshold:type threshold, track by_src, count 5, seconds 60;
    classtype:web-application-attack;
    sid:1000001;
    rev:1;
)

# Chặn bắt tay TLS yêu cầu các host Dynamic DNS đáng ngờ
drop tls any any -> any any (
    msg:"CHẶN BẢO MẬT - SNI Dynamic DNS nằm trong danh sách đen";
    flow:established,to_server;
    tls.sni; content:"duckdns.org"; endswith; nocase;
    classtype:bad-unknown;
    sid:1000002;
    rev:1;
)

Thêm tệp local.rules vào danh sách rule-files trong /etc/suricata/suricata.yaml, kiểm tra lại cú pháp với suricata -T, và khởi chạy Suricata ở chế độ hàng đợi:

sudo suricata -c /etc/suricata/suricata.yaml -q 0 -D

Khi một payload độc hại kích hoạt rule, Suricata sẽ gửi tín hiệu yêu cầu Netfilter hủy gói tin ngay lập tức. Kết nối sẽ bị ngắt và Suricata sẽ ghi lại sự kiện vào eve.json với thông tin "action":"blocked".

Lời khuyên thực tiễn

Quá trình xử lý gói tin ở tốc độ cao thường làm phát sinh những trường hợp ngoại lệ mà môi trường thử nghiệm sạch sẽ không bao giờ gặp phải. Hãy áp dụng ba tinh chỉnh củng cố hệ thống production sau để duy trì tỷ lệ rớt gói gần bằng 0 và tránh nguy cơ cạn kiệt dung lượng ổ đĩa.

1. Vô hiệu hóa tính năng Hardware NIC Offloading

Các card mạng hiện đại sử dụng Large Receive Offload (LRO) và Generic Receive Offload (GRO) để gộp các frame nhận được thành các gói tin nhân tạo có kích thước lên tới 64KB trước khi chuyển cho kernel. Việc tái hợp nhất này làm biến dạng kích thước gói tin và khiến việc so khớp signature theo ranh giới chuẩn MTU 1500-byte bị sai lệch.

Hãy tắt tính năng offload trên interface giám sát bằng ethtool:

sudo ethtool -K eth0 rx off tx off gro off lro off tso off gso off

Để cấu hình này có hiệu lực sau mỗi lần khởi động lại máy, hãy thêm hook ethtool vào cấu hình Netplan hoặc thiết lập qua một service systemd riêng biệt.

2. Tinh chỉnh bộ nhớ và thời gian chờ (Flow Timers)

Các cuộc tấn công SYN flood quy mô lớn và các đợt quét mạng diện rộng có thể làm tràn bảng trạng thái của Suricata bằng các kết nối mở một nửa (half-open) bị bỏ rơi. Trong /etc/suricata/suricata.yaml, hãy rút ngắn thời gian chờ trạng thái TCP để giải phóng nhanh chóng các kết nối không còn hoạt động:

flow-timeouts:
  tcp:
    new: 5
    established: 300
    closed: 0
    emergency-new: 1
    emergency-established: 60
    emergency-closed: 0

Khi xảy ra tấn công, các bộ đếm thời gian khẩn cấp (emergency timers) sẽ giảm tải áp lực bộ nhớ chỉ trong vài giây, ngăn chặn lỗi kernel panic do cạn kiệt RAM (OOM).

3. Luân chuyển log trước khi đầy ổ đĩa

Một đường truyền 10Gbps bận rộn có thể tạo ra từ 15GB đến 40GB dữ liệu log eve.json mỗi ngày. Nếu không luân chuyển log định kỳ, bạn sẽ nhanh chóng dùng hết dung lượng phân vùng root chỉ trong vài ngày. Hãy thiết lập chính sách logrotate hàng ngày tại /etc/logrotate.d/suricata có nén file và kích hoạt mở lại file log qua tín hiệu USR2/HUP:

/var/log/suricata/*.json /var/log/suricata/*.log {
    daily
    rotate 7
    missingok
    compress
    delaycompress
    sharedscripts
    postrotate
        /bin/kill -HUP $(cat /var/run/suricata.pid 2>/dev/null) 2>/dev/null || true
    endscript
}

Hãy cho Suricata chạy ở chế độ thụ động trong hai tuần đầu tiên. Khoảng thời gian này giúp bạn đo lường tải trên interface mạng, phát hiện các cảnh báo gây nhiễu và tinh chỉnh lại các rule tùy biến. Khi hệ thống đã vận hành ổn định, bạn có thể tự tin định tuyến lưu lượng qua NFQueue để ngăn chặn các mối đe dọa ngay trên đường truyền trước khi chúng tiếp cận được các máy chủ của bạn.

Share: