[blog]
1 2 3 4 5 6
7 8 9 10 11 12 13
14 15 16 17 18 19 20
21 22 23 24 25 26 27
28 29 30 31

2011/7/30 (土)

HTTPサーバーをcherokeeに乗り換えた

cherokeeは、HTTPサーバーである。超マイナー。だが、速度的にはnginxといい勝負らしい。さっそく先月から、8080ポートをcherokeeで走らせていたが、とにかく使いやすい。なんと、標準でGUIでサーバー設定ができるのだ。具体的には、ウィザード形式でバーチャルサーバーの設定や、アプリケーションのインストールができる。

この図が、バーチャルサーバー設定

cherokee.png

でもって、バーチャルサーバーごとの詳細設定。

cherokee2.png

ここでは、拡張子がCGIのときはFastCGI、拡張子がPHPのときは、PHP-FPMを動かし、ファイルが存在しないときは、クエリをindex.phpに送る設定にしてある。

2011/4/25 (月)

恐怖の睡眠

睡眠障害の気があるので、先日一泊入院して睡眠障害の診断を受けてきた。さて、睡眠障害ではどのようなことをやるのか?要は、病院で体中に電極を貼り付けて、ただ寝るだけだ。測るのは、心電図、脳波、呼吸、血中酸素濃度で、これを一晩測る。というわけで、病院に19時についたらすぐに病院内のシャワーを浴びて、電極をつける。ずり落ちるのを防止するために、よく包帯をまいたあとに付けるあのあみを頭からかぶる。旗からみると顔がサボテンである。まぁ、電極をつけるのはいいが、血中濃度を測るのに指にセンサーをかませなければならない。これが、かなりの違和感である。蒸れるし。で、23時に眠くなったのでそのまま就寝。ものすごく寝苦しい。全然眠れん。結果2回ぐらい起きてトイレに行ったりしていた。

で、先週の金曜日に結果が出たわけだが・・・。

「睡眠時無呼吸症候群ですね」
(゚Д゚ )
「しかも、値が30超えているので重症ですよ」
工エエェェ(´д`)ェェエエ工
「ただ、深い眠りにもなっているので、閉塞型と出ているけど中枢型かもしれません」
エッ(゚Д゚≡゚Д゚)マヂ?~
「あと、酸素濃度がこの状態だと、一般的に言う呼吸困難ですね」
( ( ( ( ;゚Д゚)))ガクガクブルブル

なんてこった。つまり、毎晩、死の淵さまよっているってことですね。どうりで、規則正しい生活している割に昼間眠いわけだ・・・。いくら、規則正しい生活していても、夜眠れてないんじゃ、昼間眠くなるのは当然のことで。

2011/3/30 (水)

nginx+php-fpm(PHP5.3)環境にPHPMotionを導入してみた。

以前は、画像と動画はGallery3、オーディオファイルはPodHawkを使っていたが、複数こういったプログラムがあると管理が面倒である。というわけで、動画や画像、音楽などを管理できるツールがないかと探していた。そんななか見つけたのがPHPMotionである。正確には、YouTubeクローンと紹介されているが、メディアファイル専門のCMSといったほうが正しいだろう。公式サイトを見る限りHTMLソースは汚いが、テーマが充実している。日本でもVPSの流行と共に、少しずつだが知られているようだ。

以前は、PHP5.3に対応していなかったので見送っていたが、ちょうと3日前に対応版をリリースしたらしい。早速インストールしてみた。やり方は、まず、必要なライブラリをapt-getでインストールする。ちなみに、今まで使っていたUbuntu x64 10.10が相次ぐトラブルの挙句、壊れたのに頭に来たので、OSをDebianに変更した。

下準備

まず、/etc/apt/sources.listに以下の行を追加

deb http://www.debian-multimedia.org squeeze main non-free
deb-src http://www.debian-multimedia.org sid main

で、次に、キーを読み込ませる。

aptitude install debian-multimedia-keyring

そしたら、

apt-get update
apt-get install ffmpeg php5-ffmpeg mplayer mencoder flvtool2 unzip

次に、Installing PHPShield Loaders - PHP5.3.x Serverを参考にプロテクトをインストールする。OSSと異なり、コア部分は、プロプライエタリらしい。これを使って復号化して実行しているようだ。まず、

php -i|grep extension_dir

で、phpのextension_dirを取得する。自分の場合、extension_dir => /usr/lib/php5/20090626だった。

cd /usr/lib/php5/20090626
wget http://downloads.phpmotion.com/phpshield-loaders/linux/i386/ixed.5.3

で、PHPShieldをインストールする。で、php.iniに読み込ませるわけだが、最近のPHPは、/etc/php5/conf.d内にファイルをおけば、わざわざphp.iniを書き換えなくても済む。したがって、/etc/php5/conf.d/内にphpshield.iniを設置して、中身を

extension=ixed.5.3

と入れるだけで、問題は無い。あとは、php5-fpmをリロードするだけだ。

service php5-fpm reload

これで、準備完了。

インストール

公式サイトのダウンロードのページに自分のメールアドレスを入れてファイルをダウンロードし、インストールしたい場所で展開する。

unzip phpmotion.zip

で、ブラウザからそこにアクセス。サブドメインのルートにおいているものとする。

http://[Your server]/setup/

あとは、ガイド通りに進めていくだけ。nginxでは、php.iniをオーバーライド(.htaccessにおけるphp_valueみたいなの)するときに、fastcgi_param PHPVALUE ""の括弧内に記入する。したがって、nginxのphpのlocation設定は以下のようになる。ちなみに、自分はphp5-fpmへの接続をポート開放などが面倒なので、ソケット接続にしているので注意。

location ~ \.php$ {
	fastcgi_pass	unix:/var/run/php-fpm.socket;
	fastcgi_index	index.php;
	fastcgi_param	PHP_VALUE	"
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 1500
session.gc_maxlifetime = 14000
safe_mode = off
Thread saftery = disabled
enable_dl = On
";
	include			fastcgi_params;
}

括弧内に改行があるって?気にしないでくれ。

次にパーミッションの設定、データーベースの設定など、これらは説明する必要はないだろう。画面の指示通りに進めればいい。

RewriteRuleをNginx用に書き換える

どうも、PHPMotionは、デフォルトで静的なURLにアクセスするようハードコーディングされているらしい。Apacheを使っている場合は問題ないが、Nginxを使っているので独自に設定が必要である。とりあえず、.htaccessの設定をnginxの設定ファイルにコピーして、RewriteBaseが、/になっているので、RewriteRuleをrewriteに書き換えて^を^/にして、書き換え先のスクリプトのファイル名の前に/を追加し、[L]をlast;に書き換えてはい終わり。

#PHP Motion
server{
	listen		80;
	server_name	[ドメイン名];
	root		[PHPMotion設置ディレクトリ];
	index		index.php;

	add_header	X-UA-Compatible 	edge;
	add_header	X-Content-Type-Options	nosniff;
	add_header	X-Frame-Options		SameDomain;
	
	# Main Menu Links #
	rewrite ^/videos/load/(.+)$					/seemore.php?load=$1				last;
	rewrite ^/videos/load/(.+)/(.+)$			/seemore.php?load=$1&page=$2		last;

	rewrite ^/audios/load/(.+)$					/audio.php?load=$1					last;
	rewrite ^/audios/load/(.+)/(.+)$			/audio.php?load=$1&page=$2			last;

	rewrite ^/audio/album/(.+)/(.+)$			/audio.php?album=$1					last;
	rewrite ^/audio/album/(.+)/(.+)/(.+)$		/audio.php?album=$1&page=$3			last;

	rewrite ^/blogs/load/(.+)$ 					/blogs.php?load=$1					last;
	rewrite ^/blogs/load/(.+)/(.+)$				/blogs.php?load=$1&page=$2			last;

	rewrite ^/albums/load/(.+)$					/albums.php?load=$1					last;
	rewrite ^/albums/(.+)/(.+)$					/albums.php?load=$1&page=$2			last;

	rewrite ^/people_ajax						/people_ajax.php last;
	rewrite ^/people/(.+)/(.+)$					/people.php?load=$1&page=$2			last;
	rewrite ^/people							/people.php							last;
	rewrite ^/upload-media						/upload.php							last;

	rewrite ^/groups$							/groups.php							last;
	rewrite ^/search							/search.php							last;


	# Action Links #
	rewrite ^/videos/(.+)/(.+)$					/play.php?vid=$1					last;
#	rewrite ^/audio/(.+)/(.+)$					/play_audio.php?audio=$1

	rewrite ^/category/(.+)$					/category_home.php?cid=$1			last;
	rewrite ^/category/(.+)/(.+)$				/category_home.php?cid=$1&page=$2	last;

	rewrite ^/subcategory/(.+)/(.+)$			/category_home.php?sub=$1 last;
	rewrite ^/subcategory/(.+)/(.+)/(.+)$		/category_home.php?sub=$1&page=$3	last;

	rewrite ^/genre/(.+)$						/genre_home.php?cid=$1 last;
	rewrite ^/genre/(.+)/(.+)$					/genre_home.php?cid=$1&page=$2		last;

#	rewrite ^/view-album/(.+)/(.+)$				/album_view.php?album=$1
#	rewrite ^/view-image/(.+)/(.+)$				/album_view.php?image=$1
	rewrite ^/read_blog/(.+)/(.+)$				/read_blog.php?id=$1				last;

	rewrite ^/blogs/category/(.+)/(.+)$			/blogs.php?cat_id=$1				last;
	rewrite ^/blogs/category/(.+)/(.+)/(.+)$	/blogs.php?cat_id=$1&page=$3		last;

	rewrite ^/members/(.+)$						/memberprofile.php?user=$1			last;

	#-------------------------------------------------------------#
	# redirect directory browsing attempts
	rewrite ^/videos(.?)$ 						/seemore.php	last;
	rewrite ^/audios(.?)$ 						/audio.php		last;
	rewrite ^/blogs(.?)$ 						/blogs.php		last;
#	rewrite ^/members(.?)$						/people			[R=301]
	rewrite ^/albums(.?)$ 						/albums.php		last;

	location ~ \.php$ {
		fastcgi_pass	unix:/var/run/php-fpm.socket;
		fastcgi_index	index.php;
		fastcgi_param	PHP_VALUE	"
upload_max_filesize = 100M
post_max_size = 100M
max_execution_time = 1500
session.gc_maxlifetime = 14000
safe_mode = off
Thread saftery = disabled
enable_dl = On
";
		include			fastcgi_params;
	}

	location ~* ^.+.(gif|jp?eg|png|css|js|ico|zip|7z|rar|lzh|exe|html|avi|mp4|mp3|m4a|swf|flv)$ {
	#	FileETag on;
	#	etag_format \"%X%X\";
		expires max;
		add_header Cache-Control max-age;
	}
}

これでよしと。

2011/1/24 (月)

Mabinogi Assistがネクソンに訴えられる?

ネクソンに訴えられたらしい。Modそのものは単なるリバースエンジニアリングなので法律上問題は無い(しかも、開発元は韓国のJinsu氏だったり、台湾のCedricOdin氏なので、自分がどうこうする問題ではない)けど、カスタムマップは問題かもしれない。VanaWikiみたくトレースしたマップにしないと著作権に引っかかっても仕方あるまい。というか、そもそもゲーム内マップをそのまま使うのは容量的にもメリットがないなぁ。このメインサイトが含まれる理由は、おそらく、ギャラリーにアップされているカスタムマップだろうか。

しかし、よく良く考えてみると、どうも怪しい。まず、第一にlogue.beではマビノギのツール関連のコンテンツは一切無い。全部mabiassist.logue.beに移動済みだ。今となってはMMLのコンテンツとErinn Exploerが残るのみである。

本当にこれはNexonからのメールなのだろうか?最近偽装メール多いし、本文を読む限りModに対する著作権の考え方があまりに稚拙だ。リバースエンジニアリングがダメだというならば、表現の自由云々以前に、例え特許をとっていたとしても

特許権者による独占実施、または限られたライセンス者との寡占実施において、価格カルテルやライセンス期間中の改良研究禁止、ライセンス期間満了後の当業参入禁止などは公正な競争を妨げるものであり、各種の知的財産法による権利保護範囲を逸脱する行為として独占禁止法によって禁止され得る

と、独占禁止法にもあるように、リバースエンジニアリングを禁じる規約そのものが違法でありうるし無効である。

なお、Erinn Explorerは画像くっつけているだけなので、改変には当たらない。これがダメなら、Mabinogi Wikiやその他の攻略を銘打つサイトだってヤバイだろ。スクリーンショットを組み合わせていると主張するにしても、取得したマップ画像をそのまま使った上に攻略情報を書き込んでいる。これだって、立派な改変行為である。まぁ、あくまでも日本のNexonから訴えられただけなので、韓国のNexonや米国のNexon、台湾のガマニア、中国の世紀天成、ヨーロッパやオセアニアのNexonのクライアントから抽出すれば、少なくとも日本のNexonは無関係なので、規約上問題はないことになるな。(そもそも、中国語版カスタムマップは、海豚小站のものを使用しているし、台湾版はのカスタムマップは、Mabinogi奇幻世界をそのまま使っているだけだし、韓国語版カスタムマップは韓国のRoberty氏のマップであるため対象外である。英語版にいたっては、Tiara Moonshine Modの物に切り替えるだけで問題は無いだろう。)そもそも、メールには、ほんとうの意味での著作権を持つ開発元のdevCatの名前すら無いし・・・。たしかに著作権はNexonにあるだろうが、devCatが著作権を放棄しているわけがないし、その名前がない時点でなりすましの可能性が非常に高い。

同一保持権侵害じゃないかと思うかもしれない。実際DOAの裸パッチで裁判になってMod開発した側が敗訴したケースがあるが、そもそも裁判の争点は「改変したデーターを販売した行為」であって、「メモリ空間にパッチをあてる行為」を禁じたものではない。その証拠にプロアクションリプレイは今も売られてる。しかも、MabiAssistはOSSである上に、金銭的授与、営利などを目的としてない。あくまでも、クライアントのメモリ空間のみにパッチを当てるだけであり、サーバーとの通信に一切介入しない。したがって裁判沙汰になっても自分が負けることはないだろう。これがダメなら、改変ドライバはおろか、仕様が一定でない自作PCとかも当然アウトだろうな。

つーか、Half LifeのModでサービスやってるクチで言えた事だろうか?世界中のMod作者を敵にまわす覚悟があるのだろうか?

SourceForgeにいたっては、ちゃんとSourceForgeのガイドラインに従っているため、自分に直接言うのは筋違いである。そもそも、SourceForgeの設置されているアメリカでは、リバースエンジニアリングは連邦裁判所によって正当な権利であると認められている。そもそも、Mabinogi Assistは日本向けに作られているソフトではなく、多言語であるし、自分だけが作っているわけではない。MITライセンス上他のパックに流用されることだってあるし、その逆もまたしかりである。KukuLiteや、mod_TwinTailと違ってれっきとしたオープンソースである。まぁ、本体のメモリパッチがGPLなのに、全体MITとしているのは問題だが・・・。(一応そのことは書いてはあるけど)詰まるところ、支援ツールに関するサイトをSourceForgeの管理下に戻せば終わる問題である。これで、mabiassist.logue.beでは、ファイル配布を行っていないため問題なし。

つーか、こんな弱小サイト訴える前に、BOT、Kuku氏からバージョンアップの度に報告される脆弱性、アカウントハック、RMT業者をどうにかしろよ!

そろそろ引退時かなぁ・・・。バンされてないようだけど、やる気失せた。


逆にNexonも著作権守っているのか疑わしい。例えばクライアントに含まれるTrueTypeフォント。英語表記部分や、数字の部分にはTrubuchet MSフォントが使われている。しかし、不思議なことにWindows OSに含まれるTrubuchet MSとはファイルサイズが異なるのだ。プロパティを見ても同じバージョン5.00なのに、クライアントに含まれるTrubuchet MSは、124kなのに対し、OSに含まれるフォントは、133k。改変行為をしたと考えるのが自然だろう。それ以前に本当にMicrosoftの許可を得ているのだろうか?そうなると、日本語で使われているDFP特太ゴシック体もちゃんと承諾受けているのか怪しい。どちらもれっきとした商用フォントである。たまたま開発したマシンにOfficeが入っていて、それにバンドルされていたフォントを丸々ゲームのクライアントに流用したように見えるのは気のせいだろうか?

追伸

よく良く考えてみると、「本支援ツールで使用している「マビノギ」に関する文章、画像、その他の著作権及び一切の知的財産権は株式会社ネクソンジャパンおよび韓国NEXON社に帰属します。NEXON著作権ガイドラインも併せてご覧ください。」という文章が抜けていた。これが原因だったらしい。

2010/12/12 (日)

HTML5のrel=norefererのサポート方法

最近なぜか、Assemblaに繋がらない。というわけで、PukiWiki Adv.の更新ができない状態。そんななか、こんなスクリプトを作ってみた。

リファラーは、IEの場合location.hrefで、それ以外の場合Data SchemeでMetaタグリダイレクトページをクライアント側でつくることで、消すことができる。なお、HTML5では、rel属性にnorefererを入れることでリファラーをリンク先に残さないという仕様が加えられているため、これをJavaScriptで実装してみることにした。

$(document).ready(function(){
	// aタグで、relにnorefererが含まれるリンクをクリックしたときに起きる処理をオーバーライド
	$('a[rel*=noreferer]').click(function () {
		// aタグのhref属性を取得
		var uri = $(this).attr('href');
		if(navigator.userAgent.indexOf("MSIE")!==-1){
			// IEの場合、location.replaeでリファラー消えるからいいや
			location.href = uri;
		}else{
			// IE以外の場合、dataスキーマーでリファラーを消すためのページを偽造
			// このとき、単にuriをencodeURIComponentに通すと、URLに%が含まれていたときに二重変換されてしまう。
			// このため、uriにreplace(/%/g,"%")をし、%を%に予め変換しておく
			location.href = "data:text/html;charset=utf-8,%3Chtml%3E%0D%0A%3Cscript%20%3E%0D%0Alocation.replace(%22" + encodeURIComponent(uri.replace(/%/g,"%")) + "%22)%3B%0D%0A%3C%2Fscript%3E%0D%0A%3C%2Fhtml%3E%0D%0A";
		}
		return false;	// 本来のaタグクリック時の処理をキャンセル
	});
});

たったこれだけ。あとは、rel="noreferer"を加えるだけ。ちなみに、relはclassのように複数指定可能なので、rel="nofollow norefferer"でもHTML的に間違っていない。ちなみに、Google Chromeだと標準でサポートされているぞ。(たぶんSafariも)

よく良く考えてみると、dataスキーマって怖いな。URLで許可されている字数以内なら悪意を持ったプログラムとかも作れるしなぁ。gzip圧縮とか組み合わせればバレにくいかも。

2010/12/5 (日)

今日日のスパマー

VPSを使っていてふと思った。VPSはいうなれば、「ネットワーク越しに操作可能なパソコンを、まるまる1台借りている」ような物じゃないかと思う。つまり、その気になれば攻撃用のホストとしても利用可能なのではないだろうか?(その攻撃に使うサーバーマシンの負荷がどれくらいかかるかというのは抜きにして)ちょっとでも、Unix操作に慣れると誰でも考えそうなことである。cronで定期的にスパムメールなりスパムコメントを送信するプログラムは結構昔からあったし。(cronが使えない場合は、サイトを閲覧したタイミングで実行するようにすればいいし。例えばカウンタに連動させるとか)

一方、スパマーにとってもVPSはおいしいものである。わざわざバックドアをしかけたPCを用意するまでもなく、もともと自在に操れるPCがあるわけだから。自分のパソコンとVPS上のPCは、つながってないため匿名性も高い。定期的にVPSを変えれば足が付く可能性も減るだろう。ログを残さない匿名プロクシとして使うことも可能である。なんせ、「何でもできる」し。

よく良く考えてみると、最近の奇妙なアクセスやスパム更新は、なんとかhostingとかって名前が多いような。以下は、最近MabinogiのMMLを荒らしたホストである。

1290082707122.193.111.5122.193.111.5Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
129075056669.39.86.22369.39.86.223.static.a2webhosting.comMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
1291443817173.208.107.177173-208-107-177.rdns.squidproxies.comMozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12
129147820585.9.105.24385.9.105.243Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
1291456057173.208.107.64173-208-107-64.rdns.squidproxies.comMozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.12) Gecko/20101026 Firefox/3.6.12
129121528972.43.50.131route1.mlti.orgMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)rckqloaz
129117256781.208.106.18181-208-106-181.ip.fastwebnet.itMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
1290944763218.36.213.64218.36.213.64Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
1290644894194.70.47.25no-dns-yet.demon.co.ukMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)qktkvhbu
1290539771193.52.26.211login.hpclr.univ-montp2.frMozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
1290126325183.101.159.145183.101.159.145Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1)
129004454967.215.238.210hosted.by.pacificrack.comMozilla/5.0 (Windows; U; Windows NT 5.0; ru; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
129008917367.215.238.210hosted.by.pacificrack.comMozilla/5.0 (Windows; U; Windows NT 5.0; ru; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
129008945888.198.61.23288-198-61-232.eurohost.mdMozilla/5.0 (Windows; U; Windows NT 5.0; ru; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
129009031367.215.238.210hosted.by.pacificrack.comMozilla/5.0 (Windows; U; Windows NT 5.0; ru; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
129009223967.215.237.98client832.surehost.ruMozilla/5.0 (Windows; U; Windows NT 5.0; ru; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6
129009536867.215.237.98client832.surehost.ruMozilla/5.0 (Windows; U; Windows NT 5.0; ru; rv:1.8.1.6) Gecko/20070725 Firefox/2.0.0.6

69.39.86.223.static.a2webhosting.comは、アメリカの日本語学校のようである。公開プロクシリストに入っていることから、学生がサーバーをクラックしてバックドアを仕掛けたのだろうか?hosted.by.pacificrack.comは、サイトのcPanelにつながる。完全にスパム用ホストとしてサーバー会社から借りたが、うっかりApacheを起動したままになっているのだろう。興味深いのは、UAがいずれも、MSIE6.0かFireFoxの2.0という、レガシーブラウザになっているところである。レガシーブラウザを弾くだけでどうにかなりそうだが・・・。

FireFoxはともかくMSIE6.0にするメリットは無いはずである。北欧では締め出しが始まっているし、大手ポータルサイトでもサポート対象外にしているし。謎である。まぁ、管理する側からすれば弾きやすいわけだが。

Stop Forum spam

これらのホスト名でGoogleで検索すると面白いサイトがヒットする。StopForumSpam.comだ。最近頭を悩ますホスト名でだいたいこのサイトに掲載されていることが多い。マジオススメ。

ちなみに、この記事を書いている最近24時間のスパムの送信元として多い国は、

  1. ロシア
  2. ウクライナ
  3. アメリカ
  4. ノルウェー
  5. 中国
  6. ドイツ
  7. イギリス(?)
  8. ポーランド
  9. ラトビア
  10. フランス
  11. インド

という順番だった。ウクライナとノルウェーの人口比のスパム率が高いのが気になる。中国は案外少ないようだ。(もっとも、日本ではこのサービスを使用している人が少ないからかもしれないが。)APIも公開されているので、そのうちPukiWiki Adv.にも組み込むとしよう。

Iptables自動更新スクリプト

StopForumSpam.comでは、ipリストを配布しているので、ファイアウォール構築(iptables) - Fedoraで自宅サーバー構築を参考にスクリプトを組んでみた。

#!/bin/bash

# ファイアウォール停止(すべてのルールをクリア)
service iptables stop
echo iptablesを初期化しています…。
iptables -F

#---------------------------------------#
# 設定開始								#
#---------------------------------------#

# インタフェース名定義
LAN=eth0

#---------------------------------------#
# 設定終了								#
#---------------------------------------#

# 内部ネットワークのネットマスク取得
echo 内部ネットワークの情報を取得中…。
LOCALNET_MASK=`ifconfig $LAN|sed -e 's/^.*マスク:\([^ ]*\)$/\1/p' -e d`

# 内部ネットワークアドレス取得
echo Get local network address.
LOCALNET_ADDR=`netstat -rn|grep $LAN|grep $LOCALNET_MASK|cut -f1 -d' '`
LOCALNET=$LOCALNET_ADDR/$LOCALNET_MASK

echo 内部ネットワークマスク :$LOCALNET_MASK
echo 内部ネットワークアドレス:$LOCALNET_ADDR

# デフォルトルール(以降のルールにマッチしなかった場合に適用するルール)設定
echo デフォルトのルールを設定しています…
iptables -P INPUT   DROP   # 受信はすべて破棄
iptables -P OUTPUT  ACCEPT # 送信はすべて許可
iptables -P FORWARD DROP   # 通過はすべて破棄

# 自ホストからのアクセスをすべて許可
iptables -A INPUT -i lo -j ACCEPT

# 内部からのアクセスをすべて許可
iptables -A INPUT -s $LOCALNET -j ACCEPT

# 内部から行ったアクセスに対する外部からの返答アクセスを許可
iptables -A INPUT -m state --state ESTABLISHED,RELATED -j ACCEPT

# SYN Cookiesを有効にする
# ※TCP SYN Flood攻撃対策
sysctl -w net.ipv4.tcp_syncookies=1 > /dev/null
sed -i '/net.ipv4.tcp_syncookies/d' /etc/sysctl.conf
echo "net.ipv4.tcp_syncookies=1" >> /etc/sysctl.conf

# ブロードキャストアドレス宛pingには応答しない
# ※Smurf攻撃対策
sysctl -w net.ipv4.icmp_echo_ignore_broadcasts=1 > /dev/null
sed -i '/net.ipv4.icmp_echo_ignore_broadcasts/d' /etc/sysctl.conf
echo "net.ipv4.icmp_echo_ignore_broadcasts=1" >> /etc/sysctl.conf

# ICMP Redirectパケットは拒否
sed -i '/net.ipv4.conf.*.accept_redirects/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
	sysctl -w net.ipv4.conf.$dev.accept_redirects=0 > /dev/null
	echo "net.ipv4.conf.$dev.accept_redirects=0" >> /etc/sysctl.conf
done

# Source Routedパケットは拒否
sed -i '/net.ipv4.conf.*.accept_source_route/d' /etc/sysctl.conf
for dev in `ls /proc/sys/net/ipv4/conf/`
do
	sysctl -w net.ipv4.conf.$dev.accept_source_route=0 > /dev/null
	echo "net.ipv4.conf.$dev.accept_source_route=0" >> /etc/sysctl.conf
done

# フラグメント化されたパケットはログを記録して破棄
iptables -A INPUT -f -j LOG --log-prefix '[IPTABLES FRAGMENT] : '
iptables -A INPUT -f -j DROP

# 外部とのNetBIOS関連のアクセスはログを記録せずに破棄
# ※不要ログ記録防止
iptables -A INPUT ! -s $LOCALNET -p tcp -m multiport --dports 135,137,138,139,445 -j DROP
iptables -A INPUT ! -s $LOCALNET -p udp -m multiport --dports 135,137,138,139,445 -j DROP
iptables -A OUTPUT ! -d $LOCALNET -p tcp -m multiport --sports 135,137,138,139,445 -j DROP
iptables -A OUTPUT ! -d $LOCALNET -p udp -m multiport --sports 135,137,138,139,445 -j DROP

# 1秒間に4回を超えるpingはログを記録して破棄
# ※Ping of Death攻撃対策
iptables -N LOG_PINGDEATH
iptables -A LOG_PINGDEATH -m limit --limit 1/s --limit-burst 4 -j ACCEPT
iptables -A LOG_PINGDEATH -j LOG --log-prefix '[IPTABLES PINGDEATH] : '
iptables -A LOG_PINGDEATH -j DROP
iptables -A INPUT -p icmp --icmp-type echo-request -j LOG_PINGDEATH

# 全ホスト(ブロードキャストアドレス、マルチキャストアドレス)宛パケットはログを記録せずに破棄
# ※不要ログ記録防止
iptables -A INPUT -d 255.255.255.255 -j DROP
iptables -A INPUT -d 224.0.0.1 -j DROP

# 113番ポート(IDENT)へのアクセスには拒否応答
# ※メールサーバ等のレスポンス低下防止
iptables -A INPUT -p tcp --dport 113 -j REJECT --reject-with tcp-reset

echo デフォルトのルールを設定完了。

echo Stop Forum Spamのブラックリストを取得中…
# http://www.stopforumspam.com/downloads/listed_ip_1.zipから最新版IPアドレスリストを取得する
wget http://www.stopforumspam.com/downloads/listed_ip_1.zip
unzip listed_ip_1.zip
iptables -N FORUMSPAMHOST
rm ./listed_ip_1.zip


# 最新版IPアドレスリストが取得できなかった場合
if [ ! -f ./listed_ip_1.txt ]; then
	if [ -f /tmp/listed_ip_1.txt ]; then
		echo ブロックリストの取得ができませんでした。過去のバックアップから読み込みます。
		return
	else
		echo ブロックリストの取得ができませんでした。
		exit 1
	fi
else
	echo 古いブロックリストを削除しています。
	rm /tmp/listed_ip_1.txt
	echo ブロックリストを更新しています。
	mv ./listed_ip_1.txt /tmp/listed_ip_1.txt
fi

echo iptablesにブロックリストを反映しています。しばらくお待ちください…。
# update firewall
if [ -s /tmp/listed_ip_1.txt ]; then
	for ip in `cat /tmp/listed_ip_1.txt`
	do
#		echo $ip
		iptables -A INPUT   -s $ip  -j FORUMSPAMHOST
		iptables -A OUTPUT  -d $ip  -j FORUMSPAMHOST
		iptables -A FORWARD -s $ip  -j FORUMSPAMHOST
		iptables -A FORWARD -d $ip  -j FORUMSPAMHOST
	done
fi

iptables -A FORUMSPAMHOST  -j LOG  --log-level info --log-prefix "SPAMHOST -- DENY "
iptables -A FORUMSPAMHOST  -j DROP
echo ブロックリストの更新が完了しました。

#----------------------------------------------------------#
# 各種サービスを公開する場合の設定(ここから)			   #
#----------------------------------------------------------#

echo 各種サービス用のポートを開いています…

# 外部からのTCP22番ポート(SSH)へのアクセスを許可
# ※SSHサーバーを公開する場合のみ
iptables -A INPUT -p tcp --dport 22 -j ACCEPT

# 外部からのTCP/UDP53番ポート(DNS)へのアクセスを許可
# ※外部向けDNSサーバーを運用する場合のみ
#iptables -A INPUT -p tcp --dport 53 -j ACCEPT
#iptables -A INPUT -p udp --dport 53 -j ACCEPT

# 外部からのTCP80番ポート(HTTP)へのアクセスを許可
# ※Webサーバーを公開する場合のみ
iptables -A INPUT -p tcp --dport 80 -j ACCEPT

# 外部からのTCP443番ポート(HTTPS)へのアクセスを許可
# ※Webサーバーを公開する場合のみ
iptables -A INPUT -p tcp --dport 443 -j ACCEPT

# 外部からのTCP21番ポート(FTP)へのアクセスを許可
# ※FTPサーバーを公開する場合のみ
#iptables -A INPUT -p tcp --dport 21 -j ACCEPT

# 外部からのPASV用ポート(FTP-DATA)へのアクセスを許可
# ※FTPサーバーを公開する場合のみ
# ※PASV用ポート60000:60030は当サイトの設定例
#iptables -A INPUT -p tcp --dport 60000:60030 -j ACCEPT

# 外部からのTCP25番ポート(SMTP)へのアクセスを許可
# ※SMTPサーバーを公開する場合のみ
#iptables -A INPUT -p tcp --dport 25 -j ACCEPT

# 外部からのTCP465番ポート(SMTPS)へのアクセスを許可
# ※SMTPSサーバーを公開する場合のみ
#iptables -A INPUT -p tcp --dport 465 -j ACCEPT

# 外部からのTCP110番ポート(POP3)へのアクセスを許可
# ※POP3サーバーを公開する場合のみ
#iptables -A INPUT -p tcp --dport 110 -j ACCEPT

# 外部からのTCP995番ポート(POP3S)へのアクセスを許可
# ※POP3Sサーバーを公開する場合のみ
#iptables -A INPUT -p tcp --dport 995 -j ACCEPT

# 外部からのTCP143番ポート(IMAP)へのアクセスを許可
# ※IMAPサーバーを公開する場合のみ
#iptables -A INPUT -p tcp --dport 143 -j ACCEPT

# 外部からのTCP993番ポート(IMAPS)へのアクセスを許可
# ※IMAPSサーバーを公開する場合のみ
#iptables -A INPUT -p tcp --dport 993 -j ACCEPT

# 外部からのUDP1194番ポート(OpenVPN)へのアクセスを許可
# ※OpenVPNサーバーを公開する場合のみ
#iptables -A INPUT -p udp --dport 1194 -j ACCEPT

# VPNインタフェース用ファイアウォール設定
# ※OpenVPNサーバーを公開する場合のみ
#[ -f /etc/openvpn/openvpn-startup ] && /etc/openvpn/openvpn-startup

# 外部からのTCP5900/5901番ポート(VNC)へのアクセスを許可
#iptables -A INPUT -p tcp --dport 5900 -j ACCEPT
#iptables -A INPUT -p tcp --dport 5901 -j ACCEPT

# 外部からのTCP/UDP10000番ポート(Webmin)へのアクセスを許可
iptables -A INPUT -p tcp --dport 10000 -j ACCEPT
iptables -A INPUT -p udp --dport 10000 -j ACCEPT

# 外部からのTCP/UDP20000番ポート(Usermin)へのアクセスを許可
#iptables -A INPUT -p tcp --dport 20000 -j ACCEPT
#iptables -A INPUT -p udp --dport 20000 -j ACCEPT

echo 各種サービス用の設定が完了しました。

#----------------------------------------------------------#
# 各種サービスを公開する場合の設定(ここまで)			   #
#----------------------------------------------------------#

# 拒否IPアドレスからのアクセスはログを記録せずに破棄
# ※拒否IPアドレスは./deny_ip.txtに1行ごとに記述しておくこと
iptables -N DENIED_IP
if [ -s ./deny_ip.txt ]; then
	echo 拒否IPリストが見つかりました。iptablesに反映させています…。
	for ip in `cat ./deny_ip.txt`
	do
		iptables -A INPUT   -s $ip  -j DENIED_IP
		iptables -A OUTPUT  -d $ip  -j DENIED_IP
		iptables -A FORWARD -s $ip  -j DENIED_IP
		iptables -A FORWARD -d $ip  -j DENIED_IP
	done
	echo 拒否IPリストの反映が完了しました。
fi

# 上記のルールにマッチしなかったアクセスはログを記録して破棄
iptables -A INPUT -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES INPUT] : '
iptables -A INPUT -j DROP
iptables -A FORWARD -m limit --limit 1/s -j LOG --log-prefix '[IPTABLES FORWARD] : '
iptables -A FORWARD -j DROP

# サーバー再起動時にも上記設定が有効となるようにルールを保存
service iptables save

# iptables 1.4.3.1バグ対処
iptables -V|grep 1.4.3.1 > /dev/null 2>&1
if [ $? -eq 0 ]; then
	sed -i s/"-s \!"/"\! -s"/g /etc/sysconfig/iptables
	sed -i s/"-d \!"/"\! -d"/g /etc/sysconfig/iptables
fi

# ファイアウォール起動
service iptables start

iptables-save > /etc/iptables.up.rules

ちなみに、引用元の、ファイアウォール構築(iptables) - Fedoraで自宅サーバー構築では、LOCALNET_MASKの取得部分が

LOCALNET_MASK=`ifconfig $LAN|sed -e 's/^.*Mask:\([^ ]*\)$/\1/p' -e d`

になっていたが、日本語環境で使っている場合、コマンドの実行結果の「Mask」の部分が「マスク」になるため、

LOCALNET_MASK=`ifconfig $LAN|sed -e 's/^.*マスク:\([^ ]*\)$/\1/p' -e d`

にしなければならなかった。結構はまった。環境によっては変える必要があるかも。

あと、注意したいのは、StopForumSpamへの同一ドメインからの1日のダウンロード回数が制限されていること。このスクリプトで使用している1時間ごとに更新されるリスト(listed_ip_1.zip)は、1日に24回しかダウンロード出来ない。スクリプトがエラーになるのを防ぐために、/etc/ディレクトリにバックアップを置くようにしてある。

おまけ

banned_ip.txt。とりあえず、amazonのVPSと、殿堂入り国内スパムホストのOCN丸の内、NTT-PC東京は弾いておこう。P2P用のキックリストの流用だが、amazonをのぞくこれらの国内のホストは過去にもスパムメールを送信していたことで有名である。逝ってよし!

67.202.0.0/18
72.44.32.0/19
75.101.128.0/17
79.125.0.0/18
114.150.59.38/32
118.8.11.232/32
124.154.252.140/32
124.154.253.197/32
174.129.0.0/16
216.182.224.0/20
221.191.121.165/32

218.124.47.12
219.208.92.39

ちなみに、最後の2行は、30分にわたり5秒に1回という非常識なアクセスをしてきやがったYahoo BBのホスト。ark-westのようなリファラースパムも行っているようだ。

どうでもいいけど、ルーターに同じリストを入れたところ、75.101.137.232:80から、明らかにポートスキャンされているようなログが出てきたんだが・・・。

2010/11/4 (木)

nginx+php-fpm導入

移転してから自分でサーバーの中身をいじるようになったためか、ちょっとでも重くなるとすぐにWebminで負荷を見るようになった。まぁ、それ以前に設定が面倒だからとPHPをApacheモジュールで使っていたので重いのも当然である。で、CGIモードでPHPを動かす方法を調べていたのだが、そもそもApacheに拘る理由とはなんだろうか?と考えた。HTTPデーモンと聞くと無意識にApacheと考えてしまいそれ以外、見落としているプログラムがあるかもしれない。そういえば、昔Windowsでサーバーひらいている人はAN-HTTPD使ってた気がするし、MacはMacでOS標準のWeb共有というプログラムでWebサーバー開いていたような。

というわけで、他のHTTPDサーバーについて調べてみた。すると、lighttpdというのとnginxというのが浮かび上がった。どちらも共通しているのが、PHPを別プロセスで動かしているところである。どっちにするか迷ったが、開発背景と、コンフィグファイルの構文から後者のnginxを選ぶことにした。なんと、nginxはロシア製である。どうやら、ロシアの開発者が自社のポータルサイト向けに作ったHTTPDサーバーらしい。最初から設計方針がはっきりしている点がポイント高い。ちsourceForgeや最近話題のGitHubなどで使われているらしい。まぁ、弱小個人サイトに導入するほどのものではないが、どうせやるならってことで。

まずは、Ubuntuにインストール。例によってapt-getで。

apt-get install nginx

すると、/etc/nginx以下に設定ファイルが置かれる。

まずは、nginx.confの設定。PukiWiki Adv.の開発でお世話になっているHTML5 ★ Boilerplate推奨nginx.confを参考に設定を組む。この推奨設定は、Yslowのガイドラインに基づいた設定になっている。

nginxの設定

nginx.conf

user				www-data;
worker_processes	1;

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

events {
	# When you need > 8000 * cpu_cores connections, you start optimizing
	# your OS, and this is probably the point at where you hire people
	# who are smarter than you, this is *a lot* of requests.
	worker_connections 8000;

	# This sets up some smart queueing for accept(2)'ing requests
	# Set it to "on" if you have > worker_processes
	accept_mutex off;

	# These settings are OS specific, by defualt Nginx uses select(2),
	# however, for a large number of requests epoll(2) and kqueue(2)
	# are generally faster than the default (select(2))
	# use epoll; # enable for Linux 2.6+
	# use kqueue; # enable for *BSD (FreeBSD, OS X, ..)
}

http {
	# Set the mime-types
	include	  	/etc/nginx/mime.types;

	# And the fallback mime-type
	# default_type application/octet-stream;

	# Format for our log files
	log_format main '$remote_addr - $remote_user [$time_local] $status '
		'"$request" $body_bytes_sent "$http_referer" '
		'"$http_user_agent" "$http_x_forwarded_for"';

	# Click tracking!
	access_log	/var/log/nginx/access.log;

	# ~2 seconds is often enough for HTML/CSS, but connections in
	# Nginx are cheap, so generally it's safe to increase it
	keepalive_timeout 5;

	# You usually want to serve static files with Nginx
	sendfile on;

	tcp_nopush on; # off may be better for Comet/long-poll stuff
	tcp_nodelay off; # on may be better for Comet/long-poll stuff

	# Enable Gzip
	gzip on;
	gzip_http_version 1.0;
	gzip_comp_level 2;
	gzip_min_length 1100;
	gzip_buffers 4 8k;
	gzip_proxied any;
	gzip_types text/plain text/xml application/xml application/xml+rss text/css text/javascript application/javascript application/json;

	gzip_static on;

	gzip_proxied expired no-cache no-store private auth;
	gzip_disable "MSIE [1-6]\.";
	gzip_vary on;

	upstream backend {
#		server	127.0.0.1:9000;
		server	unix:/var/run/php-fpm.socket;
	}

	include /etc/nginx/conf.d/*.conf;
	include /etc/nginx/sites-enabled/*;
}

次にデフォルトのサイト設定を行う。サイトごとの設定は、./sites-enabled/ディレクトリに設置する。とりあえず、テストなのでポートは8080を使用しよう。

server {
	## listen for ipv4; this line is default and implied
	listen		8080;
	## listen for ipv6
	#listen		[::]:80 default ipv6only=on;

	# e.g. "localhost" to accept all connections, or "www.example.com"
	# to handle the requests for "example.com" (and www.example.com)
	server_name _;
	# server_name  localhost;

	# Path for static files
	root   /var/www;

	index  index.html index.htm index.php index.cgi;

	expires 1M;

	location / {
		# First attempt to serve request as file, then
		# as directory, then fall back to index.html
		try_files $uri $uri/ /index.html;
	}

	#error_page  404  /404.html;

	# redirect server error pages to the static page /50x.html
	#
	#error_page   500 502 503 504  /50x.html;
	#location = /50x.html {
	#	root   /var/www/nginx-default;
	#}

	# proxy the PHP scripts to Apache listening on 127.0.0.1:80
	#
	#location ~ \.php$ {
	#	proxy_pass   http://127.0.0.1;
	#}

	# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
	#
	location ~ \.php$ {
		fastcgi_pass   backend;
		fastcgi_index  index.php;
		fastcgi_param  SCRIPT_FILENAME  /var/www$fastcgi_script_name;
#		fastcgi_param  SCRIPT_FILENAME  $document_root$fastcgi_script_name;
		include fastcgi_params;
	}

	# deny access to .htaccess files, if Apache's document root
	# concurs with nginx's one
	#
	location ~ /\.ht {
		deny  all;
	}
}

次にサービスに登録する。http://code.google.com/p/nginx-init-ubuntu/で配布されているシェルスクリプトを使おう。ただし、DAEMONと、NGINX_CONF_FILEの値が違うためそのままでは動かない。以下のように変更すること。

#------------------------------------------------------------------------------
#                               Consts
#------------------------------------------------------------------------------
PATH=/usr/local/sbin:/usr/local/bin:/sbin:/bin:/usr/sbin:/usr/bin
-DAEMON=/usr/local/sbin/nginx
+DAEMON=/usr/sbin/nginx
 
PS="nginx"
PIDNAME="nginx"				#lets you do $PS-slave
PIDFILE=$PIDNAME.pid                    #pid file
PIDSPATH=/var/run
 
DESCRIPTION="Nginx Server..."
 
RUNAS=root                              #user to run as
 
SCRIPT_OK=0                             #ala error codes
SCRIPT_ERROR=1                          #ala error codes
TRUE=1                                  #boolean
FALSE=0                                 #boolean
 
lockfile=/var/lock/subsys/nginx
NGINX_CONF_FILE="/usr/local/nginx/conf/nginx.conf"
+NGINX_CONF_FILE="/etc/nginx/nginx.conf"

設定が完了したら、/etc/init.d/nginxにこのファイルを保存し、chmod 755 、/etc/init.d/nginxで実行権限を与え、/usr/sbin/update-rc.d -f nginx defaultsを実行。

この例では、/var/wwwをサイトのトップにしてある。nginxをシェルから起動してhttp://localhost:8080/で確認して、ちゃんとアクセス出来るか試してみよう。 こんな感じでいいだろう。

php-fpmの設定

次にphp5-fpmのインストールと設定である。

apt-get install php5-fpm

で、/etc/php5/fpmに設定ファイルが置かれる。

自分は以下のように設定した。

;;;;;;;;;;;;;;;;;;;;;
; FPM Configuration ;
;;;;;;;;;;;;;;;;;;;;;

; All relative paths in this configuration file are relative to PHP's install
; prefix.

; Include one or more files. If glob(3) exists, it is used to include a bunch of
; files from a glob(3) pattern. This directive can be used everywhere in the
; file.
;include=/usr/local/php/etc/fpm.d/*.conf

;;;;;;;;;;;;;;;;;;
; Global Options ;
;;;;;;;;;;;;;;;;;;

[global]
; Pid file
; Default Value: none
pid = /var/run/php-fpm.pid

; Error log file
; Default Value: /usr/local/php/var/log/php-fpm.log
error_log = /var/log/php-fpm/php-fpm.log

; Log level
; Possible Values: alert, error, warning, notice, debug
; Default Value: notice
log_level = error

; If this number of child processes exit with SIGSEGV or SIGBUS within the time
; interval set by emergency_restart_interval then FPM will restart. A value
; of '0' means 'Off'.
; Default Value: 0
;emergency_restart_threshold = 0

; Interval of time used by emergency_restart_interval to determine when
; a graceful restart will be initiated.  This can be useful to work around
; accidental corruptions in an accelerator's shared memory.
; Available Units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;emergency_restart_interval = 0

; Time limit for child processes to wait for a reaction on signals from master.
; Available units: s(econds), m(inutes), h(ours), or d(ays)
; Default Unit: seconds
; Default Value: 0
;process_control_timeout = 0

; Send FPM to background. Set to 'no' to keep FPM in foreground for debugging.
; Default Value: yes
daemonize = yes

;;;;;;;;;;;;;;;;;;;;
; Pool Definitions ;
;;;;;;;;;;;;;;;;;;;;

; Multiple pools of child processes may be started with different listening
; ports and different management options.  The name of the pool will be
; used in logs and stats. There is no limitation on the number of pools which
; FPM can handle. Your system will tell you anyway :)

; Start a new pool named 'www'.
[www]

; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
;listen = 127.0.0.1:9000
listen = /var/run/php-fpm.socket

; Set listen(2) backlog. A value of '-1' means unlimited.
; Default Value: -1
listen.backlog = 1
 
; List of ipv4 addresses of FastCGI clients which are allowed to connect.
; Equivalent to the FCGI_WEB_SERVER_ADDRS environment variable in the original
; PHP FCGI (5.2.2+). Makes sense only with a tcp listening socket. Each address
; must be separated by a comma. If this value is left blank, connections will be
; accepted from any ip address.
; Default Value: any
;listen.allowed_clients = 127.0.0.1

; Set permissions for unix socket, if one is used. In Linux, read/write
; permissions must be set in order to allow connections from a web server. Many
; BSD-derived systems allow connections regardless of permissions.
; Default Values: user and group are set as the running user
;                 mode is set to 0666
listen.owner = www-data
listen.group = www-data
listen.mode = 0666

; Unix user/group of processes
; Note: The user is mandatory. If the group is not set, the default user's group
;       will be used.
user = www-data
group = www-data

; Choose how the process manager will control the number of child processes.
; Possible Values:
;   static  - a fixed number (pm.max_children) of child processes;
;   dynamic - the number of child processes are set dynamically based on the
;             following directives:
;             pm.max_children      - the maximum number of children that can
;                                    be alive at the same time.
;             pm.start_servers     - the number of children created on startup.
;             pm.min_spare_servers - the minimum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is less than this
;                                    number then some children will be created.
;             pm.max_spare_servers - the maximum number of children in 'idle'
;                                    state (waiting to process). If the number
;                                    of 'idle' processes is greater than this
;                                    number then some children will be killed.
; Note: This value is mandatory.
pm = dynamic

; The number of child processes to be created when pm is set to 'static' and the
; maximum number of child processes to be created when pm is set to 'dynamic'.
; This value sets the limit on the number of simultaneous requests that will be
; served. Equivalent to the ApacheMaxClients directive with mpm_prefork.
; Equivalent to the PHP_FCGI_CHILDREN environment variable in the original PHP
; CGI.
; Note: Used when pm is set to either 'static' or 'dynamic'
; Note: This value is mandatory.
;pm.max_children = 50
pm.max_children = 25
; The number of child processes created on startup.
; Note: Used only when pm is set to 'dynamic'
; Default Value: min_spare_servers + (max_spare_servers - min_spare_servers) / 2
;pm.start_servers = 20
pm.start_servers = 10
; The desired minimum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
;pm.min_spare_servers = 5
pm.min_spare_servers = 3
; The desired maximum number of idle server processes.
; Note: Used only when pm is set to 'dynamic'
; Note: Mandatory when pm is set to 'dynamic'
;pm.max_spare_servers = 35
pm.max_spare_servers = 17
; The number of requests each child process should execute before respawning.
; This can be useful to work around memory leaks in 3rd party libraries. For
; endless request processing specify '0'. Equivalent to PHP_FCGI_MAX_REQUESTS.
; Default Value: 0
;pm.max_requests = 500
pm.max_requests = 250
; The URI to view the FPM status page. If this value is not set, no URI will be
; recognized as a status page. By default, the status page shows the following
; information:
;   accepted conn    - the number of request accepted by the pool;
;   pool             - the name of the pool;
;   process manager  - static or dynamic;
;   idle processes   - the number of idle processes;
;   active processes - the number of active processes;
;   total processes  - the number of idle + active processes.
; The values of 'idle processes', 'active processes' and 'total processes' are
; updated each second. The value of 'accepted conn' is updated in real time.
; Example output:
;   accepted conn:   12073
;   pool:             www
;   process manager:  static
;   idle processes:   35
;   active processes: 65
;   total processes:  100
; By default the status page output is formatted as text/plain. Passing either
; 'html' or 'json' as a query string will return the corresponding output
; syntax. Example:
;   http://www.foo.bar/status
;   http://www.foo.bar/status?json
;   http://www.foo.bar/status?html
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;pm.status_path = /status
 
; The ping URI to call the monitoring page of FPM. If this value is not set, no
; URI will be recognized as a ping page. This could be used to test from outside
; that FPM is alive and responding, or to
; - create a graph of FPM availability (rrd or such);
; - remove a server from a group if it is not responding (load balancing);
; - trigger alerts for the operating team (24/7).
; Note: The value must start with a leading slash (/). The value can be
;       anything, but it may not be a good idea to use the .php extension or it
;       may conflict with a real PHP file.
; Default Value: not set
;ping.path = /ping

; This directive may be used to customize the response of a ping request. The
; response is formatted as text/plain with a 200 response code.
; Default Value: pong
;ping.response = pong
 
; The timeout for serving a single request after which the worker process will
; be killed. This option should be used when the 'max_execution_time' ini option
; does not stop script execution for some reason. A value of '0' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_terminate_timeout = 0
 
; The timeout for serving a single request after which a PHP backtrace will be
; dumped to the 'slowlog' file. A value of '0s' means 'off'.
; Available units: s(econds)(default), m(inutes), h(ours), or d(ays)
; Default Value: 0
;request_slowlog_timeout = 0
 
; The log file for slow requests
; Default Value: /usr/local/php/var/log/php-fpm.log.slow
;slowlog = /usr/local/php/var/log/php-fpm.log.slow
 
; Set open file descriptor rlimit.
; Default Value: system defined value
;rlimit_files = 1024
 
; Set max core size rlimit.
; Possible Values: 'unlimited' or an integer greater or equal to 0
; Default Value: system defined value
;rlimit_core = 0
 
; Chroot to this directory at the start. This value must be defined as an
; absolute path. When this value is not set, chroot is not used.
; Note: chrooting is a great security feature and should be used whenever
;       possible. However, all PHP paths will be relative to the chroot
;       (error_log, sessions.save_path, ...).
; Default Value: not set
;chroot =
 
; Chdir to this directory at the start. This value must be an absolute path.
; Default Value: current directory or / when chroot
;chdir = /var/www
 
; Redirect worker stdout and stderr into main error log. If not set, stdout and
; stderr will be redirected to /dev/null according to FastCGI specs.
; Default Value: no
;catch_workers_output = yes
 
; Pass environment variables like LD_LIBRARY_PATH. All $VARIABLEs are taken from
; the current environment.
; Default Value: clean env
;env[HOSTNAME] = $HOSTNAME
;env[PATH] = /usr/local/bin:/usr/bin:/bin
;env[TMP] = /tmp
;env[TMPDIR] = /tmp
;env[TEMP] = /tmp

; Additional php.ini defines, specific to this pool of workers. These settings
; overwrite the values previously defined in the php.ini. The directives are the
; same as the PHP SAPI:
;   php_value/php_flag             - you can set classic ini defines which can
;                                    be overwritten from PHP call 'ini_set'.
;   php_admin_value/php_admin_flag - these directives won't be overwritten by
;                                     PHP call 'ini_set'
; For php_*flag, valid values are on, off, 1, 0, true, false, yes or no.

; Defining 'extension' will load the corresponding shared extension from
; extension_dir. Defining 'disable_functions' or 'disable_classes' will not
; overwrite previously defined php.ini values, but will append the new value
; instead.

; Default Value: nothing is defined by default except the values in php.ini and
;                specified at startup with the -d argument
;php_admin_value[sendmail_path] = /usr/sbin/sendmail -t -i -f www@my.domain.com
;php_flag[display_errors] = off
;php_admin_value[error_log] = /var/log/fpm-php.www.log
;php_admin_flag[log_errors] = on
;php_admin_value[memory_limit] = 32M

キモとなるのはlistenの部分で、多くのサイトでは127.0.0.1:9000にしているが、自分の場合これをやったら502 Bad Gatewayエラーが多発したので、Socketによる通信でphp-fpmを動かすことにした。

ポイントとなるのは以下の箇所。

/etc/nginx/nginx.conf
	upstream backend {
#		server	127.0.0.1:9000;
		server	unix:/var/run/php-fpm.socket;
	}
/etc/php5/fpm/main.conf
; The address on which to accept FastCGI requests.
; Valid syntaxes are:
;   'ip.add.re.ss:port'    - to listen on a TCP socket to a specific address on
;                            a specific port;
;   'port'                 - to listen on a TCP socket to all addresses on a
;                            specific port;
;   '/path/to/unix/socket' - to listen on a unix socket.
; Note: This value is mandatory.
;listen = 127.0.0.1:9000
listen = /var/run/php-fpm.socket

お気づきだろうか?nginx.confのserverの部分と、php5-fpmのmain.confのlistenの部分の設定は揃えなければならない。一般的な例では、このパスが、/var/run/php-fpm/php-fpm.sockになっていたが、自分の環境の場合、php-fpmディレクトリが消えてしまってちゃんと動かなかったことがあったので、/var/run/php-fpm.socketというファイル名にしてある。注意したいのは、nginx側でsocketファイルを指定する場合、unix:/var/run/php-fpm.socket; というように、unix:が必要になるところ。

テスト

念のため正常に動作するかチェック。以下のコマンドで確認できる。

nginx -t

エラーがでなければ動作開始しよう。ただし、phpが動作するかどうかまではわからない。

service nginx start

あと、phpの動作確認に、/var/wwwに内容が<?php phpinfo(); ?>のphpinfo.phpを作成しよう。

service php5-fpm start

2010/10/19 (火)

サーバーのセットアップ

サーバーOSは、Ubuntuの64bitにした。メモリの上限が512Mなのに64bitにする意味はあるのか疑わしいが、やっぱり時代は64bitだろう。さて、S@@Ses側でインストールされるUbuntuのバージョンは10.04で前のバージョンである。というか、最新版はまだ先週出たばっかり。とりあえず、Ubuntu Tips/インストール/Ubuntu 10.10 へアップグレードを行うにはを参考に10.10にアップする。

普段はWinSCPを使うことが多いが、どうもちゃんとコマンドを打てないのでTera Termを使うことにした。

Linux rad-xen-vweb?? ?.?.??-??-server #??-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010 x86_64 GNU/Linux
Ubuntu 10.04.1 LTS

Welcome to the Ubuntu Server!
 * Documentation:  http://www.ubuntu.com/server/doc

The programs included with the Ubuntu system are free software;
the exact distribution terms for each program are described in the
individual files in /usr/share/doc/*/copyright.

Ubuntu comes with ABSOLUTELY NO WARRANTY, to the extent permitted by
applicable law.

$

まずは、suでroot権限になる。

$su
パスワード:

sudo apt-get install update-manager-core

次に、/etc/update-manager/release-upgradesを修正するわけだが、編集ソフトがはいっていないためaptでnanoをインストールする。

$sudo apt-get install nano

でもって、

$sudo nano /etc/update-manager/release-upgrades

で、Prompt=ltsをPrompt=normalに変更。Control+Xで終了。

$sudo do-release-upgrade

でアップグレード開始。とおもったら、容量が足りない。調べてみるとbootドライブがたったの100M。とりあえず

$cd /boot
$ls

で内容を確認。

System.map-2.6.32-22-server  initrd.img-2.6.32-22-server
System.map-2.6.32-25-server  initrd.img-2.6.32-25-server
lost+found                    config-2.6.32-22-server
vmlinuz-2.6.32-22-server      config-2.6.32-25-server
vmlinuz-2.6.32-25-server     grub

なぁ、System.map-2.6.32-22-serverとか、古いバージョンのファイルっていらなくね?

$rm System.map-2.6.32-22-server
$rm initrd.img-2.6.32-22-server
$rm config-2.6.32-22-server
$vm linuz-2.6.32-22-server

なんとか、容量稼げた。アップグレード実行!今度はうまくいった。

$sudo do-release-upgrade

いくつかダイアログが出たが、設定は極力そのままにしておこう。/etc/securettyも、そのままでいいか。

あと、「grub-pcを設定しています」という画面が出てきた。おそらくブートローダーの位置を指定するのだろう。/bootデバイスは、100Mちょいのドライブなので、そこにGrubをインストール。なぜか2番目に表示されてるが・・・。

最後に「サポートが中止された(あるいはリポジトリに存在しない)パッケージを削除しますか?」というのが出るが不安なので、削除しないことにする。

で、リブート→起動せず。

おかしい。さっそくSaaSesに問い合わせてみる。すると、

「アップデートを行ってみたところ」とのことでしたが、その内容がUbuntu 10.10へのアップデートの場合、下記の箇所で問題が発生する場合があることを確認致しました。
  • /boot内にある2種のうち、古い側のものを削除した場合
  • https://wiki.ubuntu.com/LucidLynx/ReleaseNotes/jaの「Ubuntuサーバのネットワークアップグレード(推奨)」の方法でアップデートを行った場合、終盤の「不要パッケージの削除」を「する」とした場合 もし上記に該当する場合は、それぞれについて
    • *-2.6.32.25*を削除する
    • 不要パッケージの削除を「しない」
      と選ぶことをご検討下さい。

つまり、新しい方を残したのが原因らしい。したがって

$rm System.map-2.6.32-25-server
$rm config-2.6.32-25-server
$rm initrd.img-2.6.32-25-server
$rm linuz-2.6.32-25-server

が、正解らしい。

早速アップグレード実行。

$sudo do-release-upgrade

残りの手順はそのままでいいらしい。でもってリブート。

アップグレード完了後、シェルにはなぜか両方のバージョンが・・・。

Linux rad-xen-vweb?? ?.?.??-??-server #36-Ubuntu SMP Thu Jun 3 20:38:33 UTC 2010 x86_64 GNU/Linux
Ubuntu 10.10

Welcome to the Ubuntu Server!
 * Documentation:  http://www.ubuntu.com/server/doc
Ubuntu 10.04.1 LTS

Welcome to the Ubuntu Server!
 * Documentation:  http://www.ubuntu.com/server/doc

ちなみに、/bootの中身はこうなってた。

$ls /boot
System.map-2.6.32-22-server   initrd.img-2.6.32-25-server
System.map-2.6.35-22-virtual  initrd.img-2.6.35-22-virtual
abi-2.6.35-22-virtual         lost+found
config-2.6.32-22-server       vmcoreinfo-2.6.35-22-virtual
config-2.6.35-22-virtual      vmlinuz-2.6.32-22-server
grub                          vmlinuz-2.6.35-22-virtual

いいのか?これで?

次に、https://wiki.ubuntulinux.jp/UbuntuTips/Install/UpgradeMaverickを参考に日本語リポジトリを有効にする。

$su
$wget -q https://www.ubuntulinux.jp/ubuntu-ja-archive-keyring.gpg -O- | sudo apt-key add -
$wget -q https://www.ubuntulinux.jp/ubuntu-jp-ppa-keyring.gpg -O- | sudo apt-key add -
$sudo wget https://www.ubuntulinux.jp/sources.list.d/maverick.list -O /etc/apt/sources.list.d/ubuntu-ja.list
$apt-get update

これで、サーバーのアップグレードは完了。

Webminの設定

Web上でサーバーの管理を行うというと普通想像するのがCpanelだが、今回のサーバーではWebminを使っている。調べてみるとサーバーというよりUnixそのものを直接操作できるらしい。しかし、どうも標準のテーマは使いにくい。そこで、Webminのテーマサイトを確認して使いやすそうなものを探していると、Stressfreeというテーマがあるのを見た。インターフェースはMacOSみたいで使いやすそうだ。というわけで、まず、これをインストール。

Webmin設定>Webminテーマ>Install Themeで、「FTP またはhttp URL から」の項目に、ダウンロードURL(http://webmin-theme-stressfree.googlecode.com/files/theme-stressfree-2.08.tar.gz)を直接入れて「テーマのインストール」をクリック。インストールが完了したら、Webmin設定>Webminテーマ>Change themeで「StressFree Theme」を選択する。これでインストール完了だ。

あと、サーバーの負荷状況を調べるために、MRTGを入れておこう。WebminstatsモジュールでWebminと統合できるようだ。Webmin設定>Webminモジュール>Installから、「FTP またはhttp URL から」を選んでダウンロードURLを「http://sf.net/projects/webminstats/files/Sysstats/1.6/sysstats-1.6.tgz」にする。「サードパーティ製モジュール」にwebminstatsといれてもインストールできるが、古いバージョンなので手動で。

2010/10/13 (水)

いろいろ検証してみた結果、S@@Sesが一番よさそうである。

月額のランニングコストが最安な上に、OSが選べる。(まぁ、初心者が使う分にはどれも似たり寄ったりだろうが・・・。)選べるOSは、CentOS、Ubuntu、Debianのみっつ。Debianはよくわからん。Ubuntuは手軽、CentOSはお堅いというイメージがある。そういえば、会社のサーバー担当が社内に6万円のDELLのサーバーを数台持ち込んで、1日かけてCentOSをインストールしてたっけ。なんでも、RedHat Linux Enterpriseの無料版らしい。ベースとなっているのがRedHatなのでそりゃ安定性は一番いいだろう。

しかし、個人用途では面白みにかける。自分が求めるのは、安定性ではなく先進性である。多少不安定だろうが、新しいのを使いそれを修正するために勉強し、中身を知る。そうなると、CentOSはないことに。最近はUbuntuが良く話題になるのでこれの64bit版を入れてもらうことにした。

使用期間は、10/27までなので、それまでにサイトを移転するようにしよう。

Linuxといえば、昔大学でSorarisを使ってたときに、ピザボックスのような機体の端末からサーバーマシンにアクセスして使っていたなぁ。ネットブートというやつだ。クライアントマシンには、OSはおろかハードディスクすらついてない。サーバーからOSを読み取って起動していると説明された。つまり、今で言うところのリモートデスクトップである。ということは、最近のLinuxでも当然できるはず。調べてみたら、VNCというのを使うらしい。昔はX Windowとか書いてあった気がするが、まいっか。

2010/10/12 (火)

サイト移転計画

現在契約中のcoreserverは、本来ならば先月末で契約がきれているはずだが、8月下旬に発生した度重なるサーバートラブルで1ヶ月契約期間延長になっていた。まぁ、月額500円ちょいなので、そういったトラブルもありだろう。とくにレスポンスが悪いという不満はない。しかし、別の問題で困っている。スパム対策だ。現在、あからさまなスパムのアクセスは、手動でhtaccessではじいているが、時々これでは弾けないケースが出てきた。.dynamic.tttmaxnet.comなんかがそうだった。1時間おきぐらいに閲覧ログが埋まるぐらいの連続アクセス。DNSで逆引きしてIPで弾いてもアクセスしてくる。仕方が無いのでPukiWiki Plus!側で弾くことにしたが、PHPが動く前に弾かないとあまり意味が無い。

もうひとつの問題としてリファラースパムである。一日数アドレスぐらい入っている。ダイエットサプリとか。中でも有料SEOが目立つ。いろいろなサイトのアクセスログを汚すだけでなく、無駄なトラフィックを増やすだけである。まさにゴキブリといっても過言はないだろう。

Referer spam Block List 20101012.txt

あまりにもバカバカしい。まぁ対策するには、相手のHTMLをwgetか何かで拾ってきてXMLパーサでaタグのhref属性を取得して自分のサイトのアドレスが含まれているかどうかを確認して、含まれてなかったらブラックリスト行きという感じのアルゴリズムでいいだろう。しかし、PHPでそれをやっていてはたまらない。そういえば、どっかでRubyで書かれたそういうプログラムあったような・・・。

あった、これだ。

で、リストに表示されたアドレスは永遠にキックと。しかし、Apacheの設定をいじるため通常のレンタルサーバーでは動かない。ましてや、500円ぐらいの共有サーバーじゃね・・・というのがこれまでの常識だったが、仮想プライベートサーバー(VPS)というのが話題になっているらしい。なんでも、root権限付きのレンタルサーバーだとか。調べてみると、これまでのレンタルサーバーは、1つのサーバー上で走る1つのOS上にいくつかのアカウントが入っているのに対して、VPSでは1つのサーバーにアカウント毎のOSを同時起動しているようなものらしい。これには、CPUの仮想化技術が使われているとのこと。しかも、ServermanやS@@Sesでは500円を切る価格で使えるとのこと。

すばらしい。ちょうど比較サイトを見かけたので吟味してみることにする。