Назад | Перейти на главную страницу

haproxy + stunnel + keep-alive?

Я бы хотел поставить stunnel перед haproxy 1.4 для обработки HTTPS-трафика. Мне также нужен stunnel, чтобы добавить X-Forwarded-For заголовок. Этого можно добиться с помощью "stunnel-4.xx-xforwarded-for.diff" патчи с сайта haproxy.

Однако в описании упоминается:

Обратите внимание, что этот патч не работает с keep-alive, ...

Мой вопрос: что это будет значить для меня на практике? Я не уверен,

  1. если речь идет о поддержании активности между
    • клиент и станнель
    • stunnel и haproxy
    • или хапрокси и бэкэнд сервер?
  2. что это означает для производительности: если у меня есть 100 значков на веб-странице, будет ли браузер согласовывать 100 полных SSL-соединений или он может повторно использовать SSL-соединение, просто создавая новые TCP-соединения?

Речь идет о HTTP keep-alive, который позволяет нескольким запросам ресурсов проходить через один сеанс TCP (а с SSL - один сеанс SSL). Это очень важно для производительности SSL-сайта, так как без поддержки активности SSL-подтверждение потребовалось бы для каждого запрошенного ресурса.

Итак, проблема здесь в одном большом сеансе поддержки активности от клиента на всем пути к внутреннему серверу. Это важно для производительности и воспринимается как нечто само собой разумеющееся для современных HTTP-серверов, но в этом патче говорится, что он его не поддерживает. Давайте разберемся, почему ..


Сеанс поддержания активности - это просто несколько запросов, один за другим - как только сервер завершает свой ответ на один запрос, сервер не отправляет FIN пакет для завершения сеанса TCP; клиент может просто отправить еще одну партию заголовков.

Чтобы понять, что делает этот патч, вот пример диалога keep-alive:

Клиент:

GET / HTTP/1.1
Connection: keep-alive
Host: domain.com
...

Сервер:

HTTP/1.1 200 OK
Content-Type: text/html; charset=UTF-8
Server: Apache
Content-Length: 34
.... (other headers)
<html><head>content!</head></html>

Вот где остановится несохраняемое соединение. Но keep-alive позволяет клиенту просто запустить другой:

GET /images/some/image.on.the.page.jpg HTTP/1.1
Connection: keep-alive
Host: domain.com
...

Для идентификатора клиента при проксировании некоторые обратные прокси-серверы могут добавлять в X-Forwarded-For заголовок в каждом клиентском запросе. Это сообщает вышестоящему серверу, откуда исходит запрос (вместо каждого запроса, инициируемого с IP-адреса обратного прокси-сервера), для корректности ведения журнала и других потребностей приложения.

В X-Forwarded-For заголовок необходимо вводить в каждый запрос клиентского ресурса, отправляемый через соединение keep-alive, поскольку полные заголовки отправляются каждый раз; обработка X-Forwarded-For заголовок и преобразование в «настоящий» IP-адрес запроса выполняется для каждого запроса, а не для TCP-keep-alive-session. И, может быть, есть отличное программное обеспечение обратного прокси, которое использует один сеанс поддержки активности для обслуживания запросов от нескольких клиентов.

Вот где этот патч терпит неудачу.


Патч на этом сайте следит за буфером сеанса TCP на предмет окончания первого набора заголовков HTTP в потоке и вводит новый заголовок в поток после окончания этого первого набора заголовков. После этого он считает X-Forwarded-For задание выполнено, и останавливает сканирование на предмет окончания новых наборов заголовков. Этот метод не знает обо всех будущих заголовках, поступающих через последующие запросы.

Не могу их винить; stunnel на самом деле не был построен для обработки и перевода содержимого своих потоков.

Эффект, который это окажет на вашу систему, заключается в том, что первый запрос потока поддержки активности получит X-Forwarded-For заголовок введен правильно, и все последующие запросы будут работать нормально, но у них не будет заголовка.

Если нет другого патча для инъекции заголовка, который может обрабатывать несколько клиентских запросов на одно соединение (или настроить его с помощью наших друзей в Stack Overflow), вам может потребоваться изучить другие варианты завершения SSL.

STunnel 4.45 исправляет это должным образом, используя некоторые новые возможности (протокол прокси), поставляемые с HAProxy 1.15.

Он также устраняет проблемы с предыдущими патчами и Keep Alive.

Подобно тому, что я опубликовал в другом потоке, HAProxy поддерживает собственный SSL с обеих сторон, начиная с версии 1.5-dev12. Таким образом, наличие X-Forwarded-For, HTTP keep-alive, а также заголовок, сообщающий серверу, что соединение было выполнено через SSL, очень просты:

listen front
    bind :80
    bind :443 ssl crt /etc/haproxy/haproxy.pem
    mode http
    option http-server-close
    option forwardfor
    reqadd X-Forwarded-Proto:\ https if { is_ssl }
    server srv1 1.1.1.1:80 check ...
    ...

Это намного проще, чем исправлять stunnel, и намного лучше, чем сбрасывать keep-alive.

Расширяя отличный ответ от Шейна, вы можете использовать Nginx в качестве терминатора SSL перед HAproxy. Он правильно обрабатывает поддержку активности между клиентом и nginx, которая является наиболее чувствительной к задержке стороной, и устанавливает новое соединение с серверной частью для каждого клиентского запроса, отправляя X-FORWARDED-FOR в каждом из них.