Chạy foreground
Chạy trực tiếp từ terminal, hữu ích khi kiểm tra cấu hình lần đầu hoặc gỡ rối:
Linux:
# Chạy với file blackhole-fwd.yml trong thư mục hiện tại
blackhole-fwd start
# Chỉ định file cấu hình khác
blackhole-fwd -c /path/to/blackhole-fwd.yml start
# Chạy với log level debug (tương đương đặt logging.level: "debug")
blackhole-fwd -v startWindows (PowerShell):
.\blackhole-fwd.exe start
.\blackhole-fwd.exe -c "D:\siem\blackhole-fwd.yml" start
.\blackhole-fwd.exe -v startMột số điểm cần nhớ:
- Flag cấu hình là
-c/--config. Mặc định làblackhole-fwd.ymltrong thư mục làm việc; nếu file này chưa có, process thử./config.ymlrồi./config.yaml. - Nếu file tại đúng đường dẫn
--configkhông tồn tại, khởi động thoát ngay với lỗiFailed to read file for hashing: blackhole-fwd.yml, xem Troubleshooting. - Không truyền subcommand nào thì binary chỉ in banner, không chạy pipeline.
- Trên Windows, process tự chuyển thư mục làm việc về thư mục chứa executable, nên config, log và database luôn nằm cạnh binary. Trên Linux, thư mục làm việc là nơi bạn khởi chạy từ đó.
Xác minh:
tail -f logs/default.log
# kỳ vọng thấy: "Orchestrator started successfully"Nếu cấu hình có section registry: với HTTP listener bật:
curl -s http://127.0.0.1:18080/health
# kỳ vọng: {"status":"ok"}Chạy như service
Cài và quản lý bằng CLI
Cần quyền administrator (Windows) hoặc root (Linux):
blackhole-fwd service install # cài service, cài xong tự khởi động
blackhole-fwd service status # kiểm tra trạng thái
blackhole-fwd service start # khởi động
blackhole-fwd service stop # dừng
blackhole-fwd service uninstall # gỡ serviceWindows
Get-Service -Name "blackhole-fwd" # trạng thái
Start-Service -Name "blackhole-fwd"
Stop-Service -Name "blackhole-fwd"
Restart-Service -Name "blackhole-fwd" # stop + startLinux
Unit file nằm ở /etc/systemd/system/blackhole-fwd.service (cần systemd hoặc OpenRC, cài bằng quyền root):
sudo systemctl status blackhole-fwd
sudo systemctl start blackhole-fwd
sudo systemctl stop blackhole-fwd
sudo systemctl restart blackhole-fwd
sudo systemctl enable blackhole-fwd # tự khởi động khi boot (đã enable sẵn khi cài)
sudo journalctl -u blackhole-fwd -f # chỉ xem được phần stderrService dùng cấu hình nào
Service được ghi nhận là <đường dẫn executable> --service --service-name blackhole-fwd. Hai hệ quả:
Ở chế độ service, stdout bị tắt nên file log là nơi duy nhất có log runtime. journalctl chỉ nhận phần stderr, chủ yếu là thông báo Error: ... khiến process thoát ngay khi khởi động. Chi tiết xem Xem log.
Xác minh:
blackhole-fwd service status
# kỳ vọng: ✅ Service is running
sudo systemctl is-enabled blackhole-fwd
# kỳ vọng: enabledGet-Service -Name "blackhole-fwd"
# kỳ vọng: Status = RunningChạy trong container
Image ghcr.io/gcsclabs/blackhole-forwarder được build trên nền distroless, lệnh mặc định là --config /etc/blackhole/blackhole-fwd.yml start:
docker run -d --name blackhole-fwd \
-v /host/config/blackhole-fwd.yml:/etc/blackhole/blackhole-fwd.yml:ro \
-v blackhole-fwd-data:/home/nonroot \
-p 514:514/udp -p 514:514/tcp \
ghcr.io/gcsclabs/blackhole-forwarder:latest- Mount cấu hình read-only là đủ, file chỉ được đọc lúc khởi động và khi hot-reload phát hiện thay đổi.
- Thư mục làm việc trong container là
/home/nonroot: databaseblackhole-fwd.dbvàlogs/nằm ở đó. Mount volume tại/home/nonrootđể giữ dữ liệu qua mỗi lần restart. - Publish các port theo bảng Port lắng nghe, chỉ publish port nào có section cấu hình tương ứng.
- Image không có shell, nên không thể
docker exec ... shvào, xem Troubleshooting.
Chi tiết image và các biến thể cài, xem Cài đặt.
Xác minh:
docker logs -f blackhole-fwd
# kỳ vọng thấy: "Orchestrator started successfully"Dừng Forwarder
| Chế độ | Cách dừng |
|---|---|
| Foreground | Ctrl+C (Linux/Windows) hoặc SIGTERM |
| Service | service stop, systemctl stop blackhole-fwd, Stop-Service blackhole-fwd |
| Container | docker stop blackhole-fwd (gửi SIGTERM, process có xử lý) |
Quy trình dừng là fast stop, chuỗi log khi dừng:
Shutdown signal received. Exiting.
Shutting down Orchestrator...
Stopping Orchestrator (fast stop)...
Stopped!Xác minh:
tail -5 logs/default.log
# kỳ vọng dòng cuối: "Stopped!"
pgrep -x blackhole-fwd # Linux: không in ra gìGet-Process blackhole-fwd # Windows: báo Cannot find a process (đã không còn process)Xem log
Vị trí log
Log ghi relative tới thư mục làm việc của process:
| File | Nội dung |
|---|---|
logs/default.log | Log chính (info, debug, warn) |
logs/default-error.log | Chỉ các dòng mức ERROR |
Thư mục logs/ được tự động tạo khi khởi động.
Xác định thư mục làm việc
# Linux, thư mục làm việc của process
readlink /proc/$(pgrep -x blackhole-fwd)/cwd
# hoặc: pwdx $(pgrep -x blackhole-fwd)
# Linux, process đang dùng config nào
sudo tr '\0' ' ' < /proc/$(pgrep -x blackhole-fwd)/cmdline; echo- Chạy foreground (Linux): thư mục bạn khởi chạy từ đó.
- Chạy service (Linux): thư mục chứa executable (được set lúc
service install). - Windows: process tự chuyển về thư mục chứa executable, nên log nằm ở
<thư mục chứa blackhole-fwd.exe>\logs\. Xác định nhanh:
$exeDir = (Get-Process blackhole-fwd).Path | Split-Path
Get-ChildItem "$exeDir\logs"Đọc log
Linux:
tail -f logs/default.log # theo dõi log chính
tail -n 200 logs/default-error.log # 200 dòng lỗi gần nhất
grep "ERROR" logs/default.log | tail -50
# Service: journal chỉ có stderr (lỗi khởi động làm process thoát)
sudo journalctl -u blackhole-fwd --since "10 minutes ago"Windows:
Get-Content ".\logs\default.log" -Tail 50 -Wait
Get-Content ".\logs\default-error.log" -Tail 50Xác minh:
ls -l logs/
# kỳ vọng thấy default.log và default-error.log, default.log tăng kích thước khi có sự kiện
grep "Orchestrator started successfully" logs/default.log | tail -1Log rotation và kích thước
Rotation luôn bật, không có công tắc bật/tắt. Cách chia file:
| File | Số file xoay | Cỡ mỗi file | Tổng dung lượng |
|---|---|---|---|
logs/default.log | 5 | max_size_mb / 5 | ≈ max_size_mb |
logs/default-error.log | 10 | max_size_mb | ≈ 10 × max_size_mb |
Điều khiển bằng cấu hình logging (mặc định max_size_mb: 10):
logging:
level: "info"
dir: "./logs"
file: "default.log"
error_file: "default-error.log"
max_size_mb: 10Muốn đổi dung lượng hay vị trí: sửa logging rồi khởi động lại, section này không hot-reload. Tham chiếu đầy đủ tại Cấu hình logging.
Xác minh:
du -sh logs/
ls logs/ | wc -l
# dung lượng ổn định quanh max_size_mb (log chính) dù process chạy lâu,
# số file không vượt 5 (log chính) và 10 (log lỗi)Port lắng nghe
Mỗi port chỉ mở khi section cấu hình tương ứng tồn tại trong config:
| Port | Giao thức | Mục đích | Mở khi | Trường bind mặc định |
|---|---|---|---|---|
| 514 | UDP + TCP | rsyslog source | có rsyslog_server (kèm source rsyslog) | 0.0.0.0:514, rsyslog_server.udp_addr, rsyslog_server.tcp_addr |
| 162 | UDP | Nhận SNMP trap | có snmp_server (kèm source snmp) | 0.0.0.0:162, snmp_server.trap_addr |
| 1883 | TCP | Embedded MQTT broker | có mqtt_server | 0.0.0.0:1883, mqtt_server.server.listen |
| 50051 | TCP | Embedded gRPC server | có grpc_server và ít nhất một source grpc | 0.0.0.0:50051, grpc_server.listen_addr |
| 8080 | TCP | HTTP CONNECT proxy | có proxy_server | 0.0.0.0:8080, proxy_server.addr |
| 18080 | TCP | HTTP next-hop (REST forwarder) + /health | có registry: và registry.http_server.enabled (mặc định true) | 0.0.0.0:18080, registry.http_server.listen_addr |
Ngoài ra Forwarder có kết nối ra ngoài tới SNMP agent ở cổng 161 khi cấu hình poll.
Cú pháp từng section server: xem Embedded servers.
Xác minh:
# Linux, chỉ ra các port đang nghe và process sở hữu
sudo ss -tulnp | grep -E ':(514|162|1883|50051|8080|18080)'
# hoặc
sudo netstat -tulnp | grep -E ':(514|162|1883|50051|8080|18080)'# Windows
netstat -an | findstr ":18080"
netstat -an | findstr ":50051"Kỳ vọng: mỗi port có dòng LISTEN/udp gắn với process blackhole-fwd, chỉ với port có section cấu hình bật. Port thiếu section thì không xuất hiện.
Health endpoint và route next-hop
Khi cấu hình có section registry: và registry.http_server.enabled (mặc định true), Forwarder mở HTTP listener (mặc định 0.0.0.0:18080) làm next-hop: chuyển tiếp request của thiết bị con lên Registry và expose endpoint kiểm tra trạng thái cục bộ.
Các route
| Method | Route | Header bắt buộc | Ghi chú |
|---|---|---|---|
GET | /health | Không có | Trả về {"status":"ok"} |
GET | /client/config | x-device-ip-address | Chuyển tiếp lên Registry. Khi Registry trả 401/404, tự auto-join nếu có thêm x-device-name và x-device-type |
PATCH | /client/config | x-device-ip-address | Body được chuyển tiếp nguyên vẹn |
POST | /client/alerts | x-device-ip-address | Body JSON, tối đa 1 MiB |
POST | /devices/join | Không có (thông tin thiết bị nằm trong body) | Đăng ký thiết bị con |
Ví dụ curl
# 1. Health
curl -s http://127.0.0.1:18080/health
# {"status":"ok"}
# 2. Lấy cấu hình cho một thiết bị
curl -s -H "x-device-ip-address: 10.0.0.5" http://127.0.0.1:18080/client/config
# 3. Thiếu header bắt buộc → 400
curl -s http://127.0.0.1:18080/client/config
# {"error":"missing required header x-device-ip-address"}
# 4. Gửi alert (body JSON, tối đa 1 MiB)
curl -s -X POST \
-H "x-device-ip-address: 10.0.0.5" \
-H "Content-Type: application/json" \
-d '{"event":"connectivity-test"}' \
http://127.0.0.1:18080/client/alertsXác minh:
curl -s http://127.0.0.1:18080/health
# kỳ vọng đúng: {"status":"ok"}
curl -s -o /dev/null -w "%{http_code}\n" http://127.0.0.1:18080/client/config
# kỳ vọng: 400 (thiếu x-device-ip-address)Route config, alerts và join là next-hop: status trả về chính là status của Registry trả về. Nếu không tới được Registry, route trả 502 kèm body {"error": ...}. Chi tiết cấu hình listener: xem Cổng REST next-hop.
Hot-reload
Cơ chế
- Phát hiện thay đổi bằng cách poll SHA-256 mỗi
hot_reload.poll_interval_ms(mặc định 5000 ms), với debouncehot_reload.debounce_ms(mặc định 1000 ms).hot_reload.enabledmặc định true. - Không dùng inotify, không cần
SIGHUP, chỉ cần file cấu hình thay đổi nội dung là được.
Thay đổi local
Một thay đổi local được phát hiện sẽ:
- Đọc lại cấu hình vào bộ nhớ,
- Ghi lại snapshot
.blackhole-resolved.yamlcạnh file cấu hình, - Log
Local config reloaded successfully.
Nếu nguồn cấu hình đang active là Registry, mọi sửa local bị bỏ qua hẳn: log Remote config is active — ignoring local config change (N files).
Update do Registry push
Chỉ update từ Registry mới chạy diff theo identifier để thêm, bỏ hoặc khởi động lại từng component riêng lẻ. Cấu hình remote không hợp lệ bị từ chối và giữ bản cũ: log Remote config validation failed: ..., skipping update.
Nguồn cấu hình lúc khởi động có thể là local, persisted (trong database) hoặc remote, xem dòng log Resolved config snapshot written (source: ...) và file .blackhole-resolved.yaml.
Không hot-reload được (phải khởi động lại)
logging, hot_reload, registry, resources_threshold, channel_buffers và mọi embedded server section: rsyslog_server, snmp_server, mqtt_server, proxy_server, grpc_server, cùng registry.http_server.
Chi tiết phạm vi hot-reload: xem Hot-reload.
Xác minh:
printf '\n# reload test %s\n' "$(date +%s)" >> blackhole-fwd.yml
sleep 7
grep "Local config reloaded successfully" logs/default.log | tail -1
ls -l .blackhole-resolved.yamlKỳ vọng: dòng Local config reloaded successfully xuất hiện sau tối đa ~6 giây (poll 5 s + debounce 1 s) và snapshot được ghi lại. Nếu thay vào đó log báo Remote config is active — ignoring local config change, thì cấu hình đang do Registry quản lý.
Resource guard
Cấu hình
resources_threshold:
cpu:
threshold_percentage: 80.0
sustained_secs: 60
memory:
threshold_percentage: 80.0
sustained_secs: 60
disk:
threshold_percentage: 101.0 # > 100 nghĩa là tắt theo dõi disk
sustained_secs: 60
check_interval: 10 # giâyTheo dõi một metric chỉ hoạt động khi threshold_percentage <= 100. Mặc định: CPU 80%, memory 80%, disk 101% (tắt), kiểm tra mỗi 10 giây, ngưng 60 giây liên tục mới tính là vượt ngưỡng.
Hành vi
| Thời điểm | Hành vi |
|---|---|
| Lúc khởi động | Metric đã bật mà ≥ ngưỡng → process thoát ngay với Startup blocked due to resource constraints: ... |
| Đang chạy | Vượt ngưỡng liên tục qua sustained_secs → tạm dừng pipeline với log PAUSING ORCHESTRATOR due to resource constraints: collector, transform, shipper dừng, queue được flush, không drop event, không tắt process |
| Khi hồi phục | Pipeline chạy lại với log RESUMING ORCHESTRATOR - resources have stabilized |
Xác minh:
grep -E "PAUSING ORCHESTRATOR|RESUMING ORCHESTRATOR" logs/default.log | tail -10
# kỳ vọng có cả hai loại dòng khi sự kiện vượt ngưỡng rồi hồi phục
grep "Startup blocked due to resource constraints" logs/default.log
# kỳ vọng: không có (nếu khởi động thành công)Device guard
Device guard là danh sách chặn (deny-list) token thiết bị, giữ trong bộ nhớ, được cập nhật từ Registry theo trạng thái thiết bị, không phải allow-list đọc từ file cấu hình:
- Không có khóa YAML nào cấu hình device guard.
- Danh sách rỗng nghĩa là cho phép mọi token, không phải chặn mọi token.
- Một device không ở trạng thái
Activethì token của nó bị đưa vào danh sách; request gRPC mang metadatax-device-tokenbị từ chối vớipermission_denied(device is disabled by supervisor guard). - Stream gRPC đang mở với token đó bị ngắt ngay khi token bị chặn, log
Terminating gRPC stream because device token <token> was disabled by supervisor guard. - Ở nhánh HTTP next-hop, token đi kèm header
x-device-tokenkhi chuyển tiếp lên Registry.
Cách xử lý khi một thiết bị bị từ chối: đặt lại trạng thái Active cho device đó ở Registry (token được gỡ khỏi deny-list). Request mới sẽ thông qua, nhưng stream đã bị ngắt phải kết nối lại.
Xác minh:
grep "disabled by supervisor guard" logs/default.log | tail -5
# kỳ vọng: các dòng này xuất hiện khi device không Active,
# không còn dòng mới sau khi device chuyển sang ActiveChi tiết cấu hình phía Registry: xem Device guard.
Đồng bộ cấu hình và xác thực
Các lệnh dùng hằng ngày khi có section registry::
# Xác thực với Registry: đăng ký device rồi push cấu hình local lên
blackhole-fwd auth --key "<API key>"
# Kéo cấu hình từ Registry về (ghi vào file local; --output để chỉ đích file)
blackhole-fwd configure pull --output ./pulled-config.yml
# Đẩy cấu hình local lên Registry
blackhole-fwd configure push
# Sinh JSON schema của cấu hình ra file config.jsonschema cạnh file config
blackhole-fwd configure schemaXác minh:
blackhole-fwd auth --key "<API key>"
# kỳ vọng log/console: "Authentication successful!" và
# "Configuration pushed to remote server successfully"
# (khi đã cấu hình registry: và đã auth)
blackhole-fwd configure pull --output ./pulled-config.yml
ls -l pulled-config.yml
# kỳ vọng: file tồn tại và có nội dung YAML
blackhole-fwd configure push; echo $?
# kỳ vọng: 0
blackhole-fwd configure schema
ls -l config.jsonschema
# kỳ vọng: file JSON schema nằm cạnh file cấu hìnhChi tiết: xem Registry.
Backup cấu hình và trạng thái
Thành phần cần backup
| Thành phần | Vị trí |
|---|---|
| File cấu hình | blackhole-fwd.yml (đường dẫn đang dùng) |
| Snapshot cấu hình hiệu lực | .blackhole-resolved.yaml, nằm cạnh file cấu hình |
| Database + persistent queue | ./blackhole-fwd.db, là một thư mục (sled), chứa cả hàng đợi tin nhắn chưa gửi |
| Log (tuỳ chọn) | ./logs/ |
Tìm đường dẫn đang dùng
# Linux
sudo tr '\0' ' ' < /proc/$(pgrep -x blackhole-fwd)/cmdline; echo
sudo readlink /proc/$(pgrep -x blackhole-fwd)/cwd
# Service (Linux): không có --config trong cmdline,
# config nằm trong thư mục chứa executable# Windows
Get-CimInstance Win32_Process -Filter "Name='blackhole-fwd.exe'" |
Select-Object -ExpandProperty CommandLine
$exeDir = (Get-Process blackhole-fwd).Path | Split-PathBackup
Dừng service trước khi sao chép, database đang được process giữ:
sudo systemctl stop blackhole-fwd
sudo mkdir -p /backup/blackhole-fwd
sudo cp -r /path/to/blackhole-fwd.yml /backup/blackhole-fwd/
sudo cp -r /path/to/.blackhole-resolved.yaml /backup/blackhole-fwd/
sudo cp -r /path/to/blackhole-fwd.db /backup/blackhole-fwd/
sudo systemctl start blackhole-fwd$exeDir = (Get-Process blackhole-fwd).Path | Split-Path
Stop-Service blackhole-fwd
Copy-Item "$exeDir\blackhole-fwd.yml" D:\backup\
Copy-Item "$exeDir\.blackhole-resolved.yaml" D:\backup\
Copy-Item "$exeDir\blackhole-fwd.db" D:\backup\blackhole-fwd.db -Recurse
Start-Service blackhole-fwdPhục hồi: đặt các file trở lại đúng chỗ rồi khởi động lại service.
Xác minh:
ls -l /backup/blackhole-fwd
# kỳ vọng: blackhole-fwd.yml, .blackhole-resolved.yaml, blackhole-fwd.db/ (thư mục)
sudo systemctl start blackhole-fwd
grep "Resolved config snapshot written" logs/default.log | tail -1
# kỳ vọng: dòng mới với source phù hợp (local/persisted/remote)Kiểm tra phiên bản
blackhole-fwd --version
# hoặc
blackhole-fwd -V.\blackhole-fwd.exe --versionKỳ vọng in ra dòng dạng blackhole-fwd <phiên bản> (ví dụ blackhole-fwd 0.7.5). Dùng blackhole-fwd --help để xem toàn bộ flag và subcommand hợp lệ.
Xem thêm
- ./overview - Forwarder là gì
- ./quickstart - Chạy lần đầu
- ./install - Cài đặt và cài service
- ./configuration - Tham chiếu cấu hình
- ./troubleshooting - Khắc phục sự cố
- /components/agent/overview - Agent là gì
