├── LICENSE ├── config.lua ├── README.md ├── Dockerfile └── nginx.conf /LICENSE: -------------------------------------------------------------------------------- 1 | MIT License 2 | 3 | Copyright (c) 2018 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | -------------------------------------------------------------------------------- /config.lua: -------------------------------------------------------------------------------- 1 | --WAF config file,enable = "on",disable = "off" 2 | 3 | --waf status 4 | config_waf_enable = "on" 5 | --log dir 6 | config_log_dir = "/usr/local/openresty/waf_logs" 7 | --rule setting 8 | config_rule_dir = "/usr/local/openresty/nginx/conf/waf/rule-config" 9 | --enable/disable white url 10 | config_white_url_check = "on" 11 | --enable/disable white ip 12 | config_white_ip_check = "on" 13 | --enable/disable block ip 14 | config_black_ip_check = "on" 15 | --enable/disable url filtering 16 | config_url_check = "on" 17 | --enalbe/disable url args filtering 18 | config_url_args_check = "on" 19 | --enable/disable user agent filtering 20 | config_user_agent_check = "on" 21 | --enable/disable cookie deny filtering 22 | config_cookie_check = "on" 23 | --enable/disable cc filtering 24 | config_cc_check = "on" 25 | --cc rate the xxx of xxx seconds 26 | config_cc_rate = "10/60" 27 | --enable/disable post filtering 28 | config_post_check = "on" 29 | --config waf output redirect/html 30 | config_waf_output = "html" 31 | --if config_waf_output ,setting url 32 | --config_waf_redirect_url = "https://blog.evi0s.com" 33 | config_output_html=[[ 34 | 403 Forbidden 35 | ]] 36 | 37 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Openresty WAF 2 | 3 | Openresty with WAF installed 4 | 5 | Force HTTPS & HTTP2, TLSv1.3 Supported 6 | 7 | SSL Cert & PrivKey required 8 | 9 | ## Components 10 | 11 | * **Openresty** 12 | 13 | version 1.17.8.2 14 | 15 | * **Nginx** 16 | 17 | version 1.17.8.2 18 | 19 | * **Openssl** 20 | 21 | version 1.1.1c 22 | 23 | * **WAF** 24 | 25 | [unixhot/waf](https://github.com/unixhot/waf) 26 | 27 | ## Build 28 | 29 | ```bash 30 | git clone https://github.com/evi0s/Openresty-WAF.git 31 | cd Openresty-WAF 32 | docker build -t user/name . 33 | ``` 34 | 35 | ## Deploy 36 | 37 | Copy SSL Cert & Privkey to a path 38 | 39 | ```bash 40 | mkdir /home/user/openresty-waf 41 | cd /home/user/openresty-waf 42 | mkdir ssl && mkdir html 43 | cp /path/to/your/fullchain ./ssl/fullchain.pem # Fullchain name unmodifiable 44 | cp /path/to/your/privkey ./ssl/privkey.pem # Private key name unmodifiable 45 | openssl dhparam -out ./ssl/dhparam.pem 2048 46 | ``` 47 | 48 | Deploy 49 | 50 | ```bash 51 | docker run -it -d \ 52 | -p 80:80 \ 53 | -p 443:443 \ 54 | -v /home/user/openresty-waf/ssl/:/usr/local/openresty/nginx/ssl/:ro \ 55 | -v /home/user/openresty-waf/html/:/usr/local/openresty/nginx/html/ \ 56 | --name=nginx-waf \ 57 | user/name 58 | ``` 59 | 60 | ## Deploy without build 61 | 62 | ```bash 63 | docker run -it -d \ 64 | -p 80:80 \ 65 | -p 443:443 \ 66 | -v /home/user/openresty-waf/ssl/:/usr/local/openresty/nginx/ssl/:ro \ 67 | -v /home/user/openresty-waf/html/:/usr/local/openresty/nginx/html/ \ 68 | --name=nginx-waf \ 69 | evi0s/openresty-waf 70 | ``` 71 | 72 | ## Configs 73 | 74 | * WAF logs 75 | 76 | ``` 77 | /usr/local/openresty/waf_logs/ 78 | ``` 79 | 80 | Can be modified in config.lua 81 | 82 | * Nginx access log 83 | 84 | ``` 85 | /usr/local/openresty/nginx/access.log 86 | ``` 87 | 88 | Can be modified in nginx.conf 89 | 90 | * WAF warning html 91 | 92 | Can be modified in config.lua 93 | 94 | * WAF CC Blocking 95 | 96 | Default: **10** Requests Max within **60** seconds 97 | 98 | Can be modified in config.lua 99 | 100 | ## Links 101 | 102 | * [Openresty](http://openresty.org/cn/) 103 | * [unixhot/waf](https://github.com/unixhot/waf) 104 | 105 | -------------------------------------------------------------------------------- /Dockerfile: -------------------------------------------------------------------------------- 1 | # Dockerfile to build Openresety Installed Containers with WAF (alpine) 2 | FROM alpine:3 3 | MAINTAINER evi0s 4 | 5 | RUN echo "====> Install dependencies" && \ 6 | sed -i 's/dl-cdn.alpinelinux.org/mirrors.tuna.tsinghua.edu.cn/g' \ 7 | /etc/apk/repositories && \ 8 | apk update && \ 9 | apk add --no-cache readline-dev pcre-dev \ 10 | perl make gcc g++ git zlib-dev libc-dev linux-headers && \ 11 | echo "====> Install Openssl" && \ 12 | cd /tmp && \ 13 | wget --no-check-certificate https://www.openssl.org/source/openssl-1.1.1c.tar.gz && \ 14 | tar zxf openssl-1.1.1c.tar.gz && \ 15 | cd openssl-1.1.1c && \ 16 | ./config shared zlib --prefix=/usr/local/openssl \ 17 | --openssldir=/usr/local/openssl \ 18 | --libdir=lib shared -Wl,-R,'$(LIBRPATH)' \ 19 | -Wl,--enable-new-dtags enable-ec_nistp_64_gcc_128 enable-tls1_3 && \ 20 | make -j$(($(grep processor /proc/cpuinfo | wc -l) * 2)) && \ 21 | make install && rm -rf /usr/local/openssl/share/* && \ 22 | echo "/usr/local/openssl/lib" >> /etc/ld.so.conf && \ 23 | export PATH=$PATH:/usr/local/openssl/bin && \ 24 | echo "===> Install Openresty" && \ 25 | cd /tmp && \ 26 | wget --no-check-certificate https://openresty.org/download/openresty-1.17.8.2.tar.gz && \ 27 | tar zxf openresty-1.17.8.2.tar.gz && \ 28 | cd openresty-1.17.8.2 && \ 29 | sed -i 's/\/\.openssl//g' bundle/nginx-1.17.8/auto/lib/openssl/conf && \ 30 | ./configure --prefix=/usr/local/openresty \ 31 | --with-luajit --with-http_stub_status_module \ 32 | --with-pcre --with-pcre-jit --with-openssl=/usr/local/openssl \ 33 | --with-http_v2_module --with-http_ssl_module \ 34 | --with-http_realip_module --with-http_gzip_static_module \ 35 | --with-openssl-opt="enable-tls1_3 enable-ec_nistp_64_gcc_128" && \ 36 | make -j$(($(grep processor /proc/cpuinfo | wc -l) * 2)) && \ 37 | make install && \ 38 | echo "===> Gen Certs" && \ 39 | mkdir /usr/local/openresty/nginx/ssl && \ 40 | cd /usr/local/openresty/nginx/ssl/ && \ 41 | openssl genrsa -des3 -passout pass:Pa5sK3y -out ca.key 2048 && \ 42 | openssl req -passin pass:Pa5sK3y -new -subj "/C=CN/ST=Beijing/L=LocalDomain/O=LocalDomain/OU=LocalDomain/CN=localhost" \ 43 | -key ca.key -out ca.csr && \ 44 | mv ca.key ca.origin.key && \ 45 | openssl rsa -passin pass:Pa5sK3y -in ca.origin.key -out privkey.pem && \ 46 | openssl x509 -req -days 3650 -in ca.csr -signkey privkey.pem -out fullchain.pem && \ 47 | openssl dhparam -out dhparam.pem 2048 && \ 48 | echo "===> Install WAF" && \ 49 | cd /tmp && \ 50 | git clone https://github.com/unixhot/waf.git && \ 51 | cp -a ./waf/waf /usr/local/openresty/nginx/conf/ && \ 52 | rm -rf /usr/local/openresty/nginx/conf/waf/config.lua && \ 53 | mkdir /usr/local/openresty/waf_logs && \ 54 | apk del gcc g++ make git perl linux-headers --purge && \ 55 | rm -rf /tmp/* && rm -rf /var/cache/apk/* 56 | 57 | COPY nginx.conf /usr/local/openresty/nginx/conf/nginx.conf 58 | 59 | COPY config.lua /usr/local/openresty/nginx/conf/waf/config.lua 60 | 61 | # Chown dir 62 | RUN addgroup -g 82 -S www-data && \ 63 | adduser -u 82 -D -S -G www-data www-data && \ 64 | chown -R www-data:www-data /usr/local/openresty/ 65 | 66 | # Expose ports 67 | EXPOSE 80 443 68 | 69 | # Start Openresty 70 | CMD /usr/local/openresty/nginx/sbin/nginx -g "daemon off;" 71 | 72 | -------------------------------------------------------------------------------- /nginx.conf: -------------------------------------------------------------------------------- 1 | user www-data www-data; 2 | 3 | worker_processes auto; 4 | 5 | error_log /usr/local/openresty/nginx/logs/nginx_error.log error; 6 | 7 | pid /usr/local/openresty/nginx/nginx.pid; 8 | 9 | worker_rlimit_nofile 65535; 10 | 11 | events 12 | { 13 | use epoll; 14 | worker_connections 65535; 15 | multi_accept on; 16 | } 17 | 18 | http 19 | { 20 | lua_shared_dict limit 50m; 21 | lua_package_path "/usr/local/openresty/nginx/conf/waf/?.lua"; 22 | init_by_lua_file "/usr/local/openresty/nginx/conf/waf/init.lua"; 23 | access_by_lua_file "/usr/local/openresty/nginx/conf/waf/access.lua"; 24 | 25 | include mime.types; 26 | default_type application/octet-stream; 27 | 28 | server_names_hash_bucket_size 128; 29 | client_header_buffer_size 32k; 30 | large_client_header_buffers 4 32k; 31 | client_max_body_size 50m; 32 | 33 | sendfile on; 34 | tcp_nopush on; 35 | 36 | keepalive_timeout 60; 37 | 38 | tcp_nodelay on; 39 | 40 | gzip on; 41 | gzip_min_length 1k; 42 | gzip_buffers 4 16k; 43 | gzip_http_version 1.1; 44 | gzip_comp_level 2; 45 | gzip_types text/plain application/javascript application/x-javascript text/javascript text/css application/xml application/xml+rss; 46 | gzip_vary on; 47 | gzip_proxied expired no-cache no-store private auth; 48 | gzip_disable "MSIE [1-6]\."; 49 | 50 | server_tokens off; 51 | access_log off; 52 | 53 | server 54 | { 55 | listen 80; 56 | server_name default_server; 57 | rewrite ^(.*)$ https://$host$1 permanent; 58 | } 59 | 60 | server 61 | { 62 | listen 443 ssl http2; 63 | server_name default_server; 64 | index index.html index.htm; 65 | root /usr/local/openresty/nginx/html; 66 | 67 | ssl_certificate /usr/local/openresty/nginx/ssl/fullchain.pem; 68 | ssl_certificate_key /usr/local/openresty/nginx/ssl/privkey.pem; 69 | ssl_session_timeout 5m; 70 | ssl_protocols TLSv1 TLSv1.1 TLSv1.2 TLSv1.3; 71 | ssl_prefer_server_ciphers on; 72 | ssl_ciphers "TLS13-AES-256-GCM-SHA384:TLS13-CHACHA20-POLY1305-SHA256:TLS13-AES-128-GCM-SHA256:TLS13-AES-128-CCM-8-SHA256:TLS13-AES-128-CCM-SHA256:EECDH+CHACHA20:EECDH+CHACHA20-draft:EECDH+AES128:RSA+AES128:EECDH+AES256:RSA+AES256:EECDH+3DES:RSA+3DES:!MD5"; 73 | ssl_session_cache builtin:1000 shared:SSL:10m; 74 | # openssl dhparam -out /usr/local/openresty/nginx/conf/ssl/dhparam.pem 2048 75 | ssl_dhparam /usr/local/openresty/nginx/ssl/dhparam.pem; 76 | 77 | if ($http_user_agent ~* "Baiduspider-render|qihoobot|Baiduspider|Googlebot|Googlebot-Mobile|Googlebot-Image|Mediapartners-Google|Adsbot-Google|Feedfetcher-Google|Yahoo! Slurp|Yahoo! Slurp China|YoudaoBot|Sosospider|Sogou spider|Sogou web spider|MSNBot|ia_archiver|Tomato Bot") 78 | { 79 | return 403; 80 | } 81 | 82 | location ~ .*\.(js|css)?$ 83 | { 84 | expires 12h; 85 | } 86 | 87 | location ~ .*\.(gif|jpg|jpeg|png|bmp|swf)$ 88 | { 89 | expires 30d; 90 | } 91 | 92 | access_log /usr/local/openresty/nginx/access.log; 93 | } 94 | } 95 | --------------------------------------------------------------------------------