web-dev-qa-db-ja.com

HAProxyがアンダースコア付きのHTTPヘッダーをドロップしないようにする方法

アンダースコアを含む特定のHTTPヘッダーを必要とするAPIバックエンドサーバーがあります。これはベストプラクティスではなく、ヘッダーにはハイフンを使用する必要があることはわかっていますが、これを変更することはできません。

オプションunderscores_in_headers onを使用してプロキシサーバーとしてnginxを使用していました。これにより、nginxはこれらのヘッダーを削除しません。

ここで、HAProxyに切り替えて、構成を変更する前にnginxとして、アンダースコア付きのヘッダーを削除します。 HAProxyがアンダースコア付きのヘッダーをドロップしないようにする方法はありますか?

2
Thomas

HAProxyがアンダースコア付きのヘッダーをドロップすることを実際にテストしましたか?

ソースコードからはそうではないようです。この回答では、次のことを説明しようと思います。

  • hTTPでヘッダーのアンダースコアが許可される理由
  • nginxがデフォルトでそれらをドロップする理由と
  • hAProxyがそうしないと私が信じる理由。

HTTP/1.1&Nginx

RFC 7230 3.2.6 のHTTP/1.1仕様によると、ヘッダーフィールドのアンダースコア(___)に問題はありません。それは珍しいことです。

フィールド値コンポーネント

ほとんどのHTTPヘッダーフィールド値は、空白または特定の区切り文字で区切られた一般的な構文コンポーネント(トークン、引用符で囲まれた文字列、およびコメント)を使用して定義されます。区切り文字は、トークンで許可されていないUS-ASCII視覚文字のセット(DQUOTEおよび_(),/:;<=>?@[\]{}_)から選択されます。

_token         = 1*tchar

tchar         = "!" / "#" / "$" / "%" / "&" / "'" / "*"
              / "+" / "-" / "." / "^" / "_" / "`" / "|" / "~"
              / DIGIT / ALPHA
              ; any VCHAR, except delimiters
_

Nginxの落とし穴とよくある間違い: HTTPヘッダーがない(消える) デフォルトでサイレントにドロップされる理由を説明します:

_underscores_in_headers on;_を明示的に設定しない場合、NGINXはアンダースコア付きのHTTPヘッダーをサイレントにドロップします(これはHTTP標準に従って完全に有効です)。これは、ダッシュとアンダースコアの両方がそのプロセス中にアンダースコアにマップされるため、ヘッダーをCGI変数にマップする際のあいまいさを防ぐために行われます。


HAProxy

残念ながら、HAProxyにはそのような設定がありません。 HAProxyを介してunderscoreを検索する場合 構成マニュアル 、それは環境変数のコンテキストでのみ言及されます)ノード名(DNS名のように)、プロキシ名およびACL名。 HTTPリクエストの章には記載されていません。

HAProxyがアンダースコア付きのヘッダーを削除する場合、構成からできることは何もないため、Nginxに固執するか、HAProxyのソースコードを変更する必要があります。

しかし、HAProxyがヘッダーをドロップする場所を見つけようとしましたが、_proto_http.c_の関数void capture_headers()およびvoid http_msg_analyzer()からそのようなものを見つけることができませんでした。

また、_proto_http.c_はすべてのASCII文字をタイプ別にリストし、_(),/:;<=>?@[\]{}_は_HTTP_FLG_SEP_としてリストされ、アンダースコアは通常のトークンとしてリストされます。

_495 /* It is about twice as fast on recent architectures to lookup a byte in a
496  * table than to perform a boolean AND or OR between two tests. Refer to
497  * RFC2616/RFC5234/RFC7230 for those chars. A token is any ASCII char that is
498  * neither a separator nor a CTL char. An http ver_token is any ASCII which can
499  * be found in an HTTP version, which includes 'H', 'T', 'P', '/', '.' and any
500  * digit. Note: please do not overwrite values in assignment since gcc-2.95
501  * will not handle them correctly. It's worth noting that chars 128..255 are
502  * nothing, not even control chars.
503  */
504 const unsigned char http_char_classes[256] = {
505     [  0] = HTTP_FLG_CTL,

545     ['('] = HTTP_FLG_SEP,
546     [')'] = HTTP_FLG_SEP,
547     ['*'] = HTTP_FLG_TOK,
548     ['+'] = HTTP_FLG_TOK,
549     [','] = HTTP_FLG_SEP,
550     ['-'] = HTTP_FLG_TOK,
551     ['.'] = HTTP_FLG_TOK | HTTP_FLG_VER,

570     ['A'] = HTTP_FLG_TOK,
571     ['B'] = HTTP_FLG_TOK,
572     ['C'] = HTTP_FLG_TOK,

600     ['_'] = HTTP_FLG_TOK,
_

ここで、___は、AB、およびCと同じように通常の_HTTP_FLG_TOK_です。特別なことは何も起こらないはずです。

3
Esa Jokinen