IT 리뷰/블로그 SEO

워드프레스 index.php CPU 70% 과부하 wp-login 공격·해외 트래픽 차단·SSH 로그 확인

잡가이버 2026. 5. 28. 04:40
반응형

워드프레스 index.php CPU 70% 먹고 서버 다운될 때 (로그인 공격·봇 트래픽 정리)

워드프레스가 갑자기 느려지거나 서버가 멎어서 확인해보면, index.php가 CPU를 70% 이상 잡아먹는 경우가 있습니다. 겉으로는 “서버가 다운됐다”처럼 보이지만, 실제로는 로그인 시도 폭주봇 트래픽 때문에 PHP-FPM/Apache 프로세스가 몰려서 생기는 상황이 많습니다.

워드프레스 데이터베이스 연결 중 오류 화면 - 과부하 또는 DB 접속 문제로 발생
데이터베이스 연결 중 오류

이런 과부하 상황에서는 종종 데이터베이스 연결 중 오류도 같이 보입니다.

wp-config.php의 DB 계정/비밀번호가 틀린 경우도 있지만, 실제로는 트래픽 폭주로 DB까지 밀려서 일시적으로 연결이 끊긴 것처럼 보이는 경우가 더 많습니다.

먼저 확인할 것: cPanel/WHM에서 과부하 징후

우선 씨패널이나 WHM에 로그인해서 리소스 사용률동시 프로세스를 확인합니다.

여기서 CPU·메모리가 튀는 시점과 접속 급증이 맞물리면, 대부분은 특정 URL로 요청이 몰린 상태입니다.

SSH에서 바로 보는 과부하 원인

서버에 SSH 접속이 가능하다면, 아래 명령으로 “누가 / 어디를 때리고 있는지”가 금방 잡힙니다.

# CPU 많이 쓰는 프로세스 상위
top -o %CPU

# php-fpm / apache 관련 프로세스 확인
ps aux --sort=-%cpu | head -n 20

# 특정 도메인의 php 프로세스가 많을 때(권한 있는 환경에서)
pgrep -af "php|php-fpm|httpd|apache2" | head -n 30

로그인 공격이 의심되면 wp-login.php, xmlrpc.php로 POST가 몰리는지부터 확인합니다.

# Apache(대부분 cPanel) 도메인 로그 위치 예시
ls -al /usr/local/apache/domlogs/ 2>/dev/null | head

# Nginx 사용 시(환경마다 다름)
ls -al /var/log/nginx/ 2>/dev/null | head

# 최근 wp-login 요청이 많은지 확인(경로는 실제 도메인 로그로 바꿔서 사용)
tail -n 2000 /usr/local/apache/domlogs/your-domain.com \
| grep -E "wp-login\.php|xmlrpc\.php" | tail -n 50

로그인 시도 많은 IP 뽑기(자주 쓰는 형태)

IP별 요청 횟수를 세면 “몇 개 IP가 서버를 태우고 있는지”가 보입니다.

# wp-login.php 요청을 가장 많이 보내는 IP Top 20
grep "wp-login\.php" /usr/local/apache/domlogs/your-domain.com \
| awk '{print $1}' | sort | uniq -c | sort -nr | head -n 20

# xmlrpc.php도 같이 확인
grep "xmlrpc\.php" /usr/local/apache/domlogs/your-domain.com \
| awk '{print $1}' | sort | uniq -c | sort -nr | head -n 20

# 특정 IP의 POST 요청만 추적
grep "1.2.3.4" /usr/local/apache/domlogs/your-domain.com | tail -n 50

여기서 특정 국가/대역 IP가 수천~수만 건씩 찍히면, 그 순간부터는 IP 하나씩 막는 방식은 금방 한계가 옵니다.

IP 차단이 버거울 때: 국가 단위 차단(클라우드플레어)

저도 비슷한 상황에서 해외에서 갑자기 트래픽이 폭증했는데, 광고 수익이 늘기는커녕 RPM만 급락하고 서버만 죽는 케이스를 겪었습니다.

이런 패턴이면, 공격/봇 트래픽을 의심하고 국가 단위로 먼저 걸러주는 게 체감이 큽니다.

Cloudflare 보안 규칙에서 국가 차단 설정 화면 - 특정 국가 트래픽 차단
클라우드플레어 - 보안 - 보안규칙 - 규칙생성 원하는 국가를 추가합니다.

클라우드플레어를 쓰고 있다면, 보안 규칙에서 원하는 국가를 차단할 수 있습니다. 완벽하진 않지만(우회/프록시가 있기 때문에) “서버가 멎는 수준”에서는 일단 숨통이 트입니다.

그리고 로그인 공격이 중심이면, 사이트 전체를 막는 것보다 /wp-login.php, /xmlrpc.php 같은 민감한 경로만 더 강하게 다루는 편이 부작용이 적습니다.

클라우드플레어를 쓰는 김에 같이 켜두면 좋은 것

  • 봇 차단 기능을 켜서 기본 봇 트래픽을 먼저 줄이기
  • /wp-login.php에 대해 Challenge 또는 Rate 제한을 걸어두기
  • /xmlrpc.php는 사용하지 않으면 아예 막아두기(REST API와 별개라서, 안 쓰는 사이트가 훨씬 많습니다)

클라우드플레어 없이 막고 싶을 때: 로그인 시도 제한 플러그인

클라우드플레어를 쓰지 않는 환경이면, 최소한 로그인 시도 제한은 넣어두는 게 좋습니다.

대표적으로 LLA(로그인 무차별 차단) 계열 플러그인이 있고, 로그인이 몰리면 서버가 먼저 지치는 걸 확 줄여줍니다.

워드프레스 로그인 시도 제한(LLA/Limit Login Attempts) 설정 화면 예시

국가 차단을 “전 세계에서 한국만 허용”처럼 한 번에 잡고 싶을 때도, 플러그인/방화벽 조합이 오히려 편한 경우가 있습니다. (클라우드플레어에서 한국 제외 전부 선택하려면 진짜 번거롭죠…)

효과는 사이트마다 다르지만, 서버가 죽는 현상만큼은 일단 잡히는 편이라 저는 이런 방식으로 먼저 안정화시켜두고, 이후에 로그를 보면서 규칙을 다듬습니다.

“강제로” 정리: 환경/레지스트리/명령어로 꼬임 잡기

로그인이 몰릴 때 서버가 멎는 환경은, 단순히 “차단”만으로 끝나지 않고 같은 증상이 다시 재발하는 경우가 많기 때문에 아래 설정을 한번 확인해보세요

1) wp-login / xmlrpc에 몰리는지 확인(접속 경로부터 고정)

먼저 공격/봇이 어디로 몰리는지 확정합니다. 아래처럼 특정 경로가 압도적으로 많으면 대응이 쉬워집니다.

# wp-login.php / xmlrpc.php 요청 상위 경로 확인
tail -n 20000 /usr/local/apache/domlogs/your-domain.com \
| awk '{print $7}' | sort | uniq -c | sort -nr | head -n 30

여기서 /wp-login.php, /xmlrpc.php가 상위권을 도배하면 로그인 공격 성격이 강합니다.

2) 서버에서 임시 차단(iptables/ufw) — 응급용

당장 서버가 멎는 수준이면, 상위 IP 몇 개만이라도 응급으로 막고 숨을 돌리는 게 먼저입니다. (환경마다 방화벽 도구가 다르니, 아래는 “대표 예시”로만 봐주세요.)

# (예시) 특정 IP 차단 - 환경에 따라 작동 방식이 다를 수 있음
# ufw 사용하는 서버
sudo ufw deny from 1.2.3.4

# iptables 사용하는 서버
sudo iptables -I INPUT -s 1.2.3.4 -j DROP

IP 단위 차단은 잠깐 숨 고르는 용도로 생각하는 게 편합니다. 패턴이 바뀌면 금방 다시 들어옵니다.

3) 워드프레스 쪽에서 “불필요한 입구” 줄이기

로그인 공격이 심한 사이트는 입구가 너무 많아서 서버가 계속 갈립니다. 아래 항목만 정리해도 체감이 큽니다.

  • xmlrpc.php 미사용이면 차단 (앱/외부 연동 안 쓰는 블로그는 대부분 해당)
  • 관리자 계정 2단계 인증 적용
  • 기본 관리자 아이디(admin) 계열 사용 금지
  • 로그인 시도 제한 플러그인으로 실패 누적 시 자동 차단

4) SSH에서 “어떤 IP가 로그인만 두드리는지” 깔끔하게 뽑기

접속 로그가 크면 grep/awk 조합이 가장 빠릅니다.

# wp-login.php로 POST를 많이 치는 IP 상위
grep "wp-login\.php" /usr/local/apache/domlogs/your-domain.com \
| grep "POST" \
| awk '{print $1}' | sort | uniq -c | sort -nr | head -n 30

# 로그인 성공/실패가 섞인 상황이면 상태코드까지 같이 보기(환경에 따라 로그 포맷 다름)
grep "wp-login\.php" /usr/local/apache/domlogs/your-domain.com \
| awk '{print $1, $(NF-1)}' | head -n 50

여기서 상위 IP가 특정 국가/클라우드 ASN으로 쏠리면, 클라우드플레어의 국가 차단/봇 차단 쪽이 훨씬 수월합니다.

5) “꼬임”이 생겼을 때: 캐시·서비스 재시작으로 정리

공격 트래픽이 멈췄는데도 계속 CPU가 높게 유지되면, PHP 프로세스가 쌓여있거나 웹서버가 물려있는 경우가 있습니다. 이럴 때는 우선 상태를 확인하고 정리합니다.

# php-fpm이 과하게 떠 있는지 확인
ps aux | grep -E "php-fpm|php" | grep -v grep | wc -l

# Apache / Nginx 프로세스 확인
ps aux | grep -E "httpd|apache2|nginx" | grep -v grep | head -n 20

서비스 재시작은 서버마다 구성/권한이 달라서 함부로 적진 않지만, 관리 권한이 있는 환경이라면 “정리”가 필요할 때가 있습니다. 재시작 전에는 반드시 현재 접속/작업 상황을 확인하세요.

반응형
그리드형