Gマイナー志向

とくに意味はありません

ApacheのAddHandlerはセキュリティ上の懸念から使用すべきではない

元ネタはこちら。

どういうことか

次のような指定は危険である。

AddHandler php5-script .php

この時に指定される.phpはファイル名の末尾である必要はない。例えば、

aaa.php.html
bbb.php.png

などもphp5-scriptとして解釈されてしまうのだ。これは.XXX.YYYと複数の拡張子が書かれた場合、.XXXと.YYYもAddHandlerの対象となることが原因。

ちなみに次のような場合にはphp5-scriptとして解釈されない。

ccc.php_foo (.php_fooとして解釈されるため)
ddd.php_bar.html (.php_barと.htmlとして解釈されるため)

実はこのことはApacheのドキュメントにも明記されている

Apache モジュール mod_mime 複数の拡張子のあるファイル

ファイル名のドット区切りでの最後の部分を使って、 特定の部分のメタデータマッピングしたい場合は、 Add* ディレクティブは使わないでください。 たとえば foo.html.cgiCGI スクリプトとして処理したいけれども、 bar.cgi.html は CGI スクリプトとしては処理したくない場合、 AddHandler cgi-script .cgi とする代わりに 次のようにしてください
Configure handler based on final extension only

<FilesMatch \.cgi$>
SetHandler cgi-script
</FilesMatch>

つまり仕様です。

あなたのサイト、大丈夫?

RHELCentOSでmod_phpが用意する/etc/httpd/conf.d/php.confは以下のように記載されていた。

AddHandler php5-script .php
AddType text/html .php

ビンゴです。
基本的に第三者がアップロードしたファイル名をそのまま使っていたりしなければ大丈夫だろうけど、うっかりミスでやってしまう可能性もあるし怖いですね。

対策

元ブログでや上記Apache公式ドキュメントでもFilesMatchとSetHandlerを組み合わせて使えと書かれていた。

  <FilesMatch "\.(php|php5|phtml)$">
    SetHandler application/x-httpd-php
  </FilesMatch>

  <FilesMatch "\.phps$">
    SetHandler application/x-httpd-php-source
  </FilesMatch>

上記RHEL/CentOSphp.confも、とりあえずFilesMatchで囲んでやれば対策になりそう。

<FilesMatch "\.php$">
  AddHandler php5-script .php
  AddType text/html .php
</FilesMatch>

FilesMatchの中であればAddHandlerでもいいんじゃないかと思う。冗長だけどね。

残念ながら世の中にはAddHandlerを設定する方法を紹介するサイトで溢れかえっているし、Apache公式ドキュメントですら一部にAddHandlerを使っている。これは啓蒙活動が必要だね、というのが元ブログの主張でした。

Mt.Gox第2回債権者集会 質疑応答メモ

有給休暇を使ってMt.Goxの第2回債権者集会に参加してきました。ちなみに第1回も参加していました。
債権者集会での配布資料は既に公開されていますが、その場にいないとわからない質疑応答について以下に走り書きのメモを残しておきます。

内容については正確ではない可能性があります。ちなみにマイクやカメラによる記録は禁止でした。

5万ビットコインが紛失している件の進捗について

ビットコインの消失の有無、経緯については引き続き調査中。

Paywardに協力を仰ぐとのことだが、どのように組織されて調査されているのか

トーマツを中心に調査している段階。
データに不完全性がみられるため調査が難航している。
ただ、Payward、Krakenさんにご協力頂いて調査しようとしているところ。
何時頃にどういう結論がでるかについては、今の段階ではわからない。
調査の進行次第。ただ、私どもとして調査を真剣に真摯に進めていく。

ビットコインアドレスの公開について

調査に支障がないようであれば開示しようと考えている段階であったが、
調査に支障があるかがポイント。警視庁から要請があったため開示していない。

開示できるのか?いつなのか?についてははっきりしたことはわからない。
トーマツとPaywardと相談の上、可能であれば開示したい。

Paywardとの契約内容についてWebサイトで開示されるのか

ご意見として承るが、開示することに支障があるのかは確認が必要。総合的に考えて開示できるかどうかを検討したい。

Mt.Goxの事業自体はどうなるのか。Paywardが譲り受けるわけではないようだが、Paywardとしては3000万円でライバルを潰した形にみえる

継続している・保有している事業とはなにかが焦点になる。取引所は閉鎖しており、再開は予定していない。システムの譲渡については、バグがあって脆弱性があるためソフトウェアを必要としている者がいないと考える。そのため事業譲渡が難しい。そもそも譲渡対象となる事業自体が存在するかが怪しい。
個人情報については第三者に譲渡するつもりはない。個人情報を勝手に譲渡するなという意見を債権者から頂いているため、第三者に提供する予定はない。

Paywardからの支援について

色々な協力に無償でお願いした。どのくらいの範囲までを無償で協力すればいいのかを決めて欲しいとの要望から、500時間を上限と設定した。様々な作業が500時間で終わらない場合はそのタイミングで調整する予定。

カルプレス氏の弁済について、すでに時間が経っているが返済の目処は

通知等を行っているが、資力がないため返せずにいるのだと思われる。返済されないようであれば(資料のとおり)必要な法的措置を取る予定。どのような、いつ行うのかについては未定。

カルプレス氏自身の口から説明して欲しい

現段階では回答を差し控えさせていただく

ビットコインの消失経緯調査結果報告時期は未定とのことだが、債権届出の期間への影響はあるのか

ない

債権届出以後、配当までのスケジュールは

現時点では未定。
平成27年9月9日に債権届出の認識の結果を報告する。そのタイミングで不正な行為があったかの調査、正当な調査結果を踏まえて債権者の債権額を判断する。その後のスケジュールについては現時点では申し上げられない。

保有するビットコインの数が202149.22738490003 BTCとあるが、本当に10桁あるのか。本来のビットコインでは小数点以下8桁までのはずだが

ご指摘感謝。確認する。

Mt.GoxからTIBANNEへ毎月コンサル料として支払われているのではないかとインターネット上で噂になっているが

Mt.GoxからTIBANNEへの支払いはあるが、コンサルではない。Mt.Goxは社員はいないが、TIBANNEがサーバや事務所、従業員を用意して、Mt.Goxがそれ借りている扱いになっていた。
事務所はTIBANNE所有だったので、Mt.Goxは賃料としてTIBANNEに支払っていた。サーバ代も。
現在はMt.GoxはTIBANNEとは異なる事務所に移した。そちらはMt.Goxで借りているのでTIBANNEへの支払いは発生しなくなった。
インターネット接続もTIBANNE経由で払っていたが、現在は直接払っている。
不必要なサーバはやめたりして支払っている。徐々に金額が減っているのはそのため。

ビットコインを現金化して債権者に配当として配る場合、20万ビットコインを捌ける市場が現状ない。また売り出すと事前に宣言すると、それを機にビットコインの価値が暴落する可能性がある。債権者としては歯がゆいので慎重に対応していただきたい

同様のアドバイスを他の方からも頂いている。対応については現在検討中。

預金残高、帳簿残高の調査についてはどうなっているのか。

不正なビットコイン等消失の調査には預金残高、帳簿残高などの調査も含まれている。合わせて調査を実施している。

システムの保全になぜTIBANNEを利用するのか。信用できないではないか

実際にデータの保全・保存を行っているのは富士通、TIBANNEがデータ保全・保存をしているわけではない。
しかし、システムの詳細についてはTIBANNEが把握しているため、TIBANNEに協力してもらう必要がある。

Mt.Goxは社員もサーバも事務所もない、実態がなければ詐欺じゃないのか

裁判所としてはそうは考えていない

過去のMt.Goxの決算書の提出は可能か

検討する

配当のスケジュールは?ざっくりとしたスケジュールも出せないか

5/29までに債権届出、認定が9/9だが、予測するのは難しい。現時点では回答できない。

財産目録、その他に12億円と記載があるが、その他で12億というのはないんじゃないか。

プロバイダ、資金配布する業者、もうひとつは米国で差し押さえがされている5億円が含まれている。

債権届出はビットコインでの届け出になるのか

ビットコインで配当するかどうかも含めて現在検討中だが、ビットコインで配当するとしても、それが債権届出の際の金銭の代わりにはならないと考えている。

カルプレス氏、現在何をしているのか教えて欲しい

現段階では管財人との調整で忙しい

カルプレス氏はフランスに帰るつもりはあるのか

フランスに帰る予定はない

まとめ

第1回のようなカオスな質疑応答にはなりませんでした。
次回は平成27年4月22日(水) 午後1時半からだそうです。

第4回ISUCON本戦でやったこと考えたこと

いい感じにパフォーマンスチューニングするコンテスト第4回ISUCONの本戦に「ご注文はPHPですか?」として参加しました。最終スコアは26位の6598です。途中の最高スコア(remote)は8000強ぐらい。

↑ピンクの線です。

メンバー
アイコン https://pbs.twimg.com/profile_images/1536770974/square1024_2_normal.jpg https://pbs.twimg.com/profile_images/497897656308350976/wKvhLHq8_normal.jpeg https://pbs.twimg.com/profile_images/2704710656/b3e622404badbefd22b2e516bed625d2_normal.png
Twitter @do_aki @matsuu @netmarkjp
職業 インフラエンジニア インフラエンジニア インフラエンジニア
得意言語 PHP Perl Python
当日の役割 右腕 左腕 ファシリテータ
予選のblog こちら こちら こちら
本戦のblog こちら こちら こちら

予選はGo言語で実装しましたが、本戦もGo言語で臨みました。

事前準備(プロファイラ編)

アクセスログを解析するプログラムをnetmarkjpせんせいがPythonで実装したものをGo言語で再実装しました。名前はあとづけですがkataribe(語り部)です。中二病っぽい!

また、ISUCON4予選で辛かったGo環境のプロファイラ周りですが、wall timeベースのお手製プロファイラをnetmarkjpせんせいに作成していただきました。こちらも名前はあとづけですがkagenui(影縫い)です。中二病っぽい!

事前準備(Redis編)

予選から本戦までの間で、ニコニコカドカワ祭りの期間中に購入したRedis入門を片手にRedisのお勉強。

Redis入門 インメモリKVSによる高速データ管理 (アスキー書籍)

Redis入門 インメモリKVSによる高速データ管理 (アスキー書籍)

いやぁこの本、入門どころじゃないですね。すごい。Redisも凄いがこの本も凄い。Redisの可能性を感じました。
この本をざっと読んだあとにISUCON3本戦の問題をRedisで再実装してました。
ISUCON4本戦がRedis実装だったのでキタッ!って思ってたんですが、Redisライブラリとしてredigoで練習していたものの、ISUCON4本戦ではgo-redisが使われてて「お、おう」ってなった件。

GoでRedisを扱うならやっぱりgo-redisなんでしょうか。

やったこと&考えたこと

ざっと列挙するとこんな感じ

プロファイラで動画のレスポンスに時間がかかっていることを確認

Redisから取り出すコストを減らすためにnginxでキャッシュして返そう→実装した。

レポート生成に必要なログがファイルに吐かれている

スケールアウトするためにnginxのアクセスログで同じ内容を出力してsyslogでかき集めればいいんじゃね?
よく調べたらアクセスログだけでは生成が難しい。ログはRedisに流し込もう→実装した

動画はRedisに突っ込みつつ、ファイルを生成するようにするか

突っ込まれたものを非同期にファイル生成を考えたが、自分たちで時間内に実装できる自信がなかった→未実装
素直にファイル出力するようにすればよかったね。

Chunkedで返すような実装があった(が使われてないように見える)

無理矢理にでもChunkedで返せばスコアがあがるのでは?→未実装

MD5でレスポンスが正しいか確認している模様

MD5コリジョンなもっと短いレスポンスを返せばいいんじゃね?→未実装

まとめ

最後のMD5コリジョンを狙うのは我ながら名案だと思ったので、あとで復習しようと思います。

SSLv3亡き今、ciphersuiteはFIPS@STRENGTH:!aNULL:!eNULLでいいんじゃなかろうか

今までSSL(TLS)のciphersuite設定はmozilla wikiのSecurity/Server Side TLS]の記述を個人的に推奨してきましたが、Historyを追ってるとたまに迷走してるし、今の設定が本当に良いのか怪しくなってきたので、もう

FIPS@STRENGTH:!aNULL:!eNULL

でいいんじゃないかと思いました。 FIPS準拠、PCI準拠になるし。
https://matsuu.net/ は2014年10月現在このciphersuiteを実践中です*1

反論お待ちしております。

追記:ciphersuite以外の設定は引き続きmozilla wikiのSecurity/Server Side TLS]を参照するか、Generate Mozilla Security Recommended Web Server Configuration Filesをオススメします。

*1:opensslのバージョンは1.0.1j

第4回ISUCON予選にチーム「ご注文はPHPですか?」で参戦して1日目暫定10位になりましたがPHP使ってません

いい感じにパフォーマンスチューニングするコンテスト第4回ISUCONに参戦しました。まだ現時点で本戦に進めるのかわからないのですが、1日目で暫定10位になりました。

PHPでも十分に戦える!と思った方、ごめんなさい。Go言語使いました。

チーム紹介

チーム名
ご注文はPHPですか?
チーム略称
ごちぺち
予選スコア
44000〜45000ぐらい(暫定)
メンバー
アイコン https://pbs.twimg.com/profile_images/1536770974/square1024_2_normal.jpg https://pbs.twimg.com/profile_images/497897656308350976/wKvhLHq8_normal.jpeg https://pbs.twimg.com/profile_images/2704710656/b3e622404badbefd22b2e516bed625d2_normal.png
Twitter @do_aki @matsuu @netmarkjp
職業 インフラエンジニア インフラエンジニア インフラエンジニア
得意言語 PHP Perl Python
当日の役割 右腕 左腕 ファシリテータ

えぇ、ぺちぱー(PHPer)で有名なdo_aki先生がいるチームですが、Go言語を使いました。

役割分担大事。特にファシリテータ大事です。fujiwara組もたぶんfujiwaraさんがファシリテータだと思います。

Go言語を選んだ理由

ノリと勢い

予選の9日前(9/18)に顔合わせ&作戦会議*1で「どうせならGo言語で出てみる?」となったので。

Go言語の勉強について

Go言語の経験はほとんど無く、9/18からA Tour of Goを始めた程度の素人。
9/20あたりから前回のISUCON3予選のAMIに含まれてるGo実装でチューニング実践してみた程度。三人ともISUCON出場経験がはあったのでチューニングはなんとかなりました。ISUCON3予選問題のチューニング結果は50000ぐらい。Go言語つええええ。

ISUCON3の予選問題はGo言語の勉強に最適ですよ奥さん。

今回の予選の対応方法

基本的にnginxのアクセスログとにらめっこです。

アクセスログ応答時間を出力するようにして、リクエスURIごとのトータル時間、アクセス回数、平均応答時間を算出する簡単なスクリプトを用意。その数字をみて、どのリクエストを改善すべきかを決定していきました。

いきなりソースを見たり、topやdstatなどでボトルネックを調べたりしたくなるんだけどもそこはグッと抑える。これは過去にISUCONに出た経験から導き出されたやり方でした。

ソースの編集について

幸い全員Vim使いで、ターミナル上で編集することに抵抗がないので、3人とも1台のインスタンスSSH接続、役割分担しながらプログラムや設定などを書き換えていく感じでした。
BitBucket上のgitにリポジトリを作りましたが、そこからデプロイ&継続的インテグレーションの類は使ってません。サーバ上で編集したものを同じユーザ名でcommit&pushした程度です。

また、リポジトリを一応用意しましたが、綺麗に保つ努力はしませんでした。時間がもったいないから。main.go.hogeファイルとか平気で作ってました。短時間決戦なので気にしない。

どんな実装になったか

ミドルウェアはGoに変えた以外殆ど変わってません。nginx+Go+MySQLです。NginxとMySQLのバージョンアップもしませんでした。

できるだけ前の方で返すべく以下のような実装にしました。

  • スタイルシートや画像ファイルなどの静的ファイルはnginxから返す
  • ログイン失敗でbanされたIP/ユーザをチェックするためにlogin_logをSELECTしている部分は、ログイン失敗した回数をGo上でカウント、banされたリストもGo言語上で保持してMySQLを参照しない*2
  • usersテーブルは初回のデータ投入以降増えないので、初回に全部Go実装上にキャッシュしてGoで返す
  • 最終ログイン日時もユーザ毎にGo上で記録しておき、Go上で返す
  • トップページは出力パターンが4パターンしかないので、4パターンの静的HTMLファイルを生成しておき、nginxでCookieの値を見てrewriteして静的ファイルを返す

それぞれの修正を適用するたびにアクセスログ応答時間を見て遅いリクエストを改善していく感じですね。

結果としてこのような対策になったので、今回MySQLのチューニングは殆どやってません。my.cnfの設定も大した設定は追加してないし、インデックスも結果的には何も追加しませんでした。

なお、プログラム以外の具体的な変更内容はnetmarkjp先生がブログに詳しくかかれているのでそちらをご参照ください。

便利情報

いくつかピックアップ

BitBucketは無料でプライベートなgitリポジトリを作れる

情報をもらさずにリポジトリを共有できて便利

BitBucketのプライベートなgitリポジトリと連携できるCIはWerckerが便利

wercker、便利ですよ!今回使ってないけど。boxにwercker/golangを使えばGo1.3系をにも対応してます。

Vimで同じファイル複数人で開きたいけどreadonlyでいい場合は-Rオプションが便利

vim -Rで最初からreadonlyで開くことができるので邪魔せずに便利

mysqltuner.plが便利

MySQLのざっとしたチューニングはこれを少し参考にしてます。

curl http://mysqltuner.pl > mysqltuner.pl
perl mysqltuner.pl

でも今回は殆ど使わなかった。

iotopコマンドが便利

disk ioを発生させているプロセスが何かわかります。

yum install -y iotop
iotop -o
dstatのオプションは-tlamp -N loが便利

今回は1台構成でloしか使わないので-N loをつけると便利です。

yum install -y dstat
dstat -tlamp -N lo

loの通信量が多くなれば、おそらくたくさん捌けてるんだな(スコアがあがるかもな)と判断できます。

Goのつらかったこと

いくつかピックアップ

経験が浅い

基礎的なことを把握してなかった。例えばinit()ってどこでどう呼ばれるのか知らなかった。

使えるプロファイラがない

pprofはCPU時間ベースのプロファイリングやchannelによるblock頻度を出力できるものの、Go以外の理由(mysqlなど)で待ちになった場合も含めて簡単にプロファイリングする術を見つけられませんでした。

なんとかNitroなるものを見つけてこれをtimer代わりにStepで調査してたのですが、Goroutineを使いはじめると破綻するし、アクセスが増えた場合の調査が難しいので結局あまり使えず。いいソリューションないですかね。

まとめ

よく言われる「推測するな、計測せよ」ですね。
dstatやtopを見てると計測してる気になるんですが、計測すべきはスコアに直結する応答時間でした、って感じです。

*1:作戦会議という名の飲み会

*2:login_logは最初からデータが入っているのでそのデータもキャッシュしておく必要がある

DockerでPublic JNetHack serverを立ててみた

Dockerfileの練習も兼ねて、DockerでPublic JNetHack serverを立ててみました。UTF-8対応のtelnetクライアントを用意して、

telnet nethack.matsuu.net

JNetHackをプレイできます。全プレーヤー統一ランキング機能があるみたいです。
詳しくはこちら → https://matsuu.net/nethack/

Docker環境があれば誰でもPublic JNetHack serverを用意できます

Docker Hubに登録したので、誰でもサーバを用意できます。

docker run --detach --publish=23:23 matsuu/jnethack-server

同じインスタンスを使っている限りはアカウントとセーブデータは残ります。

詳しくはこちら → https://github.com/matsuu/docker-jnethack-server

手元でこっそりプレイするためのDockerfileも用意しました

こちらもDocker Hubに登録したのですぐにプレイが可能です。

docker run -it matsuu/jnethack

毎回上記コマンドで起動するとランキングが保存されないのでよしなに頑張って下さい。

詳しくはこちら → https://github.com/matsuu/docker-jnethack

nginx-1.7.1でsyslogにログを飛ばせるようになったので試してみた

nginxのアクセスログやエラーログをsyslogに直接飛ばす機能は商用版のNGINX Plusでのみ提供されていたのだが、1.7.1でオープンソース版にもその機能が取り込まれた。

CHANGES

Changes with nginx 1.7.1                                         27 May 2014

    *) Feature: the "error_log" and "access_log" directives now support
       logging to syslog.

早速試してみた。

docker-nginx

syslogサーバのホスト名は仮にlogserverとする。

Dockerfile
FROM centos:latest
ADD nginx.repo /etc/yum.repos.d/
RUN yum install -y nginx
ADD access_log.conf /etc/nginx/conf.d/
EXPOSE 80
CMD ["/usr/sbin/nginx", "-g", "daemon off; error_log syslog:server=logserver,facility=local2 notice;"]
nginx.repo
[nginx]
name=nginx repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=0
enabled=1
access_log.conf
access_log syslog:server=logserver,facility=local1 main;

具体的な書式は公式のDocumentationを参照

docker-rsyslog

syslogを受けるサーバはこんな感じか。

Dockerfile
FROM centos:latest
RUN yum install -y rsyslog
ADD remote.conf /etc/rsyslog.d/
CMD ["/sbin/rsyslogd", "-c5", "-n"]
remote.conf
$ModLoad imudp
$UDPServerRun 514
$AllowedSender UDP, 127.0.0.0/8, 10.0.0.0/8, 172.16.0.0/12, 192.168.0.0/16

local1.* /var/log/nginx_access_log
local2.* /var/log/nginx_error_log

AllowedSenderで0/0が書けなかったのでなんかダサい。もっと良い書き方ないものか。

動作確認

アクセスログ

Jun  3 10:53:33 c65d458cb3e9 nginx: 127.0.0.1 - - [03/Jun/2014:10:53:33 -0400] "GET / HTTP/1.1" 200 612 "-" "curl/7.19.7 (x86_64-redhat-linux-gnu) libcurl/7.19.7 NSS/3.13.6.0 zlib/1.2.3 libidn/1.18 libssh2/1.4.2"

エラーログ

Jun  3 10:53:23 c65d458cb3e9 nginx: 2014/06/03 10:53:23 [notice] 23#0: start worker processes
Jun  3 10:53:23 c65d458cb3e9 nginx: 2014/06/03 10:53:23 [notice] 23#0: start worker process 25

いいじゃないか、と思うでしょう。しかしsyslogには1行あたりの文字数制限があるため、長いログだとお尻が途切れて残念なことになる。

Jun  3 11:42:42 c65d458cb3e9 nginx: 127.0.0.1 - - [03/Jun/2014:11:42:42 -0400] "GET /12345678901234(中略)012345678

syslog自体は2048文字あたりが上限になるようだが、手元で試した限りは2043文字が上限になった。このあたりの詳細は調べてない。

nginxの派生で独自にsyslog対応されているTengineでも試したが、2043文字あたりが上限になるのは同じだった。syslogの制約だからそりゃそうか。

まとめ

ログをコンテナ内に蓄積しないことでよりImmutable Infrastructureっぽくなるし、1コンテナ1プロセスを実現できていいのだがsyslogには文字数制限があるので注意。

ちなみにnginxから直接fluentdに飛ばせるnginx-fluentd-moduleも試したのだが、受信側fluentdにfluent-plugin-udpが必要なのはまぁ良いとしても、記号などのエスケープ処理周りが怪しい感じで若干微妙だった。こちらもその内紹介できればと思う。

追記