From b7159293c1dc5c159f3ddef029889efada7e3047 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 19 Feb 2015 12:32:06 -0500 Subject: [PATCH 1/4] nginx: create unauth/auth ratelimiting This also removes nodelay on rate limiting and temporarily blacklists an IP address. --- conf/proxy-server-base.conf | 13 ++++++++++--- conf/rate-limiting.conf | 3 ++- 2 files changed, 12 insertions(+), 4 deletions(-) diff --git a/conf/proxy-server-base.conf b/conf/proxy-server-base.conf index fb2f3f962..96bde44e3 100644 --- a/conf/proxy-server-base.conf +++ b/conf/proxy-server-base.conf @@ -19,7 +19,7 @@ proxy_set_header Transfer-Encoding $http_transfer_encoding; location / { proxy_pass http://web_app_server; - limit_req zone=webapp burst=25 nodelay; + limit_req zone=webapp; } location /realtime { @@ -29,6 +29,9 @@ location /realtime { } location /v1/repositories/ { + # blacklisted for bad behavior 19FEB2015 + deny 107.23.4.180; + proxy_buffering off; proxy_request_buffering off; @@ -39,7 +42,11 @@ location /v1/repositories/ { client_max_body_size 20G; - limit_req zone=repositories burst=5 nodelay; + if ($http_authorization) { + limit_req zone=authrepositories + } + + limit_req zone=unauthrepositories; } location /v1/ { @@ -63,7 +70,7 @@ location /c1/ { proxy_read_timeout 2000; proxy_temp_path /var/log/nginx/proxy_temp 1 2; - limit_req zone=api burst=5 nodelay; + limit_req zone=api; } location /static/ { diff --git a/conf/rate-limiting.conf b/conf/rate-limiting.conf index 3e2538510..d3f8a3cb3 100644 --- a/conf/rate-limiting.conf +++ b/conf/rate-limiting.conf @@ -1,7 +1,8 @@ # vim: ft=nginx limit_req_zone $proxy_protocol_addr zone=webapp:10m rate=25r/s; -limit_req_zone $proxy_protocol_addr zone=repositories:10m rate=1r/s; +limit_req_zone $proxy_protocol_addr zone=authrepositories:10m rate=1r/s; +limit_req_zone $proxy_protocol_addr zone=unauthrepositories:10m rate=2r/m; limit_req_zone $proxy_protocol_addr zone=api:10m rate=1r/s; limit_req_status 429; limit_req_log_level warn; From 11c56321219a5ab13d9495b633467bf73d0eb692 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 19 Feb 2015 12:45:53 -0500 Subject: [PATCH 2/4] nginx: remove blacklisted IP --- conf/proxy-server-base.conf | 3 --- 1 file changed, 3 deletions(-) diff --git a/conf/proxy-server-base.conf b/conf/proxy-server-base.conf index 96bde44e3..bab11bf3f 100644 --- a/conf/proxy-server-base.conf +++ b/conf/proxy-server-base.conf @@ -29,9 +29,6 @@ location /realtime { } location /v1/repositories/ { - # blacklisted for bad behavior 19FEB2015 - deny 107.23.4.180; - proxy_buffering off; proxy_request_buffering off; From 01811ee7937529c543fca14ff70483105cbe7b74 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 19 Feb 2015 13:31:49 -0500 Subject: [PATCH 3/4] nginx: add missing semicolon --- conf/proxy-server-base.conf | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/conf/proxy-server-base.conf b/conf/proxy-server-base.conf index bab11bf3f..983f78762 100644 --- a/conf/proxy-server-base.conf +++ b/conf/proxy-server-base.conf @@ -40,7 +40,7 @@ location /v1/repositories/ { client_max_body_size 20G; if ($http_authorization) { - limit_req zone=authrepositories + limit_req zone=authrepositories; } limit_req zone=unauthrepositories; From 4a2b25200a4346cff675f3a8045f56eaf30498c5 Mon Sep 17 00:00:00 2001 From: Jimmy Zelinskie Date: Thu, 19 Feb 2015 16:24:05 -0500 Subject: [PATCH 4/4] nginx: make rate limiting awesome --- conf/http-base.conf | 6 +++ conf/nginx-nossl.conf | 1 - conf/nginx.conf | 5 +- conf/proxy-server-base.conf | 95 ------------------------------------- conf/rate-limiting.conf | 12 ++++- conf/server-base.conf | 21 ++++++-- 6 files changed, 34 insertions(+), 106 deletions(-) delete mode 100644 conf/proxy-server-base.conf diff --git a/conf/http-base.conf b/conf/http-base.conf index d525b3dd3..8b7ff9e0b 100644 --- a/conf/http-base.conf +++ b/conf/http-base.conf @@ -16,6 +16,11 @@ gzip_types text/plain text/xml text/css text/javascript application/x-javascript application/octet-stream; +map $proxy_protocol_addr $proper_forwarded_for { + "" $proxy_add_x_forwarded_for; + default $proxy_protocol_addr; +} + upstream web_app_server { server unix:/tmp/gunicorn_web.sock fail_timeout=0; } @@ -33,3 +38,4 @@ upstream build_manager_controller_server { upstream build_manager_websocket_server { server localhost:8787; } + diff --git a/conf/nginx-nossl.conf b/conf/nginx-nossl.conf index 13c5d73b2..549f4b4e8 100644 --- a/conf/nginx-nossl.conf +++ b/conf/nginx-nossl.conf @@ -4,7 +4,6 @@ include root-base.conf; http { include http-base.conf; - include rate-limiting.conf; server { diff --git a/conf/nginx.conf b/conf/nginx.conf index 792b58faf..77a78f70e 100644 --- a/conf/nginx.conf +++ b/conf/nginx.conf @@ -4,9 +4,7 @@ include root-base.conf; http { include http-base.conf; - include hosted-http-base.conf; - include rate-limiting.conf; server { @@ -25,8 +23,7 @@ http { server { include proxy-protocol.conf; - - include proxy-server-base.conf; + include server-base.conf; listen 8443 default proxy_protocol; diff --git a/conf/proxy-server-base.conf b/conf/proxy-server-base.conf deleted file mode 100644 index 983f78762..000000000 --- a/conf/proxy-server-base.conf +++ /dev/null @@ -1,95 +0,0 @@ -# vim: ft=nginx - -client_body_temp_path /var/log/nginx/client_body 1 2; -server_name _; - -keepalive_timeout 5; - -if ($args ~ "_escaped_fragment_") { - rewrite ^ /snapshot$uri; -} - -proxy_set_header X-Forwarded-For $proxy_protocol_addr; -proxy_set_header X-Forwarded-Proto $scheme; -proxy_set_header Host $http_host; -proxy_redirect off; - -proxy_set_header Transfer-Encoding $http_transfer_encoding; - -location / { - proxy_pass http://web_app_server; - - limit_req zone=webapp; -} - -location /realtime { - proxy_pass http://web_app_server; - proxy_buffering off; - proxy_request_buffering off; -} - -location /v1/repositories/ { - proxy_buffering off; - - proxy_request_buffering off; - - proxy_pass http://registry_app_server; - proxy_read_timeout 2000; - proxy_temp_path /var/log/nginx/proxy_temp 1 2; - - client_max_body_size 20G; - - if ($http_authorization) { - limit_req zone=authrepositories; - } - - limit_req zone=unauthrepositories; -} - -location /v1/ { - proxy_buffering off; - - proxy_request_buffering off; - - proxy_pass http://registry_app_server; - proxy_read_timeout 2000; - proxy_temp_path /var/log/nginx/proxy_temp 1 2; - - client_max_body_size 20G; -} - -location /c1/ { - proxy_buffering off; - - proxy_request_buffering off; - - proxy_pass http://verbs_app_server; - proxy_read_timeout 2000; - proxy_temp_path /var/log/nginx/proxy_temp 1 2; - - limit_req zone=api; -} - -location /static/ { - # checks for static file, if not found proxy to app - alias /static/; -} - -location /v1/_ping { - add_header Content-Type text/plain; - add_header X-Docker-Registry-Version 0.6.0; - add_header X-Docker-Registry-Standalone 0; - return 200 'true'; -} - -location ~ ^/b1/controller(/?)(.*) { - proxy_pass http://build_manager_controller_server/$2; - proxy_read_timeout 2000; -} - -location ~ ^/b1/socket(/?)(.*) { - proxy_pass http://build_manager_websocket_server/$2; - proxy_http_version 1.1; - proxy_set_header Upgrade $http_upgrade; - proxy_set_header Connection "upgrade"; -} diff --git a/conf/rate-limiting.conf b/conf/rate-limiting.conf index d3f8a3cb3..e25897d82 100644 --- a/conf/rate-limiting.conf +++ b/conf/rate-limiting.conf @@ -1,8 +1,16 @@ # vim: ft=nginx +# Check the Authorization header and, if it is empty, use their proxy protocol +# IP, else use the header as their unique identifier for rate limiting. +# Enterprise users will never be using proxy protocol, thus the value will be +# empty string. This means they will not get rate limited. +map $http_authorization $registry_bucket { + "" $proxy_protocol_addr; + default $http_authorization; +} + limit_req_zone $proxy_protocol_addr zone=webapp:10m rate=25r/s; -limit_req_zone $proxy_protocol_addr zone=authrepositories:10m rate=1r/s; -limit_req_zone $proxy_protocol_addr zone=unauthrepositories:10m rate=2r/m; limit_req_zone $proxy_protocol_addr zone=api:10m rate=1r/s; +limit_req_zone $registry_bucket zone=repositories:10m rate=1r/s; limit_req_status 429; limit_req_log_level warn; diff --git a/conf/server-base.conf b/conf/server-base.conf index d5b211c52..9651f8391 100644 --- a/conf/server-base.conf +++ b/conf/server-base.conf @@ -3,16 +3,13 @@ client_body_temp_path /var/log/nginx/client_body 1 2; server_name _; -set_real_ip_from 172.17.0.0/16; -real_ip_header X-Forwarded-For; - keepalive_timeout 5; if ($args ~ "_escaped_fragment_") { rewrite ^ /snapshot$uri; } -proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for; +proxy_set_header X-Forwarded-For $proper_forwarded_for; proxy_set_header X-Forwarded-Proto $scheme; proxy_set_header Host $http_host; proxy_redirect off; @@ -21,6 +18,8 @@ proxy_set_header Transfer-Encoding $http_transfer_encoding; location / { proxy_pass http://web_app_server; + + limit_req zone=webapp; } location /realtime { @@ -29,6 +28,18 @@ location /realtime { proxy_request_buffering off; } +location /v1/repositories/ { + proxy_buffering off; + + proxy_request_buffering off; + + proxy_pass http://registry_app_server; + proxy_read_timeout 2000; + proxy_temp_path /var/log/nginx/proxy_temp 1 2; + + limit_req zone=repositories; +} + location /v1/ { proxy_buffering off; @@ -49,6 +60,8 @@ location /c1/ { proxy_pass http://verbs_app_server; proxy_read_timeout 2000; proxy_temp_path /var/log/nginx/proxy_temp 1 2; + + limit_req zone=api; } location /static/ {