Nginx 봇 차단 설정
실제 서버에서 탐지된 공격 패턴을 기반으로 작성한 Nginx 차단 설정이다.
응답을 주지 않고 즉시 연결을 끊는 444와 오류 페이지를 반환하는 403을 상황에 맞게 사용한다.
return 444 vs return 403
| 코드 | 동작 | 사용 상황 |
|---|---|---|
444 | 응답 없이 TCP 연결 즉시 종료 | 자동화 봇, RCE 탐색, 스캐너 — 응답 자체를 주지 않아 공격자가 서버 존재를 확인하기 어렵게 함 |
403 | Forbidden 응답 반환 | 실수로 접근할 수 있는 정상 사용자가 있을 경우 — 이유를 알려주는 것이 적절한 경우 |
봇/스캐너에는 444가 권장된다. 응답을 보내지 않으므로 재시도 유발 가능성이 낮다.
설정 파일 구조
차단 규칙은 별도 파일로 분리해서 각 server 블록에 include하는 방식이 유지보수에 유리하다.
/etc/nginx/
├── nginx.conf
├── conf.d/
│ └── your-site.conf ← server 블록
└── snippets/
└── bot-blocking.conf ← 차단 규칙 (include 대상)
bot-blocking.conf 전체 설정
# /etc/nginx/snippets/bot-blocking.conf
# ────────────────────────────────────────────
# 1. PHP / phpunit RCE 탐색 차단
# ────────────────────────────────────────────
# eval-stdin.php, /vendor/phpunit 등 PHP 원격 코드 실행 취약점 스캐너 차단
location ~* "(eval-stdin\.php|/vendor/phpunit|php-cgi|php\.cgi)" {
return 444;
}
# ────────────────────────────────────────────
# 2. Path Traversal 차단
# ────────────────────────────────────────────
# URL 인코딩된 ../ 시퀀스로 상위 디렉토리에 접근하는 시도 차단
location ~* "(%2e%2e|%252e%252e|\.\.%2f|%2f\.\.)" {
return 444;
}
# ────────────────────────────────────────────
# 3. 민감 파일 노출 차단
# ────────────────────────────────────────────
# .env, .git 등 설정 파일이 웹으로 노출되는 것 차단
location ~* "(\.env|\.git|\.htaccess|\.htpasswd|\.DS_Store|web\.config)" {
return 444;
}
# ────────────────────────────────────────────
# 4. CGI 쉘 탐색 차단
# ────────────────────────────────────────────
# /cgi-bin/ 경로를 통한 쉘 스크립트 실행 시도 차단
location ~* "^/cgi-bin/" {
return 444;
}
# ────────────────────────────────────────────
# 5. Tomcat Manager / Docker API 탐색 차단
# ────────────────────────────────────────────
# 관리자 콘솔 및 Docker 원격 API 스캔 차단
location ~* "^/(manager/html|host-manager|containers/json|v\d+\.\d+/containers)" {
return 444;
}
# ────────────────────────────────────────────
# 6. ThinkPHP / Laravel RCE 쿼리 차단
# ────────────────────────────────────────────
# PHP 프레임워크 원격 코드 실행 취약점 악용 시도 차단
# 쿼리스트링에 포함되는 패턴이므로 $request_uri 기준으로 검사
if ($request_uri ~* "(invokefunction|call_user_func_array|s=index/think)") {
return 444;
}
# ────────────────────────────────────────────
# 7. WordPress 경로 차단
# ────────────────────────────────────────────
# WordPress 미사용 서버에서 wp-admin, xmlrpc.php 스캔 차단
location ~* "^/(wp-admin|wp-login\.php|xmlrpc\.php|wp-content|wp-includes)" {
return 444;
}
# ────────────────────────────────────────────
# 8. 악성 User-Agent 차단
# ────────────────────────────────────────────
# 알려진 취약점 스캐너, 크롤러 차단
map $http_user_agent $blocked_agent {
default 0;
~*masscan 1;
~*nikto 1;
~*sqlmap 1;
~*nmap 1;
~*zgrab 1;
~*python-httpx 1;
~*go-http-client 1;
}
map블록은http { }컨텍스트에 있어야 하므로nginx.conf또는conf.d/내 별도 map 파일에 작성하고,server블록에서if ($blocked_agent) { return 444; }로 사용한다.
server 블록에 적용
# /etc/nginx/conf.d/your-site.conf
# map은 http 블록에 선언 (nginx.conf 또는 별도 파일)
map $http_user_agent $blocked_agent {
default 0;
~*masscan 1;
~*nikto 1;
~*sqlmap 1;
~*nmap 1;
~*zgrab 1;
~*python-httpx 1;
~*go-http-client 1;
}
server {
listen 443 ssl;
server_name example.com;
# 봇 차단 규칙 포함
include /etc/nginx/snippets/bot-blocking.conf;
# User-Agent 차단 적용
if ($blocked_agent) {
return 444;
}
location / {
proxy_pass http://127.0.0.1:8080;
}
}
적용 방법
# 설정 문법 검사
sudo nginx -t
# 재시작 없이 설정 반영
sudo nginx -s reload
차단 로그 확인
# 444 응답 발생 확인
sudo grep ' 444 ' /var/log/nginx/access.log | tail -20
# 특정 IP의 요청 패턴 확인
sudo grep '공격자IP' /var/log/nginx/access.log