คำตอบสั้น ๆ: ตั้งเซิร์ฟเวอร์กลางรับ Log จากเครื่องอื่น แยกไฟล์ตามชื่อเครื่อง ตั้งการหมุนไฟล์ และเข้ารหัสการส่งด้วย TLS
คู่มือนี้อธิบาย rsyslog ทีละขั้นตอน พร้อมคำสั่งที่ใช้ได้จริงและปัญหาที่พบบ่อย
เมื่อเซิร์ฟเวอร์ถูกบุกรุก สิ่งแรกที่ผู้โจมตีทำคือลบ Log บนเครื่องนั้น การเก็บ Log ไว้แค่บนเครื่องที่สร้างมันจึงไม่ปลอดภัย และยังไล่ปัญหาที่เกิดข้ามหลายเครื่องได้ยากเพราะต้อง SSH เข้าไปไล่ดูทีละเครื่อง
การรวม Log ไว้ที่เดียวแก้ทั้งสองเรื่อง คู่มือนี้ตั้ง rsyslog ซึ่งติดตั้งมาพร้อมกับ Linux เกือบทุกดิสทริบิวชันอยู่แล้ว ให้ทำหน้าที่เป็นเซิร์ฟเวอร์กลาง
สิ่งที่ต้องเตรียม
- เครื่องหนึ่งเครื่องสำหรับเป็นเซิร์ฟเวอร์ Log พร้อมพื้นที่ดิสก์เพียงพอ
- เครื่องต้นทางที่ต้องการส่ง Log
- เครือข่ายภายในระหว่างกัน หรือ VPN หากอยู่คนละที่
ประเมินพื้นที่คร่าว ๆ เซิร์ฟเวอร์เว็บทั่วไปสร้าง Log ระบบราว 50-200 MB ต่อเดือนต่อเครื่อง หากรวม Log ของเว็บเซิร์ฟเวอร์ด้วยจะมากกว่านั้นหลายเท่า
ขั้นตอนที่ 1: ตั้งฝั่งเซิร์ฟเวอร์ให้รับ Log
sudo nano /etc/rsyslog.d/10-server.conf
# รับผ่าน TCP ซึ่งเชื่อถือได้กว่า UDP
module(load="imtcp")
input(type="imtcp" port="514" address="10.0.0.5")
# แยกไฟล์ตามชื่อเครื่องและชื่อโปรแกรม
template(name="RemoteLogs" type="string"
string="/var/log/remote/%HOSTNAME%/%PROGRAMNAME%.log")
# กฎนี้ใช้กับ Log ที่มาจากเครื่องอื่นเท่านั้น
if $fromhost-ip != '127.0.0.1' then {
action(type="omfile" dynaFile="RemoteLogs"
fileCreateMode="0640" dirCreateMode="0750"
fileOwner="syslog" fileGroup="adm")
stop
}
บรรทัด stop สำคัญ มันป้องกันไม่ให้ Log จากเครื่องอื่นถูกเขียนปนลงไฟล์ของเครื่องนี้ด้วย
sudo mkdir -p /var/log/remote
sudo chown syslog:adm /var/log/remote
sudo rsyslogd -N1
sudo systemctl restart rsyslog
คำสั่ง rsyslogd -N1 คือตรวจไวยากรณ์โดยไม่เริ่มทำงานจริง ใช้ทุกครั้งก่อนรีสตาร์ต
เปิดพอร์ตเฉพาะจากเครือข่ายภายใน
sudo ufw allow from 10.0.0.0/24 to any port 514 proto tcp
sudo ss -tlnp | grep 514
ขั้นตอนที่ 2: ตั้งฝั่งเครื่องต้นทางให้ส่ง Log
sudo nano /etc/rsyslog.d/90-forward.conf
# คิวบนดิสก์ กัน Log หายเมื่อเซิร์ฟเวอร์กลางล่มชั่วคราว
action(type="omfwd"
target="10.0.0.5" port="514" protocol="tcp"
queue.type="LinkedList"
queue.filename="fwdRule1"
queue.maxdiskspace="1g"
queue.saveonshutdown="on"
action.resumeRetryCount="-1")
sudo rsyslogd -N1
sudo systemctl restart rsyslog
ส่วนของคิวคือสิ่งที่ทำให้ระบบนี้ใช้งานได้จริง หากเซิร์ฟเวอร์กลางดับ เครื่องต้นทางจะเก็บ Log สะสมไว้บนดิสก์ไม่เกิน 1 GB แล้วส่งย้อนหลังให้เมื่อกลับมา
ทดสอบ
logger -t test-message "ทดสอบส่ง log จาก $(hostname)"
แล้วตรวจที่เซิร์ฟเวอร์กลาง
sudo ls -R /var/log/remote/
sudo tail /var/log/remote/web1/test-message.log
ขั้นตอนที่ 3: ส่ง Log ของ Nginx เข้ามาด้วย
Nginx เขียนไฟล์เองโดยไม่ผ่าน syslog ตามค่าเริ่มต้น เปลี่ยนให้ส่งผ่าน syslog ได้
sudo nano /etc/nginx/nginx.conf
error_log syslog:server=unix:/dev/log,tag=nginx_error warn;
access_log syslog:server=unix:/dev/log,tag=nginx_access combined;
sudo nginx -t && sudo systemctl reload nginx
วิธีนี้ทำให้ Log ของเว็บถูกส่งต่อไปเซิร์ฟเวอร์กลางด้วยกฎเดียวกัน โดยไม่ต้องตั้งค่าเพิ่ม