Che giấu PII trong System Log: Hướng dẫn Fluent Bit để loại bỏ Email, IP và Mật khẩu

Security tutorial - IT technology blog
Security tutorial - IT technology blog

Tại sao che giấu log tại nguồn lại quan trọng

Log là thành phần quan trọng để debug, nhưng chúng sẽ trở thành một gánh nặng lớn ngay khi email người dùng, địa chỉ IP hoặc thông tin đăng nhập của admin bị rò rỉ vào ELK hoặc Loki stack của bạn. Cá nhân tôi đã từng phải dọn dẹp hơn 500GB index Elasticsearch vào lúc 3 giờ sáng chỉ vì một microservice triển khai sai và bắt đầu đổ raw auth token ra log. Dưới các khung quy định như GDPR hay SOC2, một khi dữ liệu nhạy cảm đó đã nằm trên server logging tập trung, về mặt kỹ thuật, bạn đã gây ra một vụ vi phạm dữ liệu.

Cách thông minh nhất để xử lý vấn đề này là thực hiện tại biên (edge). Bằng cách loại bỏ Thông tin Định danh Cá nhân (PII) ngay trong Fluent Bit trước khi nó rời khỏi máy chủ, bạn đảm bảo rằng các bí mật dưới dạng văn bản thuần túy (plain-text secrets) không bao giờ đi qua mạng của bạn. Chiến lược này giúp cắt giảm bề mặt tấn công và giúp các kiểm toán viên tuân thủ không bị mất ngủ.

Bắt đầu nhanh (Triển khai trong 5 phút)

Nếu bạn đang chạy Fluent Bit, bạn có thể triển khai việc che giấu ngay lập tức bằng filter modify. Hãy tưởng tượng application log của bạn bao gồm một trường tên là user_password cần phải biến mất ngay bây giờ.

Thêm khối filter này vào fluent-bit.conf của bạn:

[FILTER]
    Name    modify
    Match   *
    Set     password_status [ĐÃ_CHE_GIẤU]
    Rename  user_password plain_password
    Hard_set plain_password ********

Thiết lập này đổi tên trường gốc và ghi đè giá trị bằng các dấu sao. Tuy nhiên, log thực tế hiếm khi gọn gàng như vậy. Các chuỗi nhạy cảm thường bị vùi sâu bên trong các khối tin nhắn dài và lộn xộn. Trong những trường hợp đó, biểu thức chính quy (regular expressions) là người bạn tốt nhất của bạn.

Để bắt địa chỉ IPv4 ở bất kỳ đâu trong một dòng log, hãy sử dụng cách này:

[FILTER]
    Name    modify
    Match   *
    Regexp  log /\b(?:[0-9]{1,3}\.){3}[0-9]{1,3}\b/ [IP_ĐÃ_CHE_GIẤU]

Sau khi bạn khởi động lại dịch vụ, mọi địa chỉ IPv4 trong trường đó sẽ biến thành [IP_ĐÃ_CHE_GIẤU]. Không còn lo lắng về việc rò rỉ chi tiết hạ tầng nội bộ trong các dashboard của bạn nữa.

Tìm hiểu sâu: Modify so với Lua

Fluent Bit xử lý dữ liệu dưới dạng một luồng các bản ghi (records). Để loại bỏ PII hiệu quả, bạn cần lựa chọn giữa filter modifylua dựa trên quy mô của mình. Trong khi modify cực kỳ nhanh cho các việc hoán đổi key-value đơn giản, filter lua lại xử lý tốt các logic phức tạp cần thiết cho dữ liệu lồng nhau hoặc nhiều pattern cùng lúc.

Filter Modify

Được tích hợp trực tiếp vào nhân C (C core), filter modify có tốc độ cực nhanh. Nó hoạt động trên bản ghi với mức tiêu tốn CPU tối thiểu. Bạn có thể sử dụng các quy tắc như Add, Set, hoặc Regexp để nhắm mục tiêu vào các trường cụ thể. Nếu bạn cần che giấu email trong khi vẫn giữ lại domain để debug (ví dụ: m***@company.com), modify có thể xử lý việc đó bằng cách sử dụng các capture group.

Filter Lua

Khi tôi cần loại bỏ năm loại PII khác nhau cùng lúc hoặc phân tích cú pháp JSON lồng nhau, tôi chuyển sang dùng Lua. Điều này cung cấp cho bạn một môi trường scripting đầy đủ để phân tích và làm sạch dữ liệu. Ảnh hưởng đến hiệu suất là không đáng kể đối với hầu hết các cluster — thường tăng ít hơn 3% mức sử dụng CPU — nhưng lợi ích bảo mật mang lại là rất lớn.

Sử dụng nâng cao: Bộ lọc tổng hợp

Hầu hết các hệ thống hiện đại đối mặt với sự pha trộn giữa syslog, JSON và access log. Thay vì xếp chồng hàng tá filter modify, tôi thích sử dụng một script Lua duy nhất để xử lý các pattern khác nhau một cách hiệu quả.

Tạo một tệp có tên masking.lua:

function mask_pii(tag, timestamp, record)
    local log = record["log"]
    if log == nil then return 0, timestamp, record end

    -- Loại bỏ Email
    log = string.gsub(log, "[%w%.%-_]+@[%w%.%-_]+%.%a+", "[EMAIL_ĐÃ_LOẠI_BỎ]")
    
    -- Loại bỏ IPv4
    log = string.gsub(log, "%d+%.%d+%.%d+%.%d+", "[IP_ĐÃ_LOẠI_BỎ]")

    -- Loại bỏ mật khẩu trong chuỗi JSON
    log = string.gsub(log, '"password"%s*:%s*"[^"]+"', '"password":"********"')

    record["log"] = log
    return 2, timestamp, record
end

Sau đó, gọi script này trong file cấu hình chính của bạn:

[FILTER]
    Name    lua
    Match   *
    script  masking.lua
    call    mask_pii

Điều này giữ cho cấu hình của bạn dễ đọc. Việc cập nhật các regex pattern trong một script tập trung cũng dễ dàng hơn nhiều so với việc săn tìm trong một file cấu hình dài 500 dòng.

Trước khi bạn bắt đầu cấu hình các quy tắc này, hãy đảm bảo thông tin đăng nhập dịch vụ nội bộ của bạn được bảo mật mạnh mẽ. Tôi sử dụng công cụ trên trình duyệt tại toolcraft.app/vi/tools/security/password-generator để tạo mật khẩu server. Vì nó chạy hoàn toàn ở phía client, các root credential của bạn không bao giờ truyền qua mạng, ngăn chúng bị log lại bởi một proxy chưa được cấu hình trong quá trình thiết lập.

Mẹo thực tế cho môi trường Production

1. Tránh che giấu quá mức

Đừng loại bỏ tất cả mọi thứ. Log tồn tại để giúp bạn giải quyết vấn đề. Nếu bạn che giấu user_id hoặc một request_id cụ thể, bạn sẽ thấy không thể truy vết lỗi của khách hàng. Chỉ nhắm mục tiêu vào dữ liệu thực sự nhạy cảm hoặc bị quy định nghiêm ngặt.

2. Kiểm tra với Stdout

Đừng bao giờ đưa một regex mới thẳng lên production. Hãy sử dụng output plugin stdout để xác minh các filter của bạn tại local trước. Nó cho phép bạn thấy chính xác cách các quy tắc hoạt động trước khi chúng đi vào hệ thống lưu trữ đắt đỏ của bạn.

[OUTPUT]
    Name   stdout
    Match  *

3. Hiệu suất ở quy mô lớn

Nếu bạn đang đẩy 100.000 sự kiện mỗi giây, mỗi mili giây đều đáng quý. Trong môi trường traffic cao, hãy sử dụng filter modify dựa trên C cho 80% trường hợp sử dụng (như che giấu IP) và dành Lua cho 20% trường hợp phức tạp liên quan đến cấu trúc lồng nhau.

4. Nhắm đúng trường dữ liệu

Nếu ứng dụng của bạn gửi JSON có cấu trúc, một regex trên trường log chung chung sẽ thất bại. Đảm bảo filter của bạn nhắm vào đường dẫn cụ thể, chẳng hạn như record["user"]["metadata"]["email"], để tránh bỏ sót dữ liệu ẩn trong các sub-object.

Bằng cách dịch chuyển bảo mật sang phía biên của pipeline, bạn xây dựng một hệ thống logging hỗ trợ các nhà phát triển mà không làm ảnh hưởng đến quyền riêng tư của người dùng. Bảo mật không chỉ là ngăn chặn hacker; đó là đảm bảo luồng dữ liệu thực sự nhạy cảm của chính bạn không trở thành gánh nặng lớn nhất.

Share: