2009-03-03

Syslog-ng (Syslog new generation)

ผู้ดูแลระบบ *nix ส่วนใหญ่คงคุ้นเคยกับ syslog มาเป็นอย่างดี เพราะ syslog ถือได้ว่าเป็น log daemon ที่ใช้กันมาอย่างยาวนานและกลายเป็นมาตรฐานของการเก็บข้อมูลล็อกของระบบปฏิบัติการ *nix ในหลายๆ ตัว แต่อย่างไรก็ตาม syslog ก็มีข้อเสียบางอย่าง ที่ log daemon ตัวอื่น เช่น syslog-ng, msyslog สามารถแก้ไขข้อบกพร่องดังกล่าวได้ เอกสารฉบับนี้จะแนะนำ syslog-ng ซึ่งเป็น log daemon ตัวใหม่ที่กำลังเป็นที่นิยมกันมากขึ้น และจะกล่าวถึงการสร้าง configuration แบบละเอียดเพื่อให้สามารถนำ syslog-ng ไปใช้งานได้จริง

แนะนำ Syslog-ng (Syslog new generation)
syslog-ng สามารถแก้ไขข้อบกพร่องส่วนใหญ่ของ syslog ได้ โดย


syslog-ng สามารถทำงานได้ทั้งบน TCP และ UDP

syslog-ng สามารถทำการกรอง (filter) ข้อมูลได้ด้วย regular expression

syslog-ng สามารถทำงานในรูปแบบที่อ้างอิง priority/facility ได้ ดังนั้น มันจึงสามารถทำงานแทนที่ syslog ได้

syslog-ng สนับสนุน log forwarding ซึ่งทำให้สามารถทราบได้ว่า ต้นทางของล็อกถูกส่งมาจากเครื่องใด และผ่านเครื่องใดมาบ้าง

นอกจากนี้ syslog-ng ยังมีรูปแบบของไฟล์ configuration ที่ง่าย แต่มีความยืดหยุ่นสูง สามารถนำไปประยุกต์ใช้ให้ตรงความต้องการได้โดยง่าย

การติดตั้ง Syslog-ng
syslog-ng ได้ถูกติดตั้งไว้แล้วใน Debian แต่ในระบบปฏิบัติการอื่นนั้น ผู้ดูแลระบบจะต้องติดตั้งเองโดยการคอมไพล์จาก source ทั้งนี้จะต้องติดตั้ง libol ก่อนจึงจะสามารถติดตั้ง syslog-ng ได้

ผู้ดูแลระบบสามารถดาวน์โหลด libol และ syslog-ng ได้จาก http://www.balabit.com/downloads/ หลังจากนั้นให้ขยายไฟล์ออกมา และทำการติดตั้งดังคำสั่งด้านล่างนี้

# cd libol-x.x
# ./configure; make; make install

# cd syslog-ng-x.x
# ./configure --sysconfdir=/etc; make; make install

คำสั่งด้านบนจะทำการติดตั้ง syslog-ng ไปไว้ที่ตำแหน่งโดยดีฟอลต์ (default location) คือ /usr/local หากต้องการติดตั้ง syslog-ng ไปยัง path อื่นให้ใช้คำสั่ง ./configure --prefix=/your/dir/

หลังจากการติดตั้งแล้ว ผู้ดูแลระบบจำเป็นต้องดำเนินการบางอย่างเพื่อให้ syslog-ng ทำงานได้ตามปกติ ดังนี้

สร้างไดเรกทอรี /etc/syslog-ng
สร้างไฟล์ configuration ของ syslog-ng (หรือคัดลอกมาจากไดเรกทอรี contrib/ และ doc/) ไว้ที่ /etc/syslog-ng/syslog-ng.conf
สร้าง startup script ของ syslog-ng ไว้ที่ /etc/init.d/syslog-ng รวมทั้งสร้าง symbolic link จาก run level ต่างๆ เช่น /etc/rc2.d, /etc/rc3.d, /etc/rc5.d) ผู้ดูแลระบบสามารถคัดลอกตัวอย่าง startup script ของระบบปฏิบัติการที่ต้องการได้จากไดเรกทอรี contrib/
การใช้งาน syslog-ng
ผู้ดูแลระบบควรรัน syslog-ng ภายหลังการสร้างไฟล์ configuration เสร็จสิ้นแล้วเท่านั้น โดย syslog-ng มีออปชันในการรันค่อนข้างง่าย ดังตารางที่ 1

ตารางที่ 1 syslog-ng command line options
Flag Description
-d แสดงข้อความดีบัก
-v แสดงข้อความดีบักมากกว่าเดิม (verbose)
-f filename ใช้ filename เป็นไฟล์ configuration (default = /etc/syslog-ng/syslog-ng.conf)
-V แสดงหมายเลขเวอร์ชัน
-p pidfilename ตั้งชื่อไฟล์ proce-ID (default = /var/run/syslog-ng.pid)

Configuring Syslog-ng
Configuration ของ syslog-ng มีความยุ่งยากมากกว่าของ syslog แต่ก็ให้ประโยชน์ในแง่ของความยืดหยุ่นที่ได้และความสามารถที่มีมากกว่า หลังจากที่ทำความเข้าใจ configuration แล้ว ผู้ดูแลระบบสามารถสร้างไฟล์ configuration ง่ายๆ ขึ้นมาได้ด้วยตัวเอง และสามารถปรับปรุงให้เหมาะสมกับระบบของตนต่อไป

โดยปกติแล้ว syslog-ng จะอ่านข้อมูล configuration จากไฟล์ /etc/syslog-ng/syslog-ng.conf

ตัวอย่างที่ 1 แสดง configuration อย่างง่ายของ syslog-ng
options {
use_fqdn(no);
sync(0);
};

source s_sys { unix-stream("/dev/log"); internal(); };
source s_net { udp(); };

destination d_security { file("/var/log/security"); };
destination d_meages { file("/var/log/meages"); };
destination d_console { usertty("root"); };

filter f_authpriv { facility(auth, authpriv); };
filter f_meages { level(info .. emerg) and not facility(auth, authpriv); };
filter f_emergency { level(emerg); };

log { source(s_sys); filter(f_authpriv); destination(d_security); };
log { source(s_sys); filter(f_meages); destination(d_meages); };
log { source(s_sys); filter(f_emergency); destination(d_console); };


จากตัวอย่างจะเห็นได้ว่า ส่วนประกอบหลักของ configuration ประกอบไปด้วย 5 statement หลักคือ options{}, source{}, destination{}, filter{}, log{} ซึ่งแต่ละ statement จะคั่นด้วยเครื่องหมาย semicolon(;)

จะเห็นได้ว่ารูปแบบ configuration ของ syslog-ng.conf จะคล้ายคลึงกับรูปแบบของภาษาซี (C) ซึ่งทุกๆ statement จะต้องลงท้ายด้วยเครื่องหมาย semicolon ส่วน whitespace หรือช่องว่างนั้นไม่มีผลใดๆ ใน configuration จะใช้งานเพียงเพื่อให้สามารถอ่านได้ง่ายเท่านั้น

Global options
เป็นออปชันที่ถูกประกาศใช้งานภายใน options {} statement ซึ่งบางออปชันนั้นนอกจากสามารถใช้งานได้ใน option {} เองแล้วยังสามารถใช้งานใน statement อื่น เช่น source {}, destination {}, filter {}, log {} ได้อีกด้วย

ตารางที่ 2 options{}
Option Description
chain_hostnames( yes | no ) หลังจากแสดง hostname ของเครื่องที่ส่งล็อกมายังเครื่องนี้ผ่านทาง tcp/udp แล้ว ให้แสดง hostname ของทุกเครื่องที่ข้อมูลล็อกถูก handle (โดย syslog-ng) มาตลอดทาง ซึ่งเหตุการณ์นี้จะเกิดขึ้นเมื่อล็อกถูกส่งต่อจาก syslog-ng server ไปยัง syslog-ng server อื่นๆ เป็นทอดๆ (default = yes)
keep_hostname( yes | no ) ให้เชื่อใจ (trust) ค่า hostname ที่อยู่ใน tcp/udp message (default = no)
use_fqdn( yes | no ) บันทึก full name ของเครื่องที่ส่ง tcp/udp message (default = no)
use_dns( yes | no ) ให้ resolve ค่า IP address ในข้อมูลล็อก เป็น hostname (default = yes)
use_time_recvd( yes | no ) ตั้งค่า message timestamp เป็นเวลาที่ล็อกเดินทางมาถึง ซึ่งโดยปกติแล้วจะใช้เวลาที่ระบุในล็อก (default = no)
time_reopen( NUMBER ) เมื่อมีแพ็กเกต tcp ที่สูญหายระหว่างทางหรือเหตุที่ทำให้ไม่สามารถสื่อสารได้ตามปกติ syslog-ng จะพยายามสร้างการสื่อสารใหม่ขึ้นมา โดยจะรอเวลาตามที่ระบุ (NUMBER) หน่วยเป็นวินาที (default = 60)
time_reap( NUMBER ) เมื่อ syslog-ng เปิดไฟล์ที่เป็น inactive file (ไม่มีการเขียนข้อมูลลงไฟล์) syslog-ng จะพยายามปิดไฟล์ดังกล่าว โดยจะรอเวลาตามที่ระบุ (NUMBER) หน่วยเป็นวินาที (default = 60)
log_fifo_size( NUMBER )a ขนาดของ message ที่จะถูกนำไปเข้าคิวในหน่วยความจำก่อนที่จะถูกประมวลผล

ถ้าคิวเต็มและ syslog-ng ไม่สามารถทำงานได้ตามปกติ (busy) ข้อความล็อกที่ส่งเข้ามาจะถูกละทิ้ง แต่หากระบุขนาด FIFO จำนวนมากเกินไปก็จะทำให้สิ้นเปลืองหน่วยความจำ (default = 100)

sync( NUMBER )a จำนวนบรรทัดของ message ที่จะเขียนลงไฟล์ก่อนที่ไฟล์จะถูก synchronize (default = 0)
owner( string )a ตั้งค่าชื่อ user สำหรับไฟล์ล็อกที่ syslog-ng สร้างขึ้นมาใหม่ (default = root)
group( string )a ตั้งค่าชื่อ group สำหรับไฟล์ล็อกที่ syslog-ng สร้างขึ้นมาใหม่ (default = root)
perm( NUMBER )a ตั้งค่า file permission สำหรับไฟล์ล็อก (default = 0600)
create_dirs( NUMBER )a เป็นตัวบอกว่าจะให้ syslog-ng สร้างไดเรกทอรีใหม่ได้หรือไม่ ในกรณีที่ path ที่ระบุไม่มีอยู่จริงในระบบ (default = no)
dir_owner( string )a ตั้งค่าชื่อ user สำหรับไดเรกทอรีที่ syslog-ng สร้างขึ้นมาใหม่ (default = root)
dir_group( string )a ตั้งค่าชื่อ group สำหรับไดเรกทอรีที่ syslog-ng สร้างขึ้นมาใหม่ (default = root)
dir_perm( NUMBER )a ตั้งค่า directory permission เมื่อ syslog-ng สร้างไดเรกทอรีใหม่ (default = 700)
a : ออปชันที่สามารถนำไปใช้กับ file() ใน destination{} ได้

สำหรับออปชันที่เกี่ยวข้องกับ hostname ได้แก่ chain_hostnames(), keep_hostname(), use_fqdn() และ use_dns() นั้น สนใจเฉพาะค่า hostname ของเครื่องที่ส่งล็อกมาเท่านั้น ไม่เกี่ยวข้องกับ hostname ที่ระบุใน message body แต่อย่างใด

use_dns()
เช่น หากใน syslog-ng.conf มี statement ดังต่อไปนี้

options { use_dns(yes); };

และเครื่อง joe-chong ซึ่งมีไอพีเป็น 10.0.0.7 ส่งล็อกดังต่อไปนี้มาที่ log server

Oct 13 19:56:56 s_sys@10.0.0.7 sshd[1222]: Accepted publickey for ROOT from 10.0.0.222 port 1355 ssh2

เครื่อง log server จะทำการบันทึกล็อกดังนี้

Oct 13 19:56:56 s_sys@joe-chong sshd[1222]: Accepted publickey for ROOT from 10.0.0.222 port 1355 ssh2

จากตัวอย่างจะเห็นว่าไอพี 10.0.0.7 นั้นถูก resolve ให้เป็น joe-chong แต่ข้อมูลไอพีอื่นที่อยู่ใน message body คือ 10.0.0.222 นั้น ไม่ได้ถูก resolve ไปด้วย ดังนั้นจึงสรุปได้ว่าออปชัน use_dns(yes) นั้นจะทำการ resolve เฉพาะ hostname ที่อยู่ในส่วนต้นบรรทัดของ message เท่านั้น

นอกจากนี้ออปชันบางตัวที่เกี่ยวข้องกับไฟล์และไดเรกทอรี ยังสามารถใช้งานได้ทั้งใน global options() และ destination() ซึ่งก็คือ modifier ของออปชัน file() เช่น owner(), group() เป็นต้น ทั้งนี้หากมีการระบุค่าออปชันบางตัวที่ซ้ำกันใน options() section และ section อื่นๆ ค่าที่ระบุใน section อื่นๆ จะถูกนำไปใช้แทนที่ค่าใน options() section

keep_hostname() เป็นออปชันที่ใช้งานค่อนข้างมาก ซึ่งจะตั้งค่าดีฟอลต์เป็น no ซึ่งหมายถึง syslog-ng จะไม่ใช้ค่า hostname ที่ส่งมา มันจะทำการ resolve หา hostname จาก source IP address ของแพ็กเกตที่ส่งล็อกเข้ามา เพื่อป้องกันการปลอม hostname จากเครื่องที่ส่งล็อกเข้ามา ซึ่งจะแตกต่างจาก syslog ซึ่งใช้ค่า hostname ตามที่ได้รับมาจาก log message

chain_hostnames() โดยดีฟอลต์มีค่าเป็น yes ซึ่งหมายถึง syslog-ng จะแสดงรายชื่อ host ทุก host ที่ message ถูกส่งต่อมา (relayed by syslog-ng) โดย host ดังกล่าวต้องเป็น host ที่ติดตั้ง syslog-ng และทำหน้าที่ redirect ข้อมูลล็อกมายัง log server (ไม่ใช่ host ที่เป็น network host ตามปกติ เช่น router, firewall)

ตัวอย่างที่ 2 แสดงผลของการใช้งาน keep_hostname() และ chain_hostnames() ซึ่งทั้งสองค่าถูกตั้งค่าดีฟอลต์ให้เป็น yes โดยในตัวอย่างข้อมูลล็อกจะถูกสร้างขึ้นโดยเครื่องปัจจุบัน (locally) จากนั้นจะถูกส่งต่อไปยัง host1 ซึ่งมี hostname จริงๆ เป็น "linux" ซึ่งจะส่งข้อมูลล็อกต่อไปยัง host2 โดย host2 จะทำหน้าที่ตรวจสอบ hostname ผ่านทาง DNS จากนั้นล็อกจึงจะถูกส่งต่อไปยัง host3 ต่อไป

ตัวอย่างที่ 2 แสดงตัวอย่างล็อกที่ถูกส่งต่อผ่านโฮสต์ Original log entry on host1:
Oct 9 23:57:16 s_loc@linux syslog-ng[1656]: syslog-ng version 1.4.13 starting

Entry as sent to and recorded by host2:
Oct 9 23:57:16 s_loc@linux/host1 syslog-ng[1656]: syslog-ng version 1.4.13 starting

Same log entry as relayed from host2 to host3:
Oct 9 23:57:16 s_loc@linux/host1/host2 syslog-ng[1656]: syslog-ng version 1.4.13 starting


สิ่งที่น่าสนใจจากตัวอย่างที่ 2 คือ

เมื่อ host2 บันทึกข้อมูลล็อก ตัว syslog-ng ได้ตรวจสอบข้อมูลจาก DNS แล้วพบว่า จริงๆ แล้ว host1 นั้นมี DNS name เป็น linux แต่ syslog-ng เองก็ยังไม่มั่นใจ จึงเพิ่ม hostname "linux" ต่อท้าย hostname "host1" (host1 อาจจะเป็นชื่อที่ปลอมมา)
timestamp ที่ระบุในล็อกทั้งสามชุดมีเวลาที่ตรงกัน ซึ่งหมายถึง เวลาที่เห็นนั้นถูกสร้างขึ้นจากเครื่องที่ให้กำเนิดล็อกแล้วจึงส่งล็อกต่อไปเรื่อยๆ ผ่านโฮสต์ต่างๆ ซึ่งโฮสต์เหล่านั้นไม่ได้ตั้งค่า use_time_recd() ให้เป็น yes โฮสต์ต่างๆ จึงไม่ได้แก้ไขข้อมูล timestamp จึงมีผลให้เวลาทั้งสามจุดตรงกันหมด
จากข้อมูลล็อกที่ host1 จะพบคำว่า s_loc อยู่ ซึ่งค่าดังกล่าวเป็นค่า source{} ของ syslog-ng ที่อยู่บน host1
ตัวอย่างที่ 3 แสดง configuration ของ syslog-ng บนเครื่อง host1 options{};
source s_loc {unix-stream("/dev/log"); internal(); };
destination d_host2 { udp("host2" port(514)); };
destination d_local { file("/var/log/messages"); };
log { source(s_loc); source(s_net); destination(d_host2); destination(d_local); };


Sources
จากตัวอย่างที่ 3 มีการประกาศค่า source{} หนึ่งครั้ง โดยข้อมูลภายใน source{} ซึ่งก็คือ source driver ทำหน้าที่ระบุถึงแหล่งที่มาของข้อมูลล็อก ทั้งนี้ใน syslog-ng.conf หนึ่งๆ สามารถประกาศ source{} ได้ไม่จำกัดครั้ง ซึ่งภายใน source{} แต่ละตัวนั้นสามารถบรรจุ driver ได้ไม่จำกัดเช่นกัน

รูปแบบการประกาศ source{}

source sourcelabel1 { drivers([options]); drivers([options]); etc. };

โดย sourcelabel หมายถึง string ที่ใช้เพื่ออ้างอิงกลุ่มของ source driver เพื่อให้สามารถนำไปใช้งานต่อได้อย่างสะดวก เช่น

source s_loc { unix-stream("/dev/log"); internal(); };

จากบรรทัดด้านบน s_loc เป็นชื่อที่ถูกใช้เพื่ออ้างอิงถึงข้อมูลล็อกที่ถูกดึงมาจาก /dev/log และข้อมูลล็อกจาก syslog-ng เอง

syslog-ng มีความหยืดหยุ่นอย่างมากในการใช้งาน source driver ซึ่งสามารถรับข้อมูลล็อกได้จาก Unix socket เช่น /dev/log หรือล็อกจาก syslog-ng เอง รวมทั้งล็อกที่ส่งมาจากเครื่องอื่นผ่านทาง TCP, UDP protocol และยังสามารถรับล็อกจากไฟล์พิเศษเช่น ไฟล์ใน /proc ได้อีกด้วย ตารางที่ 3

ตารางที่ 3 Source drivers
Source Description
internal() ล็อกที่รับมาจาก syslog-ng daemon เอง
file("filename" [options]) ล็อกที่อ่านมาจากไฟล์ที่ระบุไว้ เช่น /proc/kmsg
pipe("filename") ล็อกที่รับมาจาก name pipe
unix-stream("filename" [options]) ล็อกที่รับมาจาก Unix socket ที่อยู่ในโหมด connection-oriented stream เช่น /dev/log (maximum concurrent connections default = 100)
unix-dgram("filename" [options]) ล็อกที่รับมาจาก Unix socket ที่อยู่ในโหมด connectionless datagram เช่น ล็อกของ klogd จาก /dev/log
tcp([ip(address)] [port(#)] [max-connections(#)] ) ล็อกที่รับมาจากเครื่องอื่นที่ส่งข้อมูลผ่านทาง TCP ตามหมายเลขพอร์ตที่ระบุ (default = 514) โดยรับข้อมูลจาก local network interface (default = all) และสามารถระบุจำนวน concurrent connections ได้ (default = 10)
udp([ip(address)] [port(#)]) ล็อกที่รับมาจากเครื่องอื่นที่ส่งข้อมูลผ่านทาง UDP ตามหมายเลขพอร์ตที่ระบุ (default = 514) โดยรับข้อมูลจาก local network interface (default = all)

internal()
syslog-ng เองจะส่งข้อมูลล็อก เช่น startup message, errors หรือล็อกอื่นๆ ไปยัง internal() ดังนั้นหากต้องการรับล็อกของตัวโปรแกรม syslog-ng จะต้องระบุ internal() ไว้ใน source{} ด้วย

file()
file() ใช้เพื่อระบุชื่อไฟล์ที่ต้องการให้ syslog-ng ไปดึงข้อมูลล็อกมา เช่น ไฟล์ /proc/kmsg ซึ่งเป็นไฟล์ข้อมูลล็อกของเคอร์เนลหากต้องการให้ syslog-ng ดึงข้อมูลล็อกจาก text file ปกติ เช่น ล็อกของ httpd นั้น จะต้องสร้างสคริปต์ขึ้นมาเพิ่มเติมเพื่อทำหน้าที่ pipe ผลลัพธ์ของคำสั่ง tail -f [filename] ไปยัง logger (ดูรายละเอียดเพิ่มเติมเกี่ยวกับการใช้งาน logger ได้จากคำสั่ง # man logger)

unix-stream(), unix-dgram()
เป็น source driver ที่สำคัญ โดยจะรับข้อมูลจากการเชื่อมต่อแบบ connection-oriented และ connectionless Unix socket สำหรับลีนุกซ์ที่ใช้เคอร์เนลเวอร์ชัน 2.4.1 หรือสูงกว่านั้น จะใช้งาน Unix datagram socket ดังนั้นหากต้องการเก็บข็อมูลล็อกของ /dev/log จะต้องใช้ unix-dgram("/dev/log") เท่านั้น จึงจะสามารถได้รับล็อกตามปกติ เช่น

source s_loc { unix-dgram("/dev/log"); internal(); };

หากใช้ลีนุกซ์ที่มีเวอร์ชันของเคอร์เนลเป็น 2.4.0 หรือต่ำกว่า จะต้องใช้ unix-stream() ในการเก็บข้อมูลล็อกจาก /dev/log

tcp(), udp()
ทั้ง tcp() และ udp() จะรับข้อมูลล็อกจาก remote host ผ่านทาง TCP protocol (connection-oriented) และ UDP protocol (connectionless) โดยทั้งคู่สามารถตั้งให้รอรับข้อมูลล็อกผ่านทาง IP address และ port ที่ระบุได้ โดยดีฟอลต์แล้ว syslog-ng จะรอรับการเชื่อมต่อที่ 0.0.0.0:514 ซึ่งหมายถึง "รอรับการเชื่อมต่อที่ทุก network interface, port 514"

การระบุ IP address มีประโยชน์สำหรับโฮสต์ที่มี network interface มากกว่าหนึ่ง และต้องการเปิดพอร์ตรอรับล็อกจากบาง interface เท่านั้น ดังตัวอย่างที่ 4

ตัวอย่างที่ 4 ตัวอย่างการระบุ ip, port ใน source{}
source s_tcpmessages { tcp( ip(192.168.1.19) port(10514) ); };
source s_udpmessages { ucp(); };


จากตัวอย่างที่ 4 ซึ่งกำหนดให้ s_tcpmessages รับข้อมูลล็อกทุกอันที่ส่งมายัง network interface ที่มีไอพีเป็น 192.178.190.190 TCP port 10514 ส่วน s_udpmessages นั้นรอรับข้อมูลล็อกทุกอันผ่านทาง UDP port 514 ในทุกๆ local network interface

ip(), port(), max_connections()
นอกเหนือจาก ip() และ port() แล้ว ยังมี max_connections() ซึ่งใช้ร่วมกับ tcp() เพื่อจำกัดจำนวนการเชื่อมต่อพร้อมกันสูงสุด ซึ่งการใช้งานออปชันนี้ต้องใช้ค่าที่เหมาะสมกับระบบ เพราะหากกำหนดค่าที่มากไปอาจจะมีผลให้ล็อกบางส่วนถูกทิ้ง (drop) ไปเมื่อเซิร์ฟเวอร์ทำงานเกินพิกัด หากกำหนดน้อยเกินไปและมีการเชื่อมต่อเพื่อส่งล็อกถึงขีดที่กำหนดไว้ จะมีผลให้ข้อมูลล็อกถูก drop ไป จนกระทั่งจะมีช่องว่างเพียงพอที่จะสร้างการเชื่อมต่อ

ตัวอย่างที่ 5 ตัวอย่างการใช้งาน max-connections()
source s_tcpmessages { tcp( ip(192.168.1.19) port(10514) max-connections(100)); };


ค่าดีฟอลต์ของ max-connections() สำหรับ unix-stream() มีค่าเป็น 100 และสำหรับ tcp() มีค่าเป็น 10

Destinations
syslog-ng สามารถเก็บข้อมูลล็อกในรูปแบบเดียวกันกับที่ syslog เก็บได้ ไม่ว่าจะเป็น ASCII file, name pipe, remote host (ผ่านทาง UDP) และแสดงผลออกทาง TTY นอกจากนี้ syslog-ng ยังสามารถส่งข้อมูลล็อกไปยัง Unix socket, remote host (ผ่าน TCP) และส่งต่อไปยัง standard input ของโปรแกรมอื่น

ตารางที่ 5 Destination drivers Driver Description
file("filename [$MACROS]") เก็บข้อมูลล็อกลง Ascii file ตามปกติ หาก syslog-ng ไม่พบไฟล์ตามที่ระบุ มันจะสร้างให้โดยอัตโนมัติ
ส่วน MACRO นั้น ใช้เพื่อกำหนดชื่อไฟล์แบบ dynamic เช่น ตั้งชื่อไฟล์ตาม facility ของข้อมูลล็อก
(โปรดอ่านรายละเอียดเพิ่มเติม ที่เอกสารเผยแพร่เรื่อง "ทำความรู้จักกับ syslogd" )

tcp("address" [port(#);]) ส่งข้อมูลล็อกไปยัง IP address หรือ hostname ที่ระบุผ่านทาง TCP port ที่ระบุ (default port = 514)
udp("address" [port(#);]) ส่งข้อมูลล็อกไปยัง IP address หรือ hostname ที่ระบุผ่านทาง UDP port ที่ระบุ (default port = 514)
pipe("pipename") ส่งข้อมูลล็อกไปยัง name pipe เช่น /dev/xconsole
unix-stream("filename" [options]) ส่งข้อมูลล็อกไปยัง Unix socket แบบ connection-oriented เช่น /dev/log
unix-dgram("filename" [options]) ส่งข้อมูลล็อกไปยัง Unix socket แบบ connectionless เช่น /dev/log
usertty(username) ส่งข้อมูลล็อกไปยัง console ของ user ที่ระบุ
program("/path/to/program") ส่งข้อมูลล็อกเพื่อนำไปเป็น standard input ของโปรแกรมที่ระบุ

syslog-ng สามารถเก็บข้อมูลลงไฟล์ได้และมีความสามารถมากกว่า syslog ตรงที่มีการใช้งานมาโคร มาโครช่วยให้สามารถตั้งชื่อไฟล์ที่ใช้เก็บข้อมูลล็อกได้อย่างน่าดี เช่น ตั้งชื่อไฟล์ตามปีเดือนวัน หรือตั้งชื่อไฟล์ตาม facility, priority

ตัวอย่างที่ 6 ตัวอย่างการใช้งานมาโคร destination d_dailylog { file("/var/log/messages.$WEEKDAY"); };


จากตัวอย่าง configuration ด้านบน เมื่อ syslog-ng ต้องการเขียนข้อมูลล็อกลงไฟล์ มันจะสร้างไฟล์ชื่อ /var/log/messages.Tues, /var/log/messages.Wed ซึ่งขึ้นกับวันที่เก็บข้อมูลล็อกดังกล่าว

ตารางที่ 6 Macros supported in file() destinations Macro Expands to
Program ชื่อของโปรแกรมที่ส่งล็อกเข้ามา
HOST ชื่อโฮสต์ที่เป็นจุดกำเนิดล็อก
FACILITY facility ของล็อกที่ถูกส่งเข้ามา
PRIORITY or LEVEL priority ของล็อกที่ถูกส่งเข้ามา
YEAR ปีปัจจุบันa
MONTH เดือนปัจจุบันa
DAY วันที่ปัจจุบันa
WEEKDAY วันปัจจุบันa เช่น Monday
HOUR ชั่วโมงปัจจุบันa
MIN นาทีปัจจุบันa
SEC วินาทีปัจจุบันa
a : หากออปชัน use_time_recvd() ถูกตั้งค่า yes แล้ว ข้อมูลเวลาจะอ้างอิงจาก local system ขณะที่ล็อกเดินทางมาถึง แต่หาก use_time_recvd() มีค่าเป็น no ก็จะอ้างอิงเวลาจากเวลาที่ปรากฎในข้อมูลล็อก
syslog-ng จะสร้างไฟล์ขึ้นมาใหม่ หากไฟล์ที่ระบุใน file() ไม่มีอยู่จริง นอกจากนี้ syslog-ng ยังสามารถกำหนดออปชันบางตัวในระดับทั่วไป (general rule) คือให้มีผลกับ configuration ทั้งไฟล์ได้ ขณะเดียวกันก็สามารถกำหนดออปชันในระดับ per-log-file ได้ ซึ่งการกำหนดออปชันชนิดหลังนี้จะเป็นการ overridden ออปชันในระดับ general rule

ตัวอย่างที่ 7 การควบคุม file() destination d_mylog { file("/var/log/ngfiles/mylog" create_dirs(yes)\
dir_owner(root) dir_group(root) dir_perm(700)); };


จากตัวอย่างที่ 7 เป็นการระบุออปชัน dir_owner(), dir_group(), dir_perm() ใน destination{} ซึ่งค่าที่ระบุนี้จะมีผลแทนที่ค่าที่ระบุใน options{} โดยอัตโนมัติ นอกจากนี้ยังสามารถระบุออปชัน owner(), group(), perm() ได้เช่นเดียวกันกับออปชันด้านบน

โดยปกติ syslog-ng จะสร้างไฟล์ล็อกที่ไม่มีอยู่ในระบบโดยอัตโนมัติ เว้นเสียแต่ว่าไฟล์ที่ระบุดังกล่าวจะอยู่ใน path ที่ไม่มีอยู่จริงและออปชัน create_dirs() ถูกตั้งค่าเป็น no

sync() ถูกใช้เพื่อจำกัดความถี่ในการ synchronize ไฟล์ล็อก หากมีค่าสูงๆ จะทำให้ข้อมูลล็อกถูกนำไปเก็บไว้ที่แคช (cache) เป็นจำนวนมากก่อนที่จะถูก synchronize หรือบันทึกลงไฟล์ล็อกต่อไป หาก sync() มีค่าต่ำ ก็เป็นการลดความเสี่ยงในการสูญเสียข้อมูล เพราะข้อมูลที่ถูกประมวลผลแล้วจะถูกบันทึกลงไฟล์ล็อกทันที

โดยดีฟอลต์แล้ว ค่าล็อกถูกตั้งค่าเป็นศูนย์ ซึ่งหมายถึงให้บันทึกข้อมูลล็อกทุกอันในทันที โดยปกติค่า sync() ต่ำๆ จะเหมาะสำหรับระบบที่ข้อมูลล็อกไม่เยอะมาก ส่วนระบบที่มีข้อมูลล็อกจำนวนมากควรใช้ค่า sync() สูง ซึ่งค่าระหว่าง 100 ถึง 1000 นั้นถือว่ามีค่าสูงพอสมควร ซึ่งผู้ดูแลระบบจะต้องทดสอบเพื่อหาค่าที่เหมาะสมกับระบบของตนต่อไป

อย่างไรก็ตามหากระบบที่ติดตั้ง syslog-ng ได้ติดตั้งโปรแกรมจำพวก log monitoring tool เช่น Swatch แล้วไม่ควรตั้งค่า sync() ไว้สูงมากนัก เพราะอาจจะทำให้ไม่สามารถแจ้งเตือนผู้ดูแลระบบได้ในกรณีที่ไฟล์ล็อกโดนลบ

Filters
filter หรือการกรองข้อมูลเป็นส่วนที่มีความสำคัญส่วนหนึ่ง นอกเหนือจากการกรองข้อมูลโดยใช้ facility, priority แล้ว syslog-ng ยังสามารถตรวจสอบชื่อโปรแกรมที่ส่งข้อมูลล็อกมา ชื่อเครื่องที่ทำหน้าที่ส่งต่อล็อกมา และยังสามารถกรองข้อมูลล็อกตาม regular expression ที่ตั้งไว้อีกด้วย

filter{} statement ประกอบไปด้วย label (ชื่อเรียกของ filter{} ชุดนั้นๆ) และคำสั่งในการกรองข้อมูลอย่างน้อย 1 คำสั่ง โดยสามารถใช้ and, or, not ในการเชื่อมคำสั่งในการกรองข้อมูลได้

ตารางที่ 7 filter{} funtions
Function (criteria) Description
facility( facility-name ) facility ที่ต้องการ
priority( priority-name )
priority( priority-name1, priority-name2, etc, )
priority( priority-name1 .. priority-name2 ) ระดับของ priority ที่ต้องการ
- สามารถใช้เครื่องหมาย comma (,) คั่น หากต้องการมากกว่าหนึ่งระดับได้
- สามารถใช้เครื่องหมาย .. แทน priority ที่ต้องการระหว่าง priority ที่กำหนดได้ เช่น info .. warn
level( priority-name ) เช่นเดียวกันกับ priority
program( program-name ) ชื่อโปรแกรมที่สร้างล็อกขึ้นมา
host( hostname ) ชื่อ host ที่ล็อกนี้ถูกสร้าง
match( regular-expression ) regular expression ที่จะถูกนำไปเปรียบกับกับส่วน body ของล็อก
filter( filter-name ) ชื่อ filter อื่นที่ต้องการนำมากรองอีกครั้ง

จากตัวอย่างที่ 8 แสดง syslog-ng.conf ในระบบปฏิบัติการลินุกซ์เดเบียน 2.2 (Debian 2.2)

ตัวอย่างที่ 8 ตัวอย่างการใช้งาน filter{}
filter f_mail { facility(mail); };
filter f_debug { not facility(auth, authpriv, news, mail); };
filter f_messages { level(info .. warn) and not facility(auth, authpriv, cron, daemon, mail, news); };
filter f_cother { level(debug, info, notice, warn) or facility(daemon, mail); };


บรรทัดแรกในตัวอย่างที่ 8 filter f_mail กรองได้ข้อมูลล็อกทุกอันที่อยู่ใน facility mail
บรรทัดที่สอง filter f_debug กรองได้ข้อมูลล็อกทุกอันยกเว้น facility auth, authpriv, news, และ mail
บรรทัดที่สาม filter f_messages กรองได้ข้อมูลล็อกทุกอันที่มี priority ตั้งแต่ info จนถึง warn ยกเว้นข้อมูลล็อกที่มี facility เป็น auth, authpriv, cron, daemon, mail, news
บรรทัดสุดท้าย filter f_cother กรองข้อมูลล็อกที่มี priority เป็น debug, info, notice และ warn หรือ ข้อมูลล็อกที่มี facility เป็น daemin และ mail

Log statements
หลังจากที่ทำความเข้าใจส่วนประกอบต่างๆ คือ sources, filters และ destinations แล้ว ก็จะนำส่วนประกอบทั้งหมดมารวมไว้ใน log{}

ตัวอย่างที่ 9 ตัวอย่าง syslog-ng.conf
source s_loc { unix-stream("/dev/log"); internal(); };
source s_tcpmessages { tcp( ip(192.168.1.19); port(10514);); };

destination d_dailylog { file("/var/log/messages.$WEEKDAY"); };
destination d_untlog { file("/var/log/untlog" owner(unt)) perm(0600)); };

filter f_mail { facility(mail); };
filter f_messages { level(info .. warn) and not facility(auth, authpriv, cron, daemon, mail, news); };

log { source(s_tcpmessages); destination(d_untlog); };
log { source(s_loc); filter(f_mail); destination(d_untlog); };
log { source(s_loc); filter(f_messages); destination(d_dailylog); };


จาก log statement บรรทัดแรกนั้น จะทำให้ข้อมูลล็อกทุกอันที่มาจากเครื่อง 192.168.1.19 จะถูกบันทึกลงในไฟล์ /var/log/untlog
บรรทัดที่สองจะทำให้ข้อมูลล็อกของเมล์ (facility mail) ของ localhost ถูกบันทึกลงในไฟล์ /var/log/untlog
บรรทัดที่สามจะทำให้ข้อมูลล็อกของ localhost ที่ผ่านการกรองของ filter f_messages ถูกบันทึกลงในไฟล์ /var/log/messages.$WEEKDAY เช่น /var/log/Mon, /var/log/Sun

จากตัวอย่างที่ 9 อาจจะเกิดข้อสังสัยว่า ล็อกบางส่วนที่ไม่ได้ถูกจัดเก็บโดย log{} statement ทั้งสามตัวนั้นจะถูกจัดเก็บไว้ที่ใด syslog-ng มีค่า filter(DEFAULT) ซึ่งสามารถใช้ระบุในตอนท้ายเพื่อสั่งให้ syslog-ng บันทึกข้อมูลล็อกที่ไม่ได้ถูกจัดเก็บโดย log{} ก่อนหน้านี้ได้ ดังตัวอย่างที่ 10

ตัวอย่างที่ 10 ตัวอย่าง syslog-ng.conf
log { source(s_tcpmessages); destination(d_untlog); };
log { source(s_loc); filter(f_mail); destination(d_untlog); };
log { source(s_loc); filter(f_messages); destination(d_dailylog); };
log { source(s_loc); filter(DEFAULT); destination(d_dailylog); };


Advanced Configurations
ตัวอย่างที่ 11 แสดงการใช้ syslog-ng เพื่อคอยเฝ้าดูข้อมูลล็อกที่ต้องการ (log monitoring)
ตัวอย่างที่ 11
source s_local { unix_stream("/dev/log"); internal(); };
filter f_denials { match("[Dd]enied|[Ff]ail"); };
destination d_mail { program("/usr/local/sbin/mail.sh"); };
log { source(s_local); filter(f_denials); destination(d_mail); };


ตัวอย่างที่ 12 เป็นตัวอย่าง script ที่ใช้สำหรับส่งอี-เมล์

ตัวอย่างที่ 12
#!/usr/bash
while read line;
do
echo $line |mail -s "Weirdness on that Linux box" your_email@yourcompany.com
done


จุดที่น่าสนใจในตัวอย่างที่ 11 คือ match("[Dd]enied|[Ff]ail") ซึ่งหมายถึง ข้อมูลล็อกใดก็ตามที่มีคำว่า denied, Denied, Fail หรือ fail ปรากฏอยู่ ก็จะถูกส่งในรูปแบบอี-เมล์ไปยัง your_email@yourcompany.com โดย shell script ที่ชื่อ /usr/local/sbin/mail.sh

ข้อควรระวังในการใช้งานดังตัวอย่างที่ 11 คือ การใช้ program() นั้นเป็นการเรียกใช้งานโปรแกรมที่ระบุ โดยโปรแกรมนั้นจะยังคงรันอยู่จนกว่า syslog-ng จะหยุดการทำงานหรือเริ่มการทำงานใหม่ ดังนั้นผู้ดูแลระบบควรไตร่ตรองก่อนการใช้งานออปชันดังกล่าว เช่น หากรัน bash process ก็จะทำให้เกิดการสิ้นเปลืองงานทรัพยากร นอกจากนี้หากรันโปรแกรมในฐานะ root ก็จะเป็นการเพิ่มความเสี่ยงให้กับระบบอีกด้วย นอกจากนี้การใช้ระบบเตือนภัยผ่านทางอี-เมล์ดังตัวอย่างที่ 11 ยังก่อให้เกิดความเสี่ยงที่ทำให้ระบบถูกโจมตีแบบ Denial of Service ได้ เช่น ทำให้ mailbox ของผู้ดูแลระบบเต็ม


สรุป
syslog-ng เป็นโปรแกรมที่มีความหยืดหยุ่นในการทำงาน เหมาะสำหรับการนำมาใช้งานเป็นเป็น log server เป็นอย่างยิ่ง เพราะสามารถเก็บข้อมูลล็อกแยกตามเครื่องที่ส่งล็อกมาได้ นอกจากนี้ยังสามารถทำงานร่วมกับโปรแกรม sqlsyslogd เพื่อนำข้อมูลล็อกทั้งหมดบันทึกลงในฐานข้อมูลได้ ซึ่งจะนำเสนอรายละเอียดในโอกาสต่อไป

ผู้ดูแลระบบควรศึกษาคู่มือการใช้งานเพิ่มเติม เพื่อให้สามารถใช้ syslog-ng ได้อย่างเต็มประสิทธิภาพ โดยสามารถศึกษาได้จาก

ไดเรกทอรี doc ภายใต้ source ที่ขยายออกมาแล้วของ syslog-ng
หรือผ่านทางเมล์ลิงลิสต์ https://lists.balabit.hu/mailman/listinfo/syslog-ng
หรือตาม references ที่ให้ไว้ด้านล่างนี้
References
Balzs Scheidler (2000). syslog-ng reference manual. From http://www.balabit.com/products/syslog_ng/reference/book1.html
Syslog-ng FAQ. From http://www.campin.net/syslog-ng/faq.html
Michael D. Bauer. Building SECURE SERVERS with LINUX. 1st Edition, O'REILLY, 2002

No comments: