당신의 SSH 서버는 이미 하루에도 수백 번씩 공격받고 있을 가능성이 큽니다. 가능성이 크다 라는 말로는 부족합니다. 거의 100%의 확률로 당신의 서버는 하루 수백번씩의 공격을 받고 있다고 필자인 저는 확신합니다. 그런데도 상당수 개발자는 /var/log 폴더를 거의 열어보지 않습니다. 간단한 journalctl -f |grep ssh 라도 지금 한번 터미널에서 실행해보세요.

로그만 제대로 보면:

  • 누가

  • 언제

  • 어디서

  • 어떻게
    서버에 들어오려고 했는지 적나라하게 보입니다.

이 글에서는 SSH 서버 로그를 해석하는 법해킹 징후를 찾는 실전 분석 방법을 개발자 관점에서 정리해봅니다.


1. SSH 로그는 어디에 남을까?



리눅스 배포판마다 SSH 로그 위치가 조금 다릅니다.

일반적으로:

  • Ubuntu / Debian 계열

    • /var/log/auth.log
  • CentOS / RHEL 계열

    • /var/log/secure
  • systemd 기반 공통 명령

    • journalctl -u ssh.service 또는 journalctl -u sshd

tail 을 써도 좋지만 개인적으로 저는 journald 로 보는 것을 매우 선호합니다. 모든 서비스의 로그를 한곳에 모아서 볼 수 있기때문입니다.

# Ubuntu 예시
sudo tail -f /var/log/auth.log

# CentOS/RHEL 예시
sudo tail -f /var/log/secure

# systemd 서비스 로그 실시간 보기
sudo journalctl -u ssh.service -f

tip: 개발 서버라도, 최소한 가끔씩은 tail -f로 로그를 “감시하는 습관”을 들이면 좋습니다.

journald 의 구체적인 사용법에 대해서 궁금하신 분은 "여기"를 클릭해보세요!


2. SSH 로그 한 줄 해부하기

대표적인 SSH 로그 한 줄을 보면서 구조를 이해해 봅시다. (Ubuntu 예시)

2.1 공개키 로그인 성공

Jan 10 12:34:56 myserver sshd[12345]: Accepted publickey for deploy from 203.0.113.10 port 50312 ssh2: ED25519 SHA256:xxxx

각 부분의 의미:

  • Jan 10 12:34:56 : 날짜, 시간

  • myserver : 호스트 이름

  • sshd[12345] : 프로세스 이름(SSH 데몬)과 PID

  • Accepted publickey : 인증 성공, 방식은 공개키

  • for deploy : 로그인한 계정 이름

  • from 203.0.113.10 : 접속 원 IP

  • port 50312 : 클라이언트 측 포트

  • ssh2: ED25519 ... : 프로토콜/키 타입 정보

이걸 이해하면, “누가 어디서 키로 접속했는지” 빠르게 파악할 수 있습니다.

2.2 비밀번호 로그인 실패

Jan 10 12:35:01 myserver sshd[12346]: Failed password for root from 198.51.100.23 port 50320 ssh2
  • Failed password : 비밀번호 인증 실패

  • for root : root 계정으로 시도

  • from 198.51.100.23 : 원격 IP

이런 로그가 몇 초 간격으로 수십~수백 번 찍혀 있으면,
거의 확실히 무차별 대입(brute-force) 공격입니다.

2.3 존재하지 않는 유저로 로그인 시도

Jan 10 12:35:05 myserver sshd[12347]: Invalid user admin from 198.51.100.23 port 50325
  • Invalid user admin : 서버에 없는 admin 계정으로 로그인 시도

이 또한 자동화된 봇이 흔히 사용하는 패턴입니다.


3. 로그로 보는 대표적인 공격 패턴



3.1 무차별 대입 공격 (brute-force)

특징:

  • Failed password 로그가 짧은 시간에 매우 많이 발생

  • 동일한 IP에서 수십~수백 번 시도

  • root, admin, test, oracle 같은 계정 이름 사용

빠르게 확인해 보는 예:

# Failed password 전체 횟수
sudo grep "Failed password" /var/log/auth.log | wc -l

# 어떤 계정이 가장 많이 공격받는지
sudo grep "Failed password" /var/log/auth.log \
  | awk '{for (i=1;i<=NF;i++) if ($i=="for") print $(i+1)}' \
  | sort | uniq -c | sort -nr | head

3.2 존재하지 않는 유저 스캔

sudo grep "Invalid user" /var/log/auth.log | head

이 로그가 많다는 건 “이 서버에 어떤 계정이 있을지 아무렇게나 찍어보는 중”이라는 의미입니다.

3.3 특정 IP에서의 과도한 시도

어떤 IP가 특히 많이 실패하는지 확인:

sudo grep "Failed password" /var/log/auth.log \
  | awk '{print $(NF-3)}' \
  | sort | uniq -c | sort -nr | head

위에서 $(NF-3)는 보통 from <IP> 부분의 IP를 가리키지만,
환경마다 약간씩 다를 수 있으니 본인 로그 형식에 맞게 조정해야 합니다.


4. “성공한” 로그인 중에서 이상 징후 찾기

공격은 대개 실패로 남지만, 진짜 무서운 건 성공한 로그인입니다.

4.1 Accepted 로그 모으기

sudo grep "Accepted" /var/log/auth.log

이 중에서 특히 주의 깊게 볼 것:

  • 평소에 쓰지 않는 계정의 접속

  • 평소와 다른 시간대의 접속 (예: 새벽 3시)

  • 생소한 국가/대역의 IP(회사/집/VPN이 아닌 IP)

4.2 최근 접속 이력 한 번에 보기

last 명령은 최근 로그인 이력을 보여줍니다.

# 최근 SSH 로그인 기록
last -i | head

# 실패한 로그인(지원하는 환경에서)
lastb | head

이것만 정기적으로 확인해도,
“내가 접속하지 않은 시각의 접속 기록”을 쉽게 발견할 수 있습니다.


5. 실전 로그 분석: 빠른 점검 루틴 예시

SSH 서버가 하나 있다고 가정하고,
5분 만에 할 수 있는 점검 루틴을 만들어 보겠습니다.

5.1 1단계: 실패 로그인 총량 확인

sudo grep "Failed password" /var/log/auth.log | wc -l
sudo grep "Invalid user" /var/log/auth.log | wc -l
  • 갑자기 숫자가 크게 늘었다면 “공격 강도 증가”를 의심해볼 만합니다.

5.2 2단계: 최다 공격 IP TOP 10

sudo grep "Failed password" /var/log/auth.log \
  | awk '{print $(NF-3)}' \
  | sort | uniq -c | sort -nr | head
  • 상위 IP는 방화벽/fail2ban 룰에 넣을 수 있습니다.

5.3 3단계: root로 시도된 로그인

sudo grep "Failed password for root" /var/log/auth.log | tail
sudo grep "Accepted.*root" /var/log/auth.log
  • Accepted가 나와 있다면 이미 root로 로그인에 성공했다는 의미이므로 매우 위험합니다.

5.4 4단계: 최근 성공한 로그인 스캔

sudo grep "Accepted" /var/log/auth.log | tail -n 50

여기서 확인할 포인트:

  • 내가 모르는 IP인가?

  • 일반적인 근무 시간대인가?

  • 갑자기 처음 등장한 계정은 아닌가?


6. 로그만 보면 뭐하나? 바로 적용할 방어책

로그에서 공격 냄새를 맡았다면,
이제 방어 설정으로 이어져야 합니다.

6.1 비밀번호 로그인 끄기 (공개키만 허용)

/etc/ssh/sshd_config에서:

PasswordAuthentication no
PubkeyAuthentication yes

수정 후:

sudo systemctl reload sshd
# 또는
sudo service ssh restart

반드시 이미 공개키 로그인 테스트를 성공한 후에 비밀번호를 끄세요.
잘못하면 자신도 못 들어갈 수 있습니다.

6.2 root 직접 로그인 금지

PermitRootLogin no

root로 바로 들어오지 못하게 하고,
일반 계정으로 로그인 후 sudo를 사용하도록 강제하는 것이 좋습니다.

6.3 포트 변경 (소음 줄이기용)

Port 22    # -> 예: 2222로 변경
  • 포트를 바꾼다고 보안이 “강화”되는 건 아니지만,

  • 무분별한 자동 스캔/공격 로그가 상당히 줄어들어
    “진짜 이상 징후”가 더 잘 눈에 들어오게 됩니다.

6.4 fail2ban 같은 툴 사용

fail2ban은 로그를 모니터링하다가

  • 같은 IP에서

  • 짧은 시간에

  • 다수의 로그인 실패 발생 시

자동으로 방화벽 룰을 추가해 차단하는 도구입니다.

개념은 간단합니다:

  1. auth.log에서 Failed password 패턴 감시

  2. 특정 임계치 초과 시 해당 IP를 iptables/ufw로 차단

로그 분석을 자동화해서 브루트포스 공격을 자동 차단하는 셈입니다.

6.5 방화벽으로 SSH 접근 자체 제한

가능하다면:

  • 회사 VPN이나 특정 고정 IP에서만 22/tcp(또는 변경 포트) 접근 허용

  • 나머지는 전부 차단

예: ufw 간단 예시

sudo ufw allow from 203.0.113.50 to any port 22 proto tcp
sudo ufw deny 22/tcp

7. 개발자를 위한 “최소 생활 로그 점검 루틴”

개발자가 업무 중에 현실적으로 할 수 있는 수준으로 요약하면,
아래 정도만 해도 보안 민감도는 완전히 달라집니다.

주 1회 정도:

  1. 최근 일주일간 Failed password, Invalid user 수량 한 번 보기

  2. 최다 실패 IP TOP 10 확인

  3. Accepted 로그에서

    • 새로운 IP,

    • 이상한 시간대,

    • 낯선 계정이 있는지 확인

  4. 의심 IP는 방화벽/fail2ban 등으로 차단

한 번만 직접 눈으로 봐도,
“아, 이 서버는 진짜로 매일 공격받고 있구나”라는 감각이 생기고
보안 설정에 시간을 투자할 의지가 생기게 됩니다.


해커가 ssh서버를 공격하는 모습

마무리: 지금 당장 로그부터 열어보자

SSH 보안은 거창한 솔루션 이전에,
내 서버에서 실제로 어떤 일이 벌어지고 있는지 보는 것에서 시작합니다.

  1. /var/log/auth.log 또는 /var/log/secure 열어보기

  2. Failed password, Invalid user, Accepted를 기준으로 읽어보기

  3. 이상하다 싶으면 바로 설정 변경과 방화벽, fail2ban 도입 검토

지금 이 글을 다 읽었다면,
이제 “로그를 못 봐서 당하는 해킹”은 피할 준비가 된 것입니다.
이제 터미널을 열고, 직접 서버 로그를 한번 들여다보세요.

개발자에게 보안은 선택이 아니라 필수이자 루틴 이어야 합니다.

Fail2ban의 사용법은 "여기"를 클릭하시면 자세한 사용법을 확인하실 수 있습니다.