서버 침해의 대부분은 교묘한 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";
1은 「매일」을 뜻합니다. 이 모든 것을 움직이는 것은 고전적인 cron이 아니라 systemd의 타이머입니다.
systemctl list-timers | grep apt
가장 중요한 것: 보안만
주요 파일은 /etc/apt/apt.conf.d/50unattended-upgrades입니다. 거기에는 Allowed-Origins 목록이 있고(Debian에서는 Origins-Pattern), 기본으로는 보안 저장소만 켜져 있습니다. 그대로 두세요.
-updates 줄의 주석을 지우고 싶은 유혹 — 「다 업데이트되게 하자」 — 은 강합니다. 하지 마세요. 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
다만 「보고하되 묻지 말 것」 모드로 두세요. 그러지 않으면 비대화식 설치 도중에 질문을 시작해 설치를 멈춰 세웁니다. 이를 위해 /etc/needrestart/conf.d/에 $nrconf{restart} = 'l'; 한 줄을 담은 파일을 두세요.
실제로 작동하는지 확인하기
설치 없이 시험 실행:
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의 공간이 떨어졌다, 저장소가 키를 바꿨다, 손으로 수정한 뒤 타이머가 꺼졌다. 겉으로는 다 괜찮아 보이고, 패치는 몇 달째 설치되지 않았습니다.
/boot의 공간
전형적인 상황입니다. 옛 커널이 지워지지 않아 /boot 파티션이 차고, 새 커널 설치가 실패하며, 업데이트 전체가 멈춥니다. 몇 달에 한 번은 들여다볼 가치가 있습니다.
df -h /boot
sudo apt autoremove --purge
또는 같은 50unattended-upgrades에서 자동 정리를 켜세요: Remove-Unused-Kernel-Packages "true"와 Remove-Unused-Dependencies "true".
사람에게 남는 것
자동 업데이트는 반복 작업을 없애 주지만 지켜보는 일을 없애 주지는 않습니다. 언제든 답할 수 있어야 할 질문이 둘입니다. 보안 업데이트가 몇 건 기다리고 있는가, 그리고 재부팅 표시가 서 있는가. 두 답 모두 페이지의 한 줄이며, 의미의 전부는 그 한 줄이 분기에 한 번 당신이 찾아 나서는 것이 아니라 스스로 눈에 들어오는 데 있습니다.