จากภาพความทรงจำเดิมที่เคยได้ยินได้ฟังกันมา syslog รองรับ connection ที่ UDP/514 … ทุกวันนี้ภาพจำนั้นเปลี่ยนแปลงไปอย่างมาก เพื่อให้รองรับกระแสโลก IT ที่ต้องคำนึงความปลอดภัย รวมถึงความมั่นใจในการส่งข้อมูลผ่าน syslog protocol … จาก syslog server เดิม vs ความต้องการในปัจจุบัน
- คนส่งก็ส่งข้อความไป .. คนรับจะรับได้หรือไม่ ก็พอรับได้ vs ไม่ได้ log หายไม่ได้ สำคัญมาก ข้อความต้องอยู่ครบ
- ส่ง ๆ ไปใครจะมาดักอ่านกลางทางก็ไม่เป็นไรมั้ง vs ข้อมูลนี้ให้คนอื่นเห็นไม่ได้ ต้องรักษาความลับได้จนถึงปลายทาง
- ใครส่งข้อความมาให้(ก็ได้) พร้อมรับเข้ามาประมวล vs syslog จะรับข้อความจาก client ที่รู้จักเท่านั้น
เป้าหมายของ Syslog สุดโหด
นิยามที่ syslog server ที่ผมเรียกว่า syslog สุดโหดนั้น ผมอยากสื่อความหมายในมุมของการเชื่อมต่อจาก client ที่ต้องมีข้อกำหนดในการเชื่อมต่อ ไม่รองรับการเชื่อมต่อจาก client ที่ไม่สามารถพิสูจน์ตัวตนได้ และยังต้องการเข้ารหัสลับตั้งแต่ต้นทางถึงปลายทาง ดังนั้นในการกำหนดค่า configuration ของ syslog server จะต้องรองรับความสามารถดังนี้
- log หายไม่ได้ สำคัญมาก ข้อความต้องอยู่ครบ
- ข้อมูลนี้ให้คนอื่นเห็นไม่ได้ ต้องรักษาความลับได้จนถึงปลายทาง
- syslog จะรับข้อความจาก client ที่รู้จักเท่านั้น
จากเป้าหมาย 3 ข้อ ถ้าหยิบมาตีความให้เป็นข้อกำหนดทาง technical เพื่อตอบโจทย์ให้ครบทุกข้อ Syslog จะต้องรองรับ Protocol TCP, Transport Layer Security (TLS) ที่กำหนดให้ร้องขอจาก Client เพื่อตรวจสอบ Certificate จาก Client ได้ ที่เรียกว่า Mutual Authentication หรือจะเรียกรวม ๆ ว่า mTLS - Mutual Transport Layer Security
#0 เตรียมสร้าง Key Pair
ในการเตรียมทดสอบ mTLS ต้องจัดเตรียมสร้าง Key Pair ไว้ 3 ชุด และ ให้เป็นไปตามข้อกำหนดของ rsyslog และ client ที่จะนำมาทดสอบ (ในกรณีนี้เลือก Docker เป็น client ในการทดสอบ) กรณีศึกษาที่จะทดสอบ เลือกเป็น Self Signed มาใช้ในการทดสอบ
- สร้าง Key Pair เพื่อทำหน้าที่เป็น Certificated Authority
- สร้าง Key Pair สำหรับ rsyslog server ที่ signed โดย CA ในข้อที่ 1 และมีข้อมูลในส่วนของ SAN - Subject Alternative Name อยู่ด้วย
- สร้าง Key Pair สำหรับ client (ในกรณีนี้จะใส่ให้กับ Docker Daemon) ที่ signed โดย CA ในข้อที่ 1 และมีข้อมูลในส่วนของ SAN - Subject Alternative Name อยู่ด้วย
ที่ syslog server จัดวางไฟล์ ca.crt,server1.key และ server1.crt ไว้ที่ /etc/pki/rsyslog
ที่ client จัดวาง ca.crt, client1.key และ client1.crt ไว้ที่ /etc/docker/
#1 กำหนดค่าให้ rsyslog
/etc/rsyslog.conf
เป็นไฟล์หลักที่จะกำหนดการทำงานของ rsyslog เพื่อให้เป็นไปอย่างที่เราต้องการ
syslog > ~ sudo apt install -y rsyslog-gnutls
Reading package lists... Done
Building dependency tree... Done
Reading state information... Done
The following packages were automatically installed and are no longer required:
libflashrom1 libftdi1-2
Use 'sudo apt autoremove' to remove them.
Suggested packages:
gnutls-bin
[... truncated output ...]
syslog > ~ sudo vi /etc/rsyslog.conf
#- เพิ่มข้อมูลส่วนนี้ใน configuration
module(load="imtcp"
StreamDriver.Name="gtls"
StreamDriver.Mode="1" # run driver in TLS-only mode
StreamDriver.Authmode="x509/name"
PermittedPeer="docker.d8k.io"
)
input(type="imtcp" port="514")
global(
DefaultNetstreamDriver="gtls"
DefaultNetstreamDriverCAFile="/etc/pki/rsyslog/ca.crt"
DefaultNetstreamDriverCertFile="/etc/pki/rsyslog/server1.crt"
DefaultNetstreamDriverKeyFile="/etc/pki/rsyslog/server1.key"
)
syslog ~ > cat <<-EOF | sudo tee /etc/rsyslog.d/01-container-log.conf
\$template containerLogs,"/var/log/docker/%hostname%_%syslogtag:R,ERE,1,ZERO:.*cname/([^\[]+)--end%.log"
if \$syslogtag contains 'cname' then -?containerLogs
& stop
EOF
syslog > ~ sudo systemctl restart rsyslog
syslog > ~ ss -tlanp | grep 514
LISTEN 0 25 0.0.0.0:514 0.0.0.0:*
LISTEN 0 25 [::]:514 [::]:*
#2 เลือก Docker มาเป็นตัวอย่างของ Client
ในการกำหนด log driver จากเดิมที่ค่าปกติเป็น json-file ให้เปลี่ยนเป็น syslog และรองรับ mTLS จะกำหนดที่ /etc/docker/daemon.json
docker > ~ cat /etc/docker/daemon.json
{
"log-driver": "syslog",
"log-opts": {
"syslog-address": "tcp+tls://syslog.d8k.io:514",
"tag": "cname/\{\{.Name\}\}",
"syslog-tls-ca-cert": "/etc/docker/ca.crt",
"syslog-tls-cert": "/etc/docker/client1.crt",
"syslog-tls-key": "/etc/docker/client1.key"
}
}
# เพิ่มเติมข้อมูลส่วน log driver ในไฟล์
docker > ~ sudo systemctl restart docker
#3 ทดสอบการทำงาน และผลการทดสอบ
ในการทดสอบ จะสร้าง container ชื่อว่า mynginx จาก image ที่ชื่อว่า NGINX และทดลอง request ไปที่ container ตัวนี้ ซึ่งผลที่คาดว่าจะได้รับคือ มี access log เกิดขึ้นที่ syslog server ที่ /var/log/docker/<Docker host>-mynginx.log
[at Docker Host]
docker > ~ docker container run -d --name mynginx --rm nginx
68d9f69002be79e0125a6ad3b3d4cf1b94ff7aa787a2973412e834a7c1bb1542
[at Syslog Server]
syslog > ~ sudo ls -la /var/log/docker
total 16
drwxr-xr-x 2 syslog syslog 4096 Jan 6 14:44 .
drwxrwxr-x 9 root syslog 4096 Jan 6 14:44 ..
-rw-r----- 1 syslog adm 4873 Jan 6 14:49 128.199.210.227_mynginx.log
syslog > ~ sudo tail -n 3 /var/log/docker/128.199.210.227_mynginx.log
Jan 6 14:49:57 128.199.210.227 cname/mynginx[3660]: 2023/01/06 14:49:57 [notice] 1#1: getrlimit(RLIMIT_NOFILE): 1048576:1048576
Jan 6 14:49:57 128.199.210.227 cname/mynginx[3660]: 2023/01/06 14:49:57 [notice] 1#1: start worker processes
Jan 6 14:49:57 128.199.210.227 cname/mynginx[3660]: 2023/01/06 14:49:57 [notice] 1#1: start worker process 29
ข้อผิดพลาดที่อาจจะเกิดขึ้น
- ถ้า Client ไม่รองรับ mTLS จะเกิดข้อความที่ฝั่ง syslog server ว่าเกิดข้อผิดพลาดขณะเชื่อต่อ
[at client (docker.d8k.io)]
docker > ~ logger --tcp --server syslog.d8k.io --port 514 "Hello Syslog Server"
[at syslog server]
syslog > ~ sudo tail -f /var/log/syslog
[... truncated output ...]
Jan 6 14:54:29 syslog rsyslogd: gnutls returned error on handshake: An unexpected TLS packet was received. [v8.2112.0 try https://www.rsyslog.com/e/2083 ]
Jan 6 14:54:29 syslog rsyslogd: tcpsrv listener (inputname: 'imtcp') failed to process incoming connection with error -2083 [v8.2112.0 try https://www.rsyslog.com/e/2083 ]
- ถ้า Client Certificate ไม่มี SAN - Subject Alternative Name ฝั่ง syslog server ก็ไม่สามารถพิสูจน์ตัวตนของฝั่ง client ได้ก็จะไม่อนุญาตให้เชื่อมต่อ
syslog > ~ sudo tail -f /var/log/syslog
[... truncated output ...]
Jan 6 15:09:45 syslog rsyslogd: error: peer name not authorized - not permitted to talk to it. Names: CN: docker; [v8.2112.0 try https://www.rsyslog.com/e/2088 ]
Jan 6 15:09:45 syslog rsyslogd: netstream session 0x7f67e000d640 from 128.199.210.227 will be closed due to error [v8.2112.0 try https://www.rsyslog.com/e/2089 ]
- ถ้า Client ที่ไม่ได้รับอนุญาตมาขอเชื่อมต่อ ฝั่ง syslog server ก็สามารถพิสูจน์ตัวตนของฝั่ง client ได้ก็จริง แต่ว่าไม่ได้อยู่ในรายชื่อที่อนุญาตให้เชื่อมต่อ ก็จะไม่อนุญาตให้เชื่อมต่อ
syslog > ~ sudo tail -f /var/log/syslog
[... truncated output ...]
Jan 6 15:14:59 syslog rsyslogd: error: peer name not authorized - not permitted to talk to it. Names: DNSname: docker.d8k.io; CN: docker; [v8.2112.0 try https://www.rsyslog.com/e/2088 ]
Jan 6 15:14:59 syslog rsyslogd: netstream session 0x7f2f9401bef0 from 128.199.210.227 will be closed due to error [v8.2112.0 try https://www.rsyslog.com/e/2089 ]
ข้อมูลมูลเพิ่มที่เกี่ยวข้องกับ Syslog
- The Syslog Protocol
- Transport Layer Security (TLS) Transport Mapping for Syslog
- Transmission of Syslog Messages over UDP
- Signed Syslog Messages
- Transmission of Syslog Messages over TCP