목차
안녕하세요, 워드프레스 고수 여러분! 😊 혹시 여러 개의 워드프레스 사이트를 운영하면서, 각 사이트의 Wordfence 플러그인이 차단한 IP 주소들을 한눈에 보고 싶거나, 이 정보를 다른 보안 시스템(예: 서버 방화벽)에 활용하고 싶다는 생각을 해보신 적 없으신가요? 🤔 각 사이트에 일일이 접속해서 확인하는 건 너무 번거롭잖아요!
그래서 오늘은! 여러 워드프레스 사이트에 설치된 Wordfence가 차단한 IP 주소들을 자동으로 수집하고, 중복을 제거하여 하나의 ‘마스터 차단 목록‘으로 만들어주는 아주 유용한 Bash 스크립트를 소개해 드리려고 해요! 이 스크립트는 WP-CLI(WordPress Command Line Interface)를 활용하기 때문에, 서버에 직접 접근하여 명령어를 실행할 수 있는 환경에서 더욱 빛을 발한답니다. ✨ 마치 흩어져 있던 구슬들을 하나로 꿰어 멋진 목걸이를 만드는 것처럼, 이 스크립트는 여러분의 보안 관리 효율을 한층 더 높여줄 거예요! 자, 그럼 지금부터 함께 자세히 알아볼까요? 😉
🤔 잠깐! 이 스크립트는 어떤 분들에게 유용할까요?
- 🌐 여러 개의 워드프레스 사이트를 직접 서버에서 운영하시는 분!
- 🛡️ Wordfence 플러그인을 각 사이트의 주요 보안 도구로 사용하고 계신 분!
- ⚙️ WP-CLI 사용에 익숙하시거나, 서버에서 쉘 스크립트를 실행하는 데 거부감이 없으신 분!
- 🔒 수집된 차단 IP 목록을 서버 방화벽(예:
iptables
,firewalld
,ufw
)이나 다른 보안 솔루션에 연동하여 사이트 전체의 보안을 더욱 강화하고 싶으신 분!
만약 “나는 워드프레스 공유 호스팅을 쓰고, 서버 접근은 잘 몰라요~” 하시는 분들께는 조금 어려울 수 있지만, “오! 이거 완전 내 이야기인데?” 하시는 분들께는 정말 꿀팁이 될 거예요! 😊
🛠️ 준비물: 스크립트 실행을 위해 필요한 것들
- Linux 서버 환경: 이 스크립트는 Bash 쉘에서 실행되도록 작성되었어요.
- WP-CLI 설치: 워드프레스 설치 경로에서
wp
명령어를 사용할 수 있도록 WP-CLI가 설치되어 있어야 해요. WP-CLI 공식 사이트에서 설치 방법을 확인할 수 있답니다!) - Wordfence 플러그인 활성화: 정보를 추출할 워드프레스 사이트들에 Wordfence 플러그인이 설치되고 활성화되어 있어야겠죠?
- 데이터베이스 접근 권한: WP-CLI를 통해 데이터베이스에 쿼리를 실행하므로, 해당 권한이 필요해요. (스크립트에서는
--allow-root
옵션을 사용하고 있으니,root
권한으로 실행하거나 WP-CLI 설정에 따라 적절한 사용자 권한이 필요합니다.)
자, 준비되셨다면 이제 스크립트의 마법을 살펴볼까요?
📜 스크립트 전체 코드 공개! (자세한 설명과 함께 꼼꼼히!)
아래는 여러 워드프레스 사이트에서 Wordfence가 차단한 IP 주소를 수집하여 통합 목록을 만드는 Bash 스크립트 전체 코드예요. 각 부분이 어떤 역할을 하는지 주석과 함께 자세히 설명해 드릴게요! 😊
#!/bin/bash
# ==============================================================================
# Wordfence 차단 IP 통합 스크립트
# 여러 워드프레스 사이트에서 Wordfence가 차단한 IP 주소를 수집하여
# 중복을 제거한 마스터 차단 목록을 생성합니다.
# WP-CLI가 설치되어 있어야 하며, Wordfence 플러그인이 활성화된 사이트에서 작동합니다.
# ==============================================================================
# 설정: IP를 추출할 워드프레스 사이트들의 최상위 디렉터리 경로를 배열로 지정합니다.
# 예시: BLOG_DIRS=("/home/user1/public_html" "/home/user2/public_html/site2")
BLOG_DIRS=("/var/www/wordpress1" "/var/www/wordpress2") # ⬅️ 여러분의 실제 경로로 수정해주세요!
# 설정: 통합된 IP 목록을 임시로 저장할 파일과 최종 마스터 차단 목록 파일 경로를 지정합니다.
# 이 파일들이 생성될 디렉터리에 쓰기 권한이 있는지 확인해주세요.
OUTPUT_FILE="/root/wf-ip-aggr/wordfence_blocked_ips.txt" # 임시 파일
FINAL_LIST="/root/wf-ip-aggr/master_blocklist.txt" # 최종 목록 파일
# ⬅️ 이 경로들도 여러분의 환경에 맞게 수정하거나, 스크립트 실행 전 해당 디렉터리를 생성해주세요!
# ------------------------------------------------------------------------------
# 스크립트 실행 전 준비 작업
# ------------------------------------------------------------------------------
# 스크립트가 실행될 디렉터리 생성 (없을 경우)
mkdir -p "$(dirname "$OUTPUT_FILE")"
# 이전 실행에서 남아있을 수 있는 임시 파일 초기화 (빈 파일로 만들기)
> "$OUTPUT_FILE"
echo "====================================================================="
echo "Wordfence 차단 IP 수집 및 통합을 시작합니다..."
echo "대상 워드프레스 경로: ${BLOG_DIRS[*]}"
echo "임시 저장 파일: $OUTPUT_FILE"
echo "최종 차단 목록: $FINAL_LIST"
echo "====================================================================="
echo # 빈 줄 추가
# ------------------------------------------------------------------------------
# 각 워드프레스 사이트 순회 및 IP 추출
# ------------------------------------------------------------------------------
for dir in "${BLOG_DIRS[@]}"; do
echo "---------------------------------------------------------------------"
echo "사이트 처리 중: $dir"
echo "---------------------------------------------------------------------"
# 1. 대상 디렉터리가 실제로 존재하는지 확인
if [ ! -d "$dir" ]; then
echo "오류: 디렉터리를 찾을 수 없습니다: $dir. 건너뜁니다."
echo # 빈 줄 추가
continue # 다음 디렉터리로 넘어감
fi
# 2. WP-CLI 명령어가 사용 가능한지 확인
if ! command -v wp &> /dev/null; then
echo "치명적 오류: WP-CLI를 찾을 수 없습니다. WP-CLI를 설치해주세요."
exit 1 # 스크립트 종료
fi
# 3. 해당 디렉터리가 유효한 워드프레스 설치 경로인지 확인 (조용히 실행)
# WP-CLI의 'core is-installed' 명령은 워드프레스 설치 여부를 확인합니다.
# '--allow-root'는 root 사용자로 WP-CLI 실행 허용, '--quiet'는 성공 시 출력 없음.
if ! wp core is-installed --allow-root --path="$dir" --quiet; then
echo "-> 유효한 워드프레스 설치 경로가 아닙니다. 건너뜁니다."
echo # 빈 줄 추가
continue
fi
# 4. Wordfence 플러그인이 활성화되어 있는지 확인 (조용히 실행)
if ! wp plugin is-active wordfence --allow-root --path="$dir" --quiet; then
echo "-> 이 사이트에서 Wordfence 플러그인이 활성화되어 있지 않습니다. 건너뜁니다."
echo # 빈 줄 추가
continue
fi
echo "-> 워드프레스 설치 및 Wordfence 활성화 확인 완료."
# 5. 워드프레스 데이터베이스 테이블 접두사(prefix) 가져오기
# Wordfence 테이블 이름은 이 접두사를 포함합니다. (예: wp_wfblocks7)
# 오류 발생 시 스크립트가 중지되지 않도록 || true 추가 (더 나은 오류 처리 가능)
PREFIX=$(wp db prefix --allow-root --path="$dir" || true)
if [ -z "$PREFIX" ]; then
echo "오류: 데이터베이스 접두사를 가져올 수 없습니다. 건너뜁니다."
echo # 빈 줄 추가
continue
fi
echo "-> 데이터베이스 접두사: $PREFIX"
# Wordfence 차단 IP 테이블 이름 정의 (버전 7 이상 기준)
# Wordfence는 버전에 따라 테이블 이름이 변경될 수 있습니다.
# 현재 많이 사용되는 최신 버전은 'wfblocks7' 테이블을 사용합니다.
BLOCKS_TABLE_V7="${PREFIX}wfblocks7"
# 실행할 SQL 쿼리 초기화
SQL_QUERY=""
# WP-CLI를 사용하여 해당 워드프레스의 모든 DB 테이블 목록 가져오기 (--all-tables 옵션 필수)
# '--format=csv'는 쉼표로 구분된 값으로 결과를 출력하여 grep으로 검색하기 용이하게 합니다.
ALL_TABLES=$(wp db tables --allow-root --path="$dir" --all-tables --format=csv)
# 최신 Wordfence 차단 테이블(wfblocks7)이 존재하는지 확인
if echo "$ALL_TABLES" | grep -q -i "${BLOCKS_TABLE_V7}"; then
echo "-> 최신 차단 테이블 발견: $BLOCKS_TABLE_V7"
# wfblocks7 테이블에서 차단된 IP(type=1)를 추출하는 SQL 쿼리 작성
# IP 컬럼은 VARBINARY(16) 타입으로, IPv4와 IPv6 주소를 모두 저장합니다.
# - LENGTH(IP) = 4 : IPv4 주소 (바이너리 형태)
# - LENGTH(IP) = 16 : IPv6 주소 (바이너리 형태)
#
# IP 주소 변환 함수:
# - INET_NTOA(IP) : 바이너리 IPv4를 점으로 구분된 문자열로 변환 (예: 192.168.1.1)
# - INET6_NTOA(IP) : 바이너리 IPv6를 콜론으로 구분된 문자열로 변환
# - HEX(IP) : 바이너리 IP를 16진수 문자열로 변환 (INET6_NTOA 사용 권장)
# - UCASE() : IPv6 주소를 대문자로 표시 (표준 형식)
# - SUBSTRING_INDEX(INET6_NTOA(IP), ':', -1) : IPv4 매핑된 IPv6 주소(::ffff:192.168.1.1)에서 IPv4 부분만 추출
#
# `type = 1` 조건은 '영구 차단(permanent block)'된 IP만 선택합니다.
# (type의 다른 값들은 임시 차단 등 다른 의미를 가질 수 있습니다.)
SQL_QUERY="
SELECT DISTINCT
CASE
WHEN LENGTH(IP) = 4 THEN INET_NTOA(IP) -- IPv4 주소 변환
WHEN LENGTH(IP) = 16 AND INET6_NTOA(IP) LIKE '::ffff:%' THEN SUBSTRING_INDEX(INET6_NTOA(IP), ':', -1) -- IPv4-mapped IPv6 주소에서 IPv4 부분만 추출
ELSE UCASE(INET6_NTOA(IP)) -- 일반 IPv6 주소 변환 (대문자로)
END as readable_ip
FROM ${BLOCKS_TABLE_V7}
WHERE type = 1 AND IP IS NOT NULL AND IP != '';
"
# IP IS NOT NULL AND IP != '' 조건을 추가하여 유효하지 않은 IP 값 제외
else
echo "-> 최신 차단 테이블($BLOCKS_TABLE_V7)을 찾을 수 없습니다."
# 참고: 이 스크립트는 구버전 Wordfence 테이블(예: wfBlockedIPLog - IP가 문자열로 저장됨)은
# 현재 고려하지 않고 있습니다. 대부분의 최신 공격은 wfblocks7에 기록됩니다.
fi
# SQL 쿼리가 준비되었다면 실행하여 결과를 임시 파일에 추가
if [ -n "$SQL_QUERY" ]; then
# WP-CLI를 사용하여 데이터베이스 쿼리 실행
# '--silent'는 WP-CLI 자체의 메시지(예: 'SQL query executed')를 숨깁니다.
# '--skip-column-names'는 결과에서 'readable_ip' 같은 컬럼 헤더를 제외합니다.
echo "-> SQL 쿼리 실행 중..."
wp db query "$SQL_QUERY" --silent --allow-root --path="$dir" --skip-column-names >> "$OUTPUT_FILE"
# 만약 위 쿼리가 결과를 반환하지 않아도 오류는 아니므로, 성공/실패 메시지는 현재 생략.
# wc -l "$OUTPUT_FILE" 등으로 추가된 라인 수 확인 가능.
echo "-> IP 주소가 추출되어 문자열 형식으로 변환 및 추가되었습니다."
else
echo "-> 유효한 Wordfence 차단 테이블을 찾을 수 없거나 SQL 쿼리가 설정되지 않았습니다. 추출할 IP가 없습니다."
fi
echo # 빈 줄 추가
done # 모든 BLOG_DIRS 순회 완료
# ------------------------------------------------------------------------------
# 수집된 IP 목록 후처리 (정렬, 중복 제거, 빈 줄 제거)
# ------------------------------------------------------------------------------
echo "====================================================================="
echo "모든 사이트에서 IP 수집 완료."
echo "이제 수집된 IP 목록을 정렬하고 중복을 제거합니다..."
# 1. 임시 파일($OUTPUT_FILE)의 내용을 읽어서 처리:
# - `grep -v '^$'` : 빈 줄을 모두 제거합니다. (^는 줄의 시작, $는 줄의 끝을 의미)
# - `sort -u` : IP 주소를 기준으로 정렬(-n은 숫자식 정렬 시도하고,
# 고유한(unique, -u) 값만 남깁니다. (중복 제거)
# 2. 처리된 결과를 최종 마스터 차단 목록 파일($FINAL_LIST)에 저장합니다.
cat "$OUTPUT_FILE" | grep -v '^$' | sort -u -n > "$FINAL_LIST"
echo "-> 정렬 및 중복 제거 완료."
# ------------------------------------------------------------------------------
# 정리 및 결과 출력
# ------------------------------------------------------------------------------
# 임시 파일 삭제
rm "$OUTPUT_FILE"
echo "-> 임시 파일($OUTPUT_FILE) 삭제 완료."
# 최종 생성된 마스터 차단 목록의 IP 개수 확인
# `wc -l < "$FINAL_LIST"`는 파일의 라인 수를 계산합니다. (IP 하나당 한 줄)
IP_COUNT=$(wc -l < "$FINAL_LIST")
echo "====================================================================="
echo "스크립트 처리 완료!"
echo "발견된 고유 차단 IP 총 개수: $IP_COUNT"
echo "마스터 차단 목록 파일 위치: $FINAL_LIST"
echo "====================================================================="
코드 해설 타임! 🔍 (주요 부분 다시 짚어보기!)
BLOG_DIRS=("/var/www/wordpress1" "/var/www/wordpress2")
: 이 부분이 가장 중요해요! 여기에 여러분이 관리하는 워드프레스 사이트들의 최상위 폴더 경로를 정확하게 적어주셔야 해요. 여러 개라면 공백으로 구분해서 넣어주세요.OUTPUT_FILE
/FINAL_LIST
: 스크립트가 실행되면서 생성될 임시 파일과 최종 결과 파일의 경로예요. 이 경로에 파일을 생성할 수 있는 권한이 있는지, 또는 스크립트 실행 전에 해당 폴더(wf-ip-aggr
)를 미리 만들어두시는 것이 좋아요.wp core is-installed
,wp plugin is-active wordfence
: WP-CLI를 사용해서 해당 경로가 정말 워드프레스 설치 경로인지, 그리고 Wordfence 플러그인이 활성화되어 있는지 꼼꼼하게 확인해요.PREFIX=$(wp db prefix ...)
: 각 워드프레스 사이트마다 데이터베이스 테이블 접두사(예:wp_
,myblog_
등)가 다를 수 있기 때문에, WP-CLI로 정확한 접두사를 가져와서 Wordfence 테이블 이름을 완성해요.BLOCKS_TABLE_V7="${PREFIX}wfblocks7"
: Wordfence 최신 버전(7.x 이후)은 차단된 IP 정보를[접두사]wfblocks7
테이블에 저장해요. 이 테이블을 대상으로 쿼리를 실행한답니다.- IP 주소 형식 변환의 마법! ✨:
wfblocks7
테이블의IP
컬럼은 바이너리(VARBINARY) 형태로 IPv4와 IPv6 주소를 모두 저장해요. 그래서 SQL 쿼리 안에서CASE WHEN LENGTH(IP) = 4 THEN INET_NTOA(IP) ... ELSE UCASE(INET6_NTOA(IP)) END
와 같은 로직을 사용해서, 이 바이너리 IP 주소를 우리가 읽을 수 있는 익숙한 문자열 형태(예:192.168.1.1
또는2001:DB8::1
)로 예쁘게 변환해준답니다! 특히 IPv4로 매핑된 IPv6 주소(::ffff:192.168.1.1
같은 형태)에서 IPv4 부분만 쏙 뽑아내는SUBSTRING_INDEX
함수 활용도 정말 똑똑하죠? 😉
- IP 주소 형식 변환의 마법! ✨:
WHERE type = 1
: Wordfence는 차단 유형을 숫자로 구분하는데,type = 1
은 ‘영구적으로 차단된 IP‘를 의미해요. 이 조건으로 꼭 필요한 IP만 걸러낸답니다.cat "$OUTPUT_FILE" | grep -v '^$' | sort -u -n > "$FINAL_LIST"
: 모든 사이트에서 IP를 모은 후, 이 명령어로 빈 줄은 싹 없애고, IP 주소를 기준으로 정렬한 다음, 중복된 IP는 하나만 남겨서 아주 깔끔한 최종 목록을 만들어요!sort -u
는 정말 강력한 조합이죠! 👍
🚀 스크립트 실행 및 활용 아이디어!
- 스크립트 저장 및 실행 권한 부여:
- 위 코드를
wf_collect_ips.sh
같은 이름으로 서버에 저장하세요. chmod +x wf_collect_ips.sh
명령어로 실행 권한을 주세요.
- 위 코드를
- 스크립트 실행:
- 터미널에서
./wf_collect_ips.sh
명령어로 스크립트를 실행하세요. - 실행 결과로
FINAL_LIST
에 지정된 경로에master_blocklist.txt
파일이 생성되고, 그 안에 중복 없이 정리된 차단 IP 목록이 담겨 있을 거예요!
- 터미널에서
- 활용 아이디어 💡:
- 서버 방화벽에 자동 등록: 이
master_blocklist.txt
파일을 주기적으로 읽어서 서버 방화벽(iptables, firewalld, ufw 등)에 자동으로 차단 규칙을 추가하는 또 다른 스크립트를 만들 수 있어요! 이렇게 하면 개별 워드프레스 사이트뿐만 아니라 서버 전체 수준에서 악성 IP를 막을 수 있겠죠? (이건 정말 고급 활용법이랍니다! 😉) - 보안 모니터링: 어떤 IP들이 주로 차단되는지 분석해서 공격 패턴을 파악하거나, 특정 국가/지역에서의 공격이 많은지 등을 확인하는 데 활용할 수 있어요.
- 다른 보안 도구와 연동: 만약 다른 통합 보안 솔루션(SIEM 등)을 사용하고 있다면, 이 IP 목록을 해당 솔루션에 입력 데이터로 제공할 수도 있답니다.
- 서버 방화벽에 자동 등록: 이
마무리: 자동화로 더 스마트한 보안 관리! 🤖🛡️
오늘은 여러 워드프레스 사이트에서 Wordfence가 차단한 IP 주소를 자동으로 수집하고 통합하는 강력한 Bash 스크립트에 대해 알아봤어요. 처음에는 조금 복잡해 보일 수 있지만, 한번 설정해두면 정말 편리하게 여러 사이트의 보안 정보를 통합 관리할 수 있답니다! 😊 특히 서버 운영에 익숙하신 분들이라면, 이 스크립트를 기반으로 더욱 다양한 자동화 아이디어를 구현해 볼 수 있을 거예요!
보안은 끊임없는 관심과 노력이 필요한 분야지만, 이렇게 스마트한 도구들을 활용하면 훨씬 효율적으로 대처할 수 있다는 점, 잊지 마세요! 💪
혹시 이 스크립트를 사용해보시면서 궁금한 점이나 더 좋은 아이디어가 있다면 언제든지 댓글로 공유해주세요! 함께 지식을 나누면 더욱 강력한 보안 커뮤니티를 만들 수 있을 거예요! 👇
오늘 이 고급 팁이 여러분의 워드프레스 보안 여정에 큰 도움이 되었기를 바라며, 다음에 또 유용하고 흥미로운 정보로 찾아올게요! 그때까지 안전한 웹 생활하세요! 안녕! 👋