service:haproxy
Различия
Показаны различия между двумя версиями страницы.
Предыдущая версия справа и слеваПредыдущая версияСледующая версия | Предыдущая версия | ||
service:haproxy [11.02.2022 10:02] – [map()] viacheslav | service:haproxy [30.07.2024 19:21] (текущий) – внешнее изменение 127.0.0.1 | ||
---|---|---|---|
Строка 1: | Строка 1: | ||
+ | ====== haproxy ====== | ||
+ | [[https:// | ||
+ | |||
+ | Reverse proxy и NLB 7-го и 4-го уровня. | ||
+ | |||
+ | ==== Установка ==== | ||
+ | <code bash> | ||
+ | sudo apt install --no-install-recommends software-properties-common | ||
+ | sudo add-apt-repository ppa: | ||
+ | sudo apt install haproxy=2.5.\* | ||
+ | </ | ||
+ | https:// | ||
+ | |||
+ | ==== Конфиг ==== | ||
+ | Конфиг состоит из 4 основных частей: | ||
+ | - **global** - общие настройки | ||
+ | - **defaults** - значения по умолчанию для frontend и backend. Этих секций может быть несколько, | ||
+ | - **frontend** - приём пользовательских запросов, | ||
+ | - **backend** - мониторинг серверов, | ||
+ | |||
+ | Есть ещё секция **listen** - её можно использовать как объединение frontend и backend. Обычно применяется для TCP. На примере HAProxy stats page: | ||
+ | <code bash> | ||
+ | frontend stats | ||
+ | bind *:8404 | ||
+ | stats enable | ||
+ | stats uri /stats | ||
+ | stats refresh 10s | ||
+ | stats admin if { src 127.0.0.1 } | ||
+ | </ | ||
+ | https:// | ||
+ | |||
+ | Есть также секции: | ||
+ | - **resolvers** - настройка DNS (сервера тогда можно указывать как DNS-имя) | ||
+ | - **mailers** - configuring email notifications | ||
+ | - **peers** - синхронизация между узлами HAProxy. | ||
+ | |||
+ | **defaults** может быть в нескольких экземплярах - последующая сбрасывает настройки предыдущей. Положим, | ||
+ | |||
+ | **backend**\\ | ||
+ | Самые популярные варианты балансировки: | ||
+ | balance roundrobin - просто циклический перебор\\ | ||
+ | balance leastconn - выбор сервера с наименьшим числом соединений | ||
+ | |||
+ | cookie - засылается клиенту для сохранения настроек соединения - клиент продолжает общаться с тем же сервером до конца сессии. | ||
+ | |||
+ | default-server - можно перечислить опции для всех серверов, | ||
+ | |||
+ | Простейший конфиг (frontend и backend) | ||
+ | <code bash> | ||
+ | frontend http | ||
+ | bind :80 | ||
+ | acl test url_beg -i test | ||
+ | # или так: | ||
+ | # acl test path -i -m beg /test | ||
+ | use_backend test if test | ||
+ | # вариант записи в одну строку (anonymous or inline ACL) | ||
+ | # use_backend test if { path -i -m beg /test } | ||
+ | | ||
+ | # редирект на Яндекс | ||
+ | acl yandex path -i -m beg /yandex | ||
+ | http-request redirect location https:// | ||
+ | | ||
+ | # во всех остальных случаях слать на root backend (типа else) | ||
+ | default_backend root | ||
+ | |||
+ | backend test | ||
+ | balance roundrobin | ||
+ | server web1 192.168.1.31: | ||
+ | server web2 192.168.1.32: | ||
+ | |||
+ | backend root | ||
+ | balance roundrobin | ||
+ | server web1 192.168.1.31: | ||
+ | server web2 192.168.1.32: | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | # Протестировать конфиг | ||
+ | haproxy -f / | ||
+ | </ | ||
+ | |||
+ | HAProxy easily tells [[https:// | ||
+ | |||
+ | https:// | ||
+ | https:// | ||
+ | http:// | ||
+ | |||
+ | ==== tune.ssl.default-dh-param ==== | ||
+ | Предупреждение при проверке конфига, | ||
+ | [WARNING] 012/103010 (81203) : parsing [/ | ||
+ | unable to load default 1024 bits DH parameter for certificate '/ | ||
+ | , SSL library will use an automatically generated DH parameter. | ||
+ | [WARNING] 012/103010 (81203) : Setting tune.ssl.default-dh-param to 1024 by default, if your workload permits it you should set it to at least 2048. Please set a value >= 1024 to make this warning disappear. | ||
+ | Configuration file is valid | ||
+ | |||
+ | Решение: | ||
+ | <code bash> | ||
+ | sudo openssl dhparam -out / | ||
+ | |||
+ | sudo vi / | ||
+ | # Вставить в секцию global | ||
+ | ssl-dh-param-file / | ||
+ | </ | ||
+ | https:// | ||
+ | ==== Конфиг для Exchange 2013 ==== | ||
+ | OWA healthcheck page: https:// | ||
+ | |||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | [[https:// | ||
+ | |||
+ | ++++ haproxy.cfg с одной из прошлых работ | | ||
+ | |||
+ | <file bash haproxy.cfg> | ||
+ | global | ||
+ | log 127.0.0.1 local0 info | ||
+ | maxconn 10000000 | ||
+ | daemon | ||
+ | quiet | ||
+ | debug | ||
+ | tune.ssl.default-dh-param 2048 | ||
+ | |||
+ | defaults | ||
+ | log global | ||
+ | mode http | ||
+ | option httplog | ||
+ | option dontlognull | ||
+ | timeout connect 1600000ms | ||
+ | timeout client 1600000ms | ||
+ | timeout server 1600000ms | ||
+ | timeout check 1600000ms | ||
+ | stats enable | ||
+ | stats uri /stats | ||
+ | |||
+ | # в браузере вылезает окно с авторизацией перед входом | ||
+ | userlist basic-auth-list | ||
+ | user TEST insecure-password Pass123 | ||
+ | |||
+ | frontend fe_http_all | ||
+ | bind *:80 | ||
+ | mode http | ||
+ | maxconn 10000000 | ||
+ | acl autodiscover url_beg / | ||
+ | acl autodiscover url_beg / | ||
+ | # use_backend be_h_ex2013 if autodiscover | ||
+ | | ||
+ | |||
+ | frontend fe_https | ||
+ | mode http | ||
+ | maxconn 10000000 | ||
+ | #bind *:443 ssl crt / | ||
+ | bind *:443 ssl crt / | ||
+ | acl Autodiscover url_beg / | ||
+ | acl autodiscover url_beg / | ||
+ | acl bad_ip src 223.72.82.215 185.25.51.234 78.128.92.106 185.86.150.196 104.196.214.152 | ||
+ | acl good_ip_ews src -f / | ||
+ | #acl legacy_host hdr_beg(host) -i legacy. | ||
+ | #acl mail_host hdr_beg(host) -i mail. | ||
+ | acl q_host hdr_beg(host) -i q. | ||
+ | #acl mapi url_beg /mapi | ||
+ | #acl rpc url_beg /rpc | ||
+ | #acl RPC url_beg /RPC | ||
+ | acl owa url_beg /owa | ||
+ | #acl eas url_beg / | ||
+ | #acl Eas url_beg / | ||
+ | #acl ecp url_beg /ecp | ||
+ | acl ews url_beg /ews | ||
+ | acl EWS url_beg /EWS | ||
+ | acl calendar url_beg / | ||
+ | acl Calendar url_beg / | ||
+ | | ||
+ | # use_backend be_secure_ex2013 if q_host owa | ||
+ | | ||
+ | | ||
+ | | ||
+ | # use_backend be_cas01_ex2013 if owa | ||
+ | | ||
+ | | ||
+ | | ||
+ | | ||
+ | default_backend be_ex2013 # менять на активный be_cas0X_ex2013 for_change | ||
+ | # | ||
+ | |||
+ | frontend fe_imap | ||
+ | mode tcp | ||
+ | bind *:993 | ||
+ | default_backend be_imap_ex2013 | ||
+ | |||
+ | frontend fe_tls | ||
+ | mode tcp | ||
+ | bind *:143 | ||
+ | default_backend be_tls_ex2013 | ||
+ | |||
+ | #frontend fe_smtp | ||
+ | #mode tcp | ||
+ | #bind *:25 | ||
+ | # | ||
+ | |||
+ | #backend be_ecp_ex2013 | ||
+ | #maxconn 10000000 | ||
+ | #mode http | ||
+ | #balance roundrobin | ||
+ | #server cas01 192.168.5.111: | ||
+ | #server cas02 192.168.5.112: | ||
+ | |||
+ | backend be_secure_ex2013 | ||
+ | #acl q-auth http_auth(basic-auth-list) | ||
+ | # | ||
+ | maxconn 10000000 | ||
+ | mode http | ||
+ | balance roundrobin | ||
+ | server cas01 192.168.5.111: | ||
+ | server cas02 192.168.5.112: | ||
+ | |||
+ | backend be_ex2013 | ||
+ | maxconn 10000000 | ||
+ | mode http | ||
+ | balance roundrobin | ||
+ | server cas01 192.168.5.111: | ||
+ | server cas02 192.168.5.112: | ||
+ | |||
+ | backend be_cas01_ex2013 | ||
+ | maxconn 10000000 | ||
+ | mode http | ||
+ | balance roundrobin | ||
+ | server cas01 192.168.5.111: | ||
+ | |||
+ | backend be_cas02_ex2013 | ||
+ | maxconn 10000000 | ||
+ | mode http | ||
+ | balance roundrobin | ||
+ | server cas02 192.168.5.112: | ||
+ | |||
+ | backend be_ntpserv | ||
+ | maxconn 10000000 | ||
+ | mode http | ||
+ | balance roundrobin | ||
+ | server ntpserv 192.168.5.184 | ||
+ | |||
+ | backend be_ntpserv_owa | ||
+ | maxconn 10000000 | ||
+ | mode http | ||
+ | balance roundrobin | ||
+ | server ntpserv88 192.168.5.184: | ||
+ | |||
+ | backend be_imap_ex2013 | ||
+ | mode tcp | ||
+ | balance roundrobin | ||
+ | server cas01 192.168.5.111: | ||
+ | server cas02 192.168.5.112: | ||
+ | |||
+ | backend be_tls_ex2013 | ||
+ | mode tcp | ||
+ | balance roundrobin | ||
+ | server cas01 192.168.5.111: | ||
+ | server cas02 192.168.5.112: | ||
+ | |||
+ | # | ||
+ | #stats enable | ||
+ | #stats uri / | ||
+ | # | ||
+ | #stats auth admin: | ||
+ | </ | ||
+ | ++++ | ||
+ | |||
+ | |||
+ | ===== ACL ===== | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | ACLs - правила доступа, | ||
+ | |||
+ | Примеры | ||
+ | <code bash> | ||
+ | # использовать бэкенд be_example, если заголовок host в запросе совпадает с example.com (-m[atch] dom[ain]), не учитывать регистр (-i). | ||
+ | use_backend be_example if { req.hdr(host) -i -m dom example.com } | ||
+ | # генерация имени бэкенда из запроса с помощью карты. | ||
+ | use_backend be_%[req.hdr(host), | ||
+ | # редирект на https. unless = if !{}. | ||
+ | http-request redirect scheme https unless { ssl_fc } | ||
+ | # именованное правило | ||
+ | acl is_admin_range src 10.0.48.0/ | ||
+ | # запрет ходить на URL, начинающийся на /admin всем, кроме админского диапазона. | ||
+ | http-request deny if !is_admin_range { path_beg /admin/ } | ||
+ | # посылать на /login, если нет клиентского сертификата или через lua. | ||
+ | http-request redirect location /login unless { ssl_c_used } || { lua.is_auth_valid } | ||
+ | # не совсем acl, захват значения кол-ва запросов в логи, полезно для оценки и предварительных измерений (https:// | ||
+ | http-request capture sc_http_req_rate(0) len 4 | ||
+ | </ | ||
+ | |||
+ | ACLs находятся в секциях фронтэнда (чаще всего), | ||
+ | |||
+ | Линейные (inline) ACL состоит из действия (action), выборки (fetch) и необязательных конвертеров, | ||
+ | <code bash> | ||
+ | use_backend be_example if { req.hdr(host) -i -m dom example.com } | ||
+ | </ | ||
+ | У именных (named) acl после имени идёт выборка | ||
+ | <code bash> | ||
+ | acl is_example req.hdr(host) -i -m dom example.com | ||
+ | use_backend be_example if is_example | ||
+ | </ | ||
+ | |||
+ | ==== Выборка (fetch) ==== | ||
+ | Выборка получает данные, | ||
+ | |||
+ | ==== Конвертер ==== | ||
+ | Конвертеры необязательны, | ||
+ | <code bash> | ||
+ | # имя хоста в нижний регистр, | ||
+ | req.hdr(host), | ||
+ | </ | ||
+ | Некоторые конвертеры также принимают аргументы. Популярные конвертеры: | ||
+ | |||
+ | ==== Флаги ==== | ||
+ | Флаги находятся между выборками/ | ||
+ | <code bash> | ||
+ | use_backend be_example if { path -m beg /login } | ||
+ | </ | ||
+ | Часто используются: | ||
+ | |||
+ | === Сравнения === | ||
+ | Варианты сравнения: | ||
+ | <code bash> | ||
+ | # reg | ||
+ | use_backend be_static if { path -m reg / | ||
+ | # reg может сочетаться с -f | ||
+ | use_backend be_static if { path -m reg -f / | ||
+ | # регулярные выражения ресурсоёмки, | ||
+ | |||
+ | # found - если заголовка host нет, отклонить запрос | ||
+ | http-request deny unless { req.hdr(host) -m found } | ||
+ | </ | ||
+ | |||
+ | === Выборки со встроенным сравнением === | ||
+ | Выборки со встроенным сравнением: | ||
+ | |||
+ | === Сравнения с числами === | ||
+ | Сравнения с числами - eq, ge, gt, le, lt. | ||
+ | <code bash> | ||
+ | http-request deny if { sc_http_req_rate(0) gt 50 } | ||
+ | # диапазон разделён двоеточием, | ||
+ | acl ssl req.ssl_ver 3:3.1 | ||
+ | </ | ||
+ | |||
+ | ==== Значения ==== | ||
+ | Значения должны быть статическими, | ||
+ | <code bash> | ||
+ | # Строки, | ||
+ | use_backend be_static if { path_beg /images /icons } | ||
+ | # ip или их диапазоны | ||
+ | http-request deny unless { src 192.168.0.0/ | ||
+ | # Двоичные данные | ||
+ | use_backend be_multiplayer if { payload(0, | ||
+ | </ | ||
+ | |||
+ | ==== Действия ==== | ||
+ | Собственно, | ||
+ | <code bash> | ||
+ | # редирект | ||
+ | http-request redirect scheme https code 301 unless { ssl_fc } | ||
+ | http-request redirect location /login unless { req.cook(sessionid) -m found } | ||
+ | # переделать путь на лету - не редирект, | ||
+ | http-request set-path / | ||
+ | # добавить заголовок из stick table | ||
+ | http-request set-header x-pages-viewed %[sc_gpc0_rate(0)] | ||
+ | # использовать кэш | ||
+ | http-request cache-use static if {path_beg /static/ } | ||
+ | # отправлять на бэкенд be_example в соответствии с заголовком host | ||
+ | use_backend be_example if { req.hdr(host) -i -m dom www.example.com } | ||
+ | # динамически создавать имя бэкенда из заголовка в нижнем регистре | ||
+ | use_backend be_%[req.hdr(host), | ||
+ | # дополнительно задействовать карту | ||
+ | use_backend be_%[req.hdr(host), | ||
+ | </ | ||
+ | |||
+ | Порядок срабатывания действий в соответствии с фазами соединения: | ||
+ | * tcp-request connection (на раннем этапе полезно отшибать DoS-атаки с кучей соединений, | ||
+ | * tcp-request content (используемый протокол, | ||
+ | * http-request (например, | ||
+ | * http-response (например, | ||
+ | |||
+ | '' | ||
+ | '' | ||
+ | |||
+ | ==== Переменные ==== | ||
+ | Не требуются, | ||
+ | * Пути или заголовки из запроса на этапе ответа | ||
+ | * В выборках/ | ||
+ | * Задание записи в карте с sessionid cookie на основe заголовка ответа: | ||
+ | use_backend %[req.cook(sessionid), | ||
+ | http-response set-map(/ | ||
+ | res.hdr(x-sessionid-backend) if { res.hdr(x-sessionid-backend) -m found } | ||
+ | </ | ||
+ | |||
+ | Как их использовать | ||
+ | |||
+ | * В http-request/ | ||
+ | * Scope может быть txn (самый частый случай), | ||
+ | * Name может состоять из чисел, букв, точек и подчёркиваний. | ||
+ | * Во всех случаях переменная будет иметь имя **txn.name**, | ||
+ | * Значение переменной извлекается в выборке как '' | ||
+ | * В LUA - '' | ||
+ | |||
+ | ==== Карты и ACL-файлы ==== | ||
+ | ACL-файлы - это просто список для сравнения, | ||
+ | |||
+ | * Все они являются файлами на диске, который читаются на этапе запуска | ||
+ | * ACL-файлы имеют одну колонку, | ||
+ | * Все они могут быть прочитаны и изменены через runtime API: | ||
+ | * '' | ||
+ | * '' | ||
+ | * Все они могут быть изменены через модуль '' | ||
+ | |||
+ | === ACL-файлы === | ||
+ | * Одна строка на образец | ||
+ | * Образец может быть IP-адресом (диапазоном), | ||
+ | * Может быть использован с режимами сравнения '' | ||
+ | * Используется с помощью ключа '' | ||
+ | |||
+ | == Действия и ACL-файлы == | ||
+ | * http-request add-acl | ||
+ | * http-response add-acl | ||
+ | * http-request add-acl | ||
+ | * http-response add-acl | ||
+ | |||
+ | Таким образом, | ||
+ | <code bash> | ||
+ | http-request add-acl(/ | ||
+ | http-request add-acl(/ | ||
+ | </ | ||
+ | |||
+ | === Карты === | ||
+ | * Используются через " | ||
+ | * Подбирает образец, | ||
+ | * Возвращает результат поиска | ||
+ | * Сравнивать можно практически любым способом - beg, dir, dom, end, len, reg, sub | ||
+ | * Действия http-request/ | ||
+ | * Используются для: | ||
+ | * Сопоставления имён хостов бэкендам | ||
+ | * Хранения лимитов для ключей | ||
+ | |||
+ | ===== Карты (maps) ===== | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | Нужны для | ||
+ | * Направления трафика на бэкенды | ||
+ | * GeoIP | ||
+ | * API key | ||
+ | * Лимитов для доменов/ | ||
+ | |||
+ | Карта выглядит примерно так: | ||
+ | <code bash> | ||
+ | # key value | ||
+ | example.com be_example | ||
+ | haproxy.com be_haproxy | ||
+ | test.ru | ||
+ | </ | ||
+ | |||
+ | <code bash> | ||
+ | frontend fe_main | ||
+ | bind :443 ssl crt / | ||
+ | # Взять хост из заголовка, | ||
+ | # Если значения нет, использовать значение по умолчанию (здесь: | ||
+ | use_backend %[req.hdr(host), | ||
+ | </ | ||
+ | |||
+ | ==== map() ==== | ||
+ | * На вход в конвертер карты подаётся образец, | ||
+ | * Обязательным значением является путь к файлу карты. | ||
+ | * Необязательный аргумент - значение по умолчанию. | ||
+ | * Возвращает значение из второй колонки, | ||
+ | * Варианты сравнения - str, beg, sub, dir, dom, end, reg, regm, int, ip | ||
+ | |||
+ | ==== Обновление карты ==== | ||
+ | Так как haproxy читает файлы только во время инициализации, | ||
+ | |||
+ | Все методы не обновляют самих файлов карт на диске! Чтобы обновлять сами файлы, нужно отдельно запускать show map и дамп в файл (например, | ||
+ | |||
+ | Первый метод - модуль LB-Update (только для версии enterprise). Его легко настраивать, | ||
+ | <code bash> | ||
+ | dynamic-update | ||
+ | update id / | ||
+ | </ | ||
+ | |||
+ | Второй метод - через сокет (см. https:// | ||
+ | <code bash> | ||
+ | echo "show map / | ||
+ | echo "clear map / | ||
+ | echo "del map / | ||
+ | # add map не проверяет, | ||
+ | # поэтому надо сочетать это в скрипте с show map, чтобы проверить наличие до добавления | ||
+ | echo "add map / | ||
+ | echo "set map / | ||
+ | </ | ||
+ | |||
+ | При использовании nbproc у каждого процесса haproxy свой взгляд на файлы карт. В отличие от модуля lb-update здесь у каждого процесса свой сокет, и нужно обновлять карты для каждого процесса. С версии 1.9 используется усовершенствованный nbthread, позволяющий работать без потерь производительности при нескольких процессах haproxy.\\ | ||
+ | https:// | ||
+ | |||
+ | Третий - через ACL (неприменимо, | ||
+ | <code bash> | ||
+ | frontend fe_main | ||
+ | bind :80 | ||
+ | # при запросе определённого url из определённой сети | ||
+ | acl in_network src 192.168.122.0/ | ||
+ | acl is_map_add path_beg /map/add | ||
+ | # задать запись в карте (в памяти) | ||
+ | http-request set-map(/ | ||
+ | # не передавать этот запрос на бэкенд | ||
+ | http-request deny deny_status 200 if is_map_add in_network | ||
+ | # использовать бэкенд с картой при всех прочих запросах | ||
+ | use_backend %[req.hdr(host), | ||
+ | </ | ||
+ | |||
+ | ==== Примеры ==== | ||
+ | |||
+ | === Paths rate limit === | ||
+ | Карта: | ||
+ | / | ||
+ | / | ||
+ | |||
+ | <code bash> | ||
+ | frontend api_gateway | ||
+ | bind :80 | ||
+ | default_backend api_servers | ||
+ | # Set up stick table to track request rates | ||
+ | stick-table type binary len 8 size 1m expire 10s store http_req_rate(10s) | ||
+ | # Track client by base32+src (Host header + URL path + src IP) | ||
+ | http-request track-sc0 base32+src | ||
+ | # Check map file to get rate limit for path | ||
+ | http-request set-var(req.rate_limit) | ||
+ | # Client' | ||
+ | http-request set-var(req.request_rate) | ||
+ | # Subtract the current request rate from the limit | ||
+ | # If less than zero, set rate_abuse to true | ||
+ | acl rate_abuse var(req.rate_limit), | ||
+ | # Deny if rate abuse | ||
+ | http-request deny deny_status 429 if rate_abuse | ||
+ | </ | ||
+ | |||
+ | === Чёрный список === | ||
+ | Пример файла ACL. | ||
+ | <code bash> | ||
+ | acl is_admin_ip src 192.168.122.0/ | ||
+ | # добавляем-удаляем значения с админских диапазонов | ||
+ | http-request add-acl(/ | ||
+ | http-request del-acl(/ | ||
+ | # не пробрасывать никуда, | ||
+ | http-request deny deny_status 200 if is_admin_ip { path_beg /blacklist/ } | ||
+ | # блочить, | ||
+ | http-request deny if ( src -f / | ||
+ | </ | ||
+ | |||
+ | ===== Stick tables ===== | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | Хранилище " | ||
+ | Популярные значения - conn_cur, conn_rate, http_req_rate, | ||
+ | |||
+ | Используются для | ||
+ | * Привязки клиента к серверу | ||
+ | * Session cookies | ||
+ | * SSL session ID | ||
+ | * Исходный IP | ||
+ | * Лимитирования | ||
+ | * GET/POST floods | ||
+ | * Login brute force | ||
+ | * Web scraping | ||
+ | * API key usage | ||
+ | * Статистики/ | ||
+ | |||
+ | Таблица может быть **только одна** в секции frontend/ | ||
+ | Данные в неё добавляются с помощью действия '' | ||
+ | |||
+ | В примере используется пустой бэкенд с таблицей, | ||
+ | <code bash> | ||
+ | backend st_src_global | ||
+ | stick-table type ip size 1m expire 10s store http_req_rate(10s) | ||
+ | |||
+ | frontend fe_main | ||
+ | bind *:80 | ||
+ | http-request track-sc0 src table st_src_global | ||
+ | http-request deny if { sc_http_req_rate(0) gt 10 } | ||
+ | </ | ||
+ | |||
+ | ==== Multiprocessing ==== | ||
+ | * Если используется nbproc (версия 1.8 и старее), | ||
+ | * Если используется nbthread (версия 1.9 и новее), | ||
+ | |||
+ | ==== Синтаксис ==== | ||
+ | <code bash> | ||
+ | backend st_ip | ||
+ | # stick-table тип < | ||
+ | stick-table type ip size 1m expire 10s store http_req_rate(10s), | ||
+ | </ | ||
+ | * За типами string и binary идёт параметр len (длина) - это число байт для захвата, | ||
+ | * Размер - кол-во строк в таблице (здесь 1 млн), нужен, чтобы не забить всю память. Из практических соображений не нужно задавать слишком много значений, | ||
+ | * Истечение срока хранения - максимальное время, прошедшее с момента добавления, | ||
+ | |||
+ | ==== Хранение данных ==== | ||
+ | <code bash> | ||
+ | http-request track-sc0 src table st_ip | ||
+ | </ | ||
+ | * sc0 - sticky counter 0 | ||
+ | * src - выборка, | ||
+ | * Частота запросов/ | ||
+ | * Статистика: | ||
+ | * Привязка: | ||
+ | * table - какую таблицу использовать. Этот параметр не нужен, если таблица находится в той же секции. | ||
+ | |||
+ | В рамках одной сессии нужен уникальный номер sc для каждой записи. | ||
+ | |||
+ | Здесь нужны разные номера, | ||
+ | <code bash> | ||
+ | http-request track-sc0 src table st_src | ||
+ | http-request track-sc1 base32 table st_base32 | ||
+ | </ | ||
+ | |||
+ | А здесь - нет, т. к. они никогда не пересекаются: | ||
+ | <code bash> | ||
+ | http-request track-sc0 src st_src_get if METH_GET | ||
+ | http-request track-sc0 src st_src_post if METH_POST | ||
+ | </ | ||
+ | |||
+ | * Номер задаётся флагом компиляции '' | ||
+ | * Номер sc используется потом в аргументах выборки, | ||
+ | |||
+ | ==== Использование значений ==== | ||
+ | 1) С помощью выборки. Выборка, | ||
+ | <code bash> | ||
+ | http-request deny if { sc_http_req_rate(0) gt 3 } | ||
+ | </ | ||
+ | Популярные выборки: | ||
+ | |||
+ | 2) С помощью конвертера, | ||
+ | <code bash> | ||
+ | http-request deny if { src, | ||
+ | </ | ||
+ | Применяется для таблиц, | ||
+ | |||
+ | ==== Просмотр содержимого ==== | ||
+ | С помощью API-запросов. В версии Enterprise есть веб-интерфейс. | ||
+ | <code bash> | ||
+ | echo "show table st_src_global" | ||
+ | # Обновлять каждые 5 секунд | ||
+ | watch -n 5 'echo "show table st_src_global" | ||
+ | </ | ||
+ | |||
+ | ==== Примеры ==== | ||
+ | Постоянное подключение к одному из серверов (привязка) + peers | ||
+ | <code bash> | ||
+ | # Протокол peers позволяет передавать данные из таблицы на все сервера-партнёры | ||
+ | peers mypeers | ||
+ | # Имя партнёра должно совпадать с его hostname, либо с заданным в секции global его конфигурации haproxy | ||
+ | peer haproxy1 192.168.1.11: | ||
+ | peer haproxy2 192.168.1.12: | ||
+ | | ||
+ | backend mybackend | ||
+ | mode tcp | ||
+ | balance roundrobin | ||
+ | # Здесь нет указания значений, | ||
+ | stick-table type ip size 20k peers mypeers | ||
+ | # К чему привязываться при закреплении пользователя к серверу | ||
+ | stick on src | ||
+ | server srv1 192.168.1.101: | ||
+ | server srv2 192.168.1.102: | ||
+ | </ | ||
+ | |||
+ | Анти-флуд | ||
+ | <code bash> | ||
+ | backend st_src_global | ||
+ | stick-table type ip size 1m expire 10s store http_req_rate(10s) | ||
+ | | ||
+ | frontend fe_main | ||
+ | bind *:80 | ||
+ | http-request track-sc0 src table st_src_global | ||
+ | http-request deny if { sc_http_req_rate(0) gt 10 } | ||
+ | </ | ||
+ | |||
+ | Web scraping - в этом примере блокируются те IP, которые зашли на более чем 15 разных URL за последние 24 часа. | ||
+ | <code bash> | ||
+ | backend per_ip_and_url_rates | ||
+ | stick-table type binary len 8 size 1m expire 24h store http_req_rate(24h) | ||
+ | |||
+ | backend per_ip_rates | ||
+ | stick-table type ip size 1m expire 24h store gpc0, | ||
+ | |||
+ | frontend fe_main | ||
+ | bind *:80 | ||
+ | http-request track-sc0 src table per_ip_rates | ||
+ | http-request track-sc1 url32+src table per_ip_and_url_rates unless { path_end .css .js .png .jpeg .gif } | ||
+ | acl exceeds_limit sc_gpc0_rate(0) gt 15 | ||
+ | # Увеличить gpc0, если http_req_rate = 1 (он равен единице, | ||
+ | # Если url запрашивается не в первый раз, то http_req_rate будет больше 1, и это не сработает | ||
+ | http-request sc-inc-gpc0(0) if { sc_http_req_rate(1) eq 1 } !exceeds_limit | ||
+ | http-request deny if exceeds_limit | ||
+ | default_backend web_servers | ||
+ | </ | ||
+ | ===== DDoS Attack and Bot Protection ===== | ||
+ | https:// | ||
+ | https:// | ||
+ | https:// | ||
+ | |||
+ | ===== Логи ===== | ||
+ | https:// | ||
+ | |||
+ | < | ||
+ | # Дата сервер процесс[PID]: | ||
+ | Mar 10 11:13:42 vmls-haproxy1 haproxy[919886]: | ||
+ | </ | ||
+ | |||
+ | Состояние при завершении, | ||
+ | |||
+ | ===== Проверки ===== | ||
+ | https:// | ||
+ | |||
+ | ===== Кластер ===== | ||
+ | Active-Passive: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | Active-Active: | ||
+ | |||
+ | {{: | ||
+ | |||
+ | ==== Синхронизация конфигурации ==== | ||
+ | Сначала нужно [[service: | ||
+ | Синхронизация между двумя нодами, | ||
+ | Выдаёт статистику, | ||
+ | Помимо каталога с конфигурацией, | ||
+ | строку с переменной '' | ||
+ | Если были скопированы какие-то файлы, HAProxy перечитывает конфигурацию. | ||
+ | <file bash / | ||
+ | #!/bin/bash | ||
+ | |||
+ | rsyncConfig() { | ||
+ | int=`rsync -au --stats $1 $2 |grep transferred: | ||
+ | echo ${int##*:} | ||
+ | } | ||
+ | |||
+ | config=`rsyncConfig vmls-haproxy1:/ | ||
+ | certs=`rsyncConfig vmls-haproxy1:/ | ||
+ | all=$(( ${config: | ||
+ | |||
+ | if [[ $all -ne 0 ]] | ||
+ | then | ||
+ | echo "$all files transferred, | ||
+ | systemctl reload haproxy | ||
+ | echo " | ||
+ | else | ||
+ | echo "$all files transferred, | ||
+ | fi | ||
+ | </ | ||
+ | |||
+ | Добавить в cron | ||
+ | <code bash> | ||
+ | echo -e "\n# Sync HAProxy config\n*/5 *\t* * *\troot\t/ | ||
+ | </ | ||
+ | |||
+ | ===== Видео ===== | ||
+ | [[https:// | ||
+ | |||
+ | |||