diff --git a/Dockerfile b/Dockerfile index 7beaf91..9da743e 100644 --- a/Dockerfile +++ b/Dockerfile @@ -9,8 +9,9 @@ COPY entrypoint.sh /opt/entrypoint.sh COPY confs/ /opt/confs COPY scripts/ /opt/scripts COPY misc/*.mmdb /etc/nginx/geoip.mmdb +COPY fail2ban/ /opt/fail2ban -RUN apk --no-cache add php7-fpm certbot libstdc++ libmaxminddb geoip pcre yajl && \ +RUN apk --no-cache add php7-fpm certbot libstdc++ libmaxminddb geoip pcre yajl fail2ban && \ chmod +x /opt/entrypoint.sh /opt/scripts/* && \ mkdir /www && \ adduser -h /dev/null -g '' -s /sbin/nologin -D -H nginx diff --git a/confs/nginx.conf b/confs/nginx.conf index b2350cc..6b7183e 100644 --- a/confs/nginx.conf +++ b/confs/nginx.conf @@ -1,7 +1,7 @@ # /etc/nginx/nginx.conf -# do not run as daemon -daemon off; +# run as daemon +daemon on; # do NOT run as root user nginx; @@ -61,8 +61,8 @@ http { # enable/disable sending nginx version server_tokens %SERVER_TOKENS%; - # display standard logs on stdout - access_log /dev/stdout; + # where to write logs + access_log /var/log/access.log; # server config include /etc/nginx/server.conf; diff --git a/confs/server.conf b/confs/server.conf index f7535b2..71ebffe 100644 --- a/confs/server.conf +++ b/confs/server.conf @@ -22,5 +22,6 @@ server { %BLOCK_TOR_EXIT_NODE% %COOKIE_FLAGS% %ERRORS% + %USE_FAIL2BAN% include /server-confs/*.conf; } diff --git a/entrypoint.sh b/entrypoint.sh index df40035..a93714c 100644 --- a/entrypoint.sh +++ b/entrypoint.sh @@ -64,6 +64,11 @@ SERVE_FILES="${SERVE_FILES-yes}" WRITE_ACCESS="${WRITE_ACCESS-no}" REDIRECT_HTTP_TO_HTTPS="${REDIRECT_HTTP_TO_HTTPS-no}" LISTEN_HTTP="${LISTEN_HTTP-yes}" +USE_FAIL2BAN="${USE_FAIL2BAN-yes}" +FAIL2BAN_STATUS_CODES="${FAIL2BAN_STATUS_CODES-400|401|403|404|405|444}" +FAIL2BAN_BANTIME="${FAIL2BAN_BANTIME-3600}" +FAIL2BAN_FINDTIME="${FAIL2BAN_FINDTIME-60}" +FAIL2BAN_MAXRETRY="${FAIL2BAN_MAXRETRY-10}" # install additional modules if needed if [ "$ADDITIONAL_MODULES" != "" ] ; then @@ -282,6 +287,22 @@ else replace_in_file "/etc/nginx/server.conf" "%SERVE_FILES%" "" fi +# fail2ban setup +if [ "$USE_FAIL2BAN" = "yes" ] ; then + echo "" > /etc/nginx/fail2ban-ip.conf + rm -rf /etc/fail2ban/jail.d/* + replace_in_file "/etc/nginx/server.conf" "%USE_FAIL2BAN%" "include /etc/nginx/fail2ban-ip.conf;" + cp /opt/fail2ban/nginx-action.local /etc/fail2ban/action.d/nginx-action.local + cp /opt/fail2ban/nginx-filter.local /etc/fail2ban/filter.d/nginx-filter.local + cp /opt/fail2ban/jail.local /etc/fail2ban/jail.local + replace_in_file "/etc/fail2ban/jail.local" "%FAIL2BAN_BANTIME%" "$FAIL2BAN_BANTIME" + replace_in_file "/etc/fail2ban/jail.local" "%FAIL2BAN_FINDTIME%" "$FAIL2BAN_FINDTIME" + replace_in_file "/etc/fail2ban/jail.local" "%FAIL2BAN_MAXRETRY%" "$FAIL2BAN_MAXRETRY" + replace_in_file "/etc/fail2ban/filter.d/nginx-filter.local" "%FAIL2BAN_STATUS_CODES%" "$FAIL2BAN_STATUS_CODES" +else + replace_in_file "/etc/nginx/server.conf" "%USE_FAIL2BAN%" "" +fi + # edit access if needed if [ "$WRITE_ACCESS" = "yes" ] ; then chown -R root:nginx /www @@ -298,7 +319,17 @@ fi # start crond crond -# start nginx in foreground -# when nginx is killed, container get killed too +# start nginx +/usr/sbin/nginx echo "[*] Running nginx ..." -exec /usr/sbin/nginx + +if [ "$USE_FAIL2BAN" = "yes" ] ; then + fail2ban-server +fi + +# display logs +exec tail -f /var/log/access.log + +# try to gracefully stop nginx +echo "[*] Stopping nginx ..." +/usr/sbin/nginx -s stop diff --git a/fail2ban/jail.local b/fail2ban/jail.local new file mode 100644 index 0000000..25b22fb --- /dev/null +++ b/fail2ban/jail.local @@ -0,0 +1,9 @@ +[DEFAULTS] +bantime = %FAIL2BAN_BANTIME% +findtime = %FAIL2BAN_FINDTIME% +maxretry = %FAIL2BAN_MAXRETRY% + +[nginx-filter] +enabled = true +action = nginx-action +logpath = /var/log/access.log diff --git a/fail2ban/nginx-action.local b/fail2ban/nginx-action.local new file mode 100644 index 0000000..7af86d3 --- /dev/null +++ b/fail2ban/nginx-action.local @@ -0,0 +1,8 @@ +[Definition] + +actionstart = echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload +actionstop = echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload +actioncheck = +actionflush = echo "" > /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload +actionban = echo -n "deny ;" >> /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload +actionunban = sed -i "s/deny ;//g" /etc/nginx/fail2ban-ip.conf && /usr/sbin/nginx -s reload diff --git a/fail2ban/nginx-filter.local b/fail2ban/nginx-filter.local new file mode 100644 index 0000000..b617713 --- /dev/null +++ b/fail2ban/nginx-filter.local @@ -0,0 +1,7 @@ +[INCLUDES] +before = common.conf + +[Definition] +failregex = - .* \[.*\] ".*" (%FAIL2BAN_STATUS_CODES%) .* ".*" ".*" +ignoreregex = +datepattern = %%d/%%b/%%Y:%%H:%%M:%%S