시스템 보안 · 취약점 › A. Linux 서버 보안 설정 · 33/50편 (전체 033/450)
학습 단계: 2단계 · 설정 및 점검
실습 표기: 이 글의 명령어·출력·로그는 로컬 VMware 테스트 VM(Rocky Linux 9 / Ubuntu 22.04) 기준의 「실습 예시」이며, IP·계정·호스트명은 가상의 값입니다.
서버가 update.example.com 같은 이름으로 접속할 때, 그 이름을 IP로 바꾸는 순서는 /etc/nsswitch.conf가 결정합니다. 기본값은 hosts 파일을 먼저, DNS를 나중에 봅니다.
hosts: files dns (/etc/nsswitch.conf)
│ │
│ └─ ② /etc/resolv.conf 의 nameserver 에 질의
│ Ubuntu: 127.0.0.53 (systemd-resolved 스텁) → 실제 DNS 서버
└─ ① /etc/hosts 에 있으면 여기서 끝 (DNS 질의 없음)
hosts 파일에 한 줄만 추가해도 DNS를 거치지 않고 원하는 IP로 연결을 돌릴 수 있다는 점이 보안상 핵심입니다.
127.0.0.1로 돌려 업데이트·에이전트 통신을 차단할 수 있습니다.| 파일·명령 | 점검 내용 |
|---|---|
/etc/nsswitch.conf의 hosts: | 해석 순서(files → dns가 일반적) |
/etc/hosts | localhost·자기 자신 외 항목의 용도 |
/etc/resolv.conf | nameserver 주소(Ubuntu는 보통 심볼릭 링크) |
resolvectl status (Ubuntu) | 인터페이스별 실제 DNS 서버 |
getent hosts 이름 | nsswitch 순서대로 해석한 결과 |
dig +short 이름 | DNS에 직접 질의한 결과(hosts 무시) |
# 1) 해석 순서와 설정 파일 확인
grep '^hosts:' /etc/nsswitch.conf
ls -l /etc/resolv.conf && cat /etc/resolv.conf
resolvectl status 2>/dev/null | grep -E 'DNS Servers|Current DNS' # Ubuntu
# 2) hosts 파일에서 기본 항목 외 확인
grep -vE '^\s*(#|$)|localhost' /etc/hosts
# 3) 해석 결과 비교: getent(hosts 포함) vs dig(DNS만)
for d in mirrors.rockylinux.org wazuh.lab.local; do
echo "$d getent=$(getent hosts $d | awk '{print $1}') dns=$(dig +short $d | tail -1)"
done
getent와 dig 결과가 다르면 hosts 파일이 DNS 결과를 덮어쓰고 있다는 뜻이므로 그 항목의 용도를 확인합니다.
$ grep '^hosts:' /etc/nsswitch.conf
hosts: files dns myhostname
$ grep -vE '^\s*(#|$)|localhost' /etc/hosts
192.168.56.10 rocky9-web01
192.168.56.100 wazuh.lab.local
자기 호스트명과 문서화된 내부 서버 항목만 존재하는 상태가 정상입니다.
$ grep -vE '^\s*(#|$)|localhost' /etc/hosts
192.168.56.10 rocky9-web01
127.0.0.1 wazuh.lab.local
127.0.0.1 mirrors.rockylinux.org
$ stat -c '%y' /etc/hosts
2026-10-01 03:28:40.000000000 +0900
wazuh.lab.local)와 업데이트 미러를 localhost로 돌림 → 에이전트 이벤트 전송 차단 + 보안 업데이트 차단hosts 파일 변경과 그 영향이 함께 나타납니다(가상의 예시 로그).
type=PATH msg=audit(1759735720.010:2701): item=0 name="/etc/hosts" inode=33554561 nametype=NORMAL key="net_conf"
type=SYSCALL msg=audit(1759735720.010:2701): syscall=257 success=yes auid=1002 uid=0 comm="tee" exe="/usr/bin/tee" key="net_conf"
Oct 1 03:28:52 rocky9-web01 wazuh-agentd: WARNING: (1218): Unable to send message to 'wazuh.lab.local'.
| 시각 | 이벤트 | 의미 |
|---|---|---|
| 03:28:40 | /etc/hosts 수정 | 이름 해석 조작 |
| 03:28:52 | 에이전트 전송 실패 | 관제 서버 통신 단절 |
에이전트 로그가 서버 안에만 남고 관제 서버에는 도착하지 않으므로, 관제 측에서는 에이전트 연결 끊김(disconnected) Alert로 먼저 보이게 됩니다. 연결 끊김을 단순 장애로 닫지 말고 원인을 확인해야 하는 이유입니다.
/etc/hosts, /etc/resolv.conf, /etc/nsswitch.conf는 realtime FIM + report_changes로 감시합니다.<rule id="100390" level="12">
<if_sid>550</if_sid>
<field name="file">^/etc/hosts$</field>
<match>wazuh|update|mirror|security|repo</match>
<description>hosts 파일에 보안·업데이트 관련 도메인 항목 변경</description>
</rule>
<match>는 Alert 전체 로그(변경 diff 포함)에서 문자열을 찾으므로 report_changes="yes"가 켜져 있어야 위 조건이 동작합니다. 기본 레벨의 hosts 변경 Alert(550)는 그대로 두고 고위험 조건만 상향합니다.
getent/dig 결과 차이를 확인합니다.| 구분 | 핵심 내용 |
|---|---|
| 해석 순서 | nsswitch hosts: files dns → hosts 파일 우선 |
| 비교 방법 | getent hosts(파일 포함) vs dig(DNS만) |
| 악용 패턴 | 보안·업데이트·관제 도메인을 127.0.0.1로 |
| 관제 측 신호 | 에이전트 disconnected → 원인 조사 필요 |
| 면접 포인트 | "hosts로 해석된 이름은 DNS 로그에 안 남는다" |
다음 편 034. Linux 서버 보안 — 로그인 배너와 버전 정보 노출 최소화 에서는 공격자의 정보 수집을 돕는 로그인 배너와 버전 정보 노출을 줄이는 방법을 다룹니다.
이전 편: 032. Linux 서버 보안 — NTP(chrony) 시간 동기화 보안
📚 시리즈 전체 보기: 시스템 보안 · 취약점