티스토리 뷰
"개발용으로 셋팅하는데 귀찮으니 안해야지"
라는 생각을 가지면 오만임.
운영레벨로 승격하지 않은 개발이나 스테이징 서버에서
알수없는 트래픽과 CPU 스파이크를 경험하게 될 것이고
웹서버 액세스 로그를 보면
해킹 스캔 기록이 엄청나게 발생하는것을 목도하게 될 것.
Ubuntu OS 기반에 Nginx 웹서버 선택하여 진행함.
설정 요소들
Nginx 웹서버, WAF, UFW 방화벽, Fail2Ban, Ubuntu 자동 업데이트
Nginx 가상호스트 설정
http {
#......
# Declare 단일 클라이언트 ip 주소의 모든 페이지에 대해 1초에 5건의 요청 처리로 제한
limit_req_zone $binary_remote_addr zone=badbot:10m rate=10r/s;
limit_req_status 444;
# Declare 각 클라이언트 IP 주소의 모든 페이지에 대해 동시 연결 제한
## 10m == 10MB의 메모리를 할당하여 대략 16만 개의 IP 주소 저장
limit_conn_zone $binary_remote_addr zone=ddos:10m;
server {
listen 80;
listen [::]:80;
server_name _;
# https://github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker
# 참고하여 include "nginx-ultimate-bad-bot-blocker.conf"
# request method 제한
add_header Allow "GET, POST, HEAD" always;
if ( $request_method !~ ^(GET|POST|HEAD|PUT|PATCH)$ ) { return 405; }
# Limit the size of POST requests
client_max_body_size 1M;
# Timeout settings defend Slowloris attack
client_body_timeout 12s;
client_header_timeout 12s;
keepalive_timeout 5s 5s;
send_timeout 10s;
location / {
#......
# limit_req_zone 선언 사용
## burst: 초과 허용량 설정. 초과 요청이 즉시 거부되지 않고 대기열에 들어간 다음 지정된 요청 비율에 따라 처리될 수 있음을 의미
## nodelay: 선언시 초과 요청들은 지정된 비율에 따라 대기열에 들어가지 않고 즉시 처리. burst 값 이내의 요청은 추가 지연 없이 처리
limit_req zone=badbot burst=5 nodelay;
# 각 클라이언트 IP 주소의 모든 페이지에 대해 동시 10개 이하의 연결만 열도록 제한
limit_conn ddos 10;
#......
}
location /admin {
# 관리자 IP만 접속 허용
allow xxx.xxx.xxx.xxx/32;
allow 192.168.1.0/24;
deny all;
#......
}
#......
}
}
Nginx ultimate bad bot blocker
https://github.com/mitchellkrogza/nginx-ultimate-bad-bot-blocker
IP 차단 자동화
Fail2ban
- 지정한 기간동안 IP 차단 자동화
- 차단시 iptables 사용하니 셋팅 되어 있어야 함.
- ubuntu는 ufw 사용하는게 제어가 쉬움
- ufw는 명령어가 쉽도록 간략화한 iptables wrapper cli repl
Fail2ban 설치
sudo apt update && \
sudo apt install -y ufw fail2ban && \
sudo systemctl start fail2ban && \
sudo systemctl enable fail2ban && \
sudo systemctl status fail2ban --no-pager --full && \
sudo cp /etc/fail2ban/jail.conf /etc/fail2ban/jail.local && \
sudo vi /etc/fail2ban/jail.local
[DEFAULT]
ignoreip = 127.0.0.1/8 ::1 172.16.0.0/12 192.168.0.0/16 xxx.xxx.xxx.xxx/32
bantime = 7d
findtime = 1d
maxretry = 2
banaction = ufw
banaction_allports = ufw
sudo systemctl restart fail2ban && \
sudo fail2ban-client status
sudo ufw default deny incoming && \
sudo ufw default allow outgoing && \
sudo ufw allow in 80/tcp && \
sudo ufw allow in 443/tcp && \
sudo ufw allow out 80/tcp && \
sudo ufw allow out 443/tcp && \
sudo ufw allow in 22/tcp && \
sudo ufw limit 22/tcp comment 'Allow 6 connections over 30 seconds' && \
sudo ufw allow out 53/udp && \
sudo ufw allow out 25/tcp && \
sudo ufw enable && \
sudo ufw status verbose
sudo ufw delete allow in 22/tcp && \
sudo ufw allow from 192.168.0.0/16 to any port 22 proto tcp
sudo vi /etc/rsyslog.d/20-ufw.conf
# Log kernel generated UFW log messages to file
:msg,contains,"[UFW " /var/log/ufw.log
# Uncomment the following to stop logging anything that matches the last rule.
# Doing this will stop logging kernel generated UFW log messages to the file
# normally containing kern.* messages (eg, /var/log/kern.log)
& stop
sudo touch /var/log/ufw.log && \
sudo chown syslog:adm /var/log/ufw.log && \
sudo chmod o-r /var/log/ufw.log && \
sudo systemctl restart rsyslog
sudo ls -alt /etc/fail2ban/filter.d/nginx*
sudo bash -c 'cat > /etc/fail2ban/filter.d/nginx-sslerror.conf <<EOF
[Definition]
failregex = SSL_do_handshake\(\) failed .+ while SSL handshaking, client: <HOST>, server: .+
ignoreregex =
datepattern = {^LN-BEG}%%ExY(?P<_sep>[-/.])%%m(?P=_sep)%%d[T ]%%H:%%M:%%S(?:[.,]%%f)?(?:\s*%%z)?
^[^\[]*\[({DATE})
{^LN-BEG}
EOF' && \
sudo bash -c 'cat > /etc/fail2ban/filter.d/nginx-4xx.conf <<EOF
[Definition]
failregex = ^<HOST>.*"(GET|POST).*" (404|444|403|400) .*$
ignoreregex = .*(robots.txt|favicon.ico|jpg|png)
EOF' && \
sudo bash -c 'cat > /etc/fail2ban/filter.d/nginx-forbidden.conf <<EOF
[Definition]
failregex = directory index of .+ is forbidden, client: <HOST>, server: .+
ignoreregex =
EOF' && \
sudo bash -c 'cat > /etc/fail2ban/filter.d/ufw.conf <<EOF
[Definition]
failregex = [UFW BLOCK].+SRC=<HOST> DST
ignoreregex =
EOF'
sudo bash -c 'cat > /etc/fail2ban/jail.d/custom.conf <<EOF
[sshd]
enabled = true
[nginx-4xx]
enabled = true
port = http,https
filter = nginx-4xx
logpath = %(nginx_access_log)s
[nginx-http-auth]
enabled = true
port = http,https
filter = nginx-http-auth
logpath = %(nginx_access_log)s
[nginx-botsearch]
enabled = true
port = http,https
filter = nginx-botsearch
logpath = %(nginx_access_log)s
[nginx-forbidden]
enabled = true
port = http,https
filter = nginx-forbidden
logpath = %(nginx_access_log)s
[nginx-sslerror]
enabled = false
port = http,https
filter = nginx-sslerror
logpath = %(nginx_access_log)s
[ufw]
enabled = true
filter = ufw
logpath = /var/log/ufw.log
EOF'
sudo systemctl restart fail2ban && \
sudo systemctl status fail2ban --no-pager --full && \
sudo fail2ban-client status
cd ~ && \
vi fail2ban-status.sh
#!/usr/bin/env bash
for jail in $(sudo fail2ban-client status | grep 'Jail list:' | sed 's/.*://;s/,//g'); do
echo "Jail: $jail";
sudo fail2ban-client status $jail | grep 'Banned IP';
done
chmod +x fail2ban-status.sh && \
./fail2ban-status.sh
리눅스 자동 업데이트
sudo apt install -y unattended-upgrades && \
sudo dpkg-reconfigure --priority=low unattended-upgrades && \
sudo systemctl status unattended-upgrades --no-pager --full
Confirm 선택 화면 뜨면 YES 선택
참고자료
- https://scalastic.io/en/ufw-fail2ban-nginx/
- https://mytory.net/archives/13142
- https://linuxhandbook.com/ufw-logs/
- https://blog.fernvenue.com/archives/ufw-with-fail2ban/
- /var/log/ufw.log 나중에 생기는 문제 예방 가이드
- /etc/fail2ban/filter.d/ufw.conf 없어서 발생하는 경고 해결 가이드
- https://gist.github.com/bartosjiri/f7e2e6a6c8890be7f5992470ac4c9350
- https://webdock.io/en/docs/how-guides/security-guides/configuring-ufw-and-fail2ban-mitigate-basic-ddos-attacks
'보안' 카테고리의 다른 글
CrowdSec 방화벽 다중 서버 셋팅 (2) | 2025.06.09 |
---|---|
Nginx + 무료 웹방화벽 Modsecurity 3.x 조합 Docker 셋팅 (0) | 2025.05.29 |
Nginx 무료 에디션 위한 무료 WAF(웹방화벽) (1) | 2025.05.29 |
댓글
최근에 올라온 글
최근에 달린 댓글
- Total
- Today
- Yesterday
TAG
- Wordpress
- nginx
- classic asp
- 안드로이드
- 워드프레스
- Mac
- git
- IOS
- laravel
- API
- nodejs
- Docker
- iis
- iphone
- Android
- Debug
- centos
- ASP
- javascript
- sencha touch
- macos
- PHP
- JSON
- mssql
- JQuery
- CSS
- 한글
- Prototype
- IE
- Linux
일 | 월 | 화 | 수 | 목 | 금 | 토 |
---|---|---|---|---|---|---|
1 | 2 | 3 | 4 | 5 | ||
6 | 7 | 8 | 9 | 10 | 11 | 12 |
13 | 14 | 15 | 16 | 17 | 18 | 19 |
20 | 21 | 22 | 23 | 24 | 25 | 26 |
27 | 28 | 29 | 30 | 31 |
글 보관함