Displaying posts filed under

未分類

RedmineでGitのリモートリポジトリを参照

Redmineでブラウズの対象とするには local かつ bare なリポジトリでなければならないので、そのままでは使えない。そこでまず対象リポジトリのミラーとなるbareリポジトリを作る。

git clone --bare git://host/path.git
cd path
git remote add --mirror origin git://host/path.git

最近のバージョンの git では clone のオプションに –mirror を直接指定することができるらしいが、1.5.6 では上の手順が必要だった。

# git-1.6.0.6以降
git clone --mirror git://host/path.git

リポジトリを同期するには、ミラーリポジトリ内で fetch を実行する。cronで定期的に実行するよう設定しておけば実用上は十分だろう。

git fetch origin

あとはこのミラーリポジトリのパスをRedmineに設定しておく。

異なるブランチを使用する

Redmineの設定画面にはブランチ名の項目は無い。
lib/redmine/scm/adapters/git_adapter.rb
をチェックしたところ、常に”現在の”ブランチが使用されるようだ。

@branch ||= shellout("#{GIT_BIN} --git-dir #{target('')} branch") { |io| io.grep(/\*/)[0].strip.match(/\* (.*)/)[1] }

改造するのも面倒なので、異なるブランチには異なるリポジトリを割り当てることにした。上と全く同じ手順で bare リポジトリを作った後、HEADファイル内の参照を書き換える(bareリポジトリ なので checkout は使用できない)。

ref: refs/heads/your_branch

fetch の手順などは全く同じで良い。

海外ETFの本

タイトルはちょっとアレだが、至極真っ当な本。インデックス連動型の海外ETFを買って、世界経済の成長に参加しよう!というお話。敢えて一文、本書の肝となる主張を抜き出すとしたら、次の文だろうか(258ページ):

長期的にみて、世界経済が発展する限り、市場は全体として右肩上がりになります。

この理屈が理解できなかったせいで、私にとって長らく投資という行為は胡散臭い儲け話と区別がつかなかった。いや、多分今でも心の底では理解できていないと思う。失われた10年に青春を過ごした私(たちの世代)にとって、世の中というのは「短期的な上下を繰り返しながらも、緩やかに下降していく」ものだという認識が染みついているので、株価であれ、何らかの指数であれ、投資信託の基準価格であれ、中長期的に右肩上がりに上昇し続けるというのは、鼻で笑ってしまうような馬鹿げた幻想にしか思えないのだ。……むしろそういう世界観を相対化してみたくて、今の私は投資を行っているのかも知れない。

それで海外ETFだが、実際に買おうと思うと、やはり普通の投資信託よりもいろいろと敷居が高くて躊躇している。特に面倒なのが税金。海外ETFは海外株式と同じ扱いになるため、手数料の安いネット証券では特定口座が利用できない。ならば自分で確定申告を、と考えて調べてみると、これがよく分からない。売買差益が譲渡所得で申告分離課税、為替差益が雑所得で総合課税という基本は簡単なのだが、ここで日本円を米ドルに換えて、ここで○○ドルでETFを買って、ここで××ドル分を売却したとして……というリアルなシナリオに沿って考えていくと、いつどのレートでどういう所得が発生するのか、頭がこんがらがってくる。

他にも、これは本にも書いてあることだが、ETFは最低取引金額がまだ高いし、購入する際の手数料もかかるので、小額ずつ積み立てて行くのには向いていない。やはり当面は普通の投資信託で積み立てていくのが簡単そうだ。本書執筆時点では存在していなかったMSCI エマージング・マーケット・インデックスに連動するインデックスファンドも登場したことだし……。

mymemcheckをCentOSで動かす

サーバ/インフラを支える技術』に載っていた mymemcheck を試してみようと思って CentOS 5 上で実行してみたところ、いくつかの Perl モジュールが足りなくて動かなかった。例によって rpmforge で検索してみたら、やはり見つかった。

sudo yum --enablerepo=rpmforge install perl-Readonly perl-UNIVERSAL-require

相変わらず便利過ぎるぜ rpmforge。

mod_dosdetector の使い方

サーバ/インフラを支える技術』で知ったDoS攻撃判定モジュール mod_dosdetector の使い方。mod_dosdetecotr のバージョンは 0.2、環境は Apache 2.2.3 @ CentOS 5。

改造版も公開しています。

インストール

wget http://ncu.dl.sourceforge.net/sourceforge/moddosdetector/mod_dosdetector-0.2.tar.gz
tar xvzf mod_dosdetector-0.2.tar.gz
cd mod_dosdetector-0.2
make
sudo make install

httpd.conf 設定例

# 実際にはこの一行は make install で追加される
LoadModule dosdetector_module modules/mod_dosdetector.so
 
DoSDetection     on
DoSPeriod        5
DoSThreshold     10
DoSHardThreshold 25
DoSBanPeriod     30
DoSTableSize     100
DoSIgnoreContentType  image|javascript|css

DoS判定の肝となる数値は DoSPeriod, DoSThreshold, DoSHardThreshold, DoSBanPeriod の4つで、上の例ではだいたい次のような意味になる:

  1. 同一IPアドレスから5秒間に10回以上のアクセスがあった場合「DoS攻撃の疑いあり」と見なし、その後30秒間のアクセスに対しては環境変数 SuspectDoS をセットする(値は”1″)
  2. さらに5秒間のアクセス回数が25回に達した場合、「激しいDoS攻撃の疑い」と見なし、環境変数 SuspectHardDoS もセットする(値は”1″)
  3. 初めに「DoS攻撃の疑いあり」と判定してから30秒が経過したら、次のアクセスでもう一度判定をやり直す。直近5秒のアクセスが10回を下回っていれば、疑いは晴れる

アクセス数の計測はファイルの種類・有無を問わずに行われるため、デフォルトではページ内の画像やCSSなども計測対象となってしまう。それらを除外したい場合は、DoSIgnoreContentType ディレクティブで除外したいファイルの MIME type を正規表現で指定しておく(ファイル名(URL)ではないので注意)。各種画像ファイル・JavaScript・CSSファイルを除外したい場合は上例のように設定しておけば良い。

ただし多くの環境では拡張子 ico に対する MIME type の指定は行われていないはずなので、そのままだと favicon.ico が text/plain 等と見なされて除外されない(.ico に限らず、未設定の場合は httpd.conf の DefaultType になる)。次のように AddType を追加しておけば image と判定される。

AddType  image/vnd.microsoft.icon  .ico

ちなみにこれがアイコンファイルの正式な MIME type である。

DoS攻撃に対する防御設定

mod_dosdetector が行うのはあくまでも攻撃の”検出”だけなので、防御する方法はまた別に設定する必要がある。多くの場合は mod_rewrite と併用することになるだろう。例えば「激しいDoS攻撃の疑い」なアクセスに対してステータスコード503 + 静的なHTMLを返す場合は次のように設定する(Apache 2.2 only)。

RewriteEngine On
RewriteCond %{ENV:SuspectHardDoS} =1
RewriteRule .*  - [R=503,L]
 
ErrorDocument 503 /server_is_busy.html

しかし現実には、攻撃の判定とその後の防御は、匙加減が難しい。どの程度のアクセスを攻撃と見なすかはサイトによって千差万別だろうし、あまりに頻繁・過剰な反応をしてしまうとユーザが離れてしまう。

そこで個人的には、まず厳し目の設定を行って、ログを取ってみることをおすすめする。「DoS攻撃の疑いあり」なアクセスを普通のログと分けて記録するには次のように設定する。

LogFormat "%{SuspectHardDoS}e %h %l %u %t \"%r\" %>s %b \"%{Referer}i\" \"%{User-Agent}i\"" dos_suspect
CustomLog logs/dos_suspect_log dos_suspect env=SuspectDoS

ログの行頭に環境変数 SuspectHardDoS が記録されるため、どのような経過をたどって「疑いあり」から「激しい攻撃の疑い」へと移行したかも分かる。

後はこの記録を見つつ、通常のアクセスが引っかからないような適当な設定を探ることになる。もしサーバリソースの都合上、どうしても通常のアクセスが引っかてしまう可能性があるのなら、その時は防御方法をより穏当なものに設定することもできる(このあたりの柔軟性は mod_dosdetector の設計の妙だと思う)。

その他

上で触れなかったディレクティブについて少々:

DoSDetection
DoS判定機能の有効・無効を設定。on で有効
DoSTableSize
クライアントの追跡記録の最大保存数。この数値を大きくすればより多くのクライアントを同時に追跡できるが、メモリ使用量と負荷が上昇する
DoSShmemName
クライアントの追跡記録を保存しておくための共有メモリの名前。普通は設定する必要は無いはず

最後に

素晴らしいソフトウェアをオープンソースとして公開してくださった田中慎司さん(そして株式会社はてな)に感謝!

Apache 2.2ではmod_rewriteのRフラグで任意のステータスコードを返せる

昔Apache 2.0系で試したときは無理だったのに、2.2系ではできるようになっていたのか。

mod_rewriteで503 – Do You PHP はてな

上エントリーで引用されているドキュメントは古くて、現在は次のような記述に置き換わっている。

While this is typically used for redirects, any valid status code can be given here. If the status code is outside the redirect range (300-399), then the Substitution string is dropped and rewriting is stopped as if the L flag was used.

mod_rewrite – Apache HTTP Server

『このフラグは通常リダイレクトのために用いられるが、任意の妥当なステータスコードを指定することができる。もしリダイレクト以外のステータスコード(すなわち300〜399以外)が指定された場合、置換文字列は無視され、さらにLフラグが指定されたときと同じようにURLの書き換えが停止される。』

つまりリダイレクトもURLの書き換えも行われないので、デフォルトのエラー画面以外を表示するには ErrorDocument ディレクティブで指定しておく必要がある。

RewriteEngine On
RewriteCond %{some_condition} =1
RewriteRule .*  - [R=503]
 
ErrorDocument 503 /server_is_busy.html

ソースに付属している文書(CHANGES)によれば、この仕様に変わったのはバージョン2.1.1。Bugzillaで以下のような議論も見つけた。

In the <300, >=400 cases, one can think of this as [R{esponse}=nnn} as opposed to [R{edirect}], and it really harms nothing to overload it.

Bug 45478 – R flag in RewriteRule does not honor 400 and 500 range error code

Redirect の ‘R’ ではなく Response の ‘R’ と見なしてくれ、と。なるほど…。

BlockHosts の導入

ブルートフォースアタックからの防衛ツール BlockHosts 導入手順。環境は CentOS 4。

インストール

rpmで導入する場合

wget http://www.aczoom.com/tools/blockhosts/BlockHosts-2.4.0-1.noarch.rpm
sudo rpm -Uvh BlockHosts-2.4.0-1.noarch.rpm

もしくはソースからインストールする場合

wget http://www.aczoom.com/tools/blockhosts/BlockHosts-2.4.0.tar.gz
tar xvzf BlockHosts-2.4.0.tar.gz
cd BlockHosts-2.4.0
sudo python setup.py install

どちらの方法を使っても、設定ファイルは /etc/blockhosts.cfg にインストールされるし、ログローテーションのための設定ファイル /etc/logrotate.d/blockhosts もインストールされる。

/etc/blockhosts.cfg の設定

まずは最低限の設定を行う。CentOS ならほとんどの場合はデフォルトで良いと思うが、

HOSTS_BLOCKFILE = "/etc/hosts.allow"
WHITELIST = [ "127.0.0.1", "192\.168\.2\..*", ]
LOGFILES = [ "/var/log/secure", ]

このあたりは明示的に設定しておいた方が良いと思う。WHITELIST に追加する設定は自分の環境にあわせて。

/etc/hosts.allow に設定追加

こちらもまずは最低限の情報を書いて、動作確認をする。

#---- BlockHosts Additions
#---- BlockHosts Additions

この状態で以下のコマンドを実行し、正しく解析結果が表示されることを確認。

sudo blockhosts.py --verbose --dry-run

次に –dry-run オプションを外し、/etc/hosts.allow の書き換えが正しく行われることを確認する(BlockHosts Additions の間に情報が書き込まれる)。

sudo blockhosts.py --verbose

最後に /etc/hosts.allow の末尾に blockhosts.py の起動設定を追加する。以下は一例

sshd: ALL: spawn /usr/bin/blockhosts.py --verbose --echo "%c-%s" >> /var/log/blockhosts.log 2>&1 : allow

その後の設定

ほとんどの設定は /etc/blockhosts.cfg の中でも、blockhosts.py のコマンドラインオプションとしても(つまり /etc/hosts.allow の中でも)設定できる。詳しくは blockhosts.cfg の中のコメントや blockhosts.py –help を参照。

試していないが、「ipblock」の設定を行うことで、TCP/IP レベルでのブロックも行えるようだ。ip コマンドで無効なルートを設定するか、iptables でフィルタリングするか選べるらしい。blockhosts.cfg より:

#IPBLOCK = "" # (default)
#IPBLOCK = "ip route" # or use full path "/sbin/ip route"
#IPBLOCK = "iptables" # or use full path "/sbin/iptables"
# "ip route": Do TCP/IP blocking using route commands to setup null-routes.
#    ip route add  via 127.0.0.1
# "iptables": Do TCP/IP blocking, using iptables packet filtering.
#    iptables --append blockhosts --source  -j DROP

cciss経由で取得したHDDの温度をmuninでグラフ化

CCISS (HP/Compaq Smart Array Controller) に接続された HDD の SMART 情報を読み出し、温度を munin の hddtemp_smartctl プラグインでグラフ化する。

cciss に対応する smartmontools は 5.38 以降(stable)。CentOS 5.3 では標準でこのバージョンがインストールされるが、あいにく対象サーバはCentOS 4だったので、ソースからインストールした。

tar xvzf smartmontools-5.38.tar.gz
cd smartmontools-5.38
./configure
make
sudo make install

/usr/local/sbin に新たにインストールされた smartctl を使用して、温度その他の情報が取得できることを確認。以下表示例。

$ sudo /usr/local/sbin/smartctl -A -d cciss,0 /dev/cciss/c0d0
smartctl version 5.38 [i686-pc-linux-gnu] Copyright (C) 2002-8 Bruce Allen
Home page is http://smartmontools.sourceforge.net/

Current Drive Temperature:     26 C
Drive Trip Temperature:        65 C
Manufactured in week 50 of year 2006
Recommended maximum start stop count:  10000 times
Current start stop count:      19 times
Elements in grown defect list: 0

続いてmunin のプラグイン設定ファイル(/etc/munin/plugin-conf.d/hddtemp_smartctl )に設定を追加する。デバイス名の後に _[番号] を付けるのがポイント。

[hddtemp_smartctl]
user root
env.smartctl    /usr/local/sbin/smartctl
env.drives      cciss/c0d0_0 cciss/c0d0_1
env.type_cciss/c0d0_0  cciss,0
env.type_cciss/c0d0_1  cciss,1

これで値が取得できるようになる…のだが、うまくグラフが表示されない。デバイス名に / が含まれているのがまずいらしいので、プラグインファイル /usr/share/munin/plugins/hddtemp_smartctl を少し改造。munin-node-1.2.5用のパッチを置いておく。

こんな感じで表示されるようになる。

hddtemp_smartctlによるグラフ表示

hddtemp_smartctlによるグラフ

visitors でリモートホストの集計

高速・軽量なアクセス解析ツール visitors およびその日本語化バージョン。素晴らしいツールなのだが、デフォルトではアクセス元ドメインの集計が全て「numeric IP」になってしまうのが難点だった。

そこで日本語化バージョンを元に、まずはIPアドレスごとに集計を行うよう修正した(パッチダウンロード)。

diff -ur visitors_0.7.orig/visitors.c visitors_0.7/visitors.c
--- visitors_0.7.orig/visitors.c	2007-08-20 19:11:54.000000000 +0900
+++ visitors_0.7/visitors.c	2009-03-28 17:38:59.000000000 +0900
@@ -1607,13 +1607,9 @@
 	char *tld;
 	int res;
 
-	if (vi_is_numeric_address(hostname)) {
-		tld = "numeric IP";
-	} else {
-		tld = strrchr(hostname, '.');
-		if (!tld) return 0;
-		tld++;
-	}
+	tld = hostname;
+	if (!tld) return 0;
+
 	res = vi_counter_incr(&vih->tld, tld);
 	if (res == 0) return 1;
 	return 0;

あとは出力時に逆引きを行えば良い。本当は visitors.c 内で行うように修正すべきなんだろうが、よく分からないのでPerlのワンライナーで変換することにした(下例ではIPアドレスっぽいテキストを全て変換してしまうので、もう少し真面目に書いた方が良いとは思うが……)。

visitors -A -m 45 -o html access_log | perl -pe \
's%(\d{1,3}\.){3}\d{1,3}%gethostbyaddr(pack("C4", split(/\./, $&)), 2) || $&%e' \
> out.html

元々 visitors のこの機能は、トップレベルドメインを集計して国別のアクセス傾向を知るためのものなので、リモートホストの集計に用いるのは邪道かも知れない。しかし実用上はこの方が役に立つ機会は多いと思う。

この改造にあたっては以下のページを参考にした:

こちらではまずアクセスログに記録されたIPアドレスを全て逆引きする方法を紹介されているが、ログが何十万行もある場合は逆引きに時間がかかり過ぎる……。この用途に限って言えば、IPアドレスで集計して上位のアドレスだけ逆引きするという方針で十分だろう。

OpenX のインストール(日本語対応)

オープンソースの広告配信サーバ OpenX。バージョン2.6からは日本語リソースファイルもデフォルトで含まれているが、若干問題が残っている。

以下、OpenX 2.6.4 を $OPENX_PATH に www.example.com というドメインでインストールした場合の説明。MySQLは 5.0 系を使用。

データベースの文字コード設定

インストール完了後、管理画面からデータを追加する前に設定ファイルを修正する。修正すべきファイルは
$OPENX_PATH/var/www.example.com.conf.php
このファイルの中の clientCharset を utf8 に変更する。デフォルトでは多分 latin1 になっているはず。

[databaseCharset]
checkComplete=1
clientCharset=utf8

この設定をしておかないと「一見正常に動いているがDB内部では文字列が壊れている」という状態になる。

Excelの文字化け修正

デフォルトではレポート画面で出力できるExcelファイルが文字化けする。これは OpenX が内部で使用しているPEARパッケージ Spreadsheet_Excel_Writer の問題。バグレポートからパッチを落としてきて適用する。

cd $OPENX_PATH
patch -p0 < excel-all-in-one-patch.diff

ちなみにこのパッチは私が投稿したものだが、フォーラムで紹介されていた複数のパッチを一つにまとめただけで、修正の内容は理解していない。また mbstring が必須となっているため、このまま本体に取り込まれる可能性はまずないと思われる。

CentOSで最新のPHP 5.2を使用する

サードパーティのリポジトリを利用することで、2009年3月20日現在最新のphp-5.2.9をyumでインストールすることができる。リポジトリ管理者の素晴らしい仕事には頭が下がるばかりだ…。

注意:この方法でインストールされる php-mysql は MySQL 5.1.30 の libmysqlclient とリンクされる。

English : Repository Configuration – Les RPM de Remiに従ってEPELとLes RPM de Remiのリポジトリを追加。CentOS 5の場合は

wget http://download.fedora.redhat.com/pub/epel/5/i386/epel-release-5-2.noarch.rpm
wget http://rpms.famillecollet.com/el5.i386/remi-release-5-6.el5.remi.noarch.rpm
rpm -Uvh remi-release-5*.rpm epel-release-5*.rpm

php-mysql をインストールする場合は、予め remi-test リポジトリから mysqlclient16 パッケージをインストールしておく。

sudo yum --enablerepo=remi-test install mysqlclient16

自分が必要とするパッケージをインストールする(パッケージによってはEPEL内のパッケージに依存することがある)。

sudo yum --enablerepo=epel,remi install php php-cli php-mysql php-gd

インストール後はリポジトリ管理者のブログLes RPM de Remiを常にチェックしておくことをおすすめする。PHPの新しいバージョンが出た場合、今までは数日中には対応されてきた。しかしアップデートに伴って、時々パッケージの構成が変わったりライブラリのバージョンが変わったりして、すんなりアップデートできなくなることもあった。そのあたりは自己責任で。