TCP Wrapper는 libwrap 라이브러리(tcpd)를 통해 동작하는 호스트 기반 접근 제어 시스템이다.
서비스가 연결 요청을 받으면, 실제 서비스로 넘기기 전에 두 파일을 검사해 그 출발지 호스트를 허용할지 결정한다.
파일
역할
/etc/hosts.allow
접근을 허용할 호스트 목록
/etc/hosts.deny
접근을 거부할 호스트 목록
검사 순서가 가장 중요한 출제 포인트다.
검사 순서(절대 암기): ① /etc/hosts.allow를 먼저 검사 → 일치하면 허용하고 종료. ② 없으면 /etc/hosts.deny를 검사 → 일치하면 거부. ③ 어느 쪽에도 없으면 기본 허용. 즉 allow가 deny보다 우선하며, 둘 다 해당 없으면 통과한다.
파일의 문법은 서비스 : 호스트 형태다.
# /etc/hosts.deny — 기본적으로 모두 거부ALL : ALL# /etc/hosts.allow — 특정만 허용sshd : 192.168.1.0/24sshd : 192.168.1.100vsftpd : .example.comALL : 127.0.0.1
위 조합은 "기본은 전부 거부하되, SSH는 192.168.1.0/24 서브넷에서만, FTP는 example.com 도메인에서만 허용"하는 전형적인 화이트리스트 구성이다.
키워드
의미
ALL
모든 서비스 또는 모든 호스트
LOCAL
점(.)이 없는 로컬 호스트 이름
.example.com
example.com 도메인의 모든 호스트
192.168.1.
해당 네트워크 대역
EXCEPT
예외 지정 (예: ALL EXCEPT 192.168.1.5)
⚠️ 함정: hosts.deny에 ALL : ALL을 넣어 전부 막은 뒤 hosts.allow에 자신을 허용하는 걸 빠뜨리면 SSH로 들어온 본인이 차단된다(방화벽과 같은 함정). 또한 TCP Wrapper는 libwrap을 사용하는 서비스(sshd, vsftpd 등)에만 적용된다 — 모든 서비스를 막는 만능 도구가 아니다.
# 현재 모드 확인getenforce # Enforcing / Permissive / Disabled 출력sestatus # 상세 상태# 일시적 모드 변경 (재부팅 시 원복)setenforce 1 # Enforcingsetenforce 0 # Permissive# 영구 변경은 설정 파일 수정vi /etc/selinux/config# SELINUX=enforcing ← 이 값을 enforcing/permissive/disabled로
일시 vs 영구: setenforce는 enforcing↔permissive만 일시적으로 전환하며 재부팅하면 /etc/selinux/config의 값으로 돌아간다. disabled로 가거나 영구 변경하려면 /etc/selinux/config 파일을 수정하고 재부팅해야 한다. setenforce로는 disabled로 갈 수 없다는 점이 함정이다.
# 파일의 SELinux 컨텍스트 보기 (-Z)ls -Z /var/www/html# 출력 예: system_u:object_r:httpd_sys_content_t:s0# └user┘ └role┘ └──── type ────┘ └level┘
컨텍스트는 user:role:type:level 형식이며, 이 중 type(타입)이 실제 접근 제어에서 가장 중요하다.
예: 아파치(httpd) 프로세스는 httpd_t 타입으로 실행되고, httpd_sys_content_t 타입의 파일만 제공할 수 있다.
웹 콘텐츠를 엉뚱한 디렉터리에 두면 타입이 맞지 않아 "권한은 맞는데 접근이 거부되는" 현상이 생긴다.
# 파일의 컨텍스트(타입) 변경chcon -t httpd_sys_content_t /srv/web/index.html# 정책 기본값으로 컨텍스트 복원restorecon -Rv /var/www/html# SELinux 불리언(on/off 스위치) 확인·변경getsebool -asetsebool -P httpd_can_network_connect on
chcon vs restorecon: chcon은 컨텍스트를 직접 바꾸지만 임시적이라 restorecon이나 파일시스템 재라벨링 시 사라질 수 있다. 영구적으로는 semanage fcontext로 정책에 규칙을 등록한 뒤 restorecon으로 적용하는 것이 정석이다. restorecon은 정책에 정의된 "원래 있어야 할" 컨텍스트로 되돌린다.
"권한(chmod)은 분명 맞는데 서비스가 파일에 접근 못 한다"면 SELinux 컨텍스트를 의심할 수 있다. 임시로 setenforce 0(permissive)로 바꿔 문제가 사라지면 원인은 SELinux다 — 단, 운영에서는 끄지 말고 컨텍스트를 올바르게 고쳐야 한다.
핵심 해석: *.info;mail.none;authpriv.none /var/log/messages는 "모든 facility의 info 이상을 messages에 기록하되, mail과 authpriv는 제외"라는 의미다. = 기호를 붙이면(예: mail.=info) 정확히 그 수준만 잡는다. 이 facility.priority 짝 해석이 실기에서 필요하다.
# rsyslog.conf 수정 후 적용systemctl restart rsyslog# 직접 로그를 발생시켜 테스트logger -p authpriv.notice "test message"
rotate N의 의미: rotate 4 + weekly는 "매주 순환하며 최근 4개(약 4주치)를 보관"한다는 뜻이다. 순환되면 myapp.log→myapp.log.1→myapp.log.2...로 밀려나고, 5번째가 되면 가장 오래된 것이 삭제된다. compress가 있으면 .gz로 압축된다.
# 설정 문법 점검 + 강제 실행(디버그)logrotate -d /etc/logrotate.conf # -d: 디버그(실제 실행 안 함, 시뮬레이션)logrotate -f /etc/logrotate.conf # -f: 강제 즉시 실행
직접 쳐보기: /etc/logrotate.d/의 기존 파일(예: syslog)을 열어 어떤 지시어가 쓰였는지 보고, logrotate -d(디버그 모드)로 실제 파일을 건드리지 않고 어떤 동작이 일어날지 시뮬레이션해 본다. 또 logger -p local0.err "hi"로 메시지를 만든 뒤 /var/log/messages에서 추적해 facility.priority 동작을 눈으로 확인한다.
fail2ban은 로그 파일을 실시간 감시하다가 정해진 시간 창 안에 실패 패턴이 임계치를 넘으면 그 출발지 IP를 방화벽 규칙으로 일정 시간 차단한다.
SSH 무차별 대입(brute force) 대응의 사실상 표준이다.
감시 단위 하나를 jail(감옥)이라 부른다 — "어떤 로그를(logpath) 어떤 필터로(filter) 보고, 몇 번 실패하면(maxretry) 얼마 동안(bantime) 막을지"를 묶은 한 벌이다.
파일
역할
/etc/fail2ban/jail.conf
배포판이 제공하는 원본. 직접 고치지 말 것(패키지 갱신 시 덮어씀)
/etc/fail2ban/jail.local
관리자 설정. jail.conf를 덮어쓰며 여기에 작성하는 것이 원칙
/etc/fail2ban/jail.d/*.conf
서비스별로 나눠 쓰는 설정 조각
/etc/fail2ban/filter.d/*.conf
실패 로그를 알아보는 정규식(failregex) 정의
/etc/fail2ban/action.d/*.conf
실제 차단을 수행하는 동작(iptables·firewalld·nftables 등)
# /etc/fail2ban/jail.local[DEFAULT]bantime = 3600 # 차단 유지 시간(초)findtime = 600 # 실패 횟수를 세는 시간 창(초)maxretry = 5 # 이 횟수를 넘으면 차단ignoreip = 127.0.0.1/8 192.168.1.0/24 # 절대 차단하지 않을 대역[sshd]enabled = trueport = sshlogpath = /var/log/secure # 데비안 계열은 /var/log/auth.log
systemctl enable --now fail2banfail2ban-client status # 활성 jail 목록fail2ban-client status sshd # 해당 jail의 차단 IP 개수·목록fail2ban-client set sshd unbanip 1.2.3.4 # 수동 차단 해제fail2ban-client reload # 설정 다시 읽기
설정을 jail.conf에 직접 쓰면 패키지 업데이트 때 통째로 덮어써 사라진다 — 반드시 jail.local(또는 jail.d/)에 작성한다. 또 ignoreip에 관리 대역을 넣지 않으면 암호 오타 몇 번으로 관리자 본인이 차단되고, logpath가 배포판과 어긋나면(RHEL 계열 /var/log/secure vs 데비안 계열 /var/log/auth.log) jail이 떠 있어도 아무것도 잡지 못한다.
snort는 네트워크를 지나는 패킷을 룰과 대조해 공격 시그니처를 찾아내는 대표적 오픈소스 NIDS다.
실행 방식이 세 가지 모드로 나뉘는 점이 출제 포인트다.
모드
하는 일
예
스니퍼(sniffer)
패킷을 잡아 화면에 출력만
snort -v (-d 페이로드, -e 링크 계층 헤더 추가)
패킷 로거(packet logger)
잡은 패킷을 파일로 저장
snort -l /var/log/snort
NIDS
룰과 대조해 경고 발생
snort -c /etc/snort/snort.conf
룰 한 줄은 룰 헤더 + 룰 옵션 두 토막이다.
alert tcp any any -> 192.168.1.0/24 80 (msg:"passwd access"; content:"/etc/passwd"; sid:1000001; rev:1;)
└─ 헤더: 동작 프로토콜 출발지IP 포트 방향 목적지IP 포트 ─┘ └──────────── 옵션 ────────────┘
침입자가 남기는 가장 확실한 흔적은 시스템 파일의 변조다 — /bin/ls가 바꿔치기되거나 /etc/passwd에 계정이 몰래 추가되는 식.
tripwire와 AIDE(Advanced Intrusion Detection Environment)는 감시 대상 파일의 크기·권한·소유자·해시를 기준 데이터베이스로 떠 둔다.
이후 검사에서 현재 상태와 비교해 달라진 것을 보고한다.
단계
tripwire
AIDE
설정·정책
/etc/tripwire/twcfg.txt, 정책 twpol.txt
/etc/aide.conf
기준 DB 생성
tripwire --init
aide --init
무결성 검사
tripwire --check
aide --check
정상 변경 반영
tripwire --update
aide --update
tripwire는 설정·정책을 사이트 키와 로컬 키로 서명해 보관하고(twadmin), 검사 리포트는 twprint로 읽는다.
AIDE는 기준 DB를 /var/lib/aide/aide.db.gz에 두며, --init이 만든 aide.db.new.gz를 관리자가 직접 이름을 바꿔 승격시키는 방식이다.
기준 DB는 시스템이 확실히 깨끗할 때(설치 직후) 만들어야 의미가 있다. 이미 침해된 상태에서 --init을 하면 백도어까지 "정상"으로 등록되어 도구가 무력해진다. 또 DB와 설정을 그 서버의 쓰기 가능한 위치에만 두면 침입자가 함께 조작할 수 있으므로 읽기 전용 매체나 외부 저장소에 보관하는 것이 원칙이다.
세 도구는 역할이 겹치지 않는다. fail2ban은 로그에 드러난 반복 실패를 즉시 차단(대응), snort는 네트워크 패킷에서 공격 시그니처를 탐지(NIDS), tripwire/AIDE는 파일이 바뀌었는지 사후 확인(HIDS)한다. 그래서 실무에서는 셋을 함께 배치한다.