접근 제어: IP 화이트리스트·블랙리스트와 국가 차단
웹 서버에서 IP 기반 접근 제어는 가장 기초적이면서도 효과적인 보안 수단입니다. 관리자 페이지는 사무실 IP만, 국가별 서비스 제한, 악성 봇 차단까지 다양한 시나리오를 Nginx와 Apache로 구현합니다.
Nginx IP 기반 접근 제어
allow / deny 지시어
# 특정 경로에만 접근 제한
location /admin/ {
# 허용할 IP (순서대로 평가)
allow 192.168.1.0/24; # 내부 네트워크
allow 203.0.113.10; # 사무실 고정 IP
allow 127.0.0.1; # 로컬호스트
# 나머지 모두 차단
deny all;
proxy_pass http://backend;
}
# 특정 IP를 블랙리스트로 차단
location / {
deny 198.51.100.0/24; # 악성 IP 대역
deny 203.0.113.99; # 특정 공격자 IP
allow all; # 나머지는 허용
proxy_pass http://backend;
}
전역 IP 차단 (http 블록)
http {
# geo 모듈로 IP 목록 관리
geo $blocked_ip {
default 0;
198.51.100.0/24 1; # 알려진 봇넷 대역
203.0.113.99 1; # 특정 공격자
10.0.0.0/8 0; # 내부 망 허용 유지
}
server {
if ($blocked_ip) {
return 403;
}
}
}
Nginx geo 모듈 — 국가별 접근 제어
ngx_http_geoip2_module과 MaxMind GeoIP2 데이터베이스를 사용합니다.
# MaxMind GeoIP2 데이터베이스 다운로드 (무료 계정 필요)
# https://www.maxmind.com/en/geolite2/signup
# Ubuntu에서 자동 업데이트 설정
sudo apt install mmdb-bin geoipupdate
# /etc/GeoIP.conf
AccountID YOUR_ACCOUNT_ID
LicenseKey YOUR_LICENSE_KEY
EditionIDs GeoLite2-Country GeoLite2-City
sudo geoipupdate # 데이터베이스 다운로드
# /var/lib/GeoIP/GeoLite2-Country.mmdb 생성됨
# ngx_http_geoip2_module 설치 (Ubuntu)
sudo apt install libnginx-mod-http-geoip2
# /etc/nginx/nginx.conf — http 블록
# GeoIP2 데이터베이스 경로
geoip2 /var/lib/GeoIP/GeoLite2-Country.mmdb {
$geoip2_country_code country iso_code;
}
# 허용할 국가 코드 목록
map $geoip2_country_code $allowed_country {
default 0; # 기본: 차단
KR 1; # 한국 허용
US 1; # 미국 허용
JP 1; # 일본 허용
}
server {
location / {
# 허용 국가가 아니면 403
if ($allowed_country = 0) {
return 403 "Access denied from your country.";
}
proxy_pass http://backend;
}
}
화이트리스트 전략 (내부 서비스 보호)
관리자 패널, 모니터링 대시보드, 내부 API는 화이트리스트로 철저히 보호합니다.
# 관리자 페이지: 특정 IP만 허용
location /admin {
satisfy all; # allow와 인증 모두 통과해야 접근
allow 10.0.0.0/8; # 내부망
allow 203.0.113.0/24; # VPN 대역
deny all;
auth_basic "Admin Area";
auth_basic_user_file /etc/nginx/.htpasswd;
proxy_pass http://backend;
}
# 모니터링 엔드포인트: 내부망만 허용
location /actuator {
allow 127.0.0.1;
allow 10.0.0.0/8;
deny all;
proxy_pass http://backend;
}
# 정적 파일 업로드 디렉토리: PHP/스크립트 실행 방지
location /uploads/ {
# 스크립트 타입 요청 차단
location ~* \.(php|py|sh|pl|rb|jsp)$ {
deny all;
}
alias /var/www/uploads/;
}
Apache 접근 제어
Require 지시어 (Apache 2.4+)
# /etc/apache2/sites-available/admin.conf
<Location "/admin">
# 특정 IP만 허용
<RequireAny>
Require ip 192.168.1.0/24
Require ip 203.0.113.10
Require ip 127.0.0.1
</RequireAny>
</Location>
# IP 차단 (블랙리스트)
<Location "/">
<RequireAll>
Require all granted
Require not ip 198.51.100.0/24
Require not ip 203.0.113.99
</RequireAll>
</Location>
mod_geoip2로 국가 차단
sudo apt install libapache2-mod-geoip
sudo a2enmod geoip
# /etc/apache2/conf-available/geoip.conf
GeoIPEnable On
GeoIPDBFile /var/lib/GeoIP/GeoLite2-Country.mmdb
<Location "/">
# 한국, 미국, 일본만 허용
SetEnvIf GEOIP_COUNTRY_CODE KR AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE US AllowCountry
SetEnvIf GEOIP_COUNTRY_CODE JP AllowCountry
<RequireAny>
Require env AllowCountry
Require ip 127.0.0.1 # 로컬은 항상 허용
</RequireAny>
</Location>
동적 IP 차단 자동화
로그를 분석해 공격 IP를 자동으로 차단합니다.
#!/bin/bash
# /usr/local/bin/auto-ban.sh
# 1분간 100회 이상 요청한 IP 차단
LOG="/var/log/nginx/access.log"
THRESHOLD=100
PERIOD=60 # 초
# 최근 1분 로그에서 IP별 요청 수 집계
awk -v since="$(date -d "$PERIOD seconds ago" '+%d/%b/%Y:%H:%M:%S')" \
'$4 > "["since' "$LOG" | \
awk '{print $1}' | sort | uniq -c | sort -rn | \
awk -v threshold="$THRESHOLD" '$1 >= threshold {print $2}' | \
while read ip; do
# iptables로 즉시 차단
iptables -I INPUT -s "$ip" -j DROP
echo "$(date): Banned $ip (exceeded $THRESHOLD req/min)" >> /var/log/auto-ban.log
done
# cron으로 1분마다 실행
* * * * * /usr/local/bin/auto-ban.sh
# fail2ban 사용 시 더 정교한 자동 차단 가능
sudo apt install fail2ban
접근 제어 검증
# 허용 IP에서 접근 확인
curl -I https://example.com/admin/
# HTTP/2 200
# 차단 IP에서 접근 시뮬레이션 (X-Forwarded-For 헤더)
curl -H "X-Forwarded-For: 198.51.100.1" https://example.com/
# HTTP/2 403
# Nginx 설정 확인
sudo nginx -t && sudo systemctl reload nginx
# 국가별 차단 확인
curl -H "X-Forwarded-For: 1.1.1.1" https://example.com/
# $geoip2_country_code 확인 필요