Отправка протокола прокси на сервер, который не поддерживает протокол прокси
У меня есть решение по ускорению HTTP, которое использует обратный прокси. Чтобы предоставить IP-адрес клиента серверу, я пытаюсь добавить поддержку протокола прокси в моем решении HTTP Acceleration. Хотя конечная точка решения HTTP Acceleration сама по себе не может быть шлюзом для моих серверов, мне нужно добавить поддержку прокси-протокола на сервере или добавить прокси-сервер HA перед ними.
В настоящее время для состояний протокола Proxy:
Приемник может быть настроен для поддержки как версии 1, так и версии 2 протокола. Определить версию протокола легко:
- if the incoming byte count is 16 or above and the 13 first bytes match
the protocol signature block followed by the protocol version 2 :
\x0D\x0A\x0D\x0A\x00\x0D\x0A\x51\x55\x49\x54\x0A\x02
- otherwise, if the incoming byte count is 8 or above, and the 5 first
characters match the US-ASCII representation of "PROXY" then the protocol
must be parsed as version 1 :
\x50\x52\x4F\x58\x59
- otherwise the protocol is not covered by this specification and the
connection must be dropped.
Мой сервер в основном nginx, который поддерживает протокол прокси. Хотя немногие из моих http-серверов не поддерживают прокси-протокол
Мой вопрос: если сервер не поддерживает протокол, могут ли они правильно анализировать полезную нагрузку TCP/HTTP, которая включает заголовок Proxy Protocol?
В этой же заметке я хотел бы знать, почему в спецификации прокси-протокола он не указан в качестве параметров заголовка TCP/Ip: таким образом, сервер, который не понимает этот параметр, просто проигнорирует, сделав его полностью прозрачным для сервера, который не ' не могу это поддержать. И те серверы, которые поддерживают протокол, будут отбрасывать пакеты, у которых нет опции прокси-протокола
2 ответа
Вот пример информации о протоколе прокси:
Если сервер не поддерживает протокол, могут ли они правильно проанализировать полезную нагрузку TCP/HTTP, которая включает заголовок Proxy Protocol?
Это зависит от реализации сервера.
Например, я попытался отправить информацию о протоколе прокси на HTTPServer в python, он выдал код ошибки 400. Вот реализация сервера, где он анализирует заголовок:
def parse_request(self):
"""Parse a request (internal).
The request should be stored in self.raw_requestline; the results
are in self.command, self.path, self.request_version and
self.headers.
Return True for success, False for failure; on failure, an
error is sent back.
"""
self.command = None # set in case of error on the first line
self.request_version = version = self.default_request_version
self.close_connection = 1
requestline = self.raw_requestline
requestline = requestline.rstrip('\r\n')
self.requestline = requestline
words = requestline.split()
if len(words) == 3:
command, path, version = words
if version[:5] != 'HTTP/':
self.send_error(400, "Bad request version (%r)" % version)
return False
try:
base_version_number = version.split('/', 1)[1]
version_number = base_version_number.split(".")
# RFC 2145 section 3.1 says there can be only one "." and
# - major and minor numbers MUST be treated as
# separate integers;
# - HTTP/2.4 is a lower version than HTTP/2.13, which in
# turn is lower than HTTP/12.3;
# - Leading zeros MUST be ignored by recipients.
if len(version_number) != 2:
raise ValueError
version_number = int(version_number[0]), int(version_number[1])
except (ValueError, IndexError):
self.send_error(400, "Bad request version (%r)" % version)
return False
if version_number >= (1, 1) and self.protocol_version >= "HTTP/1.1":
self.close_connection = 0
if version_number >= (2, 0):
self.send_error(505,
"Invalid HTTP Version (%s)" % base_version_number)
return False
elif len(words) == 2:
command, path = words
self.close_connection = 1
if command != 'GET':
self.send_error(400,
"Bad HTTP/0.9 request type (%r)" % command)
return False
elif not words:
return False
else:
self.send_error(400, "Bad request syntax (%r)" % requestline)
return False
self.command, self.path, self.request_version = command, path, version
# Examine the headers and look for a Connection directive
self.headers = self.MessageClass(self.rfile, 0)
conntype = self.headers.get('Connection', "")
if conntype.lower() == 'close':
self.close_connection = 1
elif (conntype.lower() == 'keep-alive' and
self.protocol_version >= "HTTP/1.1"):
self.close_connection = 0
return True
Обратите внимание, что полезные данные протокола прокси-сервера, например:
PROXY TCP4 192.168.73.178 192.168.73.185 52406 80
содержит 6 слов. Эта конкретная реализация сервера обрабатывает запрос, если в заголовке 3,2 слова или нет слов. В противном случае выдается код ошибки 400.
else:
self.send_error(400, "Bad request syntax (%r)" % requestline)
return False
Принимая во внимание, что когда я пытался отправить ту же информацию на сервер Tomcat с той же конфигурацией HAProxy, он просто игнорировал полезную нагрузку.
В общем, я бы не рисковал и не отправлял информацию о прокси, если только я не знаю, что она явно сможет с этим справиться.
Мой вопрос: если сервер не поддерживает протокол, могут ли они правильно анализировать полезную нагрузку TCP/HTTP, которая включает заголовок Proxy Protocol?
Нет, серверам, которые не поддерживают прокси-протокол, не удастся проанализировать запрос как HTTP, поскольку он не начинается с допустимого метода HTTP.
Просто опустите send-proxy
директива для внутренних серверов, которые не поддерживают протокол прокси. Имейте в виду, что вы потеряете информацию о клиенте, если вы не передадите их в заголовок, такой как X-Forwarded-For
,