| 위협 | 대책 |
|---|---|
| 비밀번호 추측 접속 | 키 전용 ssh, root 차단 |
| 권한 상승 | sudo 최소 허용, setuid 점검 |
| 앱 취약점으로 서버 장악 | 서비스 계정, SELinux |
| 오래된 패키지 | 보안 패치 주기 |
| 흔적 없는 변경 | 로그인·sudo 로그, 무결성 기준선 |
각 대책이 이 레슨의 절 하나입니다. 다섯 개를 다 하면 감사 항목의 대부분이 통과합니다.
/etc/ssh/sshd_config 에서 네 항목을 확인합니다. 바꾼 뒤 sshd -t 로 문법을 검사하고 systemctl reload sshd 로 적용합니다.
PermitRootLogin no
PasswordAuthentication no
MaxAuthTries 3
Port 22PasswordAuthentication no 는 키를 먼저 등록한 뒤 켭니다. 순서를 바꾸면 자신도 못 들어갑니다. 적용 전에 다른 터미널로 접속을 하나 더 열어 두고, 새 창에서 접속이 되는 것을 확인한 뒤 기존 창을 닫습니다.
ssh-keygen -t ed25519 -C 'kim@pc' # PC 에서 키 생성
ssh-copy-id deploy@server # 공개키 등록
ssh deploy@server # 비밀번호 없이 되는지 확인
sudo sed -i 's/^#\?PasswordAuthentication .*/PasswordAuthentication no/' /etc/ssh/sshd_config
sudo sshd -t && sudo systemctl reload sshd명령어 묶음 06 의 키 만들기와 같은 절차입니다. authorized_keys 는 600, .ssh 폴더는 700 이어야 하며 다른 사람의 키를 넣을 때는 이 권한을 유지합니다.
비밀번호 인증을 끄면 추측 공격은 무의미하지만 로그는 계속 쌓입니다. fail2ban 이 실패가 반복되는 IP 를 방화벽에서 잠시 막습니다.
sudo dnf install -y fail2ban
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd # 차단된 IP폐쇄망에서 패키지가 없으면 lastb 로 실패 목록을 주기적으로 보는 것으로 대신합니다. 내부 IP 에서 실패가 반복되면 그 PC 를 확인합니다.
SELinux 는 프로세스가 접근할 수 있는 파일·포트를 정책으로 제한합니다. RHEL 은 기본 Enforcing 이고 감사에서는 이 상태를 요구합니다.
| 명령 | 뜻 |
|---|---|
getenforce |
Enforcing / Permissive / Disabled |
sestatus |
상세 상태 |
setenforce 0 |
임시로 Permissive, 진단용 |
/etc/selinux/config |
부팅 시 모드 |
setenforce 0 은 재부팅하면 돌아옵니다. 문제를 확인하는 데만 쓰고 원인을 고친 뒤 setenforce 1 로 돌립니다. config 파일을 disabled 로 바꾸는 것은 감사 지적 사항입니다.
자바 앱이 SELinux 에 막히면 앱 로그에는 Permission denied 만 나옵니다. 진짜 이유는 감사 로그에 있습니다.
sudo ausearch -m avc -ts recent # 최근 거부 기록
sudo ausearch -m avc -ts recent | audit2why # 이유 설명
sudo grep denied /var/log/audit/audit.log | tail -n 3audit2why 가 "포트 8081 은 허용되지 않음" 이나 "파일 컨텍스트가 다름" 처럼 이유를 말해 줍니다. 그 이유에 맞는 허용 명령이 다음 절입니다.
| 상황 | 명령 |
|---|---|
| 새 포트 | semanage port -a -t http_port_t -p tcp 8081 |
| 파일 컨텍스트 복구 | restorecon -Rv /opt/myapp |
| 폴더에 컨텍스트 지정 | semanage fcontext -a -t 타입 '경로(/.*)?' |
| 불리언 켜기 | setsebool -P httpd_can_network_connect 1 |
semanage 는 policycoreutils-python-utils 패키지입니다. 대부분의 자바 앱 문제는 restorecon 한 줄로 끝납니다. 다른 곳에서 mv 로 옮겨 온 파일이 옛 컨텍스트를 갖고 있기 때문입니다.
| 명령 | 뜻 |
|---|---|
last -n 10 |
최근 로그인 성공 |
lastb -n 10 |
최근 실패 |
last reboot |
재부팅 이력 |
who / w |
지금 접속자와 작업 |
/var/log/secure |
ssh·sudo 원본 로그 |
grep 'Failed password' /var/log/secure | awk '{print $(NF-3)}' | sort | uniq -c | sort -rn | head
grep 'Accepted publickey' /var/log/secure | tail -n 5첫 줄이 실패가 많은 IP 상위 목록입니다. 운영 묶음 02 의 빈도 패턴이 보안 로그에도 그대로 쓰입니다.
sudo journalctl _COMM=sudo --since today --no-pager
sudo grep sudo /var/log/secure | grep COMMAND | tail -n 5
sudo -l # 내가 허용된 명령누가 언제 무엇을 root 로 했는지 남습니다. 명령어 묶음 03 의 visudo 로 계정마다 필요한 명령만 열어 두면 이 로그가 곧 변경 이력입니다. sudo -i 로 root 셸에 들어가면 그 안의 명령은 기록되지 않으므로 금지합니다.
find / -xdev -type f -perm -0002 ! -path '/proc/*' # 누구나 쓸 수 있는 파일
find / -xdev -type f -perm -4000 # setuid
find / -xdev -nouser -o -xdev -nogroup # 소유자 없는 파일
awk -F: '$2=="" {print $1}' /etc/shadow # 비밀번호 없는 계정
awk -F: '$3==0 {print $1}' /etc/passwd # UID 0 계정, root 하나여야
awk -F: '$3<1000 && $7 !~ /nologin|false/' /etc/passwd # 셸 있는 시스템 계정setuid 는 passwd·sudo·su 같은 시스템 명령에만 있어야 합니다. /opt·/home 아래에 있으면 의심합니다. 셸이 있는 시스템 계정은 usermod -s /sbin/nologin 으로 막습니다.
rpm -Va --nofiles --nodigest | head # 설정 변경된 패키지
rpm -V openssh-server # 한 패키지의 파일 변조 여부
dnf updateinfo list security # 적용 안 된 보안 패치
sudo dnf update --security # 보안 패치만rpm -V 출력에서 S.5....T 처럼 5 가 있으면 파일 내용이 바뀐 것입니다. 설정 파일은 바뀌는 것이 정상이고 실행 파일이 바뀌면 문제입니다. 패치는 개발 서버에서 먼저 적용하고 재부팅이 필요한지 needs-restarting -r 로 봅니다.
중요 파일의 해시를 한 번 기록해 두고 주기적으로 비교합니다. 도구 없이 sha256sum 두 줄이면 됩니다.
sudo sha256sum /etc/passwd /etc/shadow /etc/sudoers /etc/ssh/sshd_config > /var/lib/baseline.sha256
sudo sha256sum -c /var/lib/baseline.sha256 # 바뀐 파일은 FAILED배포 폴더의 jar 도 같은 방식으로 기준선을 두면 "누가 jar 를 바꿨나" 를 알 수 있습니다. aide 패키지가 같은 일을 자동으로 하지만 폐쇄망에서는 이 두 줄이 현실적입니다.