Linux/nginxで薄い応答を返す

シンプルなテキストを返して、即切断するWebサーバの例(2019-10-30)


ちょっと今回のメモは特殊で、導入するWebサーバの目的は以下になります。

  • とにかく特定のテキストを返して、切断します
  • CGIとか使いません
  • 不要な情報は返さないようにしたいです

既に稼働中のWebサーバとは別に、
squid で「特定のお客様」をご案内する、VIPルームとして使います。
そこで速さに定評のある nginx の出番です!

以下、うちのCentOS 7 環境の例です。
ひとまず yum でインストールしてみました。

# yum install nginx
(したのですが、今回は結局ソースからmakeしたので、removeしています)

その後に、
nginx -V で、入っているモジュールが確認できるわけですが、
今回どうしても欲しかった more_clear_headers に必要なモジュールは入っていないようです...
(HTTPヘッダを増やしたり削ったりする機能です)
そのため、今回はソースから make することにしました。
なお、
yum remove nginx の前に
/usr/lib/systemd/system/nginx.service だけ退避しておきました(しなくても良いです。後述)

というわけで、以下ソースからインストールします。まず以下のサイトで本体を確認します。
バージョンは、その時々の最新のものを使います。
https://nginx.org/en/download.html

# wget http://nginx.org/download/nginx-1.16.1.tar.gz
# wget http://nginx.org/download/nginx-1.16.1.tar.gz.asc
( # vi ~/.gnupg/gpg.conf
  で、必要に応じて keyserver-options auto-key-retrieve のコメントを外しておく)
# gpg --verify nginx-1.16.1.tar.gz.asc   nginx-1.16.1.tar.gz

そして、もう一つの目的となる、more_clear_headersの方を
https://github.com/openresty/headers-more-nginx-module/
(の下の、tagsディレクトリ)
で最新のバージョンを確認しました。

# wget https://github.com/openresty/headers-more-nginx-module/archive/v0.33.tar.gz
  
  取得したら、tar zxvf で展開する
  そして、nginxを展開した場所へ移動して、
  
# ./configure --prefix=インストールするPATH --add-module=上記headers-more-nginx-moduleを展開したディレクトリPATH
# make
# make install

備忘録として、configure時に、--with-http_ssl_module など
色々指定するべきオプションがありますが、
このメモでは https等は(squidで)別途対応したので、特に指定していません。
オプションも少ないせいなのかmake が、 apache や squidよりはるかに早くて驚きました。

nginx.conf の以下を更新します。

keepalive_timeout   0;      # fail2banへ回すアクセスなので、セッションさせない
more_clear_headers Server;  # HTTPレスポンスからnginxの情報を消す
 
listen       127.0.0.1:8081;  # default_server は消す
server_name  自分のサーバのドメイン名

keepalive_timeout は通常は生かして性能向上を目指します、
が、今回はファイアウォール(fail2ban)と連動させたいので敢えて offにしてます。

(ファイアウォールで止められるのは新規セッションなので、
 一回一回、新規セッションで張り直してもらうという想定です。
 後述しますが、1ファイルしか返さないので keepalive でセッション維持する必要もない)

server_tokens off で無用なNginxバージョン情報は隠す、でも良いですが、
Nginxを使っていることすらも伝える必要はないので、
今回は more_clear_headers でヘッダを削ってしまいました。

listen は今回は
ローカルからsquid経由で転送されるリクエストだけなので、こんな感じです。
普通に外部から受ける場合はポートのみ指定で80とか443とかになるかと。

あとは、追々 log_format の内容を検討予定。
それとログローテーションが要りますね。
うちのCentOS 7 だと /etc/logrotate.d/ に置きます。
(てきとうな他のログのルールをそのまま真似する感じで)

起動スクリプトは、
前述の通り最初に yum install nginx した時にできた
/usr/lib/systemd/system/nginx.service を流用させてもらうことにしましたが、
(nginx の場所と、logs/nginx.pid の場所は更新、起動時に -c で nginx.confのフルPATHを渡す)
"nginx systemd script" あたりでググるとサンプルが見つかりました
https://www.nginx.com/resources/wiki/start/topics/examples/systemd/

いずれにせよ用意できたら、

# systemctl enable nginx
# systemctl start nginx

これでひとまず、動作確認します
HTTPレスポンスも見たいので、-d をつけてwgetしてみます。

 # wget -d localhost:8081
 これの応答がnginxに置いた html/index.html ファイルに書かれたものであることに加えて、
 HTTP応答のヘッダー内容が、
 Server無し、Connection:close であることを確認する

もし初めて試す場合は nginx.conf内の keepalive_timeout, more_clear_headers の指定の有り無しで、
それぞれどんなHTTPレスポンスが返るのか、違いを比較してみると分かりやすいかもしれません。

それから、デフォルトで 50x.htmlの書き方の例が nginx.conf にありましたので、
それを参考に 404 Not Found 用のやつを作ります。

 (nginx.confへ以下を追加。50xを参考に)
 error_page  404  /40x.html;
 location = /40x.html {
     root   html;
 }
 (そして、html/40x.html の例)
 <!DOCTYPE html><html>
 <head> <title>Error</title> </head>
 <body> <h1>Not Found</h1> </body>
 </html>

あと、なんか、index.html(ダミー)もてきとーに作りなおします。

<html>Hello world</html>

とかで良いんじゃないんですか?

...という訳にも行かない場合に、もう少しそれらしい方法もメモに残すと、
「本来のサイト」の方の index.html ファイルから
link, a, img などのリンク部分を全部削ったファイルを用意しました。

(わざわざ削る目的は、応答で返すのは1ファイルだけにして、
 画像のダウンロード等で余計な負荷をサーバかけないためです)

スタイルシート(css)をlinkタグ等で外部から読んでいる場合は、
その内容をまるっと <style type="text/css"> 〜 </style> タグではさんだものを
ダミーの index.htmlの headタグへ放り込めば、概ね同じデザインになります。

うちで使っているPukiwikiもindex.htmlはCGIが作るのですが、
index.htmlがCMS(コンテンツ管理システム)やらCGIやらで生成されるから、オリジナルの内容が分からないという場合は、
実際に本来のサイトにアクセスして、wgetコマンドの結果や、Webブラウザの「ソースを表示」する機能から拾うことができます。

以上です。


今回の使用目的は主にスパムアクセス対策なわけですが、
この方法自体は、簡易なテキスト応答を次々に返すとか、応用が効きそうです。
インストール作業も含めて、nginxはやっぱり「早い」ところがステキです。