On 16.06.2014 15:00, Maxim Dounin wrote:
озвученные в RFC 7230 требования к клиенту:
http://tools.ietf.org/html/rfc7230#section-5.4
A client MUST send a Host header field in all HTTP/1.1 request
messages. If the target URI includes an authority component, then a
client MUST send a field-value for Host that is identical to that
authority component, excluding any userinfo subcomponent and its "@"
delimiter (Section 2.7.1).
- это ведь требования к синтаксису, которые обязательны для выполнения.
Нет, это не требования к синтаксису, это требования к семантике.
Запись target URI в виде valid request message - это разве не syntax?
http://tools.ietf.org/html/rfc7231#section-2
When a client constructs an HTTP/1.1 request message, it sends the
target URI in one of various forms, as defined in (Section 5.3 of
[RFC7230]). When a request is received, the server reconstructs an
effective request URI for the target resource (Section 5.5 of
[RFC7230]).
One design goal of HTTP is to separate resource identification from
request semantics, which is made possible by vesting the request
semantics in the request method (Section 4) and a few
request-modifying header fields (Section 5).
"effective request URI" - это именно что resource identification.
Они ведь разнесли "syntax" и "semantics" по двум отдельным документам:
RFC 7230: Message Syntax and Routing
RFC 7231: Semantics and Content
http://tools.ietf.org/html/rfc7231#section-6.5.1
6.5.1. 400 Bad Request
The 400 (Bad Request) status code indicates that the server cannot or
will not process the request due to something that is perceived to be
a client error (e.g., malformed request syntax, invalid request
message framing, or deceptive request routing).
Следовательно, сервер имеет право вернуть 400 статус,
если получит запрос с разными authority component
в заголовке Host и в absolute Request URI ?
Сервер имеет право вернуть 400 более или менее в любой момент.
Да, но здесь явно указывается, когда сервер возвращает 400:
в случае client error, например, "malformed request syntax"
или "deceptive request routing" - эти две причины подходят.
Кроме того, в разделе 5.5. Effective Request URI
http://tools.ietf.org/html/rfc7230#section-5.5
даже прямо говорят, что запрос может быть misdirected,
deliberately or accidentally, и что origin server должен
сам решить, обрабатывать такой запрос или нет, потому что
"it might indicate an attempt to bypass security filters,
trick the server into delivering non-public content,
or poison a cache."
именно это ведь и происходит в случае запроса
GET http://apple.com/ HTTP/1.1
Host: samsung.com
Разве ответить на такой запрос 400-м статусом не будет лучше?
Это зависит от многих факторов. Вот тут Валентин давеча
напрограммировал возврат 400, если имя, указанное в SNI, не
совпадало с именем, используемым в запросе, ибо RFC 6066 говорит:
... If the server_name is
established in the TLS session handshake, the client SHOULD NOT
attempt to request a different server name at the application layer.
Так пришлось распрограмировать обратно - потому что Chrome
использует "a different server name at the application layer",
когда считает нужным/возможным.
"SHOULD NOT" - это не запрет, а только лишь рекомендация:
http://tools.ietf.org/html/rfc2119#section-4
так что формально и фактически Chrome ничего не нарушает.
В обсуждаемой выше ситуации написано совсем иначе: "MUST".
http://tools.ietf.org/html/rfc2119#section-1
и если клиент этого не сделал - он сам прислал невалидный запрос,
так что ответить 400-м статусом на такой запрос - вполне разумно.
да и в RFC 7230 об этом тоже есть (про поведение хрома):
http://tools.ietf.org/html/rfc7230#section-2.3
server MUST NOT assume that two requests on the same connection are
from the same user agent unless the connection is secured and
specific to that agent. Some non-standard HTTP extensions (e.g.,
[RFC4559]) have been known to violate this requirement, resulting in
security and interoperability problems.
То, как ведёт себя nginx по умолчанию - вполне себе безопасно,
и проблемы нет. Какая-либо проблема появляется тогда и только
тогда, когда администратор начинает писать в конфиге $http_host,
не думая о последствиях. Есть мнение, что совсем простое решение
этой проблемы - не делать так (c) анекдот.
Когда nginx выполняет роль origin server или HTTP reverse proxy
- тогда проблем действительно нет, но когда он выполняет роль
"gateway" и communicates с backend`ом по протоколу FastCGI -
тогда получаются очень неприятные проблемы.
Причина проблем: malformed request syntax,
который не получается корректным образом передать на backend.
Что мешает в этой ситуации вернуть 400 статус? Вместо того,
чтобы отсылать на backend невалидный запрос, интерпретируя
клиентский запрос не по спецификации HTTP/1.1 а по спецификации
CGI/1.1, которая не согласуется со спецификацией протокола HTTP/1.1.
Ничего ведь не сломается и на backend не уйдет misdirected запрос.
И даже отдельной директивы никакой не надо будет создавать для этого.
Никакой легальный клиент не пострадает от этого изменения в nginx,
потому что никто кроме взломщиков не создает таких misdirected запросов,
которые не соответствуют обязательным требованиям к клиентским запросам.
--
Best regards,
Gena
_______________________________________________
nginx-ru mailing list
nginx-ru@nginx.org
http://mailman.nginx.org/mailman/listinfo/nginx-ru