리눅스 시스템 기초 · 입문편 — 본문의 "N편"은 입문 과정 번호다. 번호별 글과 전체 250편 구성은 통합 로드맵에서 확인할 수 있다.

리눅스 시스템 기초 45 / 50 · Part 5. 네트워크·보안·SOC
실습 환경: Rocky Linux 9 (10.0.0.200) · sshd 로그·프로세스 트리·ssh -v는 실습 컨테이너(OpenSSH 9.6)에서 직접 발생시킨 실제 출력
이전 글: 44. ss와 ip 명령어

1. 들어가며

Linux 서버에 원격으로 들어가는 표준 방법은 SSH다. 관리자에게는 필수 도구이고, 공격자에게는 가장 먼저 두드리는 문 이다. 인터넷에 22번 포트를 열어 두면 몇 분 안에 무차별 대입 시도가 들어오기 시작한다.

그래서 SSH는 관제에서 가장 많이 보는 로그이기도 하다. 이번 글은 49편(SSH 무차별 대입 분석)과 50편(보안관제 실습)의 기반으로서 다음을 정리한다.

  • SSH 접속은 어떤 단계를 거치며, 각 단계에서 어떤 로그가 남는가?
  • 비밀번호 인증과 공개키 인증은 어떻게 다른가?
  • sshd는 왜 프로세스가 여러 개로 나뉘는가?
  • 어떤 설정이 공격 표면을 줄이는가?

이번 글의 로그는 실습 환경에 sshd를 띄우고 틀린 비밀번호, 없는 계정, 올바른 비밀번호, 공개키 로 직접 접속해서 남긴 실제 기록이다.


2. 핵심 개념

2-1. 구성 요소

구성 요소위치역할
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클라이언트사용자의 개인키 (절대 유출 금지)

2-2. 인증 방식

방식원리장점단점
password입력한 비밀번호를 PAM이 /etc/shadow와 비교(18편)설정 간단무차별 대입·유출에 취약
publickey서버가 준 값을 클라이언트가 개인키로 서명, 서버는 authorized_keys의 공개키로 검증비밀번호가 네트워크로 가지 않음, 대입 불가개인키 관리 필요, authorized_keys가 지속성 수단 이 됨

공개키 방식에서는 개인키 자체가 전송되지 않는다. 서버는 "이 공개키의 짝이 되는 개인키를 가지고 있다"는 서명만 검증 한다.


3. 동작 원리

SSH 접속 흐름과 sshd 권한 분리 구조

3-1. 접속 4단계

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
  1. TCP 연결과 버전 교환 — 서버가 자신의 소프트웨어 버전을 알려준다. 공격자는 이 배너로 취약한 버전을 찾기도 한다.
  2. 키 교환 — 이후 통신을 암호화할 키를 합의한다. 서버는 호스트 키로 신원을 증명하고, 클라이언트는 known_hosts와 비교한다. 지문이 바뀌었다는 경고가 뜨면 중간자 공격(MITM) 이거나 서버 재설치다.
  3. 사용자 인증 — 서버가 허용하는 방식(publickey,password)으로 인증한다.
  4. 세션 — 쉘을 실행하고 로그인 기록을 남긴다.

3-2. 권한 분리 (Privilege Separation)

인증이 성공한 뒤 실습 환경의 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
프로세스권한역할
listenerroot22번 대기, 접속마다 fork
[priv]root인증 확인, PTY 할당 등 권한이 필요한 최소 작업
user@pts/N (@notty = 터미널 없는 명령 실행)사용자 권한실제 네트워크 데이터 처리

네트워크에서 들어오는 데이터를 사용자 권한 프로세스 가 처리하므로, 이 부분에 취약점이 있어도 곧바로 root 권한을 얻기 어렵다. 인증 전 단계도 권한이 없는 별도 프로세스에서 처리한다. 35편의 프로세스 트리 관점에서 정상 SSH 세션의 모양 이 바로 이것이다. 이 모양을 알아야 sshd 아래 이상한 자식을 찾을 수 있다.

3-3. 실제 로그 읽기

실습 환경에서 틀린 비밀번호 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/securejournalctl -u sshd
Ubuntu/var/log/auth.logjournalctl -u ssh

4. 실습

# 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

5. 결과 분석

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잘 쓰지 않는 두 번째 키 파일 — 놓치기 쉬운 지속성 위치

6. 보안 관점

공격흔적방어
무차별 대입 (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
호스트 키 변경클라이언트 경고지문 확인 절차

7. SOC / 보안관제 활용

7-1. SSH 로그 요약 한 번에

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

7-2. 로그인 키 지문 → 키 주인

# 로그의 지문
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

7-3. 분석 흐름

[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 조사

8. 핵심 정리

  • SSH 접속: TCP·버전 → 키 교환(서버 확인) → 사용자 인증 → 세션.
  • 공개키 인증은 개인키를 보내지 않고 서명만 검증 한다. authorized_keys는 지속성 수단이 되기도 한다.
  • sshd는 listener(root) → priv → user@pts(사용자) 로 권한을 분리한다(실습 확인).
  • 로그: Failed password(있는 계정), Invalid user(없는 계정), Accepted password/publickey(성공, 키 지문 포함).
  • 로그 위치: RHEL /var/log/secure, Ubuntu /var/log/auth.log.
  • 핵심 설정: PermitRootLogin no, PasswordAuthentication no, MaxAuthTries, AllowUsers, sshd -t로 검사 후 재시작.

9. 다음 글

다음 글 「46. Firewalld 이해」 에서는 41편 그림의 netfilter 계층을 관리하는 firewalld 를 다룬다. zone과 service 개념, runtime과 permanent 설정의 차이, SSH 접근을 관리망으로 제한하는 rich rule, 차단 로그 확인 방법, 그리고 Ubuntu의 ufw와의 차이를 정리한다.


참고 자료

profile
코드에 숨겨진 위협을 읽고 AI로 보안의 미래를 설계합니다. 프론트엔드 개발 경험을 자산 삼아 더 견고하고 지능적인 보안 운영 시스템을 구축해 나가는 과정을 기록합니다

0개의 댓글