WAF(Web Application Firewall)

1. WAF(Web Application Firewall)

 

WAF는 웹 애플리케이션 앞단에서 HTTP/HTTPS 트래픽을 분석하여 웹 공격을 탐지·차단하는 보안 장비 또는 서비스를 말한다.

일반적인 방화벽은 IP,Port, Protocol 중심으로 트래픽을 제어한다면, WAF는 웹 애플리케이션 계층(L7)에서 동작하며 웹 요청의 내용 자체를 검사한다. 웹 서비스는 대부분 인터넷에 직접 노출되어 있고, 웹 취약점 공격에 매우 취약하기 때문에 WAF가 필요하다.

- 주요기능

HTTP/HTTPS 트래픽 분석

웹 공격 탐지 및 차단

정책 기반 접근 제어 

로그 및 모니터링 

 

2. Nginx + Modsecurity 설치

 

Nginx(엔진엑스)는 고성능 웹 서버이자 리버스 프록시, 로드 밸런서 역할을 하는 오픈소스 소프트웨어이다. Apache와 달리 이벤트 기반 비동기 구조를 사용해 동시에 많은 요청을 처리하는데 강점이 있다.

👉 프록시(Proxy) : 클라이언트와 서버 사이에서 중계 역할을 하는 서버, 프록시는 요청을 대신 전달하고, 응답을 대신 받아서 클라이언트에게 전달, 프록시는 클라이언트와 서버를 직접 노출시키지 않고, 보안 강화·성능 향상·트래픽 관리와 같은 공통 기능을 중앙에서 처리하기 위해 둔다.

👉리버스 프록시 (Reverse Proxy) : 외부에서 들어오는 클라이언트 요청을 먼저 받아 실제 서버로 전달함으로써, 서버를 직접 노출하지 않고 요청을 중계하는 프록시이다.

👉포워드 프록시 (Forward Proxy) : 클라이언트의 요청을 중간에서 전달하여 외부 서버와의 통신을 대행하고, 클라이언트의 직접적인 접근을 제어하는 프록시이다.

👉로드 밸런서(Load Balancer): 여러 서버가 하나의 서비스를 제공하는 환경에서, 클라이언트 요청을 여러 서버로 분배하여 부하를 균등하게 유지하도록 하는 장치 또는 소프트웨어이다.

👉Modsecurity : 웹 서버 앞단에서 HTTP 요청과 응답을 검사해 SQL Injection, XSS 같은 웹 공격을 탐지·차단하는 오픈소스 웹 애플리케이션 방화벽(WAF) 소프트웨어이다.

 

2-1 Nginx + ModSecurity + OWASP CRS를 컴파일 및 구성하기 위해 필요한 패키지(EPEL, 개발도구, 빌드 도구, 라이브러리)를 설치한다.

 

- 패키지 저장소 활성화 

# dnf install -y epel-release

# dnf config-manager --set-enabled powertools

 

- ModSecurity 및 Nginx 빌드를 위한 필수 패키지 설치

# dnf install -y git gcc-c++ make automake libtool wget pcre pcre-devel zlib zlib-devel libxml2 libxml2-devel curl-devel yajl yajl-devel lmdb-devel ssdeep-devel lua-devel

# dnf install -y pcre2-devel

# dnf install -y openssl openssl-devel libxslt libxslt-devel

# dnf install -y gd gd-devel perl-devel perl-ExtUtils-Embed

 

- GPG 공개키 등록

# rpm —import https://artifacts.elastic.co/GPG-KEY-elasticsearch

 

- Elastic 저장소 생성

# cat <<EOF | tee /etc/yum.repos.d/elastic.repo

[elastic-8.x]

name=Elastic repository for 8.x packages

baseurl=https://artifacts.elastic.co/packages/8.x/yum

gpgcheck=1

gpgkey=https://artifacts.elastic.co/GPG-KEY-elasticsearch

enabled=1

autorefresh=1

type=rpm-md

EOF

 

2-2 Nginx + Modsecurity 설치 

 

- Modsecurity (v3) 컴파일 및 설치

# cd /usr/local/src

# git clone--depth 1 https://github.com/SpiderLabs/ModSecurity

# cd ModSecurity

# git submodule init

# git submodule update

# ./build.sh

# ./configure

# make

# make install

 

- Nginx 소스와 Modsecurity 연동을 위한 connector 모듈 준비

# cd /usr/local/src

# wget http://nginx.org/download/nginx-1.14.1.tar.gz

# tar zxvf nginx-1.14.1.tar.gz

# git clone--depth 1 https://github.com/SpiderLabs/ModSecurity-nginx.git

 

- Nginx 컴파일 (Modsecurity Dynamic Module 포함)

# cd nginx-1.14.1

# ./configure \

--prefix=/usr/share/nginx \

--sbin-path=/usr/sbin/nginx \

--modules-path=/usr/lib64/nginx/modules \

--conf-path=/etc/nginx/nginx.conf \

--error-log-path=/var/log/nginx/error.log \

--http-log-path=/var/log/nginx/access.log \

--http-client-body-temp-path=/var/lib/nginx/tmp/client_body \

--http-proxy-temp-path=/var/lib/nginx/tmp/proxy \

--http-fastcgi-temp-path=/var/lib/nginx/tmp/fastcgi \

--http-uwsgi-temp-path=/var/lib/nginx/tmp/uwsgi \

--http-scgi-temp-path=/var/lib/nginx/tmp/scgi \

--pid-path=/run/nginx.pid \

--lock-path=/run/lock/subsys/nginx \

--user=nginx \

--group=nginx \

--with-file-aio \

--with-ipv6 \

--with-http_ssl_module \

--with-http_v2_module \

--with-http_realip_module \

--with-http_addition_module \

--with-http_xslt_module=dynamic \

--with-http_image_filter_module=dynamic \

--with-http_sub_module \

--with-http_dav_module \

--with-http_flv_module \

--with-http_mp4_module \

--with-http_gunzip_module \

--with-http_gzip_static_module \

--with-http_random_index_module \

--with-http_secure_link_module \

--with-http_degradation_module \

--with-http_slice_module \

--with-http_stub_status_module \

--with-http_perl_module=dynamic \

--with-http_auth_request_module \

--with-mail=dynamic \

--with-mail_ssl_module \

--with-pcre \

--with-pcre-jit \

--with-stream=dynamic \

--with-stream_ssl_module \

--with-debug \

--with-cc-opt='-O2 -g -pipe -Wall -Wformat-security -Wp,-D_FORTIFY_SOURCE=2 -Wp,-D_GLIBCXX_ASSERTIONS -fexceptions -fstack-protector-strong -grecord-gcc-switches -m64 -mtune=generic -fasynchronous-unwind-tables -fstack-clash-protection -fcf-protection -Wno-error=cast-function-type' \

--with-ld-opt='-Wl,-z,relro -Wl,-z,now -Wl,-E' \

--add-dynamic-module=../ModSecurity-nginx

 

- 빌드된 모듈을 nginx 모듈 경로로 복사하여 로드 가능하도록 설정

# ls objs/ngx_http_modsecurity_module.so

# mkdir -p /usr/lib64/nginx/modules

# cp objs/ngx_http_modsecurity_module.so /usr/lib64/nginx/modules/

 

 

3. 웹 서버용 개인키 생성

 

- SSL 디렉터리 생성

# mkdir -p /etc/nginx/ssl

# cd /etc/nginx/ssl

 

- 개인 키 생성

# openssl genrsa -out nginx-selfsigned.key

 

- 자가서명 인증서 생성

# openssl req -new -key nginx-selfsigned.key -x509 -days 365 -out nginx-selfsigned.crt

Country Name (2 letter code) [XX]:KR

State or Province Name (full name) []:

Locality Name (eg, city) [Default City]:

Organization Name (eg, company) [Default Company Ltd]:

Organizational Unit Name (eg, section) []:

Common Name (eg, your name or your server's hostname) []: www.synergy.sec

Email Address []:

 

 

4. Modsecurity 기본 설정 및 OWASP CRS 적용

👉 OWASP CRS(Core Rule Set) : 우선 웹 방화벽은 규칙(Rule) 이 없으면 공격을 판단할 수 없다. OWASP CRS는 웹 방화벽에서 사용되는 표준 웹 공격 탐지 규칙 모음으로, ModSecurity와 함께 웹 공격을 효과적으로 차단하기 위해 사용되며, OWASP Top 10에서 정의한 주요 웹 취약점을 실제로 탐지·차단할 수 있도록 구현한 WAF 규칙 모음이다.

 

- Modsecurity 기본 설정 파일 배치

# mkdir -p /etc/nginx/modsec

# cp /usr/local/src/ModSecurity/modsecurity.conf-recommended /etc/nginx/modsec/modsecurity.conf

# cp /usr/local/src/ModSecurity/unicode.mapping /etc/nginx/modsec/

 

- modsecurity.conf 수정(차단 모드 활성화 + Audit 로그 설정)

# vi /etc/nginx/modsec/modsecurity.conf

SecRuleEngine On        # "DetectionOnly"(탐지모드) → "On" 으로 변경(차단 모드)

SecAuditEngine On        # 감사 로그 엔진 On

SecAuditLogFormat JSON

SecAuditLogType Serial

SecAuditLog /var/log/nginx/modsec_audit.log

👉JSON(JavaScript Object Notation) : JSON 형식의 감사 로그는 보안 이벤트를 구조화된 데이터로 기록하여, 자동 분석과 보안 관제를 효율적으로 수행할 수 있게 해준다. 로그를 구조화하고 로그 분석함에 있어서 자동화에 유리하다. SIEM에 연동하기 적합하다.

 

- OWASP CRS 다운로드 및 적용

# cd /etc/nginx/modsec

# git clone https://github.com/coreruleset/coreruleset.git

# mv coreruleset owasp-crs

# cp owasp-crs/crs-setup.conf.example owasp-crs/crs-setup.conf

 

- ModSecurity + CRS 로드용 main.conf 구성

# vi /etc/nginx/modsec/main.conf

Include /etc/nginx/modsec/modsecurity.conf 👉ModSecurity 기본 동작 설정

Include /etc/nginx/modsec/owasp-crs/crs-setup.conf 👉 CRS 전역 환경 및 기준값 설정

Include /etc/nginx/modsec/owasp-crs/rules/*.conf 👉CRS 공격 탐지 규칙 로드

설정 → 기준 → 규칙 순서가 보장되어야 정상 동작한다.

👉Include : 다른 설정 파일의 내용을 현재 설정 파일에 불러와서 함께 적용하도록 하는 지시어

설정과 규칙을 역할별로 분리하고, 로드 순서를 명확히 하며, 유지보수를 쉽게 하기 위해 Include를 사용

 

5. Nginx 설정(Modsecurity 활성화/리버스 프록시/HTTPS)

 

- nginx 메인 설정 : Modsecurity 모듈 로드

# vi /etc/nginx/nginx.conf

user nginx;

load_module /usr/lib64/nginx/modules/ngx_http_modsecurity_module.so;

worker_processes auto;

error_log /var/log/nginx/error.log;

pid /run/nginx.pid;

include /usr/share/nginx/modules/*.conf;

 

events {

    worker_connections 1024;

}

 

http {

    log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '

                      '$status $body_bytes_sent "$http_referer" '

                      '"$http_user_agent" "$http_x_forwarded_for"';

 

    access_log  /var/log/nginx/access.log  main;

 

    sendfile            on;

    tcp_nopush          on;

    tcp_nodelay         on;

    keepalive_timeout   65;

    types_hash_max_size 2048;

 

    include             /etc/nginx/mime.types;

    default_type        application/octet-stream;

     # 서버 블록은 /etc/nginx/conf.d/*.conf에서 별도 관리

    include /etc/nginx/conf.d/*.conf;

}

 

- 가상호스트(www.synergy.sec) 설정

# vi /etc/nginx/conf.d/default.conf

# HTTP(80) → HTTPS 리다이렉트 서버 설정

server {

    listen 80 default_server;

    listen [::]:80 default_server;

    server_name www.synergy.sec 192.168.50.10 localhost _;      # D_WAF 주소

 

     # 80포트로 오는 모든 요청을 https로 보냄

    return 301 https://$host$request_uri;

}

 

# HTTPS(443) WAF 서버 + 리버스 프록시 설정

server {

    listen 443 ssl default_server;

    listen [::]:443 ssl default_server;

    server_name www.synergy.sec 192.168.50.10 localhost _;

 

     # SSL 인증서 경로

    ssl_certificate /etc/nginx/ssl/nginx-selfsigned.crt;

    ssl_certificate_key /etc/nginx/ssl/nginx-selfsigned.key;

 

     # SSL 프로토콜 및 암호 스위트 설정

    ssl_protocols TLSv1.2 TLSv1.3;

    ssl_ciphers 'ECDHE-RSA-AES256-GCM-SHA384:ECDHE-RSA-AES128-GCM-SHA256:HIGH:!aNULL:!MD5:!RC4';

    ssl_prefer_server_ciphers on;

 

     # Modsecurity + OWASP CRS 활성화

    modsecurity on;

    modsecurity_rules_file /etc/nginx/modsec/main.conf;

 

     # 리버스 프록시 : 백엔드 D_WEB으로 전달

    location / {

        proxy_pass http://192.168.50.11;   # D_WEB (SSL Offloading)

 

        # 원래 요청이 HTTPS였음을 백엔드에 전달

        proxy_set_header X-Forwarded-Proto https;

 

        proxy_set_header Host $host;

        proxy_set_header X-Real-IP $remote_addr;

        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    }

 

     # HSTS 헤더 주입(해당 도메인에 HTTPS 강제)

    add_header Strict-Transport-Security "max-age=31536000; includeSubDomains" always;

}

 

- 설정 문법 테스트(정상인 경우)

# nginx -t

nginx: the configuration file /etc/nginx/nginx.conf syntax is ok

nginx: configuration file /etc/nginx/nginx.conf test is successful

 

- nginx 서비스 등록 및 시작

# systemctl enable nginx

# systemctl start nginx

 

6. 방화벽 설정

 

# firewall-cmd --permanent --zone=public --remove-service=cockpit

👉 Cockpit 관리 웹 서비스 접근 차단

# firewall-cmd --permanent --zone=public --remove-service=dhcpv6-client

👉 IPv6 DHCP 클라이언트 관련 트래픽을 허용하지 않도록 설정

# firewall-cmd --permanent --zone=public --remove-service=ssh

👉 SSH(22번 포트) 접근 차단

 

# firewall-cmd --permanent --zone=public --add-service=http

👉 HTTP(80번 포트)  접근 허용

# firewall-cmd --permanent --zone=public --add-service=https

👉 HTTPS(443번 포트) 접근 허용

# firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.x.x" accept'

# firewall-cmd --permanent --zone=public --add-rich-rule='rule family="ipv4" source address="192.168.x.x" accept'

👉 지정한 IPv4 주소에서 들어오는 모든 트래픽 허용

# firewall-cmd --reload

👉 방화벽 적용

 

# firewall-cmd --list-all

👉 적용된 방화벽 설정 출력

public (active)

  target: default

  interfaces: ens160

  services: http https

        rule family="ipv4" source address="192.168.x.x" accept

        rule family="ipv4" source address="192.168.x.x" accept

👉 웹 서비스(80, 443)만 공개하고, 특정 내부 IP만 추가로 허용하도록 방화벽을 제한한 설정이다.