infra
Platform

모듈 맵

[Infra Ops] OS 보안 패치와 미들웨어 버전 업 절차

0 / 52 완료

펼치기
0 / 52 완료0%

인프라 운영 & SRE · 08 / 52

[Infra Ops] OS 보안 패치와 미들웨어 버전 업 절차

yum/apt 패치 전략, 보안 패치 우선순위, 미들웨어 버전 업 절차, 패치 롤백 계획까지 — 서비스를 멈추지 않고 서버를 안전하게 유지하는 패치 관리 실무

🚨INCIDENT ALERT
HIGH

2021년 12월 10일 저녁, Log4Shell(CVE-2021-44228) 취약점 뉴스가 터졌습니다. 서버에 Java와 Log4j가 깔려있다면 원격에서 임의 코드를 실행할 수 있는 CVSS 10.0 — 역대 최악의 취약점 중 하나였습니다.

그날 밤, 전국 운영 팀에서 긴급 패치가 시작됐습니다. 6개월째 "다음 분기에 패치하자"고 미뤄왔던 팀들은 그날 밤 비상 대응을 해야 했습니다. 미리 패치 파이프라인을 갖추고 있던 팀은 두 시간 안에 끝냈고, 그렇지 않은 팀은 이틀을 꼬박 밤을 새웠습니다.

패치는 귀찮은 일이 아닙니다. 미리 해두면 두 시간, 나중에 하면 이틀입니다.

이번 챕터에서 배울 것
  • 1패치 유형(보안/버그/기능)을 분류하고 우선순위에 따라 패치 계획을 수립할 수 있다
  • 2yum update --security로 보안 패치만 선택 적용하고 이력을 확인할 수 있다
  • 3커널 패치 후 uname -r과 grubby로 새 커널 부팅 여부를 검증할 수 있다
  • 4미들웨어(Nginx, Tomcat, JDK) 버전 업 5단계 절차를 실무에 적용할 수 있다
  • 5패치 실패 시 yum history undo와 GRUB 이전 커널 선택으로 롤백할 수 있다
실습 환경 준비
패키지 관리자 확인
which yum dnf apt-get 2>/dev/null | head -3
현재 OS 버전 확인
cat /etc/os-release | grep -E 'NAME|VERSION'
설치된 커널 목록 확인
rpm -qa | grep '^kernel-[0-9]' | sort 2>/dev/null || dpkg -l linux-image-* 2>/dev/null | grep '^ii'
마지막 패치 날짜 확인
rpm -qa --last 2>/dev/null | head -10 || grep ' install\| upgrade' /var/log/dpkg.log 2>/dev/null | tail -10

패치 관리 전략

💡개념

왜 패치를 미루면 안 되는가

패치를 미루는 이유는 항상 "서비스가 안정적으로 돌고 있어서"입니다. 그 이유가 패치를 못하는 이유가 됩니다. 그런데 취약점 공격은 서비스가 잘 돌아가는 서버를 노립니다.

패치 유형 분류:

유형설명적용 시기
보안 패치 (Security)CVE 번호 부여된 취약점 수정Critical·High: 72시간 이내 / Medium: 1개월 이내
버그 패치 (Bugfix)기능 오동작 수정월별 정기 패치 주기
기능 업데이트 (Enhancement)새 기능 추가분기별 검증 후 적용

보안 패치 우선순위 (CVSS 기준):

CVSS 점수등급목표 적용 기한
9.0 ~ 10.0Critical48~72시간 이내 긴급 대응
7.0 ~ 8.9High7일 이내
4.0 ~ 6.9Medium30일 이내 정기 패치
0.1 ~ 3.9Low분기 정기 패치

패치 적용 순서 원칙:

개발계에서 먼저 적용하고 검증한 뒤 운영계로 올립니다. "개발계도 없이 운영에 바로 적용"은 패치로 인한 장애를 만드는 지름길입니다.

개발계(Dev) → 검증계(Staging) → 운영계(Prod)
        24h 관찰           24h 관찰

Critical 취약점은 검증 단계를 압축하더라도 최소 개발계 → 운영계 순서는 지킵니다.

💡개념

패치 한 번은 실제로 어떤 단계를 거치나 — 확인부터 검증·롤백 대비까지 6단계

"패치했다"는 한 마디 뒤에는 여러 단계가 숨어 있습니다. 취약점을 확인하고, 테스트 환경에서 검증하고, 변경 승인을 받고, 패키지를 적용하고, 재부팅이 필요한지 판단하고, 마지막으로 검증하며 롤백을 대비하는 순서입니다. 이 흐름을 건너뛰면 "적용은 했는데 서비스가 죽었다", "패치했다고 생각했는데 여전히 취약하다" 같은 사고가 납니다. 어느 단계를 생략했는지가 곧 사고의 원인이므로, 각 단계가 하는 일과 막히면 나오는 증상을 나눠 봅니다.

TEXT
[CVE 공지 / 정기 업데이트]
   │
   ① 취약점·업데이트 확인            (yum check-update --security · CVSS 등급)
   │
   ② 테스트 환경 검증               (개발계 먼저 적용 → 서비스 정상 확인)
   │
   ③ 변경 승인 + 백업/스냅샷        (점검 창 합의 · 롤백 지점 확보)
   │
   ④ 패키지 적용                    (yum update --security → 디스크 파일 교체)
   │
   ⑤ 재부팅 필요 판단               (커널·glibc=재부팅 / 라이브러리=서비스 재시작)
   │
   ⑥ 검증 + 롤백 대비               (서비스 헬스·버전 확인 → 이상 시 yum history undo)
   ▼
[패치 '적용' 완료 = 새 코드를 실제로 실행 중]

각 단계에서 하는 일과, 막히면 나오는 증상:

단계하는 일여기서 막히면
① 확인check-update --security로 대상만 선별, CVSS로 우선순위 결정전체 update -y로 뭉뚱그리면 기능 변경까지 딸려와 의존성 충돌 위험
② 검증개발계·통시계에 먼저 적용해 서비스가 정상 기동하는지 확인검증 없이 운영 직행 → 패치 후 서비스 기동 실패를 운영에서 처음 마주침
③ 승인·백업점검 창을 잡고 스냅샷·설정 백업으로 롤백 지점을 확보백업 없이 진행 → 문제 발생 시 되돌릴 대상이 없음
④ 적용패키지 매니저가 디스크의 파일을 새 버전으로 교체공유 라이브러리 버전 충돌 → 서비스가 필요한 .so를 못 찾아 기동 실패
⑤ 재부팅 판단needs-restarting -r/-s로 재부팅 vs 서비스 재시작을 구분커널 패치인데 재부팅 안 함 → 디스크만 새 버전, 실행 중은 옛 커널(취약 지속)
⑥ 검증·롤백uname -r·서비스 헬스로 반영을 확인, 이상 시 즉시 롤백검증 생략 → 재부팅 유발·서비스 실패를 사용자가 먼저 발견

"패치 완료"는 rpm -q가 새 버전을 보여주는 것이 아니라, 그 코드를 실행하는 프로세스가 새 버전을 물고 있고 서비스가 정상이라는 뜻입니다. 파일 교체(④)까지만 하고 재부팅·재시작(⑤)과 헬스 검증(⑥)을 생략하면 "설치는 됐으나 적용은 안 된" 상태로 남습니다. 패치 실패는 대개 ②(검증 생략)·④(의존성 충돌)·⑤(재부팅 누락)에서 갈리므로, 적용 후 needs-restarting -s(서비스)와 -r(재부팅), 그리고 systemctl status로 서비스 상태까지 확인해야 ⑥이 끝납니다.

yum/apt 패치 실무

💡개념

보안 패치 확인과 선택 적용

패치는 적용하는 것만큼 "무엇을 적용하는가"를 아는 것이 중요합니다. yum update -y로 전체를 한 번에 올리면 보안 취약점뿐 아니라 기능 변경까지 따라오고, 의존 라이브러리 버전이 바뀌면서 서비스가 중단될 수 있습니다. 보안 패치만 선별해 적용하고 변경 이력을 남기는 것이 운영 안정성과 감사 대응을 동시에 만족하는 방법입니다. 패치 전 --assumeno로 변경 범위를 먼저 확인하는 습관이 예상치 못한 사고를 막습니다.

OS 패치 관리 흐름 — 확인에서 검증까지확대

yum update -y로 전체 업데이트를 걸었다가 PHP 버전이 올라가면서 레거시 애플리케이션이 기동 실패한 경우가 있습니다. 보안 패치만 선택해서 적용하고, 변경 범위를 먼저 확인한 뒤 진행해야 이 사고를 막을 수 있습니다. 패치 이력이 남아있어야 "이 장애가 패치 때문인지"를 나중에 추적할 수 있습니다.

패치를 적용하기 전에 무엇이 바뀌는지 먼저 확인합니다. 확인 없이 업데이트하면 예상치 못한 패키지가 함께 올라가는 경우가 있습니다.

로컬 터미널
# 업데이트 가능한 패키지 전체 목록
sudo yum check-update

# 보안 패치만 확인 (Security Advisory 분류된 것만)
sudo yum check-update --security

# Ubuntu/Debian 계열
sudo apt update
apt list --upgradable 2>/dev/null | grep -i security

# 특정 패키지의 현재 설치 버전 확인
rpm -qa | grep openssl
# openssl-1.1.1k-9.el8.x86_64
# openssl-libs-1.1.1k-9.el8.x86_64

# 설치 가능한 버전 목록 (yum)
sudo yum list --showduplicates openssl | tail -10

보안 패치 적용:

로컬 터미널
# dry-run 먼저 — 실제 설치 없이 변경 목록만 확인
sudo yum update --security --assumeno

# 실제 보안 패치 적용
sudo yum update --security -y

# 특정 패키지만 업데이트 (영향 범위 최소화)
sudo yum update openssl openssl-libs -y

# Ubuntu/Debian 계열 보안 패치만
sudo apt-get upgrade -y --with-new-pkgs $(apt-get -s upgrade 2>/dev/null | grep "^Inst" | grep -i security | awk '{print $2}' | tr '\n' ' ')

패치 이력 확인:

로컬 터미널
# yum 패치 이력 (날짜별 트랜잭션 목록)
sudo yum history list | head -20
# ID  | Command                      | Date               | Action | Altered
#  15 | update --security -y         | 2024-12-10 23:14   | Update |      8

# 특정 트랜잭션 상세 내용
sudo yum history info 15

# 로그 파일로 확인
sudo grep -i "updated\|installed" /var/log/yum.log | tail -30

# apt 패치 이력 (Debian 계열)
grep "upgrade\|install" /var/log/apt/history.log | tail -30
보안 패치 목록 확인 및 선택 적용 실습
1

1. 현재 OS 버전 및 패치 이력 확인

cat /etc/os-release | grep -E '^NAME|VERSION_ID' && uname -r
2

2. 적용 가능한 보안 업데이트 목록 확인 (dry-run)

sudo apt-get -s upgrade 2>/dev/null | grep -E '^Inst|upgraded' | head -15 || sudo yum check-update --security 2>/dev/null | head -15 || echo '패키지 매니저 환경 확인 필요'
3

3. 패치 이력 확인

grep 'upgrade\|install' /var/log/apt/history.log 2>/dev/null | tail -10 || rpm -qa --last 2>/dev/null | head -10 || echo '패치 이력 없음'
🔍실행 후 확인할 것
  • uname -r 결과를 먼저 확인 — 실행 중인 커널 버전. apt-get -s upgrade | grep linux-image 패키지가 있으면 새 커널이 설치됐지만 재부팅 안 된 상태
  • apt-get -s upgrade 결과에서 "security" 포함 패키지 수가 10개 이상이면 장기 패치 미적용 서버 — 보안 감사 대상이며 CVSS 9.0 이상 취약점이 포함될 가능성 높음
  • 패치 이력 파일(/var/log/apt/history.log)이 6개월 이상 비어있고 uname -r 버전이 2년 이상 된 것이면 — 커널 패치와 패키지 패치 모두 미적용 상태로 즉시 패치 계획 수립 필요

커널 패치 절차

💡개념

커널 패치는 재부팅이 필요하다

커널 패치를 적용했는데 uname -r로 확인하니 여전히 이전 버전이었습니다. 패치는 설치됐지만 재부팅을 안 했기 때문입니다. 재부팅 계획을 세우지 않고 패치를 진행하면 패치가 됐다고 생각하는데 실제로는 취약한 상태가 지속됩니다. 반대로 재부팅 후 새 커널에서 드라이버 호환성 문제로 서버가 부팅 불가 상태가 되면, 콘솔 접근 수단이 없으면 복구 방법이 없어집니다. 재부팅 없이 커널 패치를 적용하는 kpatch(라이브 패치)도 있지만, 모든 취약점에 적용할 수 있는 것은 아닙니다.

커널 패치 반영 3단계 — ① 패치 전 실행 중 커널(uname -r)과 설치된 커널이 5.14.0-362로 동일, ② yum update kernel 직후에는 5.14.0-427이 설치되고 grub 기본 커널로 잡히지만 실행 중 커널은 여전히 옛 362라 패치했다고 착각해도 실제로는 취약 상태 지속, ③ 재부팅 후에야 실행 중 커널이 427로 전환되어 패치가 실제 반영된다. 재부팅 없이 방어하려면 kpatch 라이브 패치(일부 CVE만, Critical은 결국 재부팅)를 쓰고, 새 커널 부팅 불가에 대비해 GRUB 메뉴·grubby로 이전 커널 롤백 경로와 콘솔 접근을 확보한다확대

커널 패치 절차:

로컬 터미널
# 현재 실행 중인 커널 버전
uname -r
# 5.14.0-362.8.1.el9_3.x86_64

# 설치된 커널 전체 목록
rpm -qa | grep '^kernel-[0-9]' | sort
# kernel-5.14.0-362.8.1.el9_3.x86_64
# kernel-5.14.0-427.13.1.el9_4.x86_64  ← 이미 설치된 최신 버전

# 커널 업데이트 (재부팅 필요)
sudo yum update kernel -y

# 다음 부팅에서 사용할 기본 커널 확인
sudo grubby --default-kernel
# /boot/vmlinuz-5.14.0-427.13.1.el9_4.x86_64

# 사용 가능한 커널 목록
sudo grubby --info=ALL | grep "^kernel"

재부팅 후 새 커널 확인:

로컬 터미널
# 재부팅
sudo reboot

# 재접속 후 새 커널 버전 확인
uname -r
# 5.14.0-427.13.1.el9_4.x86_64  ← 새 커널로 올라왔으면 성공

# 기본 커널 경로와 실행 중인 커널 일치 여부 확인
sudo grubby --default-kernel

kpatch — 재부팅 없는 커널 패치:

로컬 터미널
# kpatch 설치 (RHEL/CentOS 계열)
sudo yum install kpatch kpatch-dnf -y

# 적용 가능한 라이브 패치 목록 확인
sudo kpatch list

# kpatch는 일부 취약점에만 제공되며, 커널 패치의 완전한 대체재가 아닙니다.
# Critical 커널 취약점은 결국 재부팅 패치가 필요합니다.

이전 커널로 롤백 (GRUB 사용):

재부팅 후 새 커널에서 문제가 생기면 GRUB 메뉴에서 이전 커널을 선택합니다.

로컬 터미널
# 물리 서버/KVM: 재부팅 시 GRUB 메뉴에서 방향키로 이전 커널 선택
# 클라우드 VM: 콘솔/직렬 포트 접근 후 GRUB 메뉴 선택

# CLI로 기본 커널 변경 (이전 커널로 롤백)
sudo grubby --set-default /boot/vmlinuz-5.14.0-362.8.1.el9_3.x86_64

# 변경 확인
sudo grubby --default-kernel
# /boot/vmlinuz-5.14.0-362.8.1.el9_3.x86_64

sudo reboot
커널 vs 일반 패키지 — 패치 방식 선택
OpenSSL, glibc 등 보안 라이브러리 취약점yum update --security -y → 서비스 재기동 (재부팅 불필요)
커널 레벨 취약점 (Dirty COW, Spectre 등)yum update kernel -y → 점검 시간 잡고 재부팅
재부팅 없이 커널 패치 필요 (AWS 등 클라우드)kpatch 라이브 패치 적용 (해당 CVE가 제공되는 경우)
패치 후 서비스 이상 감지yum history undo N 또는 yum downgrade 패키지명
커널 업데이트 후 부팅 불가GRUB 메뉴에서 이전 커널 선택 → grubby --set-default로 기본값 변경
커널 버전 및 재부팅 필요 여부 점검
1

1. 현재 실행 중인 커널 확인

uname -r && echo '---' && ls /boot/vmlinuz-* 2>/dev/null | sort -V | tail -3
2

2. 재부팅 없이 적용된 보안 패치 확인 (가능 여부)

rpm -qa | grep kpatch 2>/dev/null || apt list --installed 2>/dev/null | grep livepatch || echo '라이브 패치 미설치'
3

3. 재부팅 필요 여부 확인

needs-restarting -r 2>/dev/null || (ls /var/run/reboot-required 2>/dev/null && cat /var/run/reboot-required.pkgs 2>/dev/null) || echo '재부팅 불필요 또는 확인 도구 없음'
🔍실행 후 확인할 것
  • uname -r(실행 중 커널)과 ls /boot/vmlinuz-*의 최신 파일명을 비교 — 숫자가 다르면 새 커널이 설치됐지만 재부팅 안 된 상태. 패치 효과가 아직 미적용
  • /var/run/reboot-required 파일이 있으면 Ubuntu에서 재부팅 필요 — 이 파일이 생성된 날짜(stat 명령)와 패치 날짜가 일치하면 해당 패치로 인한 재부팅 대기
  • needs-restarting -r가 "Reboot is required"를 출력하면 RHEL 계열 재부팅 필요 상태 — needs-restarting -s로 서비스별 재시작 필요 목록도 함께 확인해야 전체 적용 완료

미들웨어 버전 업 절차

OS 패치 핵심 명령어와 미들웨어 버전 업 절차 — 패치 단계별 명령(확인: yum updateinfo/check-update, 백업: 스냅샷·tar, 적용: yum update --security, 검증: uname -r·grubby, 롤백: yum history undo)과 미들웨어 버전 업 7단계(Release Notes 확인→테스트 적용→설정 호환성→패키지 교체→재시작·헬스체크→구버전 제거→롤백 방안)확대

💡개념

Nginx / Tomcat / JDK 버전 업 5단계

JDK 8에서 JDK 11로 올렸더니 javax 패키지를 찾을 수 없다는 오류와 함께 Tomcat이 기동 실패했습니다. Release Notes를 읽지 않고 업그레이드했기 때문입니다. Nginx 버전 업 후 일부 ssl_ 지시어가 인식되지 않아 설정 검증에서 실패한 경우도 마찬가지입니다. 버전 업은 테스트 환경에서 충분히 검증하고 롤백 계획을 준비한 뒤에 운영에 적용해야 합니다. 미들웨어 버전 업은 OS 패키지 패치보다 영향 범위가 큽니다. 설정 파일 문법이 바뀌거나, 애플리케이션이 의존하는 API가 제거되면 서비스가 기동 자체를 못 합니다.

5단계 버전 업 절차:

1단계 — Release Notes 확인 (가장 중요)

로컬 터미널
# 현재 버전 확인
nginx -v
# nginx version: nginx/1.18.0

java -version
# openjdk version "1.8.0_392"

# Release Notes에서 반드시 확인할 항목:
# - Deprecated → Removed 항목 (기존 설정이 오류가 되는 것)
# - 기본값 변경 사항
# - 의존 라이브러리 최소 버전 변경

2단계 — 현재 설정 파일 백업

로컬 터미널
# Nginx 설정 전체 백업
sudo tar czf /opt/backup/nginx-conf-$(date +%Y%m%d).tar.gz /etc/nginx/

# Tomcat 설정 백업
sudo tar czf /opt/backup/tomcat-conf-$(date +%Y%m%d).tar.gz /opt/tomcat/conf/

# JDK 환경변수 기록
echo "JAVA_HOME=$JAVA_HOME" > /opt/backup/java-env-$(date +%Y%m%d).txt
java -version >> /opt/backup/java-env-$(date +%Y%m%d).txt 2>&1

# 현재 패키지 목록 스냅샷 (RPM 환경)
rpm -qa | sort > /opt/backup/rpm-list-$(date +%Y%m%d).txt

3단계 — 개발계에서 먼저 버전 업 및 검증

로컬 터미널
# Nginx 버전 업 (yum 환경)
sudo yum update nginx -y

# 설정 파일 문법 검사
sudo nginx -t
# nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
# nginx: configuration file /etc/nginx/nginx.conf test is successful

# 문법 오류 시 즉시 확인
sudo nginx -T 2>&1 | grep -i error

4단계 — 서비스 재기동 및 검증 체크리스트

서버 터미널
# 서비스 재기동
sudo systemctl restart nginx
sudo systemctl status nginx

# 응답 확인
curl -I http://localhost/health
# HTTP/1.1 200 OK

# 오류 로그 확인 (재기동 후 1분간)
sudo tail -f /var/log/nginx/error.log

5단계 — 이전 버전 바이너리 보관 (롤백 준비)

로컬 터미널
# 이전 버전 바이너리 보존 (yum은 자동 보존)
sudo yum list installed nginx
sudo yum list --showduplicates nginx | grep nginx

# 이전 버전으로 다운그레이드 (필요 시)
sudo yum downgrade nginx-1.18.0 -y
sudo systemctl restart nginx

JDK 버전 업 시 특별 주의사항:

로컬 터미널
# JDK 8 → 11 전환 시 javax → jakarta 패키지 변경으로 기동 실패 사례
# 애플리케이션 pom.xml 또는 build.gradle의 의존성 버전도 함께 확인 필요

# 현재 사용 중인 JDK 확인
alternatives --list | grep java
# java  auto  /usr/lib/jvm/java-11-openjdk-11.0.21.0.9-2.el9.x86_64/bin/java

# JDK 여러 버전 공존 설치 후 전환
sudo alternatives --config java

실습

보안 패치 적용 실습
1

1. 현재 설치된 패키지 버전 확인

rpm -qa --last 2>/dev/null | head -20 || dpkg -l | grep '^ii' | tail -20
2

2. 보안 업데이트 목록 확인

sudo yum check-update --security 2>/dev/null || sudo apt-get -s upgrade 2>/dev/null | grep -i security | head -20
3

3. dry-run으로 변경 범위 미리 확인

sudo yum update --security --assumeno 2>/dev/null | tail -20 || sudo apt-get -s upgrade 2>/dev/null | grep '^Inst' | grep -i security | head -20
4

4. 보안 패치 실제 적용

sudo yum update --security -y 2>/dev/null | tail -20 || echo 'apt 환경: sudo apt-get upgrade -y 실행 필요'
5

5. 패치 이력 확인

sudo yum history list 2>/dev/null | head -10 || grep 'upgrade\|install' /var/log/apt/history.log 2>/dev/null | tail -10
🔍실행 후 확인할 것
  • yum check-update --security 결과를 먼저 본다 — 출력이 없으면 보안 패치 최신 상태. kernel 패키지가 목록에 있으면 재부팅 계획을 별도 수립해야 패치 적용됨
  • dry-run(--assumeno) 출력에서 업데이트 패키지 수가 50개 이상이면 패치 적용 시간 30분 이상 예상 — 점검 시간 창(maintenance window)이 충분한지 먼저 확인
  • yum history list에 방금 트랜잭션 ID가 없으면 패치 미적용 — 패치 후 systemctl status nginx tomcat 으로 서비스 상태 확인. 서비스가 failed 상태면 즉시 yum history undo <ID>로 롤백
패치 이력 확인 및 롤백 실습
1

1. 패치 이력 목록 조회

sudo yum history list 2>/dev/null | head -15 || grep 'upgrade' /var/log/apt/history.log 2>/dev/null | tail -10
2

2. 특정 트랜잭션 상세 내용 확인

sudo yum history list 2>/dev/null | awk 'NR==2{print $1}' | xargs -I{} sudo yum history info {} 2>/dev/null | head -30 || echo 'yum history 미지원 환경'
3

3. 설치된 이전 버전 목록 확인

sudo yum list --showduplicates openssl 2>/dev/null | grep openssl | head -10 || apt-cache showpkg openssl 2>/dev/null | grep 'Versions' -A 10 | head -10
4

4. 다운그레이드 dry-run 확인 (실제 실행 없음)

sudo yum downgrade --assumeno openssl 2>/dev/null | tail -15 || echo 'Ubuntu 환경에서는 apt-get install openssl=<버전> 으로 다운그레이드 가능'
🔍실행 후 확인할 것
  • yum history list 출력에서 트랜잭션 ID(첫 번째 열)를 먼저 확인 — ID가 있어야 undo 가능. ID가 없으면 yum이 아닌 다른 방법으로 설치된 것으로 rpm -e로 직접 제거해야 함
  • yum history info <ID>의 Updated 항목 수가 예상과 다르면 의존성 패키지까지 함께 업데이트된 것 — 롤백 시 해당 패키지 수만큼 다운그레이드됨을 인지하고 진행
  • yum list --showduplicates에서 @base나 @updates가 붙은 것이 현재 설치 버전 — 다운그레이드 dry-run에 "Nothing to do"가 나오면 이전 버전이 저장소에 없거나 이미 최저 버전으로 rpm 직접 다운로드 필요

트러블슈팅

심화 — 패치는 '설치'가 아니라 '적용'까지가 끝이다

💡개념

심화: 파일 교체와 메모리 적용의 간극 — 왜 재시작해야 진짜 패치인가

앞에서 "커널 패치는 재부팅이 필요하다"까지 봤습니다. 한 단계 더 들어가면, 재부팅이 필요한 건 커널만이 아닙니다. 문제의 뿌리는 패키지 매니저가 하는 일이 '디스크의 파일 교체'까지라는 점입니다.

  • 패키지 매니저는 디스크만 바꿉니다: yum update openssl은 디스크의 libssl.so를 새 버전으로 갈아끼웁니다. 하지만 이미 실행 중이던 프로세스는 기동할 때 옛 .so를 메모리에 로드해 뒀고, 리눅스는 그 옛 파일을 (디스크에서 지워져도) 프로세스가 놓을 때까지 붙잡아 둡니다. 그 프로세스에겐 여전히 옛 코드가 돕니다 — 파일명 뒤에 (deleted)가 붙은 매핑이 바로 그 증거입니다.
  • 그래서 경계가 셋입니다: ① 공유 라이브러리(openssl·glibc 일부) 패치 → 그 라이브러리를 쓰는 서비스만 재시작(needs-restarting -s). ② 커널·glibc 핵심·systemd 패치 → 재부팅(needs-restarting -r). ③ 재부팅을 미뤄야 하는 커널 CVE → kpatch/livepatch.
  • 라이브 패치의 한계: livepatch는 실행 중 커널 함수의 진입점을 후킹해 새 함수로 우회하는 방식입니다. 코드 로직 결함은 고칠 수 있지만, 자료구조 레이아웃이나 초기화 경로가 바뀌는 패치는 우회로 표현할 수 없어 적용 대상이 아닙니다. 그래서 Critical 커널 취약점은 결국 점검 시간을 잡아 재부팅해야 합니다.

정리하면 패치의 완료 조건은 "rpm -q가 새 버전을 보여준다"가 아니라 "그 코드를 실행하는 모든 프로세스가 새 버전을 물고 있다"입니다. 그래서 성숙한 패치 SOP는 마지막에 needs-restarting -s(재시작 필요 서비스)와 -r(재부팅 필요)을 반드시 확인하는 단계를 둡니다.

상황: openssl 보안 패치를 정상 적용했습니다. rpm -q openssl은 새 버전이고, yum history에도 트랜잭션이 기록돼 있습니다. 그런데 다음 날 정기 취약점 스캔(Nessus 등)이 어제 막은 것과 같은 CVE를 여전히 리포트합니다. 담당자는 "패치가 안 됐나?" 싶어 다시 rpm -q를 찍어 보지만 버전은 분명 새것입니다.

원인: 디스크의 libssl.so는 새 버전으로 교체됐지만, 패치 전부터 떠 있던 nginx·sshd·httpd 프로세스가 기동 당시 로드한 옛 libssl.so를 메모리에서 계속 실행 중입니다. 그 옛 파일은 디스크에서 교체되며 삭제 표시가 붙었지만, 프로세스가 붙잡고 있어 사라지지 않습니다. 스캐너는 실행 중 프로세스가 실제로 물고 있는 라이브러리를 보므로, 디스크는 패치돼도 메모리가 옛것이면 취약점을 그대로 잡아냅니다. 파일은 패치됐고 메모리는 안 됐습니다.

진단: sudo needs-restarting -s로 재시작이 필요한 서비스 목록을 봅니다. 더 확실히는 sudo lsof +c0 2>/dev/null | grep -iE 'libssl|libcrypto' | grep -i deleted — 출력에 (deleted) 표시된 라이브러리를 물고 있는 PID가 곧 '옛 코드를 실행 중인 범인'입니다. 이 목록이 스캐너가 지목한 서비스와 일치하면 확정입니다.

해결: 해당 프로세스를 재시작합니다(sudo systemctl restart nginx sshd). glibc처럼 거의 모든 프로세스가 물고 있는 라이브러리가 바뀐 경우엔 서비스 하나씩 재시작하는 것보다 점검 시간을 잡아 재부팅이 현실적입니다. 재발 방지책은 패치 SOP 마지막에 needs-restarting -s(서비스)와 -r(재부팅) 확인을 못 박아, '설치'에서 멈추지 않고 '적용'까지 끝내는 것입니다(취약점 조치와 보안 심사 대응 실무).

💼
실무 맥락
현업 패턴

실제 업무에서 이 지식이 쓰이는 상황:

금융권/공공기관의 분기별 패치 관리 프로세스:

금융권에서는 보안 취약점 패치를 임의로 적용할 수 없습니다. CVE 공시 → 영향도 분석 → 패치 계획 수립 → 정보보호팀 승인 → 적용 → 결과 보고서 작성의 단계를 거칩니다.

로컬 터미널
# 실무에서 CVE 대응 시 가장 먼저 하는 작업
# 1. 영향 받는 패키지가 설치됐는지 확인
rpm -qa | grep -i log4j
# log4j-2.14.1-2.el8.noarch  ← 취약 버전 설치됨

# 2. 해당 패키지를 사용하는 서비스 식별
rpm -q --whatrequires log4j 2>/dev/null
# 또는
find /opt /app -name "log4j*.jar" 2>/dev/null

# 3. 패치 계획 문서화
# - 현재 버전: log4j-2.14.1 (CVE-2021-44228 영향 받음)
# - 패치 버전: log4j-2.17.1 이상
# - 적용 서버 목록
# - 점검 시간 (서비스 중단 여부)
# - 롤백 절차

패치 후 서비스 검증 체크리스트 (실무 표준):

로컬 터미널
# 패치 직후 확인 항목 (자동화 스크립트 예시)
echo "=== 패치 후 서비스 상태 점검 ==="
systemctl is-active nginx tomcat postgresql
echo ""
echo "=== 주요 포트 응답 확인 ==="
ss -tlnp | grep -E ':80|:443|:8080|:5432'
echo ""
echo "=== 최근 5분 에러 로그 ==="
journalctl -p err --since "5 min ago" --no-pager | tail -20

패치 관리는 "하는 것"과 "기록하는 것"이 세트입니다. 어떤 서버에 언제 무엇을 패치했는지 이력이 없으면 감사(Audit) 때 패널티를 받습니다. yum history와 변경 관리 티켓을 항상 함께 남깁니다.


명령어·단축키 빠른 참조

이 모듈에서 다룬 패치 확인·적용·검증·롤백 명령을 실전 옵션과 함께 모았습니다. "예" 열의 조합을 그대로 써도 됩니다.

명령어/단축키용도자주 쓰는 예
yum check-update --security보안 패치만 목록 확인(설치 안 함)Debian: apt list --upgradable | grep -i security
yum update --security보안 패치만 선택 적용dry-run --assumeno, 실제 적용 -y
yum update kernel -y커널 업데이트(재부팅 필요)적용 후 rebootuname -r 재확인
rpm -qa --last | head최근 설치·업데이트 이력현재 버전: rpm -qa | grep openssl
yum history list / info N패치 트랜잭션 이력 조회롤백용 트랜잭션 ID 확인
yum history undo N트랜잭션 통째로 롤백특정 패키지만: yum downgrade openssl
uname -r실행 중 커널 버전설치 커널과 다르면 재부팅 미반영
grubby --default-kernel다음 부팅 기본 커널 확인롤백 grubby --set-default /boot/vmlinuz-…
needs-restarting -r재부팅 필요 여부서비스만 재시작 대상은 needs-restarting -s
lsof +c0 | grep -i deleted옛 라이브러리 물고 있는 프로세스패치 후 스캐너 재검출 원인 추적
systemctl restart nginx패치된 .so 반영 위해 서비스 재시작라이브러리 패치의 실제 '적용' 단계
nginx -t미들웨어 버전 업 후 설정 문법 검사JDK 전환은 alternatives --config java

관련 모듈로 더 깊이:

다음 모듈에서는 WEB/WAS/DB 망 분리와 이중화 구조 설계를 다룹니다.

지식 확인

퀴즈 — 8문제

Q1

보안 패치만 선택적으로 설치하는 yum 명령어는?

Q2

패치 적용 전 반드시 수행해야 하는 사전 작업으로 가장 중요한 것은?

Q3

커널 패치 후 새 커널로 부팅됐는지 확인하는 방법으로 올바른 것은?

Q4

미들웨어 버전 업 시 하위 호환성 확인이 중요한 이유는?

Q5

보안 패치를 미루면 안 되는 이유는?

Q6

운영 서버 전체에 패치를 한 번에 적용하지 않고 단계적으로(통시계→일부→전체) 하는 이유는?

Q7

[심화] openssl 라이브러리 보안 패치를 yum으로 적용하고 rpm -q로 새 버전까지 확인했다. 그런데도 이미 실행 중이던 웹 서버가 여전히 그 취약점에 노출돼 있을 수 있는 이유는?

Q8

[심화] openssl을 패치하고 rpm -q로 새 버전을 확인했는데 다음 날 취약점 스캐너가 같은 CVE를 다시 잡았다. 파일이 새 버전인 것은 이미 확인했다. 원인을 확정하기 위해 가장 먼저 볼 것은?

0 / 8 답변

🧪 실습으로 확인하기

Nginx 설치 및 기동

초급

Linux 서버에 Nginx를 설치하고 systemd 서비스로 등록하여 80포트에서 응답하는 상태까지 만든다.

40📋 3단계💻 직접 환경
실습 시작하기 →

이것도 배워보세요