2011年7月28日木曜日

nginx+PHP-FPMでどこまでチューニングできるか

このサイトもnginx+PHP-FPM+MySQLで動作しているのですがphpをfastcgiで動かしている例は多くあったのですがPHP-FPMで書いている記事があまりない。

yumなどは使わずにソースから全てインストールします。MySQLは事前にインストールされている物とします。


nginx

nginxユーザを追加します

adduser -u 500 nginx


使わないオプションは全てOFFにします。


./configure \
--with-http_stub_status_module \
--without-http_upstream_ip_hash_module \
--without-http_gzip_module \
--without-http_autoindex_module \
--without-http_geo_module \
--without-http_map_module \
--without-http_split_clients_module \
--without-http_referer_module \
--without-http_proxy_module \
--without-http_uwsgi_module \
--without-http_limit_zone_module \
--without-http_limit_req_module \
--without-http_browser_module \



特に--with-http_stub_status_module のオプションはサーバのステータスを見てチューニングするのには必須なので必ずいれます。


nginx設定ファイル


user nginx;
worker_processes 2;

error_log /var/log/nginx/blog/error.log;
pid /var/run/nginx.pid;

events {
worker_connections 1024;
}


http {
include /usr/local/nginx/conf/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log /var/log/nginx/blog/access.log main;

sendfile on;
keepalive_timeout 0;
server_tokens off;

server {
listen 80;
server_name blog.kubox.info;
root /home/blog/public_html;
index index.php;
error_page 404 /404.html;
error_page 500 502 503 504 /50x.html;
location = /50x.html {
root html;
}


location ~*\.php$ {
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
include fastcgi_params;
fastcgi_param SCRIPT_FILENAME /home/blog/public_html$fastcgi_script_name;
}

location = /status {
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME /status;
fastcgi_pass 127.0.0.1:9000;
access_log off;
}

location /nginx_status {
stub_status on;
access_log off;
allow all;
deny all;
}

location ~ /\.ht {
deny all;
}

}
}



コンピュータはCPUの数を超えて並列処理はできないのでworker_processesはCPUの数に合わせます。2Coreなので2します。

worker_connectionsはworker_processesが同時に処理できる接続数です。


以下の行を追加するとhttp://URL/statusでPHP-FPMのステータス、http://URL/nginx_statusでnginxのステータスを見ることができます。
deny allになっているので許可するIPをAllowしてください。


location = /status {
include /usr/local/nginx/conf/fastcgi_params;
fastcgi_param SCRIPT_FILENAME /status;
fastcgi_pass 127.0.0.1:9000;
access_log off;
}

location /nginx_status {
stub_status on;
access_log off;
allow all;
deny all;
}



PHP-FPM
PHP-FPMはPHP5.3.3から組み込まれており、オプションを追加するだけでPHP-FPMが利用できます。

fastcgiは別途lighttpdをmakeして抜き出したりする手間がありましたがその必要がなくなりより高負荷サイト用に機能が追加されました。

  • 緩やかな (graceful) 停止/起動 機能を含む高度なプロセス管理



  • 異なる uid/gid/chroot/environment でのワーカーの開始、 異なるポートでのリスン、異なる php.ini の使用 (safe_mode の代替)



  • 標準出力および標準エラー出力へのログ出力



  • opcode キャッシュが壊れた場合の緊急再起動



  • 高速なアップロードのサポート



  • "slowlog" - 非常に低速に動作するログ出力スクリプト (名前から想像される内容だけでなく、ptrace やそれと同等の仕組みを使ってリモートプロセスの execute_data からの PHP バックトレースも出力します)



  • fastcgi_finish_request() - リクエストを終わらせてすべてのデータを出力した後で 何か時間のかかる処理 (動画の変換や統計情報の処理など) をさせるための特殊な関数



  • 動的/静的 な子プロセスの起動



  • 基本的な SAPI の動作状況 (Apache の mod_status と同等)



  • php.ini ベースの設定ファイル



http://www.php.net/manual/ja/install.fpm.php

configureでenable-fpmオプションを追加してください。


'./configure' \
'--with-mysql=/usr/local/mysql' \
'--enable-zend-multibyte' \
'--with-pdo-mysql' \
'--with-zlib' \
'--with-xmlrpc' \
'--with-gd' \
'--with-curl' \
'--with-jpeg-dir=/usr/local' \
'--with-png-dir=/usr/local' \
'--enable-mbstring' \
'--enable-fpm' \
'--with-fpm-user=nginx' \
'--with-fpm-group=nginx' \
'--without-SQLite' \


PHP-FPM設定ファイル


[global]
pid = /var/run/php-fpm.pid
error_log = /var/log/php/php-fpm.log
log_level = notice
emergency_restart_threshold = 0
emergency_restart_interval = 0
process_control_timeout = 0
daemonize = yes

[www]
listen = 127.0.0.1:9000
listen.backlog = -1
listen.allowed_clients = 127.0.0.1

listen.owner = nginx
listen.group = nginx
listen.mode = 0666

user = nginx
group = nginx

pm = dynamic
pm.max_children = 10
pm.start_servers = 5
pm.min_spare_servers = 3
pm.max_spare_servers = 8
pm.max_requests = 500
pm.status_path = /status

request_slowlog_timeout = 2
request_terminate_timeout= 5
slowlog = /var/log/php/$pool.log.slow



注目するところはpmから始まる設定です。

PHP-FPMはWebサーバ(nginx)がユーザから受け取ったリクエストをPHPでればPHP-FPMに処理を投げ処理をするので、nginxとPHP-FPMが同程度処理できるのが理想です。

ひとまず負荷試験を行うまでどこにボトルネックがあるかわからないので適用な値にしておきます。


メモリ
nginxとPHP-FPMが無事に起動できたら一旦メモリの状態を見てみます。


# free -m
total used free shared buffers cached
Mem: 497 385 111 0 75 154
-/+ buffers/cache: 156 341
Swap: 1027 0 1027



予想以上にメモリを使っていたのでちょっとpsしてみます。


# ps axu | grep php
root 32717 0.0 0.7 124672 3708 ? Ss 13:45 0:00 php-fpm: master process (/usr/local/etc/php-fpm.conf)
nginx 32718 0.2 9.0 139960 46368 ? S 13:45 0:00 php-fpm: pool www
nginx 32719 0.0 5.7 132708 29424 ? S 13:45 0:00 php-fpm: pool www
nginx 32720 0.1 4.6 129440 23700 ? S 13:45 0:00 php-fpm: pool www
nginx 32721 0.1 5.0 129928 25940 ? S 13:45 0:00 php-fpm: pool www
nginx 32722 0.0 5.2 130212 26900 ? S 13:45 0:00 php-fpm: pool www



PHP-FPMが結構メモリを使っているみたいです。


pmapコマンドでプロセスのメモリ利用状況をさらに詳しくみてみます。


# pmap 32717
32717: php-fpm: master process (/usr/local/etc/php-fpm.conf)
0000000000400000 8396K r-x-- /usr/local/sbin/php-fpm
0000000000e33000 464K rw--- /usr/local/sbin/php-fpm
0000000000ea7000 120K rw--- [ anon ]
0000000010021000 2288K rw--- [ anon ]
0000000040456000 4K ----- [ anon ]
0000000040457000 10240K rw--- [ anon ]
00000030f0c00000 112K r-x-- /lib64/ld-2.5.so
00000030f0e1c000 4K r---- /lib64/ld-2.5.so
00000030f0e1d000 4K rw--- /lib64/ld-2.5.so
00000030f1000000 1336K r-x-- /lib64/libc-2.5.so
00000030f114e000 2048K ----- /lib64/libc-2.5.so
00000030f134e000 16K r---- /lib64/libc-2.5.so
00000030f1352000 4K rw--- /lib64/libc-2.5.so
00000030f1353000 20K rw--- [ anon ]
00000030f1400000 8K r-x-- /lib64/libdl-2.5.so
00000030f1402000 2048K ----- /lib64/libdl-2.5.so
00000030f1602000 4K r---- /lib64/libdl-2.5.so
00000030f1603000 4K rw--- /lib64/libdl-2.5.so
00000030f1800000 520K r-x-- /lib64/libm-2.5.so
00000030f1882000 2044K ----- /lib64/libm-2.5.so
00000030f1a81000 4K r---- /lib64/libm-2.5.so
00000030f1a82000 4K rw--- /lib64/libm-2.5.so
00000030f1c00000 88K r-x-- /lib64/libpthread-2.5.so
00000030f1c16000 2044K ----- /lib64/libpthread-2.5.so
00000030f1e15000 4K r---- /lib64/libpthread-2.5.so
00000030f1e16000 4K rw--- /lib64/libpthread-2.5.so
00000030f1e17000 16K rw--- [ anon ]
00000030f2000000 80K r-x-- /usr/lib64/libz.so.1.2.3
00000030f2014000 2044K ----- /usr/lib64/libz.so.1.2.3
00000030f2213000 4K rw--- /usr/lib64/libz.so.1.2.3
00000030f2400000 236K r-x-- /lib64/libsepol.so.1
00000030f243b000 2048K ----- /lib64/libsepol.so.1
00000030f263b000 4K rw--- /lib64/libsepol.so.1
00000030f263c000 40K rw--- [ anon ]
00000030f2800000 84K r-x-- /lib64/libselinux.so.1
00000030f2815000 2048K ----- /lib64/libselinux.so.1
00000030f2a15000 8K rw--- /lib64/libselinux.so.1
00000030f2a17000 4K rw--- [ anon ]
00000030f2c00000 28K r-x-- /lib64/librt-2.5.so
00000030f2c07000 2048K ----- /lib64/librt-2.5.so
00000030f2e07000 4K r---- /lib64/librt-2.5.so
00000030f2e08000 4K rw--- /lib64/librt-2.5.so
00000030f3000000 52K r-x-- /lib64/libgcc_s-4.1.2-20080825.so.1
00000030f300d000 2048K ----- /lib64/libgcc_s-4.1.2-20080825.so.1
00000030f320d000 4K rw--- /lib64/libgcc_s-4.1.2-20080825.so.1
00000030f3800000 36K r-x-- /lib64/libcrypt-2.5.so
00000030f3809000 2044K ----- /lib64/libcrypt-2.5.so
00000030f3a08000 4K r---- /lib64/libcrypt-2.5.so
00000030f3a09000 4K rw--- /lib64/libcrypt-2.5.so
00000030f3a0a000 184K rw--- [ anon ]
00000030f4c00000 1204K r-x-- /lib64/libcrypto.so.0.9.8e
00000030f4d2d000 2044K ----- /lib64/libcrypto.so.0.9.8e
00000030f4f2c000 132K rw--- /lib64/libcrypto.so.0.9.8e
00000030f4f4d000 16K rw--- [ anon ]
00000030f5000000 84K r-x-- /lib64/libnsl-2.5.so
00000030f5015000 2044K ----- /lib64/libnsl-2.5.so
00000030f5214000 4K r---- /lib64/libnsl-2.5.so
00000030f5215000 4K rw--- /lib64/libnsl-2.5.so
00000030f5216000 8K rw--- [ anon ]
00000030f6000000 68K r-x-- /lib64/libresolv-2.5.so
00000030f6011000 2048K ----- /lib64/libresolv-2.5.so
00000030f6211000 4K r---- /lib64/libresolv-2.5.so
00000030f6212000 4K rw--- /lib64/libresolv-2.5.so
00000030f6213000 8K rw--- [ anon ]
00000030f6800000 8K r-x-- /lib64/libcom_err.so.2.1
00000030f6802000 2044K ----- /lib64/libcom_err.so.2.1
00000030f6a01000 4K rw--- /lib64/libcom_err.so.2.1
00000030f6c00000 8K r-x-- /lib64/libkeyutils-1.2.so
00000030f6c02000 2044K ----- /lib64/libkeyutils-1.2.so
00000030f6e01000 4K rw--- /lib64/libkeyutils-1.2.so
00000030f7c00000 1228K r-x-- /usr/lib64/libxml2.so.2.6.26
00000030f7d33000 2048K ----- /usr/lib64/libxml2.so.2.6.26
00000030f7f33000 36K rw--- /usr/lib64/libxml2.so.2.6.26
00000030f7f3c000 4K rw--- [ anon ]
00000030f8400000 144K r-x-- /usr/lib64/libk5crypto.so.3.1
00000030f8424000 2044K ----- /usr/lib64/libk5crypto.so.3.1
00000030f8623000 8K rw--- /usr/lib64/libk5crypto.so.3.1
00000030f8800000 32K r-x-- /usr/lib64/libkrb5support.so.0.1
00000030f8808000 2044K ----- /usr/lib64/libkrb5support.so.0.1
00000030f8a07000 4K rw--- /usr/lib64/libkrb5support.so.0.1
00000030f8c00000 584K r-x-- /usr/lib64/libkrb5.so.3.3
00000030f8c92000 2044K ----- /usr/lib64/libkrb5.so.3.3
00000030f8e91000 16K rw--- /usr/lib64/libkrb5.so.3.3
00000030f9400000 176K r-x-- /usr/lib64/libgssapi_krb5.so.2.2
00000030f942c000 2048K ----- /usr/lib64/libgssapi_krb5.so.2.2
00000030f962c000 8K rw--- /usr/lib64/libgssapi_krb5.so.2.2
00000030fa400000 280K r-x-- /lib64/libssl.so.0.9.8e
00000030fa446000 2048K ----- /lib64/libssl.so.0.9.8e
00000030fa646000 24K rw--- /lib64/libssl.so.0.9.8e
0000003100a00000 140K r-x-- /usr/lib64/libpng12.so.0.10.0
0000003100a23000 2048K ----- /usr/lib64/libpng12.so.0.10.0
0000003100c23000 4K rw--- /usr/lib64/libpng12.so.0.10.0
00002aaaaaac4000 40K r-x-- /lib64/libnss_files-2.5.so
00002aaaaaace000 2044K ----- /lib64/libnss_files-2.5.so
00002aaaaaccd000 4K r---- /lib64/libnss_files-2.5.so
00002aaaaacce000 4K rw--- /lib64/libnss_files-2.5.so
00002aaaaaccf000 32768K rw-s- /dev/zero (deleted)
00002aaaacccf000 4K rw-s- /dev/zero (deleted)
00002b9f39d31000 8K rw--- [ anon ]
00002b9f39d33000 4K rw-s- /dev/zero (deleted)
00002b9f39d3f000 4K rw--- [ anon ]
00002b9f39d40000 2904K r-x-- /usr/local/mysql/lib/libmysqlclient.so.18.0.0
00002b9f3a016000 1020K ----- /usr/local/mysql/lib/libmysqlclient.so.18.0.0
00002b9f3a115000 524K rw--- /usr/local/mysql/lib/libmysqlclient.so.18.0.0
00002b9f3a198000 24K rw--- [ anon ]
00002b9f3a19e000 132K r-x-- /usr/lib64/libjpeg.so.62.0.0
00002b9f3a1bf000 2044K ----- /usr/lib64/libjpeg.so.62.0.0
00002b9f3a3be000 4K rw--- /usr/lib64/libjpeg.so.62.0.0
00002b9f3a3bf000 4K rw--- [ anon ]
00002b9f3a3c0000 324K r-x-- /usr/local/lib/libcurl.so.4.2.0
00002b9f3a411000 2044K ----- /usr/local/lib/libcurl.so.4.2.0
00002b9f3a610000 12K rw--- /usr/local/lib/libcurl.so.4.2.0
00002b9f3a613000 4K rw--- [ anon ]
00002b9f3a614000 196K r-x-- /usr/lib64/libidn.so.11.5.19
00002b9f3a645000 2044K ----- /usr/lib64/libidn.so.11.5.19
00002b9f3a844000 4K rw--- /usr/lib64/libidn.so.11.5.19
00002b9f3a845000 28K rw--- [ anon ]
00002b9f3a88d000 316K rw--- [ anon ]
00002b9f3a8dc000 128K r-x-- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/apc.so
00002b9f3a8fc000 2048K ----- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/apc.so
00002b9f3aafc000 12K rw--- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/apc.so
00002b9f3aaff000 36K rw--- [ anon ]
00002b9f3ab08000 76K r-x-- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/oauth.so
00002b9f3ab1b000 2048K ----- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/oauth.so
00002b9f3ad1b000 8K rw--- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/oauth.so
00007fff4a564000 84K rw--- [ stack ]
00007fff4a5fc000 16K r-x-- [ anon ]
ffffffffff600000 8192K ----- [ anon ]
total 132860K



apc.soはAPCを使う上で必要なのでしょうがないですがoauth.soはそんなに頻繁にOAuthしないので一旦php.iniでコメントアウトしておきます。

PHP-FPMを再起動後、再度pmapしてみます。

pmap 11238
11238: php-fpm: master process (/usr/local/etc/php-fpm.conf)
0000000000400000 8396K r-x-- /usr/local/sbin/php-fpm
0000000000e33000 464K rw--- /usr/local/sbin/php-fpm
0000000000ea7000 120K rw--- [ anon ]
000000001a798000 2252K rw--- [ anon ]
00000000406da000 4K ----- [ anon ]
00000000406db000 10240K rw--- [ anon ]
00000030f0c00000 112K r-x-- /lib64/ld-2.5.so
00000030f0e1c000 4K r---- /lib64/ld-2.5.so
00000030f0e1d000 4K rw--- /lib64/ld-2.5.so
00000030f1000000 1336K r-x-- /lib64/libc-2.5.so
00000030f114e000 2048K ----- /lib64/libc-2.5.so
00000030f134e000 16K r---- /lib64/libc-2.5.so
00000030f1352000 4K rw--- /lib64/libc-2.5.so
00000030f1353000 20K rw--- [ anon ]
00000030f1400000 8K r-x-- /lib64/libdl-2.5.so
00000030f1402000 2048K ----- /lib64/libdl-2.5.so
00000030f1602000 4K r---- /lib64/libdl-2.5.so
00000030f1603000 4K rw--- /lib64/libdl-2.5.so
00000030f1800000 520K r-x-- /lib64/libm-2.5.so
00000030f1882000 2044K ----- /lib64/libm-2.5.so
00000030f1a81000 4K r---- /lib64/libm-2.5.so
00000030f1a82000 4K rw--- /lib64/libm-2.5.so
00000030f1c00000 88K r-x-- /lib64/libpthread-2.5.so
00000030f1c16000 2044K ----- /lib64/libpthread-2.5.so
00000030f1e15000 4K r---- /lib64/libpthread-2.5.so
00000030f1e16000 4K rw--- /lib64/libpthread-2.5.so
00000030f1e17000 16K rw--- [ anon ]
00000030f2000000 80K r-x-- /usr/lib64/libz.so.1.2.3
00000030f2014000 2044K ----- /usr/lib64/libz.so.1.2.3
00000030f2213000 4K rw--- /usr/lib64/libz.so.1.2.3
00000030f2400000 236K r-x-- /lib64/libsepol.so.1
00000030f243b000 2048K ----- /lib64/libsepol.so.1
00000030f263b000 4K rw--- /lib64/libsepol.so.1
00000030f263c000 40K rw--- [ anon ]
00000030f2800000 84K r-x-- /lib64/libselinux.so.1
00000030f2815000 2048K ----- /lib64/libselinux.so.1
00000030f2a15000 8K rw--- /lib64/libselinux.so.1
00000030f2a17000 4K rw--- [ anon ]
00000030f2c00000 28K r-x-- /lib64/librt-2.5.so
00000030f2c07000 2048K ----- /lib64/librt-2.5.so
00000030f2e07000 4K r---- /lib64/librt-2.5.so
00000030f2e08000 4K rw--- /lib64/librt-2.5.so
00000030f3000000 52K r-x-- /lib64/libgcc_s-4.1.2-20080825.so.1
00000030f300d000 2048K ----- /lib64/libgcc_s-4.1.2-20080825.so.1
00000030f320d000 4K rw--- /lib64/libgcc_s-4.1.2-20080825.so.1
00000030f3800000 36K r-x-- /lib64/libcrypt-2.5.so
00000030f3809000 2044K ----- /lib64/libcrypt-2.5.so
00000030f3a08000 4K r---- /lib64/libcrypt-2.5.so
00000030f3a09000 4K rw--- /lib64/libcrypt-2.5.so
00000030f3a0a000 184K rw--- [ anon ]
00000030f4c00000 1204K r-x-- /lib64/libcrypto.so.0.9.8e
00000030f4d2d000 2044K ----- /lib64/libcrypto.so.0.9.8e
00000030f4f2c000 132K rw--- /lib64/libcrypto.so.0.9.8e
00000030f4f4d000 16K rw--- [ anon ]
00000030f5000000 84K r-x-- /lib64/libnsl-2.5.so
00000030f5015000 2044K ----- /lib64/libnsl-2.5.so
00000030f5214000 4K r---- /lib64/libnsl-2.5.so
00000030f5215000 4K rw--- /lib64/libnsl-2.5.so
00000030f5216000 8K rw--- [ anon ]
00000030f6000000 68K r-x-- /lib64/libresolv-2.5.so
00000030f6011000 2048K ----- /lib64/libresolv-2.5.so
00000030f6211000 4K r---- /lib64/libresolv-2.5.so
00000030f6212000 4K rw--- /lib64/libresolv-2.5.so
00000030f6213000 8K rw--- [ anon ]
00000030f6800000 8K r-x-- /lib64/libcom_err.so.2.1
00000030f6802000 2044K ----- /lib64/libcom_err.so.2.1
00000030f6a01000 4K rw--- /lib64/libcom_err.so.2.1
00000030f6c00000 8K r-x-- /lib64/libkeyutils-1.2.so
00000030f6c02000 2044K ----- /lib64/libkeyutils-1.2.so
00000030f6e01000 4K rw--- /lib64/libkeyutils-1.2.so
00000030f7c00000 1228K r-x-- /usr/lib64/libxml2.so.2.6.26
00000030f7d33000 2048K ----- /usr/lib64/libxml2.so.2.6.26
00000030f7f33000 36K rw--- /usr/lib64/libxml2.so.2.6.26
00000030f7f3c000 4K rw--- [ anon ]
00000030f8400000 144K r-x-- /usr/lib64/libk5crypto.so.3.1
00000030f8424000 2044K ----- /usr/lib64/libk5crypto.so.3.1
00000030f8623000 8K rw--- /usr/lib64/libk5crypto.so.3.1
00000030f8800000 32K r-x-- /usr/lib64/libkrb5support.so.0.1
00000030f8808000 2044K ----- /usr/lib64/libkrb5support.so.0.1
00000030f8a07000 4K rw--- /usr/lib64/libkrb5support.so.0.1
00000030f8c00000 584K r-x-- /usr/lib64/libkrb5.so.3.3
00000030f8c92000 2044K ----- /usr/lib64/libkrb5.so.3.3
00000030f8e91000 16K rw--- /usr/lib64/libkrb5.so.3.3
00000030f9400000 176K r-x-- /usr/lib64/libgssapi_krb5.so.2.2
00000030f942c000 2048K ----- /usr/lib64/libgssapi_krb5.so.2.2
00000030f962c000 8K rw--- /usr/lib64/libgssapi_krb5.so.2.2
00000030fa400000 280K r-x-- /lib64/libssl.so.0.9.8e
00000030fa446000 2048K ----- /lib64/libssl.so.0.9.8e
00000030fa646000 24K rw--- /lib64/libssl.so.0.9.8e
0000003100a00000 140K r-x-- /usr/lib64/libpng12.so.0.10.0
0000003100a23000 2048K ----- /usr/lib64/libpng12.so.0.10.0
0000003100c23000 4K rw--- /usr/lib64/libpng12.so.0.10.0
00002aaaaaac4000 40K r-x-- /lib64/libnss_files-2.5.so
00002aaaaaace000 2044K ----- /lib64/libnss_files-2.5.so
00002aaaaaccd000 4K r---- /lib64/libnss_files-2.5.so
00002aaaaacce000 4K rw--- /lib64/libnss_files-2.5.so
00002aaaaaccf000 32768K rw-s- /dev/zero (deleted)
00002aaaacccf000 4K rw-s- /dev/zero (deleted)
00002aac041d0000 8K rw--- [ anon ]
00002aac041d2000 4K rw-s- /dev/zero (deleted)
00002aac041d3000 4K rw-s- /dev/zero (deleted)
00002aac041d4000 4K rw-s- /dev/zero (deleted)
00002aac041d5000 4K rw-s- /dev/zero (deleted)
00002aac041de000 4K rw--- [ anon ]
00002aac041df000 2904K r-x-- /usr/local/mysql/lib/libmysqlclient.so.18.0.0
00002aac044b5000 1020K ----- /usr/local/mysql/lib/libmysqlclient.so.18.0.0
00002aac045b4000 524K rw--- /usr/local/mysql/lib/libmysqlclient.so.18.0.0
00002aac04637000 24K rw--- [ anon ]
00002aac0463d000 132K r-x-- /usr/lib64/libjpeg.so.62.0.0
00002aac0465e000 2044K ----- /usr/lib64/libjpeg.so.62.0.0
00002aac0485d000 4K rw--- /usr/lib64/libjpeg.so.62.0.0
00002aac0485e000 4K rw--- [ anon ]
00002aac0485f000 324K r-x-- /usr/local/lib/libcurl.so.4.2.0
00002aac048b0000 2044K ----- /usr/local/lib/libcurl.so.4.2.0
00002aac04aaf000 12K rw--- /usr/local/lib/libcurl.so.4.2.0
00002aac04ab2000 4K rw--- [ anon ]
00002aac04ab3000 196K r-x-- /usr/lib64/libidn.so.11.5.19
00002aac04ae4000 2044K ----- /usr/lib64/libidn.so.11.5.19
00002aac04ce3000 4K rw--- /usr/lib64/libidn.so.11.5.19
00002aac04ce4000 28K rw--- [ anon ]
00002aac04d2c000 316K rw--- [ anon ]
00002aac04d7b000 128K r-x-- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/apc.so
00002aac04d9b000 2048K ----- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/apc.so
00002aac04f9b000 12K rw--- /usr/local/lib/php/extensions/no-debug-non-zts-20090626/apc.so
00002aac04f9e000 36K rw--- [ anon ]
00007fffbee97000 84K rw--- [ stack ]
00007fffbeffc000 16K r-x-- [ anon ]
ffffffffff600000 8192K ----- [ anon ]
total 130704K



2Mダイエットできました。


負荷試験
nginxとPHP-FPMを少しキャッシュなどで太らせたいので別のマシンからApacheBenchしてみます。


./ab -n 1000 -c 20 -t 10 http://blog.kubox.info/




# free -m
total used free shared buffers cached
Mem: 497 346 151 0 11 126
-/+ buffers/cache: 208 289
Swap: 1027 9 1017



結構メモリを消費したみたいです。

LoadAverageも結構あがりました。


top - 17:16:48 up 7 days, 2:56, 3 users, load average: 4.12, 1.24, 0.44
Tasks: 107 total, 23 running, 75 sleeping, 8 stopped, 1 zombie
Cpu(s): 89.5%us, 4.5%sy, 0.0%ni, 0.0%id, 0.0%wa, 2.5%hi, 3.5%si, 0.0%st
Mem: 509792k total, 299092k used, 210700k free, 12056k buffers
Swap: 1052248k total, 10232k used, 1042016k free, 102124k cached

PID USER PR NI VIRT RES SHR S %CPU %MEM TIME+ COMMAND
11823 nginx 16 0 124m 23m 15m R 63.8 4.7 0:02.69 php-fpm
11810 nginx 16 0 124m 23m 15m R 31.9 4.6 0:02.31 php-fpm
11805 nginx 16 0 124m 23m 15m R 25.9 4.6 0:03.59 php-fpm
11824 nginx 16 0 125m 23m 15m R 21.9 4.8 0:01.19 php-fpm
11806 nginx 16 0 124m 23m 15m R 19.9 4.6 0:03.96 php-fpm
11807 nginx 16 0 125m 23m 15m R 15.0 4.8 0:02.25 php-fpm
11825 nginx 16 0 125m 23m 15m R 15.0 4.8 0:01.55 php-fpm
10715 nginx 15 0 21728 2180 756 S 5.0 0.4 0:01.02 nginx
11123 mysql 15 0 452m 50m 5684 S 1.0 10.1 0:01.65 mysqld




エラーがでるまでApacheBenchのスレッドを上げていきます。

同時に先ほどnginxでstatusとnginx_statusを設定したページにアクセスしてプロセスの状態を見ます。


#nginx_status
Active connections: 19
server accepts handled requests
815 815 815
Reading: 0 Writing: 19 Waiting: 0


Readingはnginxがリクエストのヘッダーを読み込んでいる数、Writingはレスポンス用のリクエストを生成している数、WaitingはKeepAliveで待っている数です。

KeepAliveは0(無効)にしているので必ず0になります。KeepAliveはDoS攻撃などの耐性が低くなるのでできるだけ無効で運用します。


100スレッド目からエラーが出始めました。


Server Software: nginx
Server Hostname: blog.kubox.info
Server Port: 80

Document Path: /
Document Length: 119439 bytes

Concurrency Level: 100
Time taken for tests: 11.310 seconds
Complete requests: 100
Failed requests: 2
(Connect: 0, Receive: 0, Length: 2, Exceptions: 0)
Write errors: 0
Non-2xx responses: 2
Total transferred: 11742858 bytes
HTML transferred: 11705790 bytes
Requests per second: 8.84 [#/sec] (mean)
Time per request: 11309.898 [ms] (mean)
Time per request: 113.099 [ms] (mean, across all concurrent requests)
Transfer rate: 1013.95 [Kbytes/sec] received

Connection Times (ms)
min mean[+/-sd] median max
Connect: 10 21 6.5 20 34
Processing: 475 6205 3240.7 6199 11285
Waiting: 129 5687 3298.2 5759 11123
Total: 489 6227 3241.4 6226 11304

Percentage of the requests served within a certain time (ms)
50% 6226
66% 8179
75% 9103
80% 9653
90% 10643
95% 11059
98% 11106
99% 11304
100% 11304 (longest request)




クライアント側のログを見てみます。


[error] 5717#0: *5587 recv() failed (104: Connection reset by peer) while reading response header from upstream, client: IP, server: blog.kubox.info, request: "GET / HTTP/1.0", upstream: "fastcgi://127.0.0.1:9000", host: "hostname"


どうやらnginxが受け取ったリクエストをPHP-FPMに処理を投げたときにconnectionを切られているみたいです。

このエラーの場合はnginxはユーザからリクエストを受け取り、PHP-FPMに処理を投げているのでボトルネックはPHP-FPMだと分かります。

PHP-FPMの設定を見直すとrequest_terminate_timeout= 5が悪さをしているようでタイムアウトを少し長めします。

request_terminate_timeout= 10


150スレッド目で同様のエラーが出力されました。

PHP-FPMのステータスを負荷試験中に見るとmax children reached: 1となっているのでPHP-FPMのプロセスが常時最大に達しているのが確認できました。


pool: www
process manager: dynamic
accepted conn: 317
listen queue len: 0
max listen queue len: -1
idle processes: 0
active processes: 10
total processes: 10
max children reached: 1



PHP-FPMのプロセスを増やしたいと思います。

ApacheやnginxやPHP-FPMはforkしてプロセス間で負荷分散しつつメモリの消費を節約します。

サーバが落ちる時は大体この辺りの設定ミスです。

実際にどれぐらいforkさせるのかはサービスによって異なりますが物理リソースを無駄なく利用するにはforkで生じるメモリ使用量を把握する必要があります。

メモリのお話については割愛しますが今回のPHP-FPMでいうとforkされたプロセスが使うメモリはおおよそ7M程度です。

物理メモリ100Mは残して起きたいのでさらに20プロセス増やす事にしました。


pm = dynamic
pm.max_children = 30
pm.start_servers = 11
pm.min_spare_servers = 10
pm.max_spare_servers = 15
pm.max_requests = 500



PHP-FPMを再起動後メモリの状態を見てみます。
予想に反してあまりメモリを消費しなかったみたいです。


# free -m
total used free shared buffers cached
Mem: 497 400 97 0 52 140
-/+ buffers/cache: 207 290
Swap: 1027 9 1017




プロセス数を3倍にしたので論理的には3倍のアクセスを処理できることになります。

再度ApacheBenchで今度は450スレッドまで引き上げて負荷試験をしてみます。


Server Software: nginx
Server Hostname: blog.kubox.info
Server Port: 80

Document Path: /
Document Length: 119439 bytes

Concurrency Level: 350
Time taken for tests: 10.132 seconds
Complete requests: 82
Failed requests: 0
Write errors: 0
Total transferred: 10160997 bytes
HTML transferred: 10128261 bytes
Requests per second: 8.09 [#/sec] (mean)
Time per request: 43245.804 [ms] (mean)
Time per request: 123.559 [ms] (mean, across all concurrent requests)
Transfer rate: 979.37 [Kbytes/sec] received




心なしかレスポンスが良くなりました。

vmstatを見てみるとrがCPUコア数を超えているのでCPUの負荷がかなり高い状態になっています。
メモリはswapは少々発生していますがswap inもoutも発生していないのでとりあえず問題はありません。
procsのbとSWAPのsoが発生し始めると大幅に性能が劣化しますので注意が必要です。

nginxのエラーログとvmstatを見る限りエラーもなしでCPUのみが高負荷なので理想な負荷です。


# vmstat 1
procs -----------memory---------- ---swap-- -----io---- --system-- -----cpu------
r b swpd free buff cache si so bi bo in cs us sy id wa st
1 0 10144 73552 54424 147776 0 0 1 3 2 16 0 0 99 0 0
31 0 10144 59592 54424 147776 0 0 0 0 2099 858 57 10 33 0 0
31 0 10144 60948 54424 147792 0 0 0 0 1744 762 94 6 0 0 0
31 0 10144 58468 54424 147868 0 0 0 4 1897 681 94 6 0 0 0
31 0 10144 59212 54424 147876 0 0 0 0 1904 842 94 6 0 0 0
34 0 10144 59708 54428 147948 0 0 0 460 1777 828 94 6 0 0 0
32 0 10144 59832 54428 147944 0 0 0 0 1785 835 94 6 0 0 0
32 0 10144 59212 54428 148020 0 0 0 0 1971 763 93 7 0 0 0
31 0 10144 59832 54428 148024 0 0 0 0 1891 896 94 6 0 0 0
31 0 10144 59708 54428 148100 0 0 0 0 2010 769 94 6 0 0 0
32 0 10144 59832 54436 148080 0 0 0 480 1943 855 93 7 0 0 0
34 0 10144 70760 54436 148232 0 0 0 0 2099 1320 92 9 0 0 0
35 0 10144 69560 54436 148444 0 0 0 0 1020 1727 95 5 0 0 0


Too many open files

800スレッド目からnginxのエラーログにToo many open filesが出力され始めました。

nginxのファイルオープン数の制限に引っかかったようです。

設定ファイルにworker_rlimit_nofile 10240;を追加します。

設定を追加後もエラーが消えないのでどうやらLinuxのファイルディスクリプタに引っかかっているようです。


#vi /etc/security/limits.conf
nginx soft nofile 10240
nginx hard nofile 10240


これでエラーはでなくなりました。


最終的に1000スレッドまで達し24時間負荷をかけ続けましたが(これはJmeterで)レスポンスタイムは平均で3秒程度まで落ちたものの安定したアクセスでエラーも出力されていませんでした。

expireを使いユーザのブラウザにキャッシュさせる方法も画像が多いサイトには有効です。

1000スレッド目で負荷を与える側の限界に達したので今回はこれ以上行う事はできませんがApacheと比べて最初はメモリ使用量がやや多いですが、高負荷時は一定のペースを保つので負荷の高いサイトにnginxはオススメです。


その他やったこと
libjpeg-turboに差し替え

libjpeg-truboはlibraryを差し替えるだけで簡単にjpeg系の処理を高速化できます。
http://sourceforge.jp/projects/freshmeat_libjpeg-turbo/


tar -zxvf nasm-2.09.02.tar.gz
cd nasm-2.09.02
./configure
make
make install

tar -zxvf libjpeg-turbo-1.0.90.tar.gz
cd libjpeg-turbo-1.0.90
./configure
make
make install


/opt/libjpeg-turbo/ にインストールされるので、一旦 /usr/lib/libjpeg* をtmpなどに待避させてから入れ替えます。


mkdir /tmp/libjpeg-backup/
mv /usr/lib/libjpeg* /tmp/libjpeg-backup/
cp -aL /opt/libjpeg-turbo/lib/lib* /usr/lib/
ldconfig


WordPressは接続の度にDBを叩くのでクエリーキャッシュを多めに設定しています。

skip-name-resolve
key_buffer_size = 20M
max_allowed_packet = 1M
table_open_cache = 1024
sort_buffer_size = 1M
read_buffer_size = 1M
read_rnd_buffer_size = 4M
myisam_sort_buffer_size = 8M
thread_concurrency = 8
character-set-server = utf8
skip-character-set-client-handshake
max_connect_errors=10000
max_connections=300
table_cache=256
thread_cache_size = 30
query_cache_size = 32M
wait_timeout = 60


innodb_data_file_path = ibdata1:1024M;ibdata2:2048M:autoextend
innodb_buffer_pool_size = 128M
innodb_log_file_size = 64M
innodb_flush_log_at_trx_commit = 1
innodb_flush_method=O_DIRECT



負荷試験中のMySQLの状態を見てみます。

この3つの値が増え始めるとMySQLの負荷が高くなってくるので上記の設定で予めキャッシュさせておきます。


mysql> SHOW GLOBAL STATUS;
Max_used_connections | 2
Opened_tables | 45
Opened_files | 121

2011年7月23日土曜日

オープンソースで構築する仮想ファイアーウォール IPS編

前回の記事でVyattaのF/Wの基本的な使い方を解説いたしましたが、今回はより強固なネットワークを実現させるためにIPSを使ってみます。

VyattaのIPSはLinuxでも頻繁に使われているSnortを使っています。

Vyatta自体は非常に軽量で高速に動作しますがSnort(IPS)を利用する場合はパケットを転送するだけのルータではなく、パケットの中身を見てシグネチャと照らし合わせ、Vyattaで設定したポリシーと照らし合わすなどのプロセスがあるためメモリを多めに積んだマシンが必要になります。
また今回は紹介していないですがNATを利用する場合も同様でパケットを書き換え再度checksumする必要があるためCPUパワーが必要になります。

Snortのおさらい
Snortはオープンソースの侵入検知システム(IDS)と言われるもので、ネットワークに流れるパケットをキャプチャーし不正なパケットを検出します。

通常IDSは不正なパケットを検出し警告を出すにとどまりますが、IPSは検出し遮断します。

VyattaはSnortでこれを実現します。

不正アクセスする手法やシステムの脆弱性は常につきまとうので、Snortは定期的にルールセット(シグネチャ)を更新しています。


Snortにユーザ登録

Snortのシグネチャを定期的に更新するためにSnortにユーザ登録しoink-codeを取得します。

http://www.snort.org/


Snortの設定

早速、VyattaでIPSの設定をしてみましょう。

まず、Snortのシグネチャを取得します。

$update ips rules oinkcode ****


Snortのサーバが少し遅いので時間がかかるかもしれません。

updateを先しないとError: Missing Snort Rulesと出たりするので必ず先にUpdateしてください。

ログを見ると更新されたのかわかります。

$show ips update-log



自動アップデートとLANの設定

Snortは定期的にシグネチャを更新する必要があるので自動アップデートの設定を行い定期的にシグネチャを更新したいと思います。


$configure
#set content-inspection ips auto-update oink-code ****
#set content-inspection ips auto-update update-hour 2


この設定でAM2時に自動的に更新されます。


次にLANのネットワークを予め指定することでSnortによる誤検知を防ぐ事ができます。

$configure
#set content-inspection ips modify-rules internal-network 192.168.1.0/24


IPSの設定

VyattaのIPSではパケットをチェックする経路を選択できます。

  1. 全てのパケットをチェック

  2. 特定のインタフェースのパケットをチェック

  3. 特定のゾーン間のパケットをチェック



IPSは負荷が高いのでできるだけパケットチェック対象を絞るべきですが今回は1の全チェックで検証したいと思います。


$configure
#set content-inspection inspect-all enable



次にチェックするプロトコルを指定します。これでも同様に全チェックだと負荷が高くなります。ICMPやF/Wで既にdropしているプロトコルなどは省くべきです。


$configure
#set content-inspection traffic-filter preset all



ここでshowして設定を確認してみましょう。

$configure
#show content-inspection



+inspect-all {
+ enable
+}
+ips {
+ auto-update {
+ oink-code ***
+ update-hour 2
+ }
+ modify-rules {
+ internal-network 192.168.1.0/24
+ }
+}
+traffic-filter {
+ preset all
+}



最後にVyattaでデフォルトルールで設定されている警告レベルの設定を行います。

デフォルトルールには4つのプライオリティが準備されています。
priority-1が最も危険度が高いイベントになりpriority-3が通常の通信でも発生するようなイベントになります。
Otherはルールにマッチしなかった場合に適応されます。


  1. priority-1

  2. priority-2

  3. priority-3

  4. Other




例えば各priorityには次のようなルールがセットされています。

priority-1 trojan-activity トロイなどによるバックドアを検知します
priority-2 successful-dos DoSを検知します
priority-3 icmp-event Pingを検知します

その他にも多くあるのでドキュメントを参照してください。
show ips rulesでも確認できます。


$ show ips rules


Vyattaではこれらのpriority別に検知時の動作を指定します。

  1. alert:通信を許可しログにAlertとして記録します

  2. drop:通信を遮断しログにAlertとして記録します

  3. pass:通信を許可しそれ以外の動作をしません

  4. sdrop:通信を遮断しログには記録しません(silent drop)





今回は実験的に全てのpriorityをdropとして指定したいと思います。


$configure
#set content-inspection ips actions priority-1 drop
#set content-inspection ips actions priority-2 drop
#set content-inspection ips actions priority-3 drop
#set content-inspection ips actions other pass


そして一旦、ローカルネットワークの設定を削除してみます。


$configure
#delete content-inspection ips modify-rules internal-network 192.168.1.0/24
#commit


削除した事で全てのネットワークがIPSの対象になりました。


別のマシンからこのVyattaにPingを打ちます。

$ping 192.168.1.2
PING 192.168.1.1 (192.168.250.1) 56(84) bytes of data.

--- 192.168.250.1 ping statistics ---
16 packets transmitted, 0 received, 100% packet loss, time 15086ms



全てPingが失敗したのが確認できたと思います。

この原因を調べてみます。


$show ips log
---------------------------------------------------------------------------
2011-07-22 16:51:15.540325 {ICMP} 192.168.1.2 -> 192.168.1.3
(misc-activity) Misc activity (priority 3)
[1:382:7] ICMP PING Windows
---------------------------------------------------------------------------
2011-07-22 16:51:15.540325 {ICMP} 192.168.1.2 -> 192.168.1.3
(misc-activity) Misc activity (priority 3)
[1:384:5] ICMP PING
---------------------------------------------------------------------------


priority-3のルールによって遮断されていることがわかりました。

Pingを通すためにルールを変更したいと思います。

Pingを防いでいるルールはicmp-info.rulesですので、このルールだけを除外します。

$configure
#set content-inspection ips modify-rules exclude-category icmp-info.rules
#commit


再度Pingを実行するとPingが通ると思います。

最後に変更したローカルネットワークの設定を元に戻しておいてください。

$configure
#set content-inspection ips modify-rules internal-network 192.168.1.0/24


priority-1以外はAlertで大丈夫だと思いますが利用するネットワーク形態によって調節してみてください。

IPS導入時はこまめにログを見てフォールスポジティブとフォールスネガティブが無いかチェックし適宜ポリシーを変更する必要があります。

2011年7月21日木曜日

オープンソースで構築する仮想ファイアーウォール

仮想ファイアーウォールというとイメージしにくいと思いますがVyattaを少し使ってみたので紹介したいと思います。

長くなるので3つぐらいに分けたいと思います。

Vyatta : ビアッタ

Vyattaでできること

  • Routing

  • NAT

  • VPN

  • ※F/W

  • ※IPS

  • Loadbalance

  • VRRP

  • CUI/GUI(Webベース)


今回紹介するのは※が付いている項目です。

 

Vyattaとはそもそもなに?

VyattaはDebianベースで作られておりiptablesやsnortなどを組み合わせた“物”です。

Juniperなどのアプライアンス製のF/Wに付いている機能が網羅されている感じです。

ルーティングプロトコルも充実しているので高性能なルータとしても十分機能させることができます。

またVyattaには有料サポートも準備されおりサポートが必要な場合はそちらを使うのもいいと思います。

無料版もVPNクライアントやアンチウイルス機能が無い程度ですので十分に使えます。

イメージの配布もクラウド環境用なども準備されているのですぐに試すことができます。

http://www.vyatta.org/

 

インストール

メモリ256M、HDD 5Gもあれば十分です。

今回は検証が目的なので利用環境に応じてリソースは変更してください。

インストール自体は非常に簡単なので省略します。

Live Installのままだとリブート後全て消えてしまうのでinstall-imageだけは行ってください。
$install-image

イメージをInstallした後は必ずリブートしてください。色々おかしくなります。

初期設定が終わるまでGUIは使えないのでCLIで進めます。

ユーザ名、パスワード共にvyattaでログインできます。

Linuxライクなプロンプトが表示されていると思いますが、通常のLinuxコマンドもそのまま使えます。

lsコマンドなどを実行するとファイル/ディレクトリリストが表示されると思います。

 

基本操作

Ciscoなどの製品を使ったことがある人ならすぐになじめると思います。

Vyattaの操作はLinuxコマンドで行うのではなくVyatta専用のコマンドを利用します。

show : showに続く項目の情報を表示する
set : setに続く項目を設定する
save : 設定を起動ファイルに書き込む(設定は再起動まで反映されない)
commit : 設定を反映させる(設定後必ず行う)

$ : operationモード
operationモードでは設定の変更は行えません。

F/Wやインタフェースなどの情報を確認したい場合に利用します。

 

# : configureモード
operationモード時にconfigureコマンドを実行することでcofigureモードに移行できます。

configureモードでは全ての設定の変更が行えます。

 

IPの設定

早速IPを割り振ってみましょう。

configureモードになったら次のコマンドを実行します。
$configure
#set interface ethernet eth0 address 192.168.1.2/24
#set system gateway-address 192.168.1.1
#commit

これでeth0に192.168.1.2が割り当てられました。

SSHを起動

SSHが使えないと色々不便なのでSSHを起動します。
$configure
#set service ssh
#commit

ここまでくるとGUIを利用できます。
#set service https
#commit

先ほど設定したIPアドレスにアクセスするとGUIモードで設定を変更できます。

NTP/DNS設定
$configure
#set system time-zone Asia/Tokyo
#set system ntp server ntp.nict.jp
#set system name-server 8.8.8.8
#commit

ユーザ追加

plaintext-passwordとなっていますが、入力はプレーンテキストなのでそのままで大丈夫です。
設定後暗号化されます。

levelは適宜変更してください。
$configure
#set system login user kojiro
#set system login user kojiro level admin
#set system login user kojiro authentication plaintext-password hogehoge
#commit

F/W設定
初期設定ができたところで、本題のF/Wの設定を行いたいと思います。

F/Wを設定する前に予めIPアドレスのグループを作っておくと後々の運用が楽になります。

VMGuet01というグループを作りIPアドレス172.16.0.10を参加させました。
$configure
#set firewall group address-group VMGuet01
#set firewall group address-group VMGuet01 address 172.16.0.10
#commit

VyattaのF/Wは親ノード⇒親ノード内のルール番号(1~1024)⇒許可/拒否⇒マッチ条件 のような流れで設定します。

HTTPという親ノードを作成します
$configure
#set firewall name HTTP

ルール番号を指定する。1~1024までならどれも大丈夫ですが1から評価されてゆきマッチした時点でそれ移行を評価しないので100や200など少し間を開けて登録するのがセオリーです。
また、どれにもマッチしなかった場合はF/W全般に言えることですが暗黙の拒否があり全て拒否されます。

今回は内側(LAN)から外側(WAN)に向けた設定をしてみます。

ルールは100から使ってきます。
$configure
#set firewall name HTTP rule 100

HTTPノードに対するルール100のアクションを指定します
$configure
#set firewall name HTTP rule 100 action accept

HTTPノードに対するルール100のマッチ条件を指定します
$configure
#set firewall name HTTP rule 100 source group address-group VMGuet01
#set firewall name HTTP rule 100 destination port 80,443

この設定は送信元がVMGuet01で宛先のポートが80番(HTTP)、443(HTTPS)を許可するという意味になります。

sourceをPortやGlobalIPなどにすることで外側から内側へのアクセス制御も行えます。

commit時にエラーがでる場合などは設定が抜けている事が殆どなのでshowコマンドで設定を確認しながらやっていくといいと思います。

次はIPSを設定してみます。

2011年7月20日水曜日

GoogleのWebアプリケーション脆弱性スキャナ使い方

はてなから引っ越ししました。はてなさん今までお世話になりました。



GoogleがWebアプリケーション脆弱性スキャナskipfishを公開しました。

以前にもGoogleが開発した脆弱性診断ツールratproxyを紹介しました。

ratporxyとskipfishの大きな違いは、ratproxyは受動的な脆弱性診断ツールであったのに対してskipfishは能動的な脆弱性診断ツールです。

skipfishの特徴

  • SQLインジェクションの検出

  • コマンドインジェクションの検出

  • 秒間2000リクエスト以上実行できるパフォーマンスの高さ

  • Basic認証、cookieなども渡せる

  • 非常にファイルが軽い(1.3M)

  • HTMLで結果を出力



 

使い方
skipfishをダウンロードしてください。

展開後

make
./skipfish -o /var/www/html/skipfish -W /dir/dictionaries/complete.wl http://test.jp/


-o 結果ファイル出力先(空ディレクトリじゃないとエラーになります)
-W テストに使う辞書
-g 最大接続数 (指定推奨)

complete.wlで2時間ぐらいかかりました。

使ってみた感じ

今まで利用した脆弱性診断ツールの中では間違いなく最高速度ですが、辞書が少ない点、辞書式では難しい既存の脆弱性を発見するための仕組みがないことから簡易的な使い方や開発中のアプリケーションのような診断にしか使えないと思います。


現在はまだβ版なので今後の追加機能に期待。