2011年11月22日火曜日

EXT2をEXT3に変換する

Linux上でディスクの増設やパーティションの分割を行う時に利用partedコマンドを利用する事が多いと思います。


# parted /dev/hdd
(parted) mkpartfs
Partition name? []? 1
File system type? [ext2]? ext3
Start? 14k
End? 10G
No Implementation: Support for creating ext3 file systems is not implemented yet.


真面目にpartedコマンドでやると

No Implementation: Support for creating ext3 file systems is not implemented yet.


このようなerrorがでると思います。

そう、partedコマンドはext3に対応していないのでpartedコマンドだけでEXT3のファイルシステムを作ることはできません。

partedコマンドではEXT2としてパーティションだけ作ることにしてそこからEXT3へ変換することにします。

ext3になっていますが完成形はEXT2になります

# parted /dev/hdd
(parted) mkpart primary ext3 14k 10G
(parted) print free

Number Start End Size File system Name Flags
1 14kB 10GB 10GB ext2 primary


EXT3に変換します

# mkfs -t ext3 /dev/hddp01
mke2fs 1.39 (29-May-2006)
Filesystem label=
OS type: Linux
略......


最後にfstabに書き忘れないようにしましょう。

2011年11月3日木曜日

Macで作った秘密鍵をWindowsのPuttyで使う方法がわからなかった

MacにはOpensslが入っているのでターミナルから簡単に秘密鍵(id_rsa)と公開鍵(id_rsa.pub)を作ることができます。

ssh-keygen -t rsa


この秘密鍵をWindowsで使う必要がありPutyyで読み込もうとしたのですがUnable to use key fileと怒られログインできません。

ちなみに秘密鍵を書いたファイルの拡張はなんでも大丈夫です。

結果としてPuttyGenでMacで作成した秘密鍵を読み込ませPutty用に生成すれば普通に使えました。

Puttygen起動->Load->適当にパスワードを付ける->Macで作った秘密鍵を選択->Save Private Key -> マウスを動かす -> 保存 -> 先ほど保存したキーを使ってアクセス

これで1時間ぐらい悩んでしまった。。。。。

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時間ぐらいかかりました。

使ってみた感じ

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


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

2011年3月26日土曜日

必要な時にパソコンの電源を遠隔操作で入れる


震災の影響で電力不足がかなり深刻になってきています。


業務上の都合や個人の都合でパソコンの電源も切りたいけど切れないなど問題もあると思います。


そこで、今回は少しでも節電に協力できるようにパソコンの電源を必要な時に入れて、不要な時には切る操作をインターネットを通じて遠隔操作で行う方法を紹介します。



Wake On LAN


ネットワークを通じて電源の操作をするWake On LAN(WOL)という仕組みがあります。


WOLはサーバなどには標準で備わっている事が多く、最近のパソコンでも設定さえすればWOLを有効にすることができます。



仕組み


WOLはゲストマシンからMagicPacketと言われる特殊なパケットをUDPを利用して送信します。


MagicPacketを受け取ったホストマシンは電源を入れます。


そのため、MagicPacketを受け取るホストマシンはMagicPacketに対応したハードウェア構成である必要があります。


主なハードウェア要件


  1. 電源とマザーボードがACPIに対応している

  2. NICがMagicPacketを解釈できる


これらの主なハードウェア要件は、最近のパソコンであれば殆ど利用できます。



手順



  1. BIOSの設定

  2. NICの設定

  3. MagicPacketを送信するフリーソフトをインストール



BIOSの設定


BIOSを起動します。


通常、電源管理などの画面でWOLを有効にします。


私の端末では「Remote Wake Up」とありました。


さらに私の場合は「Low Power Mode」を無効にしないと電源切断時にNICの電源も切れてしまうのでこちらの設定は無効にします。



NICの設定


デバイスマネージャから利用しているNICの「プロパティ」→「詳細設定タブ」でWOLを有効にします。


私の場合は「Wake on Link」を「強制」に変更し「Wake On Magic Packet」をオンにします。


最後に「PEM」を「オン」にしますがこちらはNICによって無い場合があります。無い場合はドライバーをアップデートし、PEMを「オン」にしないと起動できない可能性があります。


f:id:koujirou6218:20110325164355p:image


f:id:koujirou6218:20110325164356p:image


f:id:koujirou6218:20110325164357p:image



ゲストマシンにMagicBootをインストール


MagicPacketを送信できるソフトはいくつかあるのですが今回はMagicBootを利用します。MagicBootはフリーソフトでVectorからダウンロードできます。


http://www.vector.co.jp/soft/dl/win95/net/se282263.html


MagicBootの利用にはIPアドレスとMACアドレスが必要になります。


コマンドプロンプトで次のコマンドを実行します。



ipconfig /all



IPv4アドレスと物理アドレスをMagicBootに入力します。


ファイアーウォール


MagicBootはデフォルトでUDP 3708番ポートを利用するのでファイアーウォールで防いでいる場合は開放する必要があります。


注意点


個人の家庭で利用する場合はISPから1つIPアドレスを付与されますが、このIPアドレスは定期的に変わるので固定IPを申込むかDDNSなどを利用する必要があります。


2011年3月17日木曜日

無料で使えるクラウドDB Cleardb


クラウドデータベースとしてリリースされたCleardbを紹介したいと思います。


PHP Java Objectiv-C Javascript Ruby .NETなどですぐに利用できるソースコードが公開されているので簡単に利用できます。


ClearDB API Documentation


ClearDBとは


100Mまで無料で利用できるRDBで、高いセキュリティと保守性や高速な動作をウリにしているようです。


DBの操作は提供されるAPIを利用して行います。


APIの制限は月4万回まで無料で利用できます。


http://www.cleardb.com/whatis.html


DBは負荷分散やバックアップなどがボトルネックになりがちなので、DBを異なるサーバで持てるのは大きなメリットです。



テーブルを作る


ユーザ登録が完了したらテーブルを作ります。


上部のメニュー【My Database】⇒【New】⇒【Talbe】


f:id:koujirou6218:20110316153615p:image


テーブルが作成できればブラウザ上から【QueryAnalyzer】を利用してSQLを実行することができます。



APIを利用する


APIとして利用できるパラメータはドキュメントで公開されています。


ClearDB API Documentation


この手順は最も簡単に利用できる方法ですがユーザ登録した時のユーザ名とパスワードを利用します。


次のような手順でSQLを実行します。



  1. ユーザ名とパスワードをGET/POSTメソッドで実行しセッションIDを取得する

  2. セッションIDとSQLをGET/POSTメソッドで実行する

  3. ログアウトする



実行するURLは全てURLエンコードしてください



これがAPIのベースとなるURLです



https://www.cleardb.com/v1/api.php



ログインしてセッションIDを取得する



https://www.cleardb.com/v1/api.php?action=login&username=hogeuser&password=himitu




JSON形式でレスポンスが返ってきます



{"result":"success","response":"398fe198203322b072e0745edfb2fd5f"}




SQLを実行する



https://www.cleardb.com/v1/api.php?action=sqlQuery&session_id=398fe198203322b072e0745edfb2fd5f&query=select * from user




このような手順でCleardbを操作します。



APIキーでアクセスする


前述の方法では、ユーザ名とパスワードをそのまま利用します。


この方法では多人数での利用においてリスクが高いのでAPIキーを利用します。


f:id:koujirou6218:20110316153614p:image


APIキーを利用するには、先ほど作成したテーブルと新たに【My Apps】でAppsを作り関連づけさせます。


My AppsはMySQLでいうユーザ管理にあたります。異なるAPIキーをユーザに配布しユーザごとに権限を変える事が可能になります。



上部メニューの【My Apps】をクリックし【New Apps】でAppsを作ります。(全て入力してください)



Appsを作るとそのAppsに対するApp IDが作成されます。


【Create Key】よりAPIキーを作成します。作成したAPIキーはデフォルトで【DENY READ】になっているので【Show Rules】より権限を適宜変更してください。



キーの作成が完了すれば、Cleardbで公開されているPHPコードを利用してアクセスしてみます。


https://www.cleardb.com/v1/doc/home




// Set your own API Key here.


define('CDB_API_KEY', 'ここにユーザごとのAPIキー');


// Set your own App ID here.


define('CDB_APP_ID', 'ここにApp ID');


// Include the ClearDB PHP API Client for Apps into our code.


require_once('cleardb_app_client.php');


// Create a new instance of the ClearDB class.


$cleardb = new ClearDB_App_Client();


// Retrieve an object array as results from ClearDB.


$users = $cleardb->query("INSERT INTO user (name,age) value('koujirou','24')");


?>




このような感じで普通のDBのように利用できます.



2011年2月10日木曜日

さくらVPSでLighttpd+PHP+MySQLの高速軽量サーバを作る


以前、さくらVPSで一日6万PVを処理するためにしたことを書かせていただいたのですが


DBが必要になり、以前のApache構成ではメモリとパフォーマンスに不安があったので軽量WebサーバのLighttpd(ライティ)を使ってみました。


LighttpdとPHPを使う場合は、PHPをCGIモードでインストールする必要があります。


Apache+PHPで構成されるサーバは基本的にモジュール版で動いている物が殆どですが、Lighttpdの場合はPHPモジュールがないためWebサーバ(Lighttpd)とPHPを別に動かす必要があります。


PHPを動かすためにfastcgiを使ってPHPのプロセスを管理します。


Lighttpdでは標準でfastcgiをサポートしていますので設定さえすればすぐにPHPが利用できます。



さくらVPSのコントロールパネルからすること


コントロールパネルからrootでログインしユーザを作る

作業用のユーザを作ります



adduser hogehoge


passwd hogehoge





サーバの細かい設定


SSHからhogehogeでログインする

先ほど作ったユーザをwheelに入れます



su -


usermod -aG wheel hogehoge


id hogehoge



wheelグループ以外rootに昇格できないようにします。


必ず一般ユーザをwheelに追加してからこの作業を行ってください。


rootになれなくなります。


vi /etc/pam.d/su



auth required pam_wheel.so use_uid


#コメントアウトを外す



よく使う&必要なライブラリーインストール


yum install bzip2-devel libjpeg libpng libjpeg-devel libpng-devel pcre pcre-devel bzip2 libxml2-devel



全てY



ライブラリーのパスを追加します


vi /etc/ld.so.conf



include ld.so.conf.d/*.conf


/usr/lib


/usr/local/lib


/usr/lib64


/usr/local/lib64



ldconfig




作業用ディレクトリ作成を作っておきます。


今後、ダウンロードや解凍作業などはこのディレクトリで行います。


mkdir /usr/local/work



インストール


cd /usr/local/work



MySQLダウンロード

mysql-5.5.9-linux2.6-x86_64.tar.gz


http://dev.mysql.com/downloads/mirror.php?id=401187#mirrors



MySQLのインストール

MySQLユーザの追加。


MySQLインストール作業はマニュアル通りになります。



adduser mysql -s /sbin/nologin


tar -zxvf mysql-5.5.9-linux2.6-x86_64.tar.gz -C /usr/local/


cd /usr/local/


ln -s /usr/local/mysql-5.5.8-linux2.6-x86_64 /usr/local/mysql


chown root: mysql-5.5.9-linux2.6-x86_64


cd mysql


chown -R mysql .


chgrp -R mysql .


mv data var


scripts/mysql_install_db --user=mysql --basedir=/usr/local/mysql --datadir=/usr/local/mysql/var


chown -R root .


chown -R mysql var


cp support-files/my-large.cnf /etc/my.cnf


cp bin/mysql /usr/local/bin/


cp /usr/local/mysql/support-files/mysql.server /etc/rc.d/init.d/mysql




設定ファイル編集


vi /etc/my.cnf



[client]


#password = your_password


port = 3306


socket = /tmp/mysql.sock



[mysqld]


port = 3306


socket = /tmp/mysql.sock


skip-external-locking


key_buffer_size = 256M


max_allowed_packet = 1M


table_open_cache = 256


sort_buffer_size = 1M


read_buffer_size = 1M


read_rnd_buffer_size = 4M


myisam_sort_buffer_size = 64M


thread_cache_size = 8


query_cache_size= 16M


thread_concurrency =


max_connections = 300


#skip-networking


#log-bin=mysql-bin


#binlog_format=mixed


server-id = 1


#server-id = 2


#master-host = <hostname>


#master-user = <username>


#master-password = <password>


#master-port = <port>


#log-bin=mysql-bin


#innodb_data_home_dir = /usr/local/mysql/data


innodb_data_file_path = ibdata1:512M:autoextend


#innodb_log_group_home_dir = /usr/local/mysql/data


innodb_buffer_pool_size = 256M


#innodb_additional_mem_pool_size = 20M


#innodb_log_file_size = 64M


#innodb_log_buffer_size = 8M


#innodb_flush_log_at_trx_commit = 1


#innodb_lock_wait_timeout = 50


[mysqldump]


quick


max_allowed_packet = 16M


[mysql]


no-auto-rehash


#safe-updates


[myisamchk]


key_buffer_size = 128M


sort_buffer_size = 128M


read_buffer = 2M


write_buffer = 2M


[mysqlhotcopy]


interactive-timeout




起動スクリプト編集

vi /etc/init.d/mysql


46行目辺り



basedir=/usr/local/mysql


datadir=/usr/local/mysql/var




起動します。(少し時間がかかります。)


service mysql start



MySQLにログイン


パスワードはまだ設定していないので空白でログインできます。



mysql -uroot -p




パスワードなしユーザを消してrootにパスワードを付ける



SET PASSWORD FOR [email protected]=PASSWORD('パスワード');


drop database test;


delete from mysql.user where user='';


delete from mysql.user where password='';


select user,host,password from mysql.user;




Lighttpd


今回のメインのLighttpdのインストールです。


インストール



wget http://download.lighttpd.net/lighttpd/releases-1.4.x/lighttpd-1.4.28.tar.gz


tar -zxvf lighttpd-1.4.28.tar.gz


cd lighttpd-1.4.28


./configure --disable-ipv6 --without-proxy --without-rrdtool --without-secdownload --without-trigger_b4_dl --without-webdav


make


make install




設定ファイルなどをコピーします。



cp ./doc/initscripts/rc.lighttpd.redhat /etc/init.d/lighttpd


ln -s /usr/local/sbin/lighttpd /usr/sbin/lighttpd


mkdir /etc/lighttpd


cp -r ./doc/config/* /etc/lighttpd/




Lighttpd実行ユーザを追加します。



adduser lighttpd -s /sbin/nologin




Lighttpdが必要とするディレクトリを作ります。



mkdir /var/log/lighttpd


mkdir -p /srv/www/cgi-bin


mkdir /srv/www/htdocs


mkdir -p /var/lib/lighttpd/sockets/


chown lighttpd:lighttpd /var/log/lighttpd


chown -R lighttpd:lighttpd /srv/www


chown -R lighttpd:lighttpd /var/lib/lighttpd/




Lighttpdの設定

server.tagのコメントアウトを外して、server.max-worker=10を追記しました。


server.max-workerはLighttpdの最大起動数です。


Apacheのmpmに該当しますが、アクセス数に応じて設定する必要があります。


さくらVPSの場合は10~30(100万PV/Day~300万PV/Day)ぐらいです。


vi /etc/lighttpd/lighttpd.conf



#######################################################################


##


## /etc/lighttpd/lighttpd.conf


##


## check /etc/lighttpd/conf.d/*.conf for the configuration of modules.


##


#######################################################################


#######################################################################


##


## Some Variable definition which will make chrooting easier.


##


## if you add a variable here. Add the corresponding variable in the


## chroot example aswell.


##


var.log_root = "/var/log/lighttpd"


var.server_root = "/srv/www"


var.state_dir = "/var/run"


var.home_dir = "/var/lib/lighttpd"


var.conf_dir = "/etc/lighttpd"



server.max-worker=10



##


## run the server chrooted.


##


## This requires root permissions during startup.


##


## If you run Chrooted set the the variables to directories relative to


## the chroot dir.


##


## example chroot configuration:


##


#var.log_root = "/logs"


#var.server_root = "/"


#var.state_dir = "/run"


#var.home_dir = "/lib/lighttpd"


#var.vhosts_dir = "/vhosts"


#var.conf_dir = "/etc"


#


#server.chroot = "/srv/www"


##


## Some additional variables to make the configuration easier


##


##


## Base directory for all virtual hosts


##


## used in:


## conf.d/evhost.conf


## conf.d/simple_vhost.conf


## vhosts.d/vhosts.template


##


var.vhosts_dir = server_root + "/vhosts"


##


## Cache for mod_compress


##


## used in:


## conf.d/compress.conf


##


var.cache_dir = "/var/cache/lighttpd"


##


## Base directory for sockets.


##


## used in:


## conf.d/fastcgi.conf


## conf.d/scgi.conf


##


var.socket_dir = home_dir + "/sockets"


##


#######################################################################


#######################################################################


##


## Load the modules.


include "modules.conf"


##


#######################################################################


#######################################################################


##


## Basic Configuration


## ---------------------


##


server.port = 80


##


## Use IPv6?


##


#server.use-ipv6 = "enable"


##


## bind to a specific IP


##


#server.bind = "localhost"


##


## Run as a different username/groupname.


## This requires root permissions during startup.


##


server.username = "lighttpd"


server.groupname = "lighttpd"


##


## enable core files.


##


#server.core-files = "disable"


##


## Document root


##


server.document-root = server_root + "/htdocs"


##


## The value for the "Server:" response field.


##


## It would be nice to keep it at "lighttpd".


##


server.tag = "lighttpd"


##


## store a pid file


##


server.pid-file = state_dir + "/lighttpd.pid"


##


#######################################################################


#######################################################################


##


## Logging Options


## ------------------


##


## all logging options can be overwritten per vhost.


##


## Path to the error log file


##


server.errorlog = log_root + "/error.log"


##


## If you want to log to syslog you have to unset the


## server.errorlog setting and uncomment the next line.


##


#server.errorlog-use-syslog = "enable"


##


## Access log config


##


include "conf.d/access_log.conf"


##


## The debug options are moved into their own file.


## see conf.d/debug.conf for various options for request debugging.


##


include "conf.d/debug.conf"


##


#######################################################################


#######################################################################


##


## Tuning/Performance


## --------------------


##


## corresponding documentation:


## http://www.lighttpd.net/documentation/performance.html


##


## set the event-handler (read the performance section in the manual)


##


## possible options on linux are:


##


## select


## poll


## linux-sysepoll


##


## linux-sysepoll is recommended on kernel 2.6.


##


server.event-handler = "linux-sysepoll"


##


## The basic network interface for all platforms at the syscalls read()


## and write(). Every modern OS provides its own syscall to help network


## servers transfer files as fast as possible


##


## linux-sendfile - is recommended for small files.


## writev - is recommended for sending many large files


##


server.network-backend = "linux-sendfile"


##


## As lighttpd is a single-threaded server, its main resource limit is


## the number of file descriptors, which is set to 1024 by default (on


## most systems).


##


## If you are running a high-traffic site you might want to increase this


## limit by setting server.max-fds.


##


## Changing this setting requires root permissions on startup. see


## server.username/server.groupname.


##


## By default lighttpd would not change the operation system default.


## But setting it to 2048 is a better default for busy servers.


##


server.max-fds = 2048


##


## Stat() call caching.


##


## lighttpd can utilize FAM/Gamin to cache stat call.


##


## possible values are:


## disable, simple or fam.


##


server.stat-cache-engine = "simple"


##


## Fine tuning for the request handling


##


## max-connections == max-fds/2 (maybe /3)


## means the other file handles are used for fastcgi/files


##


server.max-connections = 1024


##


## How many seconds to keep a keep-alive connection open,


## until we consider it idle.


##


## Default: 5


##


#server.max-keep-alive-idle = 5


##


## How many keep-alive requests until closing the connection.


##


## Default: 16


##


#server.max-keep-alive-requests = 16


##


## Maximum size of a request in kilobytes.


## By default it is unlimited (0).


##


## Uploads to your server cant be larger than this value.


##


#server.max-request-size = 0


##


## Time to read from a socket before we consider it idle.


##


## Default: 60


##


#server.max-read-idle = 60


##


## Time to write to a socket before we consider it idle.


##


## Default: 360


##


#server.max-write-idle = 360


##


## Traffic Shaping


## -----------------


##


## see /usr/share/doc/lighttpd/traffic-shaping.txt


##


## Values are in kilobyte per second.


##


## Keep in mind that a limit below 32kB/s might actually limit the


## traffic to 32kB/s. This is caused by the size of the TCP send


## buffer.


##


## per server:


##


#server.kbytes-per-second = 128


##


## per connection:


##


#connection.kbytes-per-second = 32


##


#######################################################################


#######################################################################


##


## Filename/File handling


## ------------------------


##


## files to check for if .../ is requested


## index-file.names = ( "index.php", "index.rb", "index.html",


## "index.htm", "default.htm" )


##


index-file.names += (


"index.xhtml", "index.html", "index.htm", "default.htm", "index.php"


)


##


## deny access the file-extensions


##


## ~ is for backupfiles from vi, emacs, joe, ...


## .inc is often used for code includes which should in general not be part


## of the document-root


url.access-deny = ( "~", ".inc" )


##


## disable range requests for pdf files


## workaround for a bug in the Acrobat Reader plugin.


##


$HTTP["url"] =~ "\.pdf$" {


server.range-requests = "disable"


}


##


## url handling modules (rewrite, redirect)


##


#url.rewrite = ( "^/$" => "/server-status" )


#url.redirect = ( "^/wishlist/(.+)" => "http://www.example.com/$1" )


##


## both rewrite/redirect support back reference to regex conditional using %n


##


#$HTTP["host"] =~ "^www\.(.*)" {


# url.redirect = ( "^/(.*)" => "http://%1/$1" )


#}


##


## which extensions should not be handle via static-file transfer


##


## .php, .pl, .fcgi are most often handled by mod_fastcgi or mod_cgi


##


static-file.exclude-extensions = ( ".php", ".pl", ".fcgi", ".scgi" )


##


## error-handler for status 404


##


#server.error-handler-404 = "/error-handler.html"


#server.error-handler-404 = "/error-handler.php"


##


## Format: <errorfile-prefix><status-code>.html


## -> ..../status-404.html for 'File not found'


##


#server.errorfile-prefix = "/srv/www/htdocs/errors/status-"


##


## mimetype mapping


##


include "conf.d/mime.conf"


##


## directory listing configuration


##


include "conf.d/dirlisting.conf"


##


## Should lighttpd follow symlinks?


##


server.follow-symlink = "enable"


##


## force all filenames to be lowercase?


##


#server.force-lowercase-filenames = "disable"


##


## defaults to /var/tmp as we assume it is a local harddisk


##


server.upload-dirs = ( "/var/tmp" )


##


#######################################################################



#######################################################################


##


## SSL Support


## -------------


##


## To enable SSL for the whole server you have to provide a valid


## certificate and have to enable the SSL engine.::


##


## ssl.engine = "enable"


## ssl.pemfile = "/path/to/server.pem"


##


## The HTTPS protocol does not allow you to use name-based virtual


## hosting with SSL. If you want to run multiple SSL servers with


## one lighttpd instance you must use IP-based virtual hosting: ::


##


## $SERVER["socket"] == "10.0.0.1:443" {


## ssl.engine = "enable"


## ssl.pemfile = "/etc/ssl/private/www.example.com.pem"


## server.name = "www.example.com"


##


## server.document-root = "/srv/www/vhosts/example.com/www/"


## }


##


## If you have a .crt and a .key file, cat them together into a


## single PEM file:


## $ cat /etc/ssl/private/lighttpd.key /etc/ssl/certs/lighttpd.crt \


## > /etc/ssl/private/lighttpd.pem


##


#ssl.pemfile = "/etc/ssl/private/lighttpd.pem"


##


## optionally pass the CA certificate here.


##


##


#ssl.ca-file = ""


##


#######################################################################




fastcgiモジュールの設定

PHPを使う場合はfastcgiのコメントアウトを外す必要があります。


vi /etc/lighttpd/modules.conf



include "conf.d/fastcgi.conf"




fastcgi本体の設定

PHPの起動数を設定します。


PHP_FCGI_CHILDREN * max-procsが最大起動します。


以下の設定ファイルの値で100万PV/Day~300万PV/Dayぐらいを処理できます。



vi /etc/lighttpd/conf.d/fastcgi.conf



server.modules += ( "mod_fastcgi" )


fastcgi.server = ( ".php" =>


( "php-local" =>


(


"socket" => socket_dir + "/php-fastcgi-1.socket",


"bin-path" => server_root + "/cgi-bin/php5",


"max-procs" => 150,


"broken-scriptfilename" => "enable",


)


),


( "php-tcp" =>


(


"host" => "127.0.0.1",


"port" => 9999,


"check-local" => "disable",


"broken-scriptfilename" => "enable",


)


),


( "php-num-procs" =>


(


"socket" => socket_dir + "/php-fastcgi-2.socket",


"bin-path" => server_root + "/cgi-bin/php5",


"bin-environment" => (


"PHP_FCGI_CHILDREN" => "3",


"PHP_FCGI_MAX_REQUESTS" => "10000",


),


"min-procs" => 1,


"max-procs" => 2,


"max-load-per-proc" => 50,


"idle-timeout" => 360,


"broken-scriptfilename" => "enable",


)


),


)





PHPダウンロード

http://php.net/downloads.php



PHPのインストール


tar -zxvf php-5.2.17.tar.gz


cd php-5.2.17


PHP5.3以上の場合は‘--enable-fastcgi’を指定する必要はない




'./configure' \


'--enable-zend-multibyte' \


'--with-zlib' \


'--with-xmlrpc' \


'--with-gd' \


'--with-jpeg-dir=/usr/local' \


'--with-png-dir=/usr/local' \


'--enable-mbstring' \


'--enable-fastcgi' \


'--with-pdo-mysql=/usr/local/mysql' \



make


make test


make install




リンクを張ります。



ln -s /usr/local/bin/php-cgi /srv/www/cgi-bin/php5


ln -s /usr/local/lib/php/extensions/no-debug-non-zts-20060613/ /usr/local/lib/extensions


ln -s /usr/local/lib/php/extensions/no-debug-non-zts-20060613/apc.so /usr/local/lib/


cp php.ini-recommended /usr/local/lib/php.ini


ln -s /usr/local/lib/php.ini /etc/



APCインストール

パフォーマンスをあげるためにAPCもインストールしておきます



pecl install APC


デフォルトでenter




ログローテート


現在の状態では無限にLogが溜まっていくのでログローテートなどで適宜ログを削除していく必要があります。


Apacheのlogrotate時にApacheが停止する問題のログローテートを利用します。


vim /etc/logrotate.d/lighttpd



/var/log/lighttpd/*log {


rotate 14


daily


missingok


sharedscripts


postrotate


for max in $(seq 1 5)


do


LHTTPD_P=`pgrep lighttpd | wc -l`


if [ "$LHTTPD_P" != 0 ]


then


`/usr/bin/pkill lighttpd` > /dev/null


sleep 5s


elif [ "$LHTTPD_P" = 0 ]


then


/etc/init.d/lighttpd start > /dev/null


break


fi


done


LHTTPD_P=`pgrep lighttpd | wc -l`


if [ "$HTTPD_P" = 0 ]


then


echo Can Not Run HTTPD | mail -s HTTPD ALERT メールアドレス


fi


endscript


}







2011年2月8日火曜日

LVSを利用したロードバランサーの構築方法


前回はロードバランサー(LB)について書きましたが今回は実際にLVSを用いてLBを構築してみます。


LVSの仕組み


LVSについては前回の記事で紹介しましたが、Linuxを高パフォーマンス、高可用性(HA)を持つサーバを作るプロジェクトや機能です。



準備


VMwareでゲストを3つ作る。


  1. LVS

  2. WEB01(ApacheなどのWEBサーバを導入しててください)

  3. WEB02(ApacheなどのWEBサーバを導入しててください)


LVSにはネットワークアダプターを2つにしてください。


片方はNATかブリッジ、もう片方はホストオンリー。



WEB01/WEB02に関してはネットワークアダプターは1つで、ホストオンリーにしてください。



OS


LVSはOSのkernelバージョンに影響します。


2.6以上であれば基本的に問題ありません。(標準では2.4 2.6に導入されています)



kernelバージョン確認



uname -r






  • 最新CentOS 32bit でも 64bitどちらも可


http://mirror.centos.org/centos/5/isos/



オプション(必須ではない)

LVSで本番運用を目指す場合は、できるだけOSを軽くしたいのでインストール時にcustomを選択し、base + editorのみインストールします。


kernelのバージョンが古くIPVSに対応していない場合はkernelを再構築する必要がありますが、それ以外の場合は特に必要ありません。



【LVS】インストール作業



baseとeditorのみをインストールした場合はコンパイラーやライブラリーが殆どインストールされていないのでインストールします。



yum install gcc libnl-devel kernel-devel openssl-devel ipvsadm





ipvsadmをソースからインストールする場合

ipvsadmはLVSに接続されるクライアントのウェイトを設定したり、LVSに接続したり、LVSから切り離したりなどLVSを操作するコマンドをサポートします。


上記でyumと一緒にインストールした場合はこの作業は不要です。


ipvsadmをダウンロードします。


http://www.linuxvirtualserver.org/software/kernel-2.6/



現在利用しているkernelのリンクを作成します。


現在使用しているkernelはuname -rで調べられます。



ln -s /usr/src/kernels/2.6.18-194.1.AXS3-i686 /usr/src/linux



tar -zxvf ipvsadm-1.24.tar.gz


cd ipvsadm-1.24


make


make install




ポートフォワーディングを有効にする

sysctl -w net.ipv4.ip_forward=1



  • 永続的に変更する


vim /etc/sysctl.conf



net.ipv4.ip_forward = 1




VIPを設定する

現在ゲストOSのLVSには、2つのIPが割り振られていると思います。



ifconfig



eth0 Link encap:Ethernet HWaddr 00:0C:29:A9:E1:AE


inet addr:172.16.0.129 Bcast:172.16.0.255 Mask:255.255.255.0


inet6 addr: fe80::20c:29ff:fea9:e1ae/64 Scope:Link


UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1


RX packets:3344953346 errors:0 dropped:0 overruns:0 frame:0


TX packets:3344935139 errors:0 dropped:0 overruns:0 carrier:0


collisions:0 txqueuelen:1000


RX bytes:1933681498 (1.8 GiB) TX bytes:760781469 (725.5 MiB)


Interrupt:67 Base address:0x2000


eth1 Link encap:Ethernet HWaddr 00:0C:29:A9:E1:B8


inet addr:10.1.0.134 Bcast:10.1.0.255 Mask:255.255.255.0


inet6 addr: fe80::20c:29ff:fea9:e1b8/64 Scope:Link


UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1


RX packets:7718486 errors:0 dropped:0 overruns:0 frame:0


TX packets:7669463 errors:0 dropped:0 overruns:0 carrier:0


collisions:0 txqueuelen:1000


RX bytes:510259346 (486.6 MiB) TX bytes:574126235 (547.5 MiB)


Interrupt:75 Base address:0x2080


lo Link encap:Local Loopback


inet addr:127.0.0.1 Mask:255.0.0.0


inet6 addr: ::1/128 Scope:Host


UP LOOPBACK RUNNING MTU:16436 Metric:1


RX packets:604367655 errors:0 dropped:0 overruns:0 frame:0


TX packets:604367655 errors:0 dropped:0 overruns:0 carrier:0


collisions:0 txqueuelen:0


RX bytes:190831055 (181.9 MiB) TX bytes:190831055 (181.9 MiB)





このeth0にはさらに1つの仮想IPアドレス(VIP)を設定します。


冗長構成ではない場合はVIPを設定する意味は殆どありませんが、冗長構成に移行する際にあらゆる設定ファイルを書き換えなければならない点とipvsadmを利用するためにVIPを設定します。


VIPは冗長化された構成内で共通に使えるIPを指定しルータ間や今回であればLVS間で利用することになります。


本来IPはユニークな物ではなければなりませんが、あえて重複させマスターにはVIPを割り当てマスターがダウンした際はバックアップにVIPを割り当てる事で冗長化します。


Linuxの場合は比較的簡単にVIPを設定することができます。




以下のコマンドは172.16.0.252というIPをデバイスeth0に割り当て、そのラベル名はeth0:lvs-vipという意味になります。ラベル名は適当な物で大丈夫です。



ip addr add 172.16.0.252 label eth0:lvs-vip dev eth0



これで、eth0に2つのIPが割り当てる事ができました。


ifconfigコマンドを打つとeth0がエイリアスされているのが伺えると思います。


172.16.0.252がVIPになります。今後、WEBへのアクセスは172.16.0.252を利用します。





eth0 Link encap:Ethernet HWaddr 00:0C:29:A9:E1:AE


inet addr:172.16.0.129 Bcast:172.16.0.255 Mask:255.255.255.0


inet6 addr: fe80::20c:29ff:fea9:e1ae/64 Scope:Link


UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1


RX packets:3344953346 errors:0 dropped:0 overruns:0 frame:0


TX packets:3344935139 errors:0 dropped:0 overruns:0 carrier:0


collisions:0 txqueuelen:1000


RX bytes:1933681498 (1.8 GiB) TX bytes:760781469 (725.5 MiB)


Interrupt:67 Base address:0x2000


eth0:lvs-vip Link encap:Ethernet HWaddr 00:0C:29:A9:E1:AE


inet addr:172.16.0.252 Bcast:0.0.0.0 Mask:255.255.255.255


UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1


Interrupt:67 Base address:0x2000


eth1 Link encap:Ethernet HWaddr 00:0C:29:A9:E1:B8


inet addr:10.1.0.134 Bcast:10.1.0.255 Mask:255.255.255.0


inet6 addr: fe80::20c:29ff:fea9:e1b8/64 Scope:Link


UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1


RX packets:7718486 errors:0 dropped:0 overruns:0 frame:0


TX packets:7669463 errors:0 dropped:0 overruns:0 carrier:0


collisions:0 txqueuelen:1000


RX bytes:510259346 (486.6 MiB) TX bytes:574126235 (547.5 MiB)


Interrupt:75 Base address:0x2080


lo Link encap:Local Loopback


inet addr:127.0.0.1 Mask:255.0.0.0


inet6 addr: ::1/128 Scope:Host


UP LOOPBACK RUNNING MTU:16436 Metric:1


RX packets:604367655 errors:0 dropped:0 overruns:0 frame:0


TX packets:604367655 errors:0 dropped:0 overruns:0 carrier:0


collisions:0 txqueuelen:0


RX bytes:190831055 (181.9 MiB) TX bytes:190831055 (181.9 MiB)





LVS設定作業


LVSの操作は先ほどインストールしたipvsadmコマンドを利用して行います。




LVS本体の設定

設定したVIPをLVSに追加します。



ex.ipvsadm -A -t VIP:ポート番号 -s 分散方式




ipvsadm -A -t 172.16.0.252:80 -s lc






分散方式

sオプションには次の分散方式が有効です。メジャーな方式のみを紹介します。


rr|wrr|lc|wlc|lblc|lblcr|dh|sh|sed|



  • rr:順番に各サーバに振分ける、最も単純な方式

  • wrr:設定されたウェイトによって負荷分散する方式。負荷分散するマシンに性能差がある場合などに利用する

  • lc:接続されているコネクション数が最も少ないところに分散する。DBやSMTPなどに有効。

  • wlc:設定されたウェイトと接続されているコネクション数から負荷の低いサーバに振分ける


etc...




クライアントの追加

LVSに接続されるクライアント(リアルサーバ)をLVSに追加します。


今回は通信方式にNATを利用します。


ex. ipvsadm -a -t VIP:ポート番号 -r クライアントのIP 通信方式



ipvsadm -a -t 172.16.0.252:80 -r 10.1.0.100 -m


ipvsadm -a -t 172.16.0.252:80 -r 10.1.0.101 -m





通信方式

通信方式は大きく分け2種類あります



  • g:DSR(DirectServerReturn)方式で行きはLVSにより分散されて来ますが帰りはLVSを通りません。


経路が1つしかないので帰りもLVSを通過しますがIPアドレスの書き換えを行わないのでApacheなどのアクセスログに残るのはLVSのeth1のアドレス(10.1.0.134)が記録されます。


ただし、IPアドレスの書き換えを行わないのでLVSの負荷が低くなりますが、リアルサーバの作業が多くなります。



  • m:NAT方式で行きも帰りもLVSを通過し、Apacheなどに残るIPアドレスは接続元のIPアドレスになります。通常はこの方式でリアルサーバの作業も殆どありませんが、LVSの負荷は高くなります。




リアルサーバ(WEB01/WEB02の設定)


リアルサーバにはLVSのeth1側のIPアドレスをゲートウェイとして指定します。



vim /etc/sysconfig/network


GATEWAY=10.1.0.134



service network restart




クライアントの接続確認


LVS側で以下のコマンドを実行します。



ipvsadm -ln




すると先ほど追加したクライアントが表示されるはずです。




IP Virtual Server version 1.2.1 (size=4096)


Prot LocalAddress:Port Scheduler Flags


-> RemoteAddress:Port Forward  Weight  ActiveConn  InActConn


TCP 172.16.0.252:80 lc


-> 10.1.0.100:80   Masq    1      0    0


-> 10.1.0.101:80   Masq   1      0   0




http://172.16.0.252 にアクセスするとWEB01かWEB02のページが表示されれば完了です。



LVSからクライアントを切り離す


ex. ipvsadm -d -t VIP:ポート番号 -r クライアントのIP





接続できない場合の対処


http://172.16.0.252 にアクセスできない場合は次のような原因が考えられます。



  1. クライアントのデフォルトゲートウェイが間違っている。ネットワークを再起動していない。

  2. クライアントのWEBサーバポートが80ではない。

  3. net.ipv4.ip_forwardが1になっていない。




問題点


LVSによりWEBサーバの冗長化は行えましたが、LVS本体の冗長化は行えてないため単一障害点が存在します。


次はLVS本体の冗長化を行いたいと思います。



参考書





2011年2月1日火曜日

ロードバランサーを構築するまで~基本編~


ある程度の規模になると複数台サーバを準備し負荷を分散させる必要があります。


負荷を分散させると一概に言っても様々な方法があるので紹介したいと思います。




ロードバランサー(LB)


負荷分散を行うための製品がLBです。


LBには負荷分散以外に次のような機能を持っていることが多いです。



  • SSLアクセレーション

  • データ圧縮

  • キャッシュ

  • フィルタリング



LBは多機能かつ高性能ではありますが、非常に高価な製品です。(400万~)


通常であれば冗長化なども必要なので数千万という単位の費用がかかります。



DNSラウンドロビン


1つのドメインに対して複数のIPを割り当てる事で負荷を分散します。


メリット


  • 負荷分散する上でもっとも簡単かつ安価にできる

  • ネットワーク的に離れたサーバにも分散できる

  • DNSサーバのみで動作する


デメリット


  • グローバルIPをサーバの数だけ準備する必要がある

  • 複数のサーバに対して均等に分散しにくい

  • サーバが停止していても振り分けられる


ゾーンファイル


test IN A 127.0.1.1


test IN A 127.0.1.2




上記の場合でも問題無く動作するのですがDNSのキャッシュ機能により一方のサーバに負荷が偏る場合があるのでTTLを明示的に短めにする事が推奨されています。



test 20m IN A 127.0.1.1


test 20m IN A 127.0.1.2




Linux Virtual Server(LVS)


LVSはLinuxを高パフォーマンス、高可用性(HA)を持つサーバを作るプロジェクトや機能です。


その成果としてできたのがロードバランシングです。


今回はLVSを中心に解説していきたいと思います。




LVSのメリット

現在LVSは=ロードバランサーとして表現されることが殆どです。


LBではなくLVSを利用するメリットをいくつかあげます。



  • LBを購入するより1/4程度のコストで運用できる

  • LB自身の冗長化も可能

  • LVSに対応したLinuxさえあればすぐに構築可能

  • ネットワーク的に離れたマシンにも分散可能


このようにローコストかつ、高いパフォーマンスを持ったLBを利用できるのは大きなメリットです。




LBを導入する際に考慮すべき点


LBには大きく分けてL4LB(レイヤー4LB)とL7LB(レイヤー7LB)があります。



L4やL7に関してはOSI参照モデルなどを参考にしてください。



L4LBの特徴

L4LBはクライアントからSYNパケットが到達した段階で振り分けるサーバを選定します。



そのためLBへの負荷は非常に低く、L7LBよりも高速に処理できると言われています。



この点に関しては近年CPUパワーが大きくなってきており殆ど差はないとされていますがスペックの低いLBの場合はL4LBの導入がよいでしょう。


DBやメールサーバなどに向いています。



L7LBの特徴

L7はL4と違い、TCPのトランザクションを全てLBで受け取りパケットの内容を見て振り分けることが可能です。


パケットの内容とは、cookieやHTTPヘッダなどを見て判断するので複数のサービスを1つのLBで受け持つ場合重要な機能になります。



Webサーバなどに向いています。



次は、実際にLVSを構築する前段階まで解説したいと思います。



2011年1月12日水曜日

MySQL:VIEWを利用する際の注意点


MySQLのVIEW機能は複数のクエリ結果を1つのテーブルとして扱え、毎回複雑なクエリを打たなくても詳細な結果が得られるのでとても便利な機能です。



無駄にかっこよく言いましたが、複雑なクエリのエイリアスを作れるということです。



いきさつ


DBはレプリケーションが有効な通常の冗長構成です。


VIEW作ったのにスレーブ側にSELECTができないという現象に遭遇し該当のテーブルを調べたところwarinigがでていました。


さらに、毎日DBのバックアップを取っていたのですがAccess denied when using LOCK TABLESのエラーも発生しました。


実際に該当のテーブルにSELECTすると1044: Access denied for userと表示されSELECTできないことを確認しました。


rootなのになぜかアクセス権がないようです。



VIEW構文


VIEWを使うには以下のクエリを使います。



利用方法は今回の記事では割愛させていただきますがこちらの記事などが詳細に解説されております。



CREATE


[OR REPLACE]


[ALGORITHM = {UNDEFINED | MERGE | TEMPTABLE}]


[DEFINER = { user | CURRENT_USER }]


[SQL SECURITY { DEFINER | INVOKER }]


VIEW view_name [(column_list)]


AS select_statement


[WITH [CASCADED | LOCAL] CHECK OPTION]



CREATE VIEW 構文



SQL SECURITY


VIEWにはVIEWを作成するたびにアクセス権を設定することができます。


デフォルトでは、CREATE VIEWを実行したユーザになります。


前述したAccess denied for userはこのアクセス権に引っかかっていたようです。


先に解決策としてはSQL SECURITY DEFINER ではなく SQL SECURITY INVOKERにする事です。


この影響でバックアップ時にテーブルロックが拒否されバックアップもできてなかったようです。



なぜおきたのか


実は各DBのユーザを厳密化するために、mysql.userテーブルはレプリケーションにより同期されない仕組みにしていました。


その結果マスターでCREATE VIEWが実行され、各スレーブにも同様のクエリが流れるがスレーブにも伝わりますがユーザがいないためSELECTした際にエラーがでるということです。


A5ERなどのツールを用いてDBを管理している場合はSQL SECURITY INVOKERが使えないことがあるので注意してください。


突然Access denied for useが出た場合はVIEWを疑ってみるといいかもしれません。




2011年1月4日火曜日

初心に戻るエンジニア


今は神戸の実家に帰省中ですが、東京に行って半年がたちました。



今年はとにかく就職し徹夜のグループワークをこなしたり、技術研修をしたり、配属先でなかなかミスの許されないエキサイティングな仕事をしています。



リリースが間近なため仕事を納めたのは夜中の2時になっていましたが、最後の方は開発者と今回の企画について気さくに話せたのでよかったと思います。



今私が働いている会社は主に3つの役に分かれます。企画・開発・インフラとありそれぞれ個別でサービス開発に携わっています。



この分別はある程度の人数を抱えた企業であると一般的で部分最適化と言われるシステムです。



大きな母集団を最適化するのはそれぞれ役割の違いや理念の違いなどで難しいとされています。しかし、母集団を小さな集合に切り分け部分集合にし、部分集合内を最適化することに注力すれば全体最適化につながるという仕組みです。



残念ながら私は、今の会社が現在のシステムになった経緯は知らないのですがこの部分最適化がうまく機能しないのがIT企業です。



発案者(つまり企画)が売れそうなサービスを考案します。それを、開発に実現可能なのか、工数、予算などをインフラを巻き込んで検討します。



そこから、部分最適化にのっとって企画、開発、インフラと別々に行動するわけですが、それぞれ別々で行動しているため思い込みや、勘違いなどで細かい修正や細かい仕様の決定でMTGを繰り返すことになります。



規模の大きいプロジェクトほどこの過程が頻繁に繰り返されるため、全体の工程の中でMTGが大部分を占めてしまいます。



その結果できあがった物やプロトタイプが企画が考案した物が異なったりして、再開発をしたり仕様の変更を検討したりする必要があったりします。



このように、部分最適化するにあたって切り離してはいけない部分があるため切り離し作業は慎重にやるべきです。




やるリスクよりやらないリスク



IT企業のようなネットを軸にしたサービスを展開している場合は、よく言われる言葉です。



ネットサービスはドッグイヤーと言われています。犬は人間の7倍歳をとるのが早く、ネットもそれぐらいのスピードで様々なサービスが作られています。



このスピードの波に乗り、ついて行くには進化するサービスに敏感に反応しスピーディに開発する必要があります。



なぜなら、ユーザはいち早く今よりもよりよりサービスを求めており、できるだけ早く使いたいからです



そして、ドッグイヤーの影響で時は金なりがよりシビアに利益として響いてきます。



その結果、やるかやらないか決めることに時間を割くよりも、とにかくやる事が重要になります。



豊富な機能より使いやすいサービス



開発したものすべてはユーザのために作った物です。使うのもユーザです。全てにおいてユーザ重視である必要があります。



しかし、最近ユーザビリティが軽視されユーザの事が考慮されておらず利益を中心とした設計が多く見られ残念です。



ユーザインタフェースは、アクセスログから解析するのが一般的です。



どのようにリンクがクリックされページにたどり着いたのか、その経路は設計通りか。設計外の場合、ボタンを大きくしたり、色を変えたり、場所を変えるなどの工夫が必要です。



これらを解析するツールもあるので利用するといいでしょう。



とにかく出してみる


ネットサービスの強みはなんと言っても、スピードです。不具合があればネットを通じてすぐに解決することができます。



日本人は完璧主義で、これまでに高い品質ですばらしいサービスを作り上げてきました。



しかし、その結果リリースが遅れ対抗サービスとして作り直すためにリリースを延期しては元も子もないですよね。



またネットは世界中とつながっているため個人、企業問わずにいつでもインターネットを介してサービスを展開することが可能です。



実際ネットの世界にはベータ版が溢れており、Googleに至ってはサービス前であるlabなんてのもあります。



もちろんセキュリティ的な面は最善を尽くす必要はありますが、その他機能的に未熟な部分に関してはユーザレビューを受けながら開発する事でよりユーザの希望に添う物を開発でき、無駄な工数を減らし次の追加機能の開発を同時進行で進めることもできるでしょう。



視点を変える、視点を加える


企画、開発、インフラ全てにおいて客観的に物事を分析する必要があります。これは、殆どの人が注意していることだと思います。



しかし、視点を加えるというのは意外と抜けていたりします。視点を加えるには、本を読んだり人の話を聞くのが一番いいと言われています。




今年やること


私は漫画を含めて技術書ぐらいしか本を読まなかったのですが、今年は月に1冊は読んでいきたいと思います。



また今年も、技術的に色々挑戦できたらいいなと思っています。特にネットワーク関連中心にやっていこうと思います。


では、今年も読みにくい記事ですがよろしくお願いします!


私はうさぎ年です。