diff --git a/.env b/.env index 243d5d9137..5c5ddb8291 100644 --- a/.env +++ b/.env @@ -189,6 +189,22 @@ GATEWAY_ALLOWED_IPS= GATEWAY_DENIED_IPS= GATEWAY_USERS= +# activate and manage http incoming request limits +# this feature is based on ip adresses and need PHRASEANET_TRUSTED_PROXIES +# defined to get real_ip +# @run +GLOBAL_REQUEST_LIMIT_ACTIVATE=0 # switch to 1 to enable limiting http requests using parameters below +GLOBAL_REQUEST_LIMIT_MEMORY=10m # For Exemple 16,000 IP addresses takes 1 megabyte, so our zone can store about 160,000 addresses. +GLOBAL_REQUEST_LIMIT_RATE=10r/s # Sets the maximum request rate. By default here the rate cannot exceed 10 requests per second +GLOBAL_REQUEST_LIMIT_BURST=20 # The burst parameter defines how many requests a client can make in excess of the rate specified by the zone +GLOBAL_REQUEST_LIMIT_NODELAY=1 # With the nodelay parameter, NGINX still allocates slots in the queue according to the burst parameter and imposes the configured rate limit. if not extra request queues waits 2 seconds to be forwarded + +API_REQUEST_LIMIT_ACTIVATE=0 # switch to 1 to enable limiting api requests using parameters below +API_REQUEST_LIMIT_MEMORY=10m # For Exemple 16,000 IP addresses takes 1 megabyte, so our zone can store about 160,000 addresses. +API_REQUEST_LIMIT_RATE=10r/s # Sets the maximum request rate. By default here the rate cannot exceed 10 requests per second +API_REQUEST_LIMIT_BURST=20 # The burst parameter defines how many requests a client can make in excess of the rate specified by the zone +API_REQUEST_LIMIT_NODELAY=1 # With the nodelay parameter, NGINX still allocates slots in the queue according to the burst parameter and imposes the configured rate limit. if not extra request queues waits 2 seconds to be forwarded + # https and reverse proxy (on/off) # set to on in the case : https behind a proxy # @run diff --git a/docker-compose.yml b/docker-compose.yml index 991fb0c4bb..3347a18f42 100644 --- a/docker-compose.yml +++ b/docker-compose.yml @@ -36,6 +36,16 @@ services: - GATEWAY_DENIED_IPS - GATEWAY_USERS - GATEWAY_CSP + - GLOBAL_REQUEST_LIMIT_ACTIVATE + - GLOBAL_REQUEST_LIMIT_MEMORY + - GLOBAL_REQUEST_LIMIT_RATE + - GLOBAL_REQUEST_LIMIT_BURST + - GLOBAL_REQUEST_LIMIT_NODELAY + - API_REQUEST_LIMIT_ACTIVATE + - API_REQUEST_LIMIT_MEMORY + - API_REQUEST_LIMIT_RATE + - API_REQUEST_LIMIT_BURST + - API_REQUEST_LIMIT_NODELAY ports: - ${PHRASEANET_APP_PORT}:80 networks: @@ -70,6 +80,16 @@ services: - GATEWAY_USERS - GATEWAY_FASTCGI_HTTPS - GATEWAY_CSP + - GLOBAL_REQUEST_LIMIT_ACTIVATE + - GLOBAL_REQUEST_LIMIT_MEMORY + - GLOBAL_REQUEST_LIMIT_RATE + - GLOBAL_REQUEST_LIMIT_BURST + - GLOBAL_REQUEST_LIMIT_NODELAY + - API_REQUEST_LIMIT_ACTIVATE + - API_REQUEST_LIMIT_MEMORY + - API_REQUEST_LIMIT_RATE + - API_REQUEST_LIMIT_BURST + - API_REQUEST_LIMIT_NODELAY networks: - internal labels: diff --git a/docker/nginx/root/entrypoint.sh b/docker/nginx/root/entrypoint.sh index a002bb9112..3ffa2f6880 100755 --- a/docker/nginx/root/entrypoint.sh +++ b/docker/nginx/root/entrypoint.sh @@ -57,6 +57,7 @@ fi #GATEWAY_DENIED_IPS="172.1.0.1,172.1.0.2" #GATEWAY_USERS="user1(password1),user2(password2) touch /etc/nginx/restrictions +touch /etc/nginx/apirestrictions touch /etc/nginx/.htpasswd if [[ ! -z $GATEWAY_ALLOWED_IPS ]] || [[ ! -z $GATEWAY_DENIED_IPS ]] || [[ ! -z $GATEWAY_USERS ]]; then @@ -81,6 +82,37 @@ if [[ ! -z $GATEWAY_ALLOWED_IPS ]] || [[ ! -z $GATEWAY_DENIED_IPS ]] || [[ ! -z echo "deny all;" >> /etc/nginx/restrictions fi fi + +echo "limit_req_status 429;" > /etc/nginx/conf.d/limits.conf + +if [[ ! -z $GLOBAL_REQUEST_LIMIT_ACTIVATE ]] && [[ "$GLOBAL_REQUEST_LIMIT_ACTIVATE" = "1" ]]; then + echo "limit_req_zone \$binary_remote_addr zone=globaliplimits:$GLOBAL_REQUEST_LIMIT_MEMORY rate=$GLOBAL_REQUEST_LIMIT_RATE;" >> /etc/nginx/conf.d/limits.conf + if [[ ! -z $GLOBAL_REQUEST_LIMIT_BURST ]]; then + if [ "$GLOBAL_REQUEST_LIMIT_NODELAY" = "on" ] || [ "$GLOBAL_REQUEST_LIMIT_NODELAY" = "1" ];then + export GLOBAL_REQUEST_LIMITS="limit_req zone=globaliplimits burst=$GLOBAL_REQUEST_LIMIT_BURST nodelay;" + else + export GLOBAL_REQUEST_LIMITS="limit_req zone=globaliplimits burst=$GLOBAL_REQUEST_LIMIT_BURST;" + fi + else + export GLOBAL_REQUEST_LIMITS="limit_req zone=globaliplimits;" + fi + echo $GLOBAL_REQUEST_LIMITS >> /etc/nginx/restrictions +fi + +if [[ ! -z $API_REQUEST_LIMIT_ACTIVATE ]] && [[ "$API_REQUEST_LIMIT_ACTIVATE" = "1" ]]; then + echo "limit_req_zone \$binary_remote_addr zone=apiiplimits:$API_REQUEST_LIMIT_MEMORY rate=$API_REQUEST_LIMIT_RATE;" >> /etc/nginx/conf.d/limits.conf + if [[ ! -z $API_REQUEST_LIMIT_BURST ]]; then + if [ "$API_REQUEST_LIMIT_NODELAY" = "on" ] || [ "$API_REQUEST_LIMIT_NODELAY" = "1" ];then + export API_REQUEST_LIMITS="limit_req zone=apiiplimits burst=$API_REQUEST_LIMIT_BURST nodelay;" + else + export API_REQUEST_LIMITS="limit_req zone=apiiplimits burst=$API_REQUEST_LIMIT_BURST;" + fi + else + export API_REQUEST_LIMITS="limit_req zone=apiiplimits;" + fi + echo $API_REQUEST_LIMITS >> /etc/nginx/apirestrictions +fi + unset GATEWAY_USERS unset GATEWAY_DENIED_IPS unset GATEWAY_ALLOWED_IPS diff --git a/docker/nginx/root/nginx.conf.sample b/docker/nginx/root/nginx.conf.sample index 7b37ac4b80..0958434447 100644 --- a/docker/nginx/root/nginx.conf.sample +++ b/docker/nginx/root/nginx.conf.sample @@ -26,6 +26,7 @@ server { if (-f /var/alchemy/Phraseanet/datas/nginx/maintenance.html) { return 401; } + include apirestrictions; rewrite ^(.*)$ /api.php/$1 last; }