Nginx 보안 모범 사례: 웹 서버 보호하기
오늘날의 디지털 환경에서 웹 서버의 보안은 무엇보다 중요합니다. 고성능 웹 서버이자 리버스 프록시인 Nginx는 많은 애플리케이션에서 널리 사용됩니다. 그러나 다른 소프트웨어와 마찬가지로 다양한 위협으로부터 보호하기 위해서는 세심한 구성과 유지 관리가 필요합니다. 이 글에서는 SSL/TLS 구성, 속도 제한, 일반적인 공격 방지, 그리고 Nginx 설치를 최신 상태로 유지하는 것의 중요성을 포함하여 필수적인 Nginx 보안 모범 사례를 설명합니다.
이러한 조치를 구현하면 Nginx 서버의 복원력이 크게 향상되어 데이터, 사용자 및 명성을 보호할 수 있습니다.
1. SSL/TLS를 사용하여 연결 보안 강화
SSL/TLS(Secure Sockets Layer/Transport Layer Security)는 서버와 클라이언트 간의 통신을 암호화하여 도청 및 중간자 공격을 방지하는 데 필수적입니다. SSL/TLS를 올바르게 구성하는 것은 웹 서버 보안의 초석입니다.
1.1 SSL 인증서 획득 및 설치
먼저 SSL 인증서가 필요합니다. Let's Encrypt(무료 인증서 제공), Comodo, DigiCert 등 신뢰할 수 있는 인증 기관(CA)에서 획득할 수 있습니다. 획득하면 일반적으로 인증서 파일(예: your_domain.crt, private.key, 그리고 잠재적으로 중간 인증서)을 받게 됩니다.
1.2 SSL/TLS용 Nginx 구성
Nginx 서버 블록 구성 파일(일반적으로 /etc/nginx/sites-available/ 또는 /etc/nginx/conf.d/에 위치)을 편집하세요. HTTPS 트래픽을 위해 포트 443에서 수신하는 서버 블록이 있는지 확인하세요.
server {
listen 443 ssl http2;
listen [::]:443 ssl http2;
server_name your_domain.com www.your_domain.com;
ssl_certificate /etc/letsencrypt/live/your_domain.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/your_domain.com/privkey.pem;
# Include recommended SSL parameters
include /etc/nginx/snippets/ssl-params.conf;
# ... other configurations (root, location blocks, etc.)
}
server {
listen 80;
listen [::]:80;
server_name your_domain.com www.your_domain.com;
# Redirect HTTP to HTTPS
return 301 https://$host$request_uri;
}
1.2.1 강화된 보안을 위한 SSL 매개변수
SSL 구성을 더욱 강화하려면 강력한 SSL 매개변수를 정의하는 것이 중요합니다. 이 설정을 위해 별도의 파일(예: /etc/nginx/snippets/ssl-params.conf)을 만들 수 있습니다.
# /etc/nginx/snippets/ssl-params.conf
# Prefer strong ciphers and protocols
ssl_protocols TLSv1.2 TLSv1.3;
ssl_prefer_server_ciphers on;
ssl_ciphers ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384;
# Enable HSTS (HTTP Strict Transport Security)
# Add includeSubDomains if applicable
add_header Strict-Transport-Security "max-age=63072000; includeSubDomains; preload" always;
# Enable OCSP Stapling for faster certificate checks
ssl_stapling on;
ssl_stapling_verify on;
resolver 8.8.8.8 8.8.4.4 valid=300s;
resolver_timeout 5s;
# Diffie-Hellman parameters (generate a strong one if needed)
# ssl_dhparam /etc/nginx/ssl/dhparams.pem;
# Session Caching
ssl_session_cache shared:SSL:10m;
ssl_session_timeout 10m;
ssl_session_tickets off;
- 팁: SSL Labs의 SSL 테스트와 같은 온라인 도구를 사용하여 SSL/TLS 구성을 분석하고 개선이 필요한 부분을 파악하세요.
- 경고: SSLv3 및 TLSv1.0/1.1과 같이 알려진 취약점이 있는 오래된 프로토콜은 사용하지 마세요.
2. 속도 제한 구현
속도 제한은 무차별 대입 공격, 서비스 거부(DoS) 공격으로부터 서버를 보호하고 개별 사용자가 리소스를 과도하게 사용하는 것을 방지하는 중요한 기술입니다.
2.1 기본 속도 제한 예시
Nginx는 이 목적을 위해 limit_req_zone 및 limit_req 지시문을 제공합니다. limit_req_zone은 요청 상태를 저장하는 공유 메모리 영역을 정의하고, limit_req는 이 제한을 특정 위치에 적용합니다.
http {
# Define a rate limiting zone for IP addresses
# 'burst=10' allows up to 10 requests to be queued if the rate is exceeded
# 'nodelay' means requests exceeding the rate are rejected immediately
limit_req_zone $binary_remote_addr zone=mylimit:10m rate=5r/s;
server {
# ...
location /login {
limit_req zone=mylimit burst=10 nodelay;
# ... your login handler configuration
}
location / {
limit_req zone=mylimit burst=20 nodelay;
# ... your main site configuration
}
}
}
이 예시에서:
* $binary_remote_addr는 클라이언트의 IP 주소를 속도 제한을 위한 키로 사용합니다.
* zone=mylimit:10m은 10MB 크기의 mylimit이라는 공유 메모리 영역을 정의합니다.
* rate=5r/s는 최대 평균 속도를 초당 5개 요청으로 설정합니다.
* burst=10은 속도 제한을 적용하기 전에 10개 요청의 버스트를 허용합니다.
* nodelay는 초과 요청이 지연되지 않고 즉시 거부되도록 합니다.
- 팁: 로그인 페이지 또는 API 엔드포인트와 같이 민감한 영역에는 더 강력한 속도 제한을 적용하세요.
- 경고: 잘못 구성된 속도 제한은 합법적인 사용자를 의도치 않게 차단할 수 있습니다. 철저히 테스트하세요.
3. 일반적인 공격 방지
Nginx는 다양한 일반적인 웹 공격을 완화하도록 구성할 수 있습니다.
3.1 크로스 사이트 스크립팅(XSS) 및 SQL 인젝션 방어
Nginx는 웹 애플리케이션 방화벽(WAF)은 아니지만, 패턴 기반으로 악성 요청을 필터링할 수 있습니다. ngx_http_security_headers_module과 같은 모듈과 사용자 정의 location 블록을 사용할 수 있습니다.
3.1.1 보안 헤더
보안 헤더를 삽입하면 일반적인 공격으로부터 사용자를 보호하는 데 도움이 됩니다. 다음을 서버 구성에 추가하세요:
add_header X-Frame-Options "SAMEORIGIN";
add_header X-Content-Type-Options "nosniff";
add_header X-XSS-Protection "1; mode=block";
add_header Referrer-Policy "strict-origin-when-cross-origin";
3.1.2 악성 패턴 차단
더 고급 필터링을 위해서는 map을 사용하여 의심스러운 패턴을 포함하는 요청을 차단할 수 있습니다. 이것은 기본적인 예시이며 전용 WAF를 대체하지는 않습니다.
http {
# Define a map for blocking bad bots/scanners
map $http_user_agent $bad_bot {
default 0;
"~*malicious_bot_pattern" 1;
"~*another_suspicious_agent" 1;
}
server {
# ...
if ($bad_bot) {
return 403;
}
# ...
}
}
3.2 디렉터리 트래버설 공격 방어
location 블록을 신중하게 구성하고 필요 없는 경우 디렉터리 목록을 비활성화하여 사용자가 웹 루트 외부의 파일에 접근하는 것을 방지하세요.
location / {
root /var/www/html;
index index.html index.htm;
try_files $uri $uri/ =404;
autoindex off; # Disable directory listing
}
# Example of restricting access to sensitive files
location ~ /\.ht {
deny all;
}
3.3 Nginx 버전 숨기기
공격자가 특정 버전과 관련된 알려진 취약점을 악용할 수 있으므로 Nginx 버전 번호를 숨기는 것이 좋은 관행입니다.
http {
server_tokens off;
# ...
}
이 지시문은 오류 페이지와 Server HTTP 응답 헤더에서 서버 버전을 제거합니다.
3.4 HTTP 메서드 제한
애플리케이션이 특정 HTTP 메서드(예: PUT, DELETE, OPTIONS)를 필요로 하지 않는 경우, 공격 표면을 줄이기 위해 이들을 비활성화할 수 있습니다.
location /api/ {
# Allow only GET and POST
if ($request_method !~ ^(GET|POST)$) {
return 405;
}
# ...
}
4. Nginx 최신 상태 유지
소프트웨어 취약점은 끊임없이 발견됩니다. Nginx를 최신 안정 버전으로 정기적으로 업데이트하는 것은 알려진 보안 결함을 패치하는 가장 효과적인 방법 중 하나입니다.
4.1 업데이트 방법
운영 체제의 패키지 관리자를 사용하여 Nginx를 업데이트하세요.
For Debian/Ubuntu:
sudo apt update
sudo apt upgrade nginx
For CentOS/RHEL:
sudo yum update nginx
- 팁: Nginx 보안 권고 또는 배포판의 보안 공지를 구독하여 중요한 업데이트에 대한 정보를 얻으세요.
- 경고: 중요한 업데이트를 수행하기 전에 항상 구성 파일을 백업하세요.
5. 추가 보안 고려 사항
- 방화벽 구성: 서버의 방화벽(예:
ufw,firewalld)이 필요한 포트(일반적으로 80 및 443)에서만 트래픽을 허용하도록 설정되어 있는지 확인하세요. - 접근 제어: 사이트의 민감한 영역에 대한 접근을 제한하기 위해 접근 제어 목록(ACL)을 구현하세요.
- 로그 모니터링: 의심스러운 활동이 있는지 Nginx 접근 및 오류 로그를 정기적으로 검토하세요.
- Fail2ban: 반복적인 로그인 실패 시도와 같은 악의적인 행동을 보이는 IP 주소를 자동으로 차단하기 위해
fail2ban과 같은 도구 사용을 고려하세요.
결론
Nginx 웹 서버를 보호하는 것은 올바른 구성, 정기적인 업데이트, 그리고 경계를 조합해야 하는 지속적인 과정입니다. 이 글에서 설명한 모범 사례, 즉 SSL/TLS 보안, 속도 제한 적용, 일반적인 공격 완화, 최신 소프트웨어 유지를 구현함으로써 서버의 보안 태세를 크게 강화하고 대부분의 위협으로부터 웹 애플리케이션을 보호할 수 있습니다.
끊임없이 진화하는 사이버 보안 환경에서 새로운 위협과 모범 사례가 나타남에 따라 보안 조치를 계속 연구하고 적용하세요.