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.cgi を CGI スクリプトとして処理したいけれども、 bar.cgi.html は CGI スクリプトとしては処理したくない場合、 AddHandler cgi-script .cgi とする代わりに 次のようにしてください
Configure handler based on final extension only<FilesMatch \.cgi$> SetHandler cgi-script </FilesMatch>
つまり仕様です。
あなたのサイト、大丈夫?
RHELやCentOSで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/CentOSのphp.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回も参加していました。
債権者集会での配布資料は既に公開されていますが、その場にいないとわからない質疑応答について以下に走り書きのメモを残しておきます。
内容については正確ではない可能性があります。ちなみにマイクやカメラによる記録は禁止でした。
Paywardに協力を仰ぐとのことだが、どのように組織されて調査されているのか
トーマツを中心に調査している段階。
データに不完全性がみられるため調査が難航している。
ただ、Payward、Krakenさんにご協力頂いて調査しようとしているところ。
何時頃にどういう結論がでるかについては、今の段階ではわからない。
調査の進行次第。ただ、私どもとして調査を真剣に真摯に進めていく。
ビットコインアドレスの公開について
調査に支障がないようであれば開示しようと考えている段階であったが、
調査に支障があるかがポイント。警視庁から要請があったため開示していない。
開示できるのか?いつなのか?についてははっきりしたことはわからない。
トーマツとPaywardと相談の上、可能であれば開示したい。
Paywardとの契約内容についてWebサイトで開示されるのか
ご意見として承るが、開示することに支障があるのかは確認が必要。総合的に考えて開示できるかどうかを検討したい。
Mt.Goxの事業自体はどうなるのか。Paywardが譲り受けるわけではないようだが、Paywardとしては3000万円でライバルを潰した形にみえる
継続している・保有している事業とはなにかが焦点になる。取引所は閉鎖しており、再開は予定していない。システムの譲渡については、バグがあって脆弱性があるためソフトウェアを必要としている者がいないと考える。そのため事業譲渡が難しい。そもそも譲渡対象となる事業自体が存在するかが怪しい。
個人情報については第三者に譲渡するつもりはない。個人情報を勝手に譲渡するなという意見を債権者から頂いているため、第三者に提供する予定はない。
Paywardからの支援について
色々な協力に無償でお願いした。どのくらいの範囲までを無償で協力すればいいのかを決めて欲しいとの要望から、500時間を上限と設定した。様々な作業が500時間で終わらない場合はそのタイミングで調整する予定。
カルプレス氏の弁済について、すでに時間が経っているが返済の目処は
通知等を行っているが、資力がないため返せずにいるのだと思われる。返済されないようであれば(資料のとおり)必要な法的措置を取る予定。どのような、いつ行うのかについては未定。
カルプレス氏自身の口から説明して欲しい
現段階では回答を差し控えさせていただく
ビットコインの消失経緯調査結果報告時期は未定とのことだが、債権届出の期間への影響はあるのか
ない
債権届出以後、配当までのスケジュールは
現時点では未定。
平成27年9月9日に債権届出の認識の結果を報告する。そのタイミングで不正な行為があったかの調査、正当な調査結果を踏まえて債権者の債権額を判断する。その後のスケジュールについては現時点では申し上げられない。
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強ぐらい。
↑ピンクの線です。
メンバー
アイコン | |||
---|---|---|---|
@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による高速データ管理 (アスキー書籍)
- 作者: Josiah L. Carlson,長尾高弘
- 出版社/メーカー: KADOKAWA / アスキー・メディアワークス
- 発売日: 2014/01/16
- メディア: Kindle版
- この商品を含むブログを見る
この本をざっと読んだあとにISUCON3本戦の問題をRedisで再実装してました。
ISUCON4本戦がRedis実装だったのでキタッ!って思ってたんですが、Redisライブラリとしてredigoで練習していたものの、ISUCON4本戦ではgo-redisが使われてて「お、おう」ってなった件。
GoでRedisを扱うならやっぱりgo-redisなんでしょうか。
やったこと&考えたこと
ざっと列挙するとこんな感じ
プロファイラで動画のレスポンスに時間がかかっていることを確認
Redisから取り出すコストを減らすためにnginxでキャッシュして返そう→実装した。
レポート生成に必要なログがファイルに吐かれている
スケールアウトするためにnginxのアクセスログで同じ内容を出力してsyslogでかき集めればいいんじゃね?
よく調べたらアクセスログだけでは生成が難しい。ログはRedisに流し込もう→実装した
動画はRedisに突っ込みつつ、ファイルを生成するようにするか
突っ込まれたものを非同期にファイル生成を考えたが、自分たちで時間内に実装できる自信がなかった→未実装
素直にファイル出力するようにすればよかったね。
Chunkedで返すような実装があった(が使われてないように見える)
無理矢理にでもChunkedで返せばスコアがあがるのでは?→未実装
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ぐらい(暫定)
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リポジトリと連携できるCIはWerckerが便利
wercker、便利ですよ!今回使ってないけど。boxにwercker/golangを使えばGo1.3系をにも対応してます。
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()ってどこでどう呼ばれるのか知らなかった。
まとめ
よく言われる「推測するな、計測せよ」ですね。
dstatやtopを見てると計測してる気になるんですが、計測すべきはスコアに直結する応答時間でした、って感じです。
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
同じインスタンスを使っている限りはアカウントとセーブデータは残ります。
手元でこっそりプレイするためのDockerfileも用意しました
こちらもDocker Hubに登録したのですぐにプレイが可能です。
docker run -it matsuu/jnethack
毎回上記コマンドで起動するとランキングが保存されないのでよしなに頑張って下さい。
nginx-1.7.1でsyslogにログを飛ばせるようになったので試してみた
nginxのアクセスログやエラーログをsyslogに直接飛ばす機能は商用版のNGINX Plusでのみ提供されていたのだが、1.7.1でオープンソース版にもその機能が取り込まれた。
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
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が必要なのはまぁ良いとしても、記号などのエスケープ処理周りが怪しい感じで若干微妙だった。こちらもその内紹介できればと思う。
追記
@matsuu nginxのsyslog出力はNGX_MAX_ERROR_STR(2048で定義)にsyslogのヘッダを加えた文字数のバッファを持っていて、色々プラマイして実質2000文字前後ですね。
— Takashi Takizawa (@ttkzw) 2014, 6月 3