Ограничение скорости NGINX не работает при использовании Cloudflare. Я могу отключить свой сайт с помощью простой команды `ab` - PullRequest
2 голосов
/ 05 мая 2020

Я реализовал довольно простое, но очень эффективное ограничение скорости на основе этого сообщения в блоге: https://www.nginx.com/blog/rate-limiting-nginx/

В основном:

limit_req_zone $binary_remote_addr zone=ip:10m rate=10r/s;

limit_req zone=ip burst=20 nodelay;

Он отлично работает. Однако недавно я попробовал Cloudflare, и это меня больше не защищает. Я могу сам закрыть сайт с помощью простой команды:

ab -k -c 1000 -n 10000 site.com/

Что происходит?

Ответы [ 3 ]

3 голосов
/ 11 мая 2020

ab -k -c 1000 -n 10000 site.com/ выполняет 1000 запросов параллельно, пока не будет выполнено в общей сложности 10 000 запросов.

Это слишком жестоко. Вполне вероятно, что ни клиент, ни сервер не настроены на обработку тысяч подключений за несколько секунд.

Настройте конфигурацию nginx и проведите осторожный тест ab -k -c 5 -n 500 site.com/

limit_req_zone $http_cf_connecting_ip zone=ip:10m rate=3r/s;
limit_req zone=ip;

limit_conn_status 429;
limit_req_status 429;

429 Too Many Requests

Это настраивает nginx для возврата стандартного кода состояния 429 Too Many Requests , когда запросы отклоняются из-за ограничения скорости.

nginx возвращает ошибка 503 по умолчанию (плохое значение по умолчанию) означает, что приложение не работает, но оно не дает сбоев, оно ограничено по скорости. Важно правильно настроить код состояния, чтобы различать guish между ошибками сервера и ограничением скорости.

Cloudflare и IP-адрес клиента

Если за облачным флэш-памятью, nginx не увидит IP клиента, но IP-адрес сервера Cloudflare. Можно подумать, что он нарушает ограничение скорости по IP, но это не совсем так.

При локальном тестировании с ab ваш тестовый компьютер разрешает только несколько серверов cloudflare. , и ab вероятно использует только первый IP. Так что нет большого количества IP-адресов клиентов, ограничение скорости должно работать нормально.

В рабочем состоянии разные клиенты будут получать доступ через разные серверы Cloudflare. Тем не менее, не так много серверов и клиентов Cloudflare в географической c области, скорее всего, будут обращаться к одним и тем же серверам Cloudflare. Таким образом, будет множество разных IP-адресов, которые несколько побеждают ограничение скорости, но, вероятно, не так много.

> nslookup mycloudflaresite.com

Name:    mycloudflaresite.com
Addresses:  104.28.14.125
            104.28.15.125
            2606:4700:3037::681c:e7d
            2606:4700:3036::681c:f7d

Cloudflare помещает исходный IP-адрес клиента в заголовок CF-Connecting-IP. Это также может быть в заголовке X-Forwarded-For или X-Real-Ip или True-Client-IP в зависимости от настроек и запросов. См. https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-

Следовательно, приведенная выше конфигурация ограничивает скорость по клиентскому IP с помощью заголовка CF-Connecting-IP. Переменная nginx $binary_remote_addr будет IP-адресом сервера cloudflare.

Не используйте X-Forwarded-For для ограничения скорости

Заголовок X-Forwarded-For может управляться клиентом. Его не следует использовать для ограничения скорости, поскольку его легко обойти.

Пример с клиентом, имеющим IP-адрес 100.11.22.33:

  • По запросу без X-Forwarded-For header => Cloudflare устанавливает X-Forwarded-For: 100.11.22.33 и CF-Connecting-IP: 100.11.22.33 по запросу.
  • По запросу с уже установленным заголовком X-Forwarded-For: dummyvalue => CloudFlare устанавливает X-Forwarded-For: dummyvalue,100.11.22.33 и CF-Connecting-IP: 100.11.22.33 по запросу.

Как видите, для клиента тривиально указать случайное значение для каждого запроса и полностью обойти любое ограничение скорости, основанное на заголовке X-Forwaded-For.

0 голосов
/ 08 мая 2020

Я бы посоветовал попробовать следующее:

(не уверен, что ваш бэкэнд PHP, но вы можете перенастроить)

# Conection Limit, taking the best from:
# http://serverfault.com/questions/177461/how-to-rate-limit-in-nginx-but-including-excluding-certain-ip-addresses
# http://gadelkareem.com/2015/01/18/limiting-connections-requests-wordpress-nginx/

geo $whitelist {
   default 0;
   # CIDR in the list below are not limited ( 1 )
   127.0.0.1/32 1;

}

map $whitelist $limit {
    0     $binary_remote_addr;
    1     "";
}

# The directives below limit concurrent connections from a 
# non-whitelisted IP address to five

limit_conn_zone      $limit    zone=conlimit:30m;
limit_conn_zone      $limit    zone=conlimit_php:30m;

limit_conn           conlimit 40;
limit_conn_log_level warn;   # logging level when threshold exceeded
limit_conn_status    503;    # the error code to return

# Limit Req Non - PHP 
limit_req_zone       $limit   zone=reqlimit:30m  rate=5r/s; 
limit_req            zone=reqlimit burst=10;

# Limit Req PHP
limit_req_zone       $limit   zone=reqlimit_php:30m  rate=1r/s; 

limit_req_log_level  warn;
limit_req_status     503;

# Location VirtualHost

limit_req            zone=reqlimit_php burst=4;
limit_conn           conlimit_php 10;

И для CF-Connecting-IP , вы можете внести IP-адреса Cloudflare в белый список через:

#!/bin/bash
cloudflare_real_ip_conf='/usr/local/nginx/conf/cloudflare_ip.conf'

echo "#Cloudflare" > ${cloudflare_real_ip_conf};
for i in `curl -sk https://www.cloudflare.com/ips-v4`; do
        echo "set_real_ip_from $i;" >> ${cloudflare_real_ip_conf};
done
for i in `curl -sk https://www.cloudflare.com/ips-v6`; do
        echo "set_real_ip_from $i;" >> ${cloudflare_real_ip_conf};
done

echo "" >> ${cloudflare_real_ip_conf};
echo "# use any of the following two" >> ${cloudflare_real_ip_conf};
echo "real_ip_header CF-Connecting-IP;" >> ${cloudflare_real_ip_conf};
echo "#real_ip_header X-Forwarded-For;" >> ${cloudflare_real_ip_conf};

, что создаст белый список CF (в настоящее время):

#Cloudflare
set_real_ip_from 173.245.48.0/20;
set_real_ip_from 103.21.244.0/22;
set_real_ip_from 103.22.200.0/22;
set_real_ip_from 103.31.4.0/22;
set_real_ip_from 141.101.64.0/18;
set_real_ip_from 108.162.192.0/18;
set_real_ip_from 190.93.240.0/20;
set_real_ip_from 188.114.96.0/20;
set_real_ip_from 197.234.240.0/22;
set_real_ip_from 198.41.128.0/17;
set_real_ip_from 162.158.0.0/15;
set_real_ip_from 104.16.0.0/12;
set_real_ip_from 172.64.0.0/13;
set_real_ip_from 131.0.72.0/22;
set_real_ip_from 2400:cb00::/32;
set_real_ip_from 2606:4700::/32;
set_real_ip_from 2803:f800::/32;
set_real_ip_from 2405:b500::/32;
set_real_ip_from 2405:8100::/32;
set_real_ip_from 2a06:98c0::/29;
set_real_ip_from 2c0f:f248::/32;

# use any of the following two
real_ip_header CF-Connecting-IP;
#real_ip_header X-Forwarded-For;
0 голосов
/ 08 мая 2020

Вы можете добавить ниже к себе nginx config

real_ip_header CF-Connecting-IP;

Подробнее см. Статью ниже

https://support.cloudflare.com/hc/en-us/articles/200170986-How-does-Cloudflare-handle-HTTP-Request-headers-

...