tl;dr
ギョームで LimitRequestFieldSize について調べる機会があったので、改めて、手元で LimitRequestFieldSize の挙動を確認した。
LimitRequestFieldSize とは
HTTP リクエストヘッダー 1 つで受け付けられるバイト数の上限ということで、設定値を 100 バイトに制限した場合、以下のようなリクエストを送信すると、各ヘッダ行で 100 バイト制限がかかることになる。
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> Cookie: name=xxxxxxxxxx
挙動を試す
検証環境
Apache の Docker コンテナを利用する。
root@71158ebff5ab:/usr/local/apache2# httpd -V
Server version: Apache/2.4.46 (Unix)
Server built: Aug 5 2020 23:20:17
Server's Module Magic Number: 20120211:93
Server loaded: APR 1.6.5, APR-UTIL 1.6.1
Compiled using: APR 1.6.5, APR-UTIL 1.6.1
Architecture: 64-bit
Server MPM: event
threaded: yes (fixed thread count)
forked: yes (variable process count)
Server compiled with....
-D APR_HAS_SENDFILE
-D APR_HAS_MMAP
-D APR_HAVE_IPV6 (IPv4-mapped addresses enabled)
-D APR_USE_SYSVSEM_SERIALIZE
-D APR_USE_PTHREAD_SERIALIZE
-D SINGLE_LISTEN_UNSERIALIZED_ACCEPT
-D APR_HAS_OTHER_CHILD
-D AP_HAVE_RELIABLE_PIPED_LOGS
-D DYNAMIC_MODULE_LIMIT=256
-D HTTPD_ROOT="/usr/local/apache2"
-D SUEXEC_BIN="/usr/local/apache2/bin/suexec"
-D DEFAULT_PIDLOG="logs/httpd.pid"
-D DEFAULT_SCOREBOARD="logs/apache_runtime_status"
-D DEFAULT_ERRORLOG="logs/error_log"
-D AP_TYPES_CONFIG_FILE="conf/mime.types"
-D SERVER_CONFIG_FILE="conf/httpd.conf"
LimitRequestFieldSize を 100 に設定してみる
LimitRequestFieldSize 100
まずは、普通にリクエストを投げてみる。
$ curl localhost:8080 -I
HTTP/1.1 200 OK
Date: Tue, 23 Feb 2021 08:45:35 GMT
Server: Apache
... 略 ...
次に、100 バイト (100 文字) の cookie を送信してみる。
$ curl -b 'name=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' http://localhost:8080/ -I
HTTP/1.1 400 Bad Request
Date: Tue, 23 Feb 2021 08:47:59 GMT
Server: Apache
Connection: close
Content-Type: text/html; charset=iso-8859-1
BadRequest が返ってきた。100 バイト制限だから 100 文字の値が受け付けられるわけではなさそう。
$ curl -b 'name=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx' http://localhost:8080/ -I
HTTP/1.1 200 OK
Date: Tue, 23 Feb 2021 08:52:41 GMT
Server: Apache
... 略 ...
実際には 88 文字まで x
を減らすと正常なレスポンス (ステータスコード: 200) が返却されるようになった。
これは、なんでだろうなーと思って、curl の --verbose
オプションを付けてリクエストヘッダを見てみた。
* Trying ::1...
* TCP_NODELAY set
* Connected to localhost (::1) port 8080 (
> HEAD / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.64.1
> Accept: */*
> Cookie: name=xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
どうやら、Cookie のキー名と、ヘッダの Cookie:
という文字列を含め 100 バイトの計算で制限がかかるようだ。(空白はカウントされない)
ちゃんとソースコードを読んだわけではないので、あくまでも予想。
LimitRequestFieldSize のデフォルト値は
httpd.h に定義されている。
https://github.com/apache/httpd/blob/2.4.x/include/httpd.h
#ifndef DEFAULT_LIMIT_REQUEST_FIELDSIZE
#define DEFAULT_LIMIT_REQUEST_FIELDSIZE 8190
default limit on bytes in any one header field
って書いてある。
気になるのが、同ソースコード内のコメントに、以下のように記述されている。
...
ざっくり意訳すると...
- これらの値は単純な DDoS を防ぐ為に存在している
- 場合によっては、推奨値よりも大きな値を設定する必要があるが、ほとんど変える必要は無い
あまり大きな数値は設定しないほうが良さそうなことが解る。
以上
手元で動かしながら、Apache の LimitRequestFieldSize の挙動を確認してみました。