새 웹 서버는 온라인에 올라간 지 몇 분 안에 스캔을 당합니다. 기본 사항만 지켰다면 그 트래픽 대부분은 자동화되어 있고 해롭지 않습니다. 이 가이드는 15분 보안 강화에서 한 걸음 더 나아가 방화벽, fail2ban을 이용한 브루트 포스 방어, 더 안전한 Nginx 설정을 다룹니다.
1단계: UFW로 기본 차단 방화벽 설정
필요한 것만 허용하고 나머지는 차단하세요. 본인이 접속하지 못하게 되는 일이 없도록 SSH를 먼저 추가하세요.
sudo ufw default deny incoming
sudo ufw default allow outgoing
sudo ufw allow OpenSSH
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp
sudo ufw enable
sudo ufw status verbose
표준이 아닌 SSH 포트를 사용한다면 OpenSSH 대신 그 포트를 허용하세요.
2단계: 반복 실패에 대한 fail2ban
fail2ban은 로그를 감시하고 로그인에 계속 실패하는 IP 주소를 차단합니다.
sudo apt install -y fail2ban
sudo tee /etc/fail2ban/jail.local > /dev/null <<'CONF'
[DEFAULT]
bantime = 1h
findtime = 10m
maxretry = 5
[sshd]
enabled = true
[nginx-http-auth]
enabled = true
[nginx-botsearch]
enabled = true
CONF
sudo systemctl enable --now fail2ban
sudo fail2ban-client status sshd
SSH 키를 사용하고 비밀번호 로그인도 끄세요. SSH 키 설명을 참고하세요.
3단계: Nginx 버전 숨기기 및 안전한 헤더 추가
/etc/nginx/nginx.conf의 http 블록 안에서:
server_tokens off;
사이트의 server 블록에서:
add_header X-Content-Type-Options "nosniff" always;
add_header X-Frame-Options "SAMEORIGIN" always;
add_header Referrer-Policy "strict-origin-when-cross-origin" always;
add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;
도메인과 사용하는 모든 하위 도메인에서 HTTPS가 동작할 때만 HSTS 헤더를 추가하세요.
4단계: 악의적인 요청 제한
요청 제한은 로그인 페이지에 대한 브루트 포스 시도를 늦춥니다.
# in the http block
limit_req_zone $binary_remote_addr zone=login:10m rate=5r/m;
# in your server block
location = /wp-login.php {
limit_req zone=login burst=5 nodelay;
# ...your usual PHP handling
}
sudo nginx -t && sudo systemctl reload nginx로 테스트하고 적용하세요.
5단계: 최신 상태 유지
sudo apt install -y unattended-upgrades
sudo dpkg-reconfigure --priority=low unattended-upgrades
자동 보안 업데이트는 직접 하지 않아도 알려진 취약점을 막아 줍니다.
지켜봐야 할 것
sudo fail2ban-client status sshd로 차단 상태를 확인하세요.- 가끔
/var/log/nginx/error.log를 검토하세요. - 프록시나 CDN 뒤에 있다면 fail2ban이 실제 클라이언트 IP를 읽는지 확인하세요. 그렇지 않으면 자신의 프록시를 차단할 수 있습니다.