티스토리 뷰

Nginx 웹프록시를 주로 사용하는데
AWS에서 PoC 운영중이던 서비스를
비용 절감 위해 오라클 클라우드 무료 서버로 옮기고
Whatap 모니터링 걸어놓고 놔뒀는데
트래픽이 없을게 확실한 서버에서 이상하게도 CPU 로드 Whatap Alert이 간간히 발생하여
Nginx access 로그를 확인해보니
해커 스캔봇이 열심히 활동하여
쓸데없고 보안에 해로운 트래픽을 유발시키고 있었음.
하여, WAF(웹어플리케이션 방화벽) 도입을 검토하게 되었고
리서치 후 사용 비용이 없는 Modsecurity로 결정.

Modsecurity를 Apache 웹서버는 매우 쉽게 붙일 수 있는데 그에 비해 Nginx는 번거롭고 정리된 최근 레퍼런스 너무 없음.

Nginx + Modsecurity 조합을
로컬 개발 환경인 macOS에도 구축하고
Ubuntu 서버에 그대로 셋팅하려니 번거로워서 docker 기반 구성 결정함.

docker compose 구성

Modsecurity 도커 이미지

⚠️ docker hub에서 Modsecurity 검색해보면 https://hub.docker.com/r/owasp/modsecurity 뜨는데 deprecated

OWASP CRS 컨테이너 이미지 (https://hub.docker.com/r/owasp/modsecurity-crs)

image: owasp/modsecurity-crs:nginx

저 이미지로 하나의 (도커) 서비스를 구성하고 별도로 nginx를 해야 되나 궁금했는데 nginx와 통합된 이미지였음.

expose 포트를 host 80포트에 binding 하면 mac에서 웹서비스에 http로 엑세스 할 수 있을거라는 추측 가능.

services:
  # 리버스프록시+웹방화벽
  nginx:
    image: owasp/modsecurity-crs:nginx
    container_name: nginx
    hostname: nginx
    labels:
      - dev.orbstack.domains=cashdab.orb.local
    restart: always
    # <https://github.com/coreruleset/modsecurity-crs-docker?tab=readme-ov-file#common-env-variables>
    environment:
      - TZ=Asia/Seoul
      # nginx proxy_pass 정의
      - BACKEND=http://web:8000
      - ERRORLOG=/var/log/nginx/error.log
      #- SERVER_NAME=_
      # <https://github.com/coreruleset/modsecurity-crs-docker?tab=readme-ov-file#nginx-env-variables>
      # 앞단에 Cloudflare 사용시 실제 IP 정의
      - REAL_IP_HEADER=CF-Connecting-IP
    ports:
      # 호스트 : 도커 컨테이너 내부에서 expose된 포트
      - "80:8080"
    volumes:
      - ./docker/modsecurity/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/REQUEST-900-EXCLUSION-RULES-BEFORE-CRS.conf
      - ./docker/modsecurity/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf:/etc/modsecurity.d/owasp-crs/rules/RESPONSE-999-EXCLUSION-RULES-AFTER-CRS.conf
    networks:
      - shared_network
    links:
      - web:web
    depends_on:
      - web
    # 로그 로테이션: 로그 크기 자동 관리
    logging:
      driver: "json-file"
      options:
        max-size: "10m"
        max-file: "5"

networks:
  shared_network:
    driver: bridge

Modsecurity 설정

규칙 설정

관리자 페이지 경로, 특정 IP 및 대역만 가능하게

# Restrict /health and not in ip range
SecRule REQUEST_URI "@beginsWith /health" "id:1000,phase:1,deny,status:403,log,msg:'Access to /health denied for non-authorized IP %{REMOTE_ADDR}',chain"
    SecRule REMOTE_ADDR "!@ipMatch 127.0.0.1,10.0.0.0/8,172.16.0.0/16,192.168.0.0/16" "t:none"

테스트

웹브라우저나 curl 사용하여 /admin 접속해서 테스트.

 

Reference

댓글
최근에 올라온 글
최근에 달린 댓글
Total
Today
Yesterday
«   2025/06   »
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
글 보관함