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 modify và lua 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.

