การเจาะเซิร์ฟเวอร์ที่สำเร็จส่วนใหญ่ไม่ได้เกิดจาก exploit อันแยบยล แต่เกิดจากช่องโหว่ที่แพตช์ออกมาหลายเดือนก่อนหน้า สาเหตุมักไม่ใช่ความขี้เกียจ: การอัปเดตด้วยมือบนเซิร์ฟเวอร์ที่ใช้งานจริงนั้นน่ากลัว เพราะบางครั้ง apt upgrade รีสตาร์ตสิ่งที่ไม่มีใครขอให้รีสตาร์ต การอัปเดตอัตโนมัติปิดคำถามนี้ได้ แต่มันมีชื่อเสียงไม่ดี — สมควรพอดีกับระดับที่มันถูกตั้งค่าอย่างรีบร้อน
มาดูการจัดวางที่แพตช์ความปลอดภัยมาถึงเอง และเวอร์ชัน PHP ไม่เปลี่ยนไปข้ามคืน
การติดตั้ง
sudo apt install unattended-upgrades apt-listchanges
sudo dpkg-reconfigure -plow unattended-upgrades
บทสนทนานี้สร้าง /etc/apt/apt.conf.d/20auto-upgrades ตรวจดูว่าได้อะไรออกมา:
APT::Periodic::Update-Package-Lists "1";
APT::Periodic::Unattended-Upgrade "1";
เลขหนึ่งหมายถึง «ทุกวัน» ทั้งหมดนี้ขับเคลื่อนด้วยไทเมอร์ของ systemd ไม่ใช่ cron แบบคลาสสิก:
systemctl list-timers | grep apt
สิ่งสำคัญที่สุด: เฉพาะความปลอดภัย
ไฟล์หลักคือ /etc/apt/apt.conf.d/50unattended-upgrades ในนั้นมีรายการ Allowed-Origins (บน Debian คือ Origins-Pattern) และโดยค่าเริ่มต้นมีเปิดใช้อยู่เฉพาะ repository ความปลอดภัย ปล่อยให้เป็นเช่นนั้น
สิ่งล่อใจให้ยกเลิกคอมเมนต์บรรทัด -updates — «ให้อัปเดตทุกอย่างเลย» — นั้นแรง อย่าทำ: repository updates นำเวอร์ชันใหม่มา ไม่ใช่แค่การแก้ไข และเซอร์ไพรส์กลางดึกก็มาจากตรงนั้นพอดี ความปลอดภัยกับความใหม่เป็นงานคนละอย่าง และอย่างที่สองทำตอนคุณนั่งอยู่หน้าคีย์บอร์ดจะดีกว่า
ถ้าแพ็กเกจใดไม่ควรอัปเดตอัตโนมัติ ก็มีบัญชีดำสำหรับมัน:
Unattended-Upgrade::Package-Blacklist {
"mariadb-server";
"php8.3-fpm";
};
ใช้มันอย่างมีสติ: ทุกบรรทัดตรงนี้หมายความว่า «ตัวนี้ฉันอัปเดตเอง» — และนั่นคือคำสัญญาที่ต้องรักษา
การรีบูต
บรรทัดสำคัญ:
Unattended-Upgrade::Automatic-Reboot "false";
การปล่อยไว้เป็น false ถูกต้องสำหรับเซิร์ฟเวอร์ที่มีเว็บไซต์: การรีบูตตอนตีสามโดยไม่บอกกล่าวแย่กว่าแพตช์ที่เลื่อนไปหนึ่งวัน แต่การตัดสินใจนั้นมีครึ่งหลังที่บังคับ และนั่นคือครึ่งที่ผู้คนลืม
เมื่อเคอร์เนล libc หรือ openssl ถูกอัปเดต ระบบจะสร้างไฟล์ /var/run/reboot-required จนกว่าจะรีบูต เวอร์ชันที่แก้แล้วอยู่บนดิสก์ในขณะที่เวอร์ชันเก่ายังทำงานในหน่วยความจำ — นั่นคือช่องโหว่ยังไม่ได้หายไปไหน แม้แพ็กเกจจะนับว่าอัปเดตแล้ว ตรวจอย่างชัดเจน:
ls -l /var/run/reboot-required
cat /var/run/reboot-required.pkgs
ไฟล์ที่สองบอกว่าอะไรกันแน่ที่ทำให้ต้องรีบูต กฎง่าย ๆ: เห็นธงเมื่อไร ให้วางแผนช่วงเวลาภายในหนึ่งถึงสองวันข้างหน้า ไม่ใช่ «สักวัน»
ไลบรารีเป็นอีกกรณีหนึ่ง openssl ถูกอัปเดตในขณะที่ nginx และ PHP-FPM ยังทำงานด้วยเวอร์ชันเก่าในหน่วยความจำ และธงรีบูตก็ไม่ปรากฏเลย ใครต้องรีสตาร์ตดูได้จาก needrestart:
sudo apt install needrestart
sudo needrestart -b
เพียงตั้งให้อยู่ในโหมด «รายงาน อย่าถาม» — มิฉะนั้นมันจะเริ่มถามคำถามกลางการติดตั้งแบบไม่โต้ตอบและทำให้ค้าง สำหรับเรื่องนั้นให้วางไฟล์ที่มีบรรทัด $nrconf{restart} = 'l'; ลงใน /etc/needrestart/conf.d/
ตรวจว่ามันทำงานจริงไหม
รันทดลองโดยไม่ติดตั้ง:
sudo unattended-upgrade --dry-run --debug
ผลลัพธ์แสดงว่าแพ็กเกจใดตรงกับกฎและแพ็กเกจใดถูกปฏิเสธเพราะอะไร สิ่งที่เกิดขึ้นจริงอยู่ในล็อก:
sudo tail -50 /var/log/unattended-upgrades/unattended-upgrades.log
ตอนนี้มีอัปเดตกี่รายการรออยู่:
apt list --upgradable 2>/dev/null | grep -i security
คำสั่งสุดท้ายนี้มีประโยชน์ที่สุดในกลุ่ม การอัปเดตอัตโนมัติที่ตั้งค่าไว้แล้วมีนิสัยพังอย่างเงียบ ๆ: /boot เต็ม repository เปลี่ยนคีย์ ไทเมอร์ถูกปิดหลังการแก้ไขด้วยมือบางอย่าง ภายนอกดูปกติดี และแพตช์ไม่ได้ติดตั้งมาหลายเดือนแล้ว
พื้นที่บน /boot
สถานการณ์คลาสสิก: เคอร์เนลเก่าไม่ถูกลบ พาร์ทิชัน /boot เต็ม การติดตั้งเคอร์เนลใหม่ล้มเหลว และการอัปเดตหยุดทั้งหมด ทุกสองสามเดือนควรดูสักครั้ง:
df -h /boot
sudo apt autoremove --purge
หรือเปิดการทำความสะอาดอัตโนมัติใน 50unattended-upgrades เดียวกัน: Remove-Unused-Kernel-Packages "true" และ Remove-Unused-Dependencies "true"
อะไรเหลือไว้ให้มนุษย์
การอัปเดตอัตโนมัติขจัดงานประจำแต่ไม่ขจัดการเฝ้าดู สองคำถามที่คุณควรตอบได้ทุกเมื่อ: มีอัปเดตความปลอดภัยรออยู่กี่รายการ และมีธงรีบูตตั้งอยู่หรือไม่ คำตอบทั้งสองคือบรรทัดเดียวบนหน้าหนึ่ง และประเด็นทั้งหมดคือให้บรรทัดนั้นสะดุดตาเอง ไม่ใช่ต้องรอให้คุณริเริ่มไปดูไตรมาสละครั้ง