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

Reply via email to