Haproxy — очень мощный и гибкий инструмент. В этой заметке мы продемонстрируем его применение в двух достаточно экзотических задачах.
Маршрутизировать запрос клиента в зависимости от авторизации.
Однажды в fastenv мы столкнулись с такой задачей: есть некий веб ресурс, где авторизуется клиент. Разным клиентам надо показывать разные web-странички. С самого рождения этой задачи меня не покидало ощущение — должно существовать простое решение админскими инструментами. Поиск «auth vhost», «auth based route» к готовому решению не привел, тогда я взял любымый haproxy и сделал на нём:
userlist server-access group private users fastenv group public users public1,test user fastenv insecure-password fastenv user public1 insecure-password public1 user test insecure-password test frontend example-vhost bind *:8080 acl auth_private1 http_auth_group(server-access) private acl auth_public1 http_auth_group(server-access) public use_backend auth-private if auth_private1 use_backend auth-public if auth_public1 default_backend auth-null backend auth-private errorfile 503 /etc/haproxy/private.http backend auth-public errorfile 503 /etc/haproxy/public.http backend auth-null errorfile 503 /etc/haproxy/null.http |
Рассмотрим ключевые моменты:
for backend in public private null; do echo "${backend^} backend" > ${backend}.http; done |
Проверяем:
curl http://example.local:8080/ Null backend # Авторизационных данных нет. curl --user fastenv:test http://example.local:8080/ Null backend # Авторизационные данные неверны. curl --user fastenv:fastenv http://example.local:8080/ Private backend # Прекрасно! Попали в нужный бекенд. curl --user public1:public1 http://example.local:8080/ Public backend curl --user test:test http://example.local:8080/ Public backend # Великолепно! |
Далее концепцию развить по вкусу. Например в бекенде auth-null можно отправить запрос на красивую страничку авторизации. Всё что от нее требуется — проставить заголовок Authorization c Basic кредами. В простейшем случае можно попросить сам haproxy требовать авторизацию. Для этого приведем auth-null к виду:
backend auth-null errorfile 503 /etc/haproxy/null.http http-request auth realm Fastenv |
Проверяем:
curl --user test:test2 http://example.local:8080/ <h1>401 Unauthorized</h1> You need a valid user and password to access this content. |
Браузер отреагирует на 401 код и выведет запрос авторизации.
Дать временный доступ к 22 порту для определенного ip.
Наверное все администраторы публичных linux серверов сталкивались с следующей ситуацией: Стоит выставить сервер наружу, как спустя несколько дней доброжелатели начинают перебирать пароли к ssh. Каждый для себя решает эту проблему по-своему. Кто-то настраивает fail2ban, кто-то настраивает access листы, кто-то вообще брутфорс проблемой не считает, ну а я просто переношу ssh на нестандартный порт. А однажды захотелось экзотики: Открывать 22 порт для клиентов внешней сети, сделавших определенный http запрос. Конечно же с авторизацией =)
Haproxy, its your turn:
userlist ssh-external-access user artem insecure-password fastenv frontend ssh-auth bind *:9090 acl auth_ok http_auth(ssh-external-access) use_backend ssh-allow if auth_ok default_backend ssh-deny backend ssh-allow errorfile 503 /etc/haproxy/ssh-allow.http stick-table type ip size 100 expire 10m store conn_cnt tcp-request content track-sc0 src backend ssh-deny errorfile 403 /etc/haproxy/ssh-denied.http http-request deny frontend ssh bind *:22 mode tcp option tcplog acl auth_ok src_conn_cnt(ssh-allow) gt 0 use_backend ssh if auth_ok backend ssh mode tcp server localhost 127.0.0.1:10522 |
Проверяем:
echo | nc example.local 22 | awk 'NR==1 {print $1}' # Ничего в ответ - всё верно. curl --user artem:google http://example.local:9090/ Try later.. echo | nc example.local 22 | awk 'NR==1 {print $1}' # Тишина. curl --user artem:fastenv http://example.local:9090/ Now this door is open for you.. # =) echo | nc example.local 22 | awk 'NR==1 {print $1}' SSH-2.0-OpenSSH_6.6.1p1 # Всё работает. У нас есть 10 минут что бы залогиниться.) |
Теперь разберем, как это работает:
P.S.
Конфиги носят минимальный характер. В реальном деле вам захочется: