리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.
리눅스 시스템 기초 45 / 50 · Part 5. 네트워크·보안·SOC
실습 환경: Rocky Linux 9 (10.0.0.200) · sshd 로그·프로세스 트리·ssh -v는 실습 컨테이너(OpenSSH 9.6)에서 직접 발생시킨 실제 출력
이전 글: 44. ss와 ip 명령어
Linux 서버에 원격으로 들어가는 표준 방법은 SSH다. 관리자에게는 필수 도구이고, 공격자에게는 가장 먼저 두드리는 문 이다. 인터넷에 22번 포트를 열어 두면 몇 분 안에 무차별 대입 시도가 들어오기 시작한다.
그래서 SSH는 관제에서 가장 많이 보는 로그이기도 하다. 이번 글은 49편(SSH 무차별 대입 분석)과 50편(보안관제 실습)의 기반으로서 다음을 정리한다.
이번 글의 로그는 실습 환경에 sshd를 띄우고 틀린 비밀번호, 없는 계정, 올바른 비밀번호, 공개키 로 직접 접속해서 남긴 실제 기록이다.
| 구성 요소 | 위치 | 역할 |
|---|---|---|
sshd | 서버 | 22번 포트에서 대기하는 데몬 |
/etc/ssh/sshd_config | 서버 | 서버 설정 (sshd_config.d/*.conf 포함) |
| 호스트 키 | 서버 /etc/ssh/ssh_host_*_key | 서버 신원 증명 |
~/.ssh/authorized_keys | 서버 사용자 홈 | 로그인을 허용할 공개키 목록 |
ssh | 클라이언트 | 접속 도구 |
~/.ssh/known_hosts | 클라이언트 | 접속했던 서버의 호스트 키 지문 |
~/.ssh/id_ed25519 | 클라이언트 | 사용자의 개인키 (절대 유출 금지) |
| 방식 | 원리 | 장점 | 단점 |
|---|---|---|---|
| password | 입력한 비밀번호를 PAM이 /etc/shadow와 비교(18편) | 설정 간단 | 무차별 대입·유출에 취약 |
| publickey | 서버가 준 값을 클라이언트가 개인키로 서명, 서버는 authorized_keys의 공개키로 검증 | 비밀번호가 네트워크로 가지 않음, 대입 불가 | 개인키 관리 필요, authorized_keys가 지속성 수단 이 됨 |
공개키 방식에서는 개인키 자체가 전송되지 않는다. 서버는 "이 공개키의 짝이 되는 개인키를 가지고 있다"는 서명만 검증 한다.

ssh -v로 본 실제 협상 과정이다(지문 생략).
debug1: Connecting to 127.0.0.1 [127.0.0.1] port 22.
debug1: Remote protocol version 2.0, remote software version OpenSSH_9.6p1 Ubuntu-3ubuntu13.19
debug1: kex: algorithm: sntrup761x25519-sha512@openssh.com
debug1: kex: host key algorithm: ssh-ed25519
debug1: Server host key: ssh-ed25519 SHA256:(생략)
debug1: Authentications that can continue: publickey,password
known_hosts와 비교한다. 지문이 바뀌었다는 경고가 뜨면 중간자 공격(MITM) 이거나 서버 재설치다.publickey,password)으로 인증한다.인증이 성공한 뒤 실습 환경의 sshd 프로세스는 이렇게 나뉘었다(실제 출력).
PID PPID USER COMMAND
1788 1 root sshd: /usr/sbin/sshd ... [listener] 0 of 10-100 startups
1897 1788 root \_ sshd: devuser [priv]
1908 1897 devuser \_ sshd: devuser@notty
| 프로세스 | 권한 | 역할 |
|---|---|---|
| listener | root | 22번 대기, 접속마다 fork |
[priv] | root | 인증 확인, PTY 할당 등 권한이 필요한 최소 작업 |
user@pts/N (@notty = 터미널 없는 명령 실행) | 사용자 권한 | 실제 네트워크 데이터 처리 |
네트워크에서 들어오는 데이터를 사용자 권한 프로세스 가 처리하므로, 이 부분에 취약점이 있어도 곧바로 root 권한을 얻기 어렵다. 인증 전 단계도 권한이 없는 별도 프로세스에서 처리한다. 35편의 프로세스 트리 관점에서 정상 SSH 세션의 모양 이 바로 이것이다. 이 모양을 알아야 sshd 아래 이상한 자식을 찾을 수 있다.
실습 환경에서 틀린 비밀번호 3회, 없는 계정 3개, 올바른 비밀번호, 공개키로 접속한 실제 sshd 로그다(syslog 앞부분 없이 sshd 메시지만 기록).
Failed password for devuser from 127.0.0.1 port 57806 ssh2
Connection closed by authenticating user devuser 127.0.0.1 port 57806 [preauth]
Invalid user admin from 127.0.0.1 port 47298
Failed password for invalid user admin from 127.0.0.1 port 47298 ssh2
Connection closed by invalid user admin 127.0.0.1 port 47298 [preauth]
Accepted password for devuser from 127.0.0.1 port 35168 ssh2
Received disconnect from 127.0.0.1 port 35168:11: disconnected by user
Disconnected from user devuser 127.0.0.1 port 35168
Accepted publickey for devuser from 127.0.0.1 port 39132 ssh2: ED25519 SHA256:MoJGub2hqRBEulQ3+ig8TyZwcwCw1V+uzOaLkryMteY
| 메시지 | 의미 | 관제 판단 |
|---|---|---|
Failed password for <user> | 존재하는 계정 의 비밀번호 틀림 | 계정명이 맞음 → 표적화 |
Invalid user <user> / for invalid user | 없는 계정 시도 | 사전(dictionary) 대입 |
[preauth] | 인증 완료 전 종료 | 실패 시도 |
Accepted password | 비밀번호 로그인 성공 | 실패 직후라면 대입 성공 |
Accepted publickey ... SHA256:... | 공개키 로그인 성공 + 키 지문 | 어떤 키가 쓰였는지 추적 |
Disconnected from user | 세션 종료 | 세션 길이 계산 |
공개키 로그의 지문은 ssh-keygen -lf로 계산한 값과 같다.
$ ssh-keygen -lf labkey.pub
256 SHA256:MoJGub2hqRBEulQ3+ig8TyZwcwCw1V+uzOaLkryMteY roror@admin-pc (ED25519)
그래서 로그의 지문을 authorized_keys 각 줄의 지문과 비교하면 어느 키(누구의 PC)로 들어왔는지 알 수 있다.
로그 위치 는 배포판마다 다르다.
| 배포판 | 파일 | journal |
|---|---|---|
| RHEL / Rocky | /var/log/secure | journalctl -u sshd |
| Ubuntu | /var/log/auth.log | journalctl -u ssh |
# 1) 서버 상태·설정
systemctl status sshd # Ubuntu: ssh
sudo sshd -T | grep -Ei '^(port|permitrootlogin|passwordauthentication|pubkeyauthentication|maxauthtries|allowusers)'
sudo sshd -t && echo "config OK" # 변경 후 문법 검사 (재시작 전 필수)
# 2) 키 생성과 등록
ssh-keygen -t ed25519 -C "roror@admin-pc"
ssh-copy-id -i ~/.ssh/id_ed25519.pub roror@10.0.0.200
# 3) 권한 확인 (틀리면 공개키 인증 거부)
ls -ld ~/.ssh; ls -l ~/.ssh/authorized_keys # 700 / 600
# 4) 등록된 키 지문 목록
ssh-keygen -lf ~/.ssh/authorized_keys
# 5) 세션·프로세스
ps -eo pid,ppid,user,args --forest | grep -A2 '[s]shd'
who; w
# 6) 로그
sudo grep -E 'Accepted|Failed|Invalid' /var/log/secure | tail # RHEL
sudo grep -E 'Accepted|Failed|Invalid' /var/log/auth.log | tail # Ubuntu
sshd -T는 기본값까지 포함한 실제 적용 설정 을 보여준다. 실습 환경의 실제 출력이다.
port 22
listenaddress 127.0.0.1:22
logingracetime 120
maxauthtries 3
permitrootlogin no
pubkeyauthentication yes
passwordauthentication yes
x11forwarding no
allowtcpforwarding yes
authorizedkeysfile .ssh/authorized_keys .ssh/authorized_keys2
| 항목 | 평가 |
|---|---|
permitrootlogin no | 양호 |
maxauthtries 3 | 양호 — 한 연결에서 3회까지만 |
passwordauthentication yes | 실습용. 운영 서버는 no 권장 → 무차별 대입 자체가 불가능해짐 |
logingracetime 120 | 인증 대기 2분. 30초 정도로 줄이면 연결 점유형 공격 완화 |
allowtcpforwarding yes | 필요 없으면 no. 터널링(포트 포워딩)으로 내부망 우회 가능 |
authorized_keys2 | 잘 쓰지 않는 두 번째 키 파일 — 놓치기 쉬운 지속성 위치 |
| 공격 | 흔적 | 방어 |
|---|---|---|
| 무차별 대입 (T1110.001) | 짧은 간격의 Failed password 대량 | 키 인증 전용, fail2ban, 접근 IP 제한 (46·49편) |
| 계정 사전 대입 | Invalid user 다수 | AllowUsers, 기본 계정 제거 |
| 유효 계정 탈취 (T1078) | 평소와 다른 IP·시각의 Accepted | 로그인 기준값, MFA |
| 키 추가로 지속성 (T1098.004) | authorized_keys 변경, 모르는 지문의 Accepted publickey | 파일 무결성 감시 (15·22편) |
| 터널링 | -L/-R/-D 포워딩 | AllowTcpForwarding no |
| 호스트 키 변경 | 클라이언트 경고 | 지문 확인 절차 |
LOG=/var/log/secure # Ubuntu: /var/log/auth.log
sudo grep -c 'Failed password' $LOG
sudo grep 'Failed password' $LOG | grep -oE 'from [0-9.]+' | sort | uniq -c | sort -rn | head
sudo grep 'Accepted' $LOG | awk '{print $1,$2,$3,$7,$9,$11}' | tail # 시각·방식·계정·IP
# 로그의 지문
sudo grep 'Accepted publickey' $LOG | grep -oE 'SHA256:[A-Za-z0-9+/]+' | sort -u
# 등록된 키 지문과 코멘트
for f in /home/*/.ssh/authorized_keys /root/.ssh/authorized_keys; do
[ -f "$f" ] && echo "== $f" && sudo ssh-keygen -lf "$f"
done
[Alert] 02:19 devuser Accepted password from 10.0.0.128 (평소 키 인증 계정 아님, 새벽)
↓
[직전] 02:10~02:19 같은 IP에서 Failed password 95회 → 대입 성공 (49편)
↓
[세션] ps --forest → sshd: devuser [priv] → sshd: devuser@pts/1 → bash
↓
[이후] sudo 거부, su 실패 (21편) · authorized_keys 변경 여부 확인
↓
[Response] 세션 종료, 계정 잠금·비밀번호 변경, PasswordAuthentication no, 10.0.0.128 조사
authorized_keys는 지속성 수단이 되기도 한다.Failed password(있는 계정), Invalid user(없는 계정), Accepted password/publickey(성공, 키 지문 포함)./var/log/secure, Ubuntu /var/log/auth.log.PermitRootLogin no, PasswordAuthentication no, MaxAuthTries, AllowUsers, sshd -t로 검사 후 재시작.다음 글 「46. Firewalld 이해」 에서는 41편 그림의 netfilter 계층을 관리하는 firewalld 를 다룬다. zone과 service 개념, runtime과 permanent 설정의 차이, SSH 접근을 관리망으로 제한하는 rich rule, 차단 로그 확인 방법, 그리고 Ubuntu의 ufw와의 차이를 정리한다.