ラベル debian の投稿を表示しています。 すべての投稿を表示
ラベル debian の投稿を表示しています。 すべての投稿を表示

2013/05/05

RaspberryPiでLVS+keepalivedを使ってHA構成にしてみた

RaspberryPiは手軽なLinux実行環境ですが、定格で5V/700mAが必要です。 古いPCやUSBハブに接続した場合には、うまく動かない可能性があります。

iPadやタブレットで充電に1000mA(==1A)が必要な状況なので、それほどUSBの電源周りも余裕のある設計になっているものも多くあるはずです。

とはいえ、USB2の定格は5V/500mAなので古めのPCや電源付きUSBハブにいろいろな機器を接続した場合には動作が不安定になる可能性があります。

またカーネルに3.6-trunk-rpiを選択した時には、2013年5月5日時点では、ファイルシステムに負荷をかけるようなタイミングでBUG: scheduling while atomic: swapper/...のエラーが出てまともに動きませんでした。

対応linuxカーネルの有効化

基本的な環境はarmelhfアーキテクチャのRaspbian "wheezy" をインストールした状態です。

Raspbianのカーネルは3.6.11#371版ですが、ip_vsモジュールなどは導入されていません。

このためパッケージからip_vsモジュールの含まれているイメージを導入します。

$ sudo apt-get install linux-image-3.2.0-4-rpi
起動時のカーネルイメージの変更

linux-image-*パッケージを導入しただけでは、再起動をしても引き続きRaspbianの付属カーネルが使われます。 ポイントは次のとおりです。

  • zImageを/boot/kernel.imgのファイル名でコピーする
  • initrdイメージがある場合は/boot/config.txtに記入する
/boot/kernel.imgファイルの置き換え

既存のkernel.imgファイルは退避して、vmlinuz-3.6-trunk-rpiファイルをコピーします。

$ cd /boot
$ sudo mv kernel.img kernel.3.6.11#371.img
$ sudo cp vmlinuz-3.2.0-4-rpi kernel.img

ちなみに/bootはvfatなので、ハードリンクなどを使う事はできません。 基本的にはcopyで対応することになります。

/boot/config.txtファイルの書き換え

initrdを使用している場合には、対象のファイル名をconfig.txtに書き換えます。

...
ramfsfile=initrd.img-3.2.0-4-rpi
ramfsaddr=0x00a00000
initramfs initrd.img-3.2.0-4-rpi 0x00a00000
...

ちゃんと確認していませんが、/bootにあるものとしてファイル名だけを記述しています。

再起動でカーネルの確認

とりあえず再起動して動作を確認します。

うまく行かない場合には別のPCに接続して編集内容を確認します。 /boot以下はVFAT領域なので、問題なく扱えるはずです。

ramfsaddrなどを指定しないと、initrdのイメージが展開されない事になります。 うまくいけばdmesgに次のようなメッセージが表示されます。

$ dmesg | grep init
...
[    1.049760] Unpacking initramfs...
[    1.710015] Freeing initrd memory: 4476K
...

パッケージの導入

ipvsadmとkeepalivedを使いますが、ipvsadmはkeepalivedの導入時に自動的にインストールされます。

keepalivedの導入

パッケージを導入します。

$ sudo apt-get install keepalived

設定

パッケージを導入しても設定ファイルは一切導入されないので、過去のログをみながら設定ファイルを構成します。

/etc/keepalived/keepalived.confの編集

今回はWebサーバではなくて、ESXi上に構成しているLDAPサーバに対してHA構成を取っています。

振り先の設定

LDAPサーバ側にいくつか設定が必要です。

/etc/sysctl.confの編集

対象サーバが1台しかない場合には、問題になりませんが、複数のslave LDAPサーバに処理を分散させるような場合にはサービス(仮想)IPとMACアドレスが強力に結びついてしまうと、ルータからダウンしたLDAPサーバに常に処理が振られてしまうのでARPリクエストに反応しないように変更する必要があります。

/etc/sysctl.confへの追加内容

net.ipv4.conf.eth0.arp_ignore=1
net.ipv4.conf.eth0.arp_announce=2

設定を反映させます。

$ sudo sysctl -p

sysctlコマンド実行後の画面出力

net.ipv4.conf.eth0.arp_ignore = 1
net.ipv4.conf.eth0.arp_announce = 2
サービス(仮想)IPの設定

IPレベルではリクエストは2台のRaspberryPiで共有されるサービス用の(仮想)IP宛てのパケットがLDAPサーバに到着します。

自分宛てのパケットだと認識しないといけないので、loopback(lo)にIPを設定します。 まだ未使用のlo:0デバイスを使います。他に使用している場合には、lo:1,lo:2など適当な番号に変更してください。

/etc/network/interfacesファイルへの追加内容

auto lo:0
iface lo:0 inet static
  address 192.168.1.182
  netmask 255.255.255.255

さいごに

RaspberryPiを入手して、いろいろ試していますが、電源の品質とカーネルの安定性が一番の問題でした。

電源はUSBハブから取っていますが、マウス、キーボードなどは本体に直接つないで他の機器はつないでいません。

PCなどに接続する場合には、2つ口の片側に接続する事で500mA 2つ分の1000mAまで電流が取れるものが多いようです。 最近ではiPadやタブレットに対応した急速充電可能なタイプであれば、1000mAまで取れるので問題ないでしょう。

SDカードはTranscendのClass10 UHS-I対応16GBと、PanasonicのClass 10 SDHC 8GBのカードを使っています。 他のARM系ボードでも使っていますが、これまでのところ問題は起きていません。

この他にも$ sudo raspi-configで変更できるパラメータは少し変更していて、安定して動くようになってから900MHzへのオーバークロックやVRAMを16Mに変更したり、

tail -5 /boot/config.txtの実行結果

# for more options see http://elinux.org/RPi_config.txt
gpu_mem=16
core_freq=250
sdram_freq=450
over_voltage=2

この記事で取り上げた品々

2012/05/05

Debian WheezyでCouchDB 1.2.0をコンパイルした時にはまった事

CouchDB 1.2.0をさくらVPSで稼働しているDebian wheezyに導入したのですが、 エラーがでてcouchjsが実行できない自体になった時のトラブルシュートのログです。

エラーの内容

couchdb自体は問題なく起動したものの、viewを参照するとvar/log/couchdb/couch.logに次のようなエラーが大量に書き込まれていました。

...
[Wed, 02 May 2012 06:30:37 GMT] [error] [<0.4852.0>] OS Process Error <0.5474.0> :: {os_process_error,
                                                     {exit_status,139}}
[Wed, 02 May 2012 06:30:37 GMT] [error] [<0.4852.0>] OS Process Error <0.5477.0> :: {os_process_error,
                                                     {exit_status,139}}
...

原因はSpiderMonkeyのライブラリバージョンにあったのですが、 突き止めるまでに時間が少しかかってしまいました。

Debian wheezyで利用可能なSpiderMonkeyのバージョン

このバージョンのDebianでは2種類のライブラリが使用可能です。

  • libmozjs-dev - Development files for the Mozilla SpiderMonkey JavaScript library
  • libmozjs10d - Mozilla SpiderMonkey JavaScript library
  • libmozjs185-1.0 - Spidermonkey javascript engine
  • libmozjs185-dev - Spidermonkey javascript library - development headers

先頭2つのlibmozjs-devとlibmozjs10dはDebianプロジェクトが開発するfirefox互換ブラウザに組み込まれているJavaScriptエンジンで基本的にはSpiderMonkeyと同一ですが、Mozillaプロジェクトが配布しているSpiderMonkeyのバージョンは1.8.xとなっています。

このライブラリを導入した状態でCouchDBのconfigureを走らせると、バージョンが新し過ぎてサポートされていない旨が表示されます。

そこでlibmozjs185-1.0とlibmozjs185-devを導入して、configureが問題なく動くようにしたのですが、これが問題を引き起した原因となりました。

configureの振舞い

先ほどリストした全てのパッケージが入った状態では、configureは問題なく完了します。

この状態ではcouchjsコマンドだけが、libmozjsとリンクされてしまいます。 正しいのはlibmozj185とリンクされている状態ですが、lddでみるとlibmozjs10dパッケージに含まれるライブラリとリンクされています。

$ ldd src/couchdb/priv/couchjs |grep js
	libmozjs.so.10d => /usr/lib/libmozjs.so.10d (0x00007fab300d0000)

まぁconfigureのバグなんですが、このお陰でviewにアクセスした時だけ結果が正しく帰ってこない事になります。

couchjsコマンドのデバッグ方法

で、原因を突き止めるために、簡単なJavaScriptで書かれたスクリプト(a.js)を準備して実行してみます。

a.jsスクリプトファイル

print("test");
 $ /usr/local/bin/couchjs a.js
Segmentation fault

どこで落ちたのか原因を探るためにstraceを使う事が多いのですが、今回はまったく役に立ちませんでした。

結局のところgdbを使ってlibmozjs.soライブラリの中で落ちている事を確認しました。

 $ gdb /usr/local/bin/couchjs
 (gdb) run a.js
 (gdb) backtrace
(gdb) backtrace 
#0  0x00000000004049e5 in ?? ()
#1  0x00007ffff76d5ab8 in ?? () from /usr/lib/libmozjs.so.10d
#2  0x00007ffff764c937 in JS_ExecuteScript () from /usr/lib/libmozjs.so.10d
#3  0x000000000040227c in main (argc=<optimized out>, argv=<optimized out>)
    at couch_js/sm185.c:389

これで無事に/usr/lib/libmozjs.so.10dの中の処理で落ちていて、本来リンクして欲しくないライブラリを参照していた事が原因だとわかりました。

回避策

この問題を避けるためには、毎回正しいlibmozjs関連のファイルをポイントするようにconfigureオプションを指定する他ありません。

幸い、couchdb 1.2.0もdebian wheezyも比較的新しいパッケージなので、昔のcouchdbのようにinclude fileから指定する必要はなくなっています。

configureを次のように実行して、libmozjs185.soをリンクしている事を確認します。

./configure --with-js-lib-name=mozjs185
checking for JS185... yes
checking for JS185... yes
checking jsapi.h usability... yes
checking jsapi.h presence... yes
checking for jsapi.h... yes
checking for JS_NewObject in -lmozjs185... yes

これでlibmozjs10dパッケージが導入されていても、エラーなくcouchdbが動きます。

さいごに

configureの中でヘッダーファイルのチェックでpkg-configを使っているのに、ライブラリのチェックでは実際にコンパイルできるか普通にチェックしてしまっているので、libmozjs.so.10dをリンクしてしまっていました。

これはバグだとは思うのですが、pkg-configにlibmoz185パッケージが入っているとは限りませんし、どちらもECMAScript Ver.5をサポートするようにできているので、関数のチェックを確実に行なうのは難しそうに思えます。

CouchDBの経験があればcouchjsが動かないだけで、libmozjs周りを見に行くとは思うのですが、今回は現象だけをみても原因がよく分からなかったために時間を数時間ロスしてしまいました。

まだtestingフェーズのdebian wheezyを使っている人が多いとは思いませんし、そんな人達は自力で解決しちゃうと思いますが、どなたかの役に立てば幸いです。

2012/05/02

さくらVPSのDebian wheezyにCouchDB 1.2.0をインストールしてみた

少し時間ができたのでCouchDB 1.0の環境を1.2にアップグレードする事にしました。

手製ツールの稼働検証やら、DTIのVPSに作った郵便番号検索の仕組みを更新するとか、1.0から1.2への変化をキャッチアップするだけで、何だかぐったりするような作業で腰が重かったのですが、この機会に(現実逃避を兼ねて)とりかかることにしました。

私のcouchdbの使い方はバックエンドサーバーとして使うものなので、フロントエンドにcouchdbを使おうとする普通の使い方をする方はSSLなどのセキュリティ設定にもっと注力する必要がある事に

進め方の方針

アップグレードとはいっても現状の環境は止めるわけにいかないので、さくらのVPSに構築したtestingステータスのDebian wheezy上に新規にEarlang, CouchDB、その他の自前ツール等々をインストールをして、切り替えることにしました。

最終的にはCNAMEで設定しているwww.yadiary.netのレコードを書き換える事で対応する予定です。

対象の環境

現行のDTIのプランは490円のCPU: shared 1core, Memory: 256MB (max. 1GB)の構成で、 スペックをみる限りはリッチですが、このアプリケーションの性能にはほとんど変化ないだろうと考えています。

さくらVPSに構築しようとしている環境は次の通りです。

  • VPSプラン: さくらのVPS 2G (CPU: shared 3core, Memory: 2GB)
  • OS: Debian wheezy (次期stable、現testing), 64bit (x86_64)
  • Earlang: OTP-R15B01
  • CouchDB: 1.2.0

ちなみにDTIにある現行機は、Debian squeezeで、Earlang/OTP-R14B, CouchDB-1.0.2という構成です。

CouchDB 1.0系と1.2系の違いについて

1.1での変更も含めた完全なリストは apache-couchdb-1.2.0.tar.gz に含まれるCHANGESファイルにあります。

Native SSLサポートが含まれていたり、細かい点ではセキュリティ上の改善点もいくつか含まれています。

インストール手順

基本的な進め方はCouchDB: 1.0.1から1.0.2のリリースアップ手順 (xstow対応版)に従って進めていきます。

バージョンアップする時には/usr/local/etc以下に配置してある設定ファイルを退避して、新しいバージョンの設定ファイルをコピー、編集する事になりますが、1.2.0でも進め方に違いはありませんでした。

今回もxstowを使って/usr/local以下にインストールするため、/usr/local/stow以下にインストールしたcouchdb-1.2.0の直下からvarディレクトリは/usr/local/var以下に移動しています。 さらにスクリプトファイルから/usr/local/stow/couchdb-1.2.0/varを参照している個所を修正します。

確認するべき対象は次のコマンドで確認しました。

$ find . -type f | while read file ; do grep 1.2.0/var $file > /dev/null 2>&1 && echo $file ;  done

以前はetcファイルも/usr/local/etcに直接展開していましたが、今回は止めました。 バージョンアップの頻度は思ったよりも多くはなくて、その度にlocal.iniをコピーしても手間ではなさそうですから。

VPSサーバでの稼働検証

普通にサーバーを立ち上げるとIPv4のloopbackアドレス(127.0.0.1)にバインドします。 手元にないサーバーへ接続する場合に、グローバルアドレスにいきなりバインドすると外部に対して無防備になってしまいます。

一般的にサービス前のサーバーに接続するために、いくつかの方法が考えられます。

稼働確認という意味では、sshが一番簡単だろうと思います。 サービスイン後も使い続けるのであれば、stunnelがお勧めです。

ただWebサーバーのVirtualHostや、SSLポートのように、アクセス時に指定するサーバー名も重要な要素となる場合には、そうも簡単にはいきません。 今後のためにはiptablesを使った方法も、見当しておく必要があります。

というわけで、今回はiptables/ip6tablesを使ってグローバルアドレスにバインドさせてみる事にします。

iptablesを使った接続制御

iptables/ip6tablesを使う場合には、既にあるルールを汚染せずに追加、削除を行なう必要があります。 ここではポート番号を5985にして、このポート番号に対する制御は事前にされていない前提で作業を行ないます。

local.iniファイルの編集

IPv6アドレスを使っていますが、IPv4アドレスを使う場合には、アドレスの他にip6tablesをiptablesに読み替えてください。

/usr/local/etc/couchdb/local.iniファイルの編集個所

port = 5985
bind_address = 2001:xxxx:31d5:87d3::1
サーバー起動前:iptablesへのルール追加

デフォルトのINPUTルールが、ACCEPTでなければ2行目は不要ですが、明示的に1行目で指定した以外のIPv6アドレスからの接続を拒否しています。

 $ sudo ip6tables -A INPUT -p tcp --dport 5985 -s 2001:3e0:a32:xxxx:8d45:678a:2fe8:xxxx -j ACCEPT
 $ sudo ip6tables -A INPUT -p tcp --dport 5985 -j DROP 

稼働確認

サーバー上の設定が反映されている事を確認します。

 $ sudo ip6tables -L
Chain INPUT (policy ACCEPT)
target     prot opt source               destination         
ACCEPT     tcp      2001:3e0:a31:1:7d44:6780:2fd9:ca43/128  anywhere             tcp dpt:5985
DROP       tcp      anywhere             anywhere             tcp dpt:5985

設定が反映されていれば、サーバーを起動します。

 $ sudo /usr/local/etc/init.d/couchdb start

これでWebサーバからアクセスする事ができます。 IPv6アドレスを使う場合にはURLが http://[2001:3e0:a32:xxxx:8d45:678a:2fe8:xxxx]:5985/_utils/のように[]で囲む点に注意が必要です。

で、いろいろ作業が終ったらサーバを停止しておきます。

 $ sudo /usr/local/etc/init.d/couchdb stop
サーバー停止後:iptablesルールの削除

偶然サーバーが起動してしまう可能性もありますが、将来的にこの方法を使う事はないので、ip6tablesルールを削除しておきます。

 $ sudo ip6tables -D INPUT -p tcp --dport 5985 -s 2001:3e0:a32:xxxx:8d45:678a:2fe8:xxxx -j ACCEPT
 $ sudo ip6tables -D INPUT -p tcp --dport 5985 -j DROP

作業が終ったところで、 $ sudo ip6tables -L で追加したルールが残っていない事を確認します。

まとめ

とりあえず、これで動くところまでは確認できました。 ここからはいままで作ってきたパッチを1.2に対応させていきます。

参考文献

CouchDBについては公式Webサイトは宣伝要素が強いので、CouchDB Wikiがより実践的で、役に立つと思います。

2012/04/21

さくらVPS 2GでのIPv6接続

さくらのVPSが受付を再開したのでメモリ2GBのプランを申し込んでみました。

レスポンスはお名前.comのVPSが良いように感じますが、お名前.comのVPSはIPv6環境としては実用レベルの環境にする事は難しいと感じたので、さくらのVPSはIPv6を中心にみていく事にします。

カスタムOSへの変更

以前と環境を合わせるために、Debian6 amd64版をまずインストールしました。 その上で6rdでのIPv6環境を構築するために、パッケージをstableからtestingに変更しています。

/etc/apt/sources.listの内容

## for 6rd kernel
deb http://ftp.jp.debian.org/debian testing main contrib non-free
deb-src http://ftp.jp.debian.org/debian testing main contrib non-free
#

6rdのガイドに従ってカーネルを更新すると、関連した周辺パッケージも導入されるので、最終的には全体をtestingパッケージに合わせる事になると思います。

 # apt-get update
 # apt-get dist-upgrade

ping6による速度計測

まずは比較用に標準でIPv6をサポートしているDTI VPSまでのping6結果です。

比較用:自宅からDTI ServersMan@VPSまでのping6結果

PING 2001:2e8:601:0:3:1:0:bc(2001:2e8:601:0:3:1:0:bc) 56 data bytes
64 bytes from 2001:2e8:601:0:3:1:0:bc: icmp_seq=1 ttl=56 time=20.6 ms
64 bytes from 2001:2e8:601:0:3:1:0:bc: icmp_seq=2 ttl=56 time=21.0 ms
64 bytes from 2001:2e8:601:0:3:1:0:bc: icmp_seq=3 ttl=56 time=19.7 ms

次に6rdでIPv6アドレスを振ったさくらVPS 2Gまでのping6結果です。

自宅からさくらVPSまでのping6結果

PING 2001:e41:31d4:87d4::1(2001:e41:31d4:87d4::1) 56 data bytes
64 bytes from 2001:e41:31d4:87d4::1: icmp_seq=1 ttl=48 time=31.4 ms
64 bytes from 2001:e41:31d4:87d4::1: icmp_seq=2 ttl=48 time=31.6 ms
64 bytes from 2001:e41:31d4:87d4::1: icmp_seq=3 ttl=48 time=31.5 ms

まとめ

ping6の結果はTokyo6to4でIPv6化したお名前.comと比べると、だいたい10倍くらい早くなっています。ちなみにさくらVPSからwww.iij.ad.jpへのping6の結果をみると、前述の30ms台というのは自宅側に問題があって、さくらのVPSとDTIのVPSにレイテンシについては20ms前後で、違いはほとんどないようです。

体感的なパフォーマンスやIPv6を除いた全体的な印象では、お名前.comがお勧めです。 さくらのVPSでは、6rdが期限延長されたとはいえ、代替案なしにIPv6サポートとがなくなるリスクはありますが、IPv6が必要な方には、現時点でのベストチョイスの一つでしょう。

もちろんIPv6についていえばDTIのServersMan@VPSでも問題はないと思います。 私自身はIPv6対応DNSサーバーが必要なのでServersMan@VPSは現状のまま維持するとは思いますが、ip6tablesに対する不満は強く持っています。

DTIが現状のままであれば、将来さくらのVPSがIPv6を公式にサポートすれば完全に移行するでしょう。 そんな風に感じた数日間でした。

2012/04/17

お名前.comのVPS(KVM)でのIPv6接続

お名前.comのサーバーを少し使ってみて、パフォーマンスには驚くばかりです。 これが1ヶ月単位の契約でも1300円ちょっとというのは、言葉になりません。

さて自宅の中も外もIPv6環境を整えているので、サーバーとして使うにはなにかしらIPv6リーチャブルでないと困ってしまいます。

今回はTokyo6to4を使って、IPv6環境を設定してみました。

6to4を使う前提

Ipv6に対応する手段として6to4はお手軽で強力な方法ですが、Ipv4の固定アドレスが必要になります。 いわゆるVPSと呼ばれるものは、固定IPv4アドレスを持っているので、問題になることはないでしょう。

自宅のサーバーなんかを6to4に接続する場合には、固定IPv4アドレスの契約をしている事と、ホームルーター(ブロードバンドルーター)を自作するのがお勧めです。

Tokyo6to4設定方法

設定情報はTokyo6to4が「6to4の利用方法」としてまとめています。

何も難しくないというか、固定IPv4アドレスからグローバルアドレスを計算する方法ぐらいしか間違えそうな要素がありません。

手動でIPv6アドレスを計算していたので、この部分については、次のようなコマンドでも自動化できると思います。

 $ env LANG=C ip -4 -o addr | awk '!/127.0./ {sub("...$","",$4);split($4,list,"."); printf "2002:%02x%02x:%02x%02x::1\n",list[1],list[2],list[3],list[4];}'

さすがに、これはない。これなら固定IPv4を素直に人間が分解して、ガイドの通りprintfコマンドに渡した方が簡単ですね。

これでガイドの通りの設定を加えるとinterfacesファイル全体は次のようになります。

$ cat /etc/network/interfaces の出力結果


# This file describes the network interfaces available on your system
# and how to activate them. For more information, see interfaces(5).

# The loopback network interface
auto lo
iface lo inet loopback

# The primary network interface
allow-hotplug eth0
iface eth0 inet dhcp

auto tun6to4
iface tun6to4 inet6 v4tunnel
        address 2002:cbbd:60af::1
        netmask 16
        gateway ::192.88.99.1
        local 203.189.96.175
        endpoint any
        ttl 64
設定の有効化

サービス開始前ならちゃんと再起動して確認した方がいいと思いますが、とりあえず設定を確認するのに再起動を繰り返すのは時間が無駄なので、次のコマンドで確認します。

$ sudo ifup tun6to4

設定を再度試すには$ sudo ifdown tun6to4で一度設定を戻してから試します。

うまくいけば再起動時にも判定されるか、reboot(shutdown -r now)して試しましょう。

各種アプリケーションからのIPv6アドレス指定方法

DNSにAAAAレコードを追加するまではIPアドレスを直接してして試すしかありません。

Tokyo6to4の設定確認方法にも載っているping6コマンドは、直接2002から始まるIPv6アドレスを渡します。

$ ping6 2002:cbbd:60af::1

しかし、firefoxなどのURLでは[]で括って渡してあげます。

http://[2002:cbbd:60af::1]/
$ wget 'http://[2002:cbbd:60af::1]/'

sshクライアントではping6と同じように2002で始まるアドレスを渡します。

$ ssh 2002:cbbd:60af::1

ここら辺がちょっと判りづらいところですよね。

本番運用する時の考慮点

とりあえずIPv4によるバックアップがあるので、IPv6へのサービス提供、サービスアクセスが常に必要でなければ6to4で十分な場合が多いと思います。固有なサービスを作りたいのであれば、避けるべきだと思います。

レイテンシについて6to4は早いとはいえず、IPv6に対応しているServersman@VPSが良いのは間違いありません。 とはいえIPv6に対応しているServersman@VPSのサーバー自身の可用性がいまいち信頼できないので、安定して稼働して欲しいなぁとは思っています。最近は調子が良いですけどね。

6to4サービスのレイテンシ

ping6の結果はだいたい15倍ぐらいの開きがあって、これが6to4サービスをサーバー側で使うことのネックになるでしょう。TCPのセッションを確立するだけで、だいたい1秒くらいかかる事になります。

$ ping6 2001:2e8:601:0:3:1:0:bc


PING 2001:2e8:601:0:3:1:0:bc(2001:2e8:601:0:3:1:0:bc) 56 data bytes
64 bytes from 2001:2e8:601:0:3:1:0:bc: icmp_seq=1 ttl=56 time=20.2 ms
64 bytes from 2001:2e8:601:0:3:1:0:bc: icmp_seq=2 ttl=56 time=20.2 ms

$ ping6 2002:cbbd:60af::1

$ ping6 2002:cbbd:60af::1
PING 2002:cbbd:60af::1(2002:cbbd:60af::1) 56 data bytes
64 bytes from 2002:cbbd:60af::1: icmp_seq=1 ttl=52 time=323 ms
64 bytes from 2002:cbbd:60af::1: icmp_seq=2 ttl=52 time=319 ms

ただ2002で始まるアドレスを使う6to4には逆引きDNSサービスが受けられます。 AAAAレコードを登録できるDNSサーバを持つ事が前提ですけれど、とりあえずはセカンダリDNSサービスに紛れる事にします。

お名前.comのVPS(KVM)で最初にやったこと

さくらのVPSが予約受け付け中で使えなかったので、お名前.comのVPSを試す事にしました。 IPv6対応については、さくらのVPSは本番運用向けではないもののIPv6へのパスがあるのに、お名前.comのIPv6サポートの意向表明だけで提供時期についてはまったく情報がないのが不満ですが、とりあえずそれ以外の部分を試す事にしました。

標準OSからカスタムOS: Debian 6への移行

とりあえず準備されているカスタムOS用のISOイメージから64bit版 Debian6を選択してインストールします。

メモリ2GBのプランで70GBのディスクが使えますが、内部はだいたい20GB + 50GBの2Disk構成になっています。 標準のCentOSでは先頭の20GBの領域が/boot用に512MBのパーティションに分けられていたり、かなり標準的な構成になっています。

とりあえず1台目の/dev/vdaはインストール時に削除します。

  • /dev/vda1 - /
  • /dev/vda2 - swap
  • /dev/vdd1 - /app

導入時のパッケージ選択ではDesktopアプリ用パッケージが選択されていたので、標準ユーティリティとSSH Serverの2つだけにチェックを入れています。

削除したパッケージ

インストールが終わり稼働したDebianにログインしてみると、Desktopパッケージは省いているものの、いくらか不要なパッケージやdaemonが動いています。

まず$ dpkg -lでパッケージのリストを眺めて、次のパッケージを削除しました。 実際には関連するパッケージが若干巻き込まれて、同時に消えます。

 # apt-get remove acpi acpid acpi-support-base libx11-6 wget w3m libxcb1
 # apt-get purge

libkrb5-3自身も不要ですが、多くのユーティリティがライブラリを参照しているため削除はできません。 それよりもX関連のパッケージが含まれている事が問題かな。

追加パッケージの導入

次に必要なファイルをインストールします。

システム管理用パッケージの導入

システム管理用にいくつかのパッケージを導入しておきます。sudoは一般ユーザから主にroot権限でコマンドを実行するために使います。

xstowは/usr/local/stowディレクトリを作成して、/usr/local以下に自前でコンパイルしたアプリケーションを管理するために使います。

 # apt-get install sudo xstow 

これと平行して各ユーザーの~/.ssh/authorized_keysに手元のコンピュータのid_dsa.pubを設定してから、/etc/ssh/sshd_configにPasswordAuthentication noを設定しています。

パスワードはkeepassxを使って管理しているので、自動生成したパスワードを設定しています。 コンソールは使えますが、実質的にパスワードを使ってログインはできなくなります。

XFSファイルシステム関連ファイルの導入
 $ sudo apt-get install xfsprogs xfslibs-dev

/dev/vdb1パーティションをXFSファイルシステムにするために必要になります。

ファイルシステムの選択は必ずしも必要ではありませんが、今回はXFSを使うためにユーティリティパッケージを導入しました。

Firebirdの導入

Debian6ではFirebird 2.5が使えるので、パッケージから導入します。

 $ sudo apt-get install firebird2.5-superclassic firebird2.5-dev

ただし、この状態では世界中からアクセスできてしまうので次の2点だけは設定しておきます。

  • $ sudo dpkg-reconfigure firebird2.5-superclassicからSYSDBAのパスワードをランダムなものに変更し、/etc/firebird/2.5/SYSDBA.passwordを更新
  • /etc/firebird/2.5/firebird.confを編集し、RemoteBindAddress = 127.0.0.1を設定

アプリケーションからはsysdbaを使わずにgsecを使って追加したユーザー、パスワードを使用して、テーブルにはGRANTで追加したユーザーのアクセス権を加えておきます。

この後の使い道

しばらく使ってみて問題がなければ、yadiary.netドメインの1台に加えるか検討する事になるでしょう。ただしIPv6が使えないので、マイグレーションの予定が立てられないのがちょっと問題かな。

IPv6の設定はTokyo6to4が使えないか、後で検討する事にします。

2011/01/25

WebSVNに"lost+found"を無視させる

自作のコードのいくつかはSubversionで管理していて、Alix上にApacheを入れてWebDAVとWebSVNで管理しています。

今回USBメモリ上にリポジトリを作成したのですが、そこをWebSVN 2.0で表示させるとlost+foundをリポジトリとして扱おうとしてエラーが表示されてしまいます。

リポジトリの表示を自動化せずに、全て手動で$config->addRepository()を/etc/websvn/config.php内で実行するのは、どんどんリポジトリを追加していて、あまりにも面倒なので削除パターンを追加することにしました。

環境

WebSVNは次の環境で稼働しています。

  • HW: Alix 2c3
  • OS: Debian lenny (5.0.8)
  • Apache: 2.2.9-10+lenny9
  • WebSVN: 2.0-4+lenny1

WebSVNの最新版は2.3系列で、それについては最後に少しふれています。

Ubuntu 10.10で確認した範囲ではWebSVN 2.3.1では、apacheプロセスが読み取れない、SVNリポジトリではないディレクトリが存在していても問題なく動いています。

挙動の変更内容

設定ファイルの中でリポジトリが格納されているディレクトリを$config->setParentPath()で指定していると想定しています。

PHPの内部ではopendir()で展開されていますが、lost+foundなどのシステム上必要なディレクトリを省くためにignoreRepoPathPattern変数を追加しました。

既存コードに倣って直接変数への代入ではなく、addIgnoreRepoPathPattern関数を使って追加する仕様にしています。

修正内容

変更を加えたのは設定ファイルのconfig.phpと、それを元にリポジトリをリストアップするconfigclass.phpファイルです。

config.phpへの設定追加

--- /etc/websvn/config.php.orig	2011-01-25 10:45:15.000000000 +0900
+++ /etc/websvn/config.php	2011-01-25 11:02:04.000000000 +0900
@@ -1,4 +1,8 @@
 <?php
+
+// $config->addIgnoreRepoPathPattern("/my/"); // test purpose only
+$config->addIgnoreRepoPathPattern("/lost\+found/");
+
 // WebSVN - Subversion repository viewing via the web using PHP
 // Copyright (C) 2004-2006 Tim Armes
 //

configclass.phpの修正内容

--- /usr/share/websvn/include/configclass.php.orig	2011-01-25 10:10:19.000000000 +0900
+++ /usr/share/websvn/include/configclass.php	2011-01-25 11:00:23.000000000 +0900
@@ -133,6 +133,8 @@
    var $contentEnc;
    var $templatePath;
 
+   var $ignoreRepoPathPattern = array();
+
    // }}}
 
    // {{{ __construct($name, $svnName, $path, [$group, [$username, [$password]]])
@@ -1012,6 +1014,15 @@
 
    // }}}
 
+   // {{{ addIgnoreRepoPathPattern
+   //
+   // Set the ignore path pattern which works with the ParentPath function.
+   function addIgnoreRepoPathPattern($pattern)
+   {
+     $this->ignoreRepoPathPattern[] = $pattern;
+   }
+   // }}}
+
    // {{{ parentPath
    //
    // Automatically set up the repositories based on a parent path
@@ -1023,6 +1034,19 @@
          // For each file...
          while (false !== ($file = readdir($handle)))
          { 
+
+/* ignore some paths */
+$flag = false;
+foreach($this->ignoreRepoPathPattern as $reg) {
+  if ( preg_match($reg, $file) ) {
+    $flag = true;
+    break;
+  }
+}
+if ($flag) {
+  continue;
+}
+
             // That's also a non hidden directory
             if (is_dir($path.DIRECTORY_SEPARATOR.$file) && $file{0} != ".")
             {

さいごに

最新版の2.3系列のconfigclass.phpをみると、リポジトリの同一名での重複登録を省くための処理と、パターンにマッチした場合にのみリポジトリに加える処理も追加されていました。

addExcludedPath()を呼べばよさそうですが、指定するパスには絶対パスで指定する必要がありそうですが、現在では、Ubuntu 10.10の例にあるように、SVNディレクトリではないディレクトリがネガティブな影響を与える心配はないようです。

一括登録からみれば省くものは限られているケースが想定できて、想定外のパターンを含めてしまう可能性もあるので、バランスですが、一般的にはinclude, excludeは正規表現のパターンでも指定できたほうが便利だとは思いますが、とりあえずは古いWebSVNを動かしているが故のワークアラウンドでした。

2011/01/09

IPSetを使ったFirewallルールの設定について

以前家のブロードバンドルータにしているAlixにIPSetを導入するところまでを、「ブロードバンドルータにしているalixをDebian squeezeにして、ipsetを導入する」に投稿していました。

しばらく前にいわゆるボットネットの一部といわれているIPとの接続を弾くためにiptablesルールを設定仕直したので、そのログをまとめておきます。

現状のiptablesの設定状況

IPSetの導入と平行してiptablesルールの見直しを行なって、起動時にはiptables-restoreを使ってルールを設定しています。

設定のメインは/etc/network/if-pre-up.d/iptablesスクリプトで、if-pre-up.dディレクトリにあるスクリプトは起動時などifupによってネットワークデバイスが設定される直前に実行されます。

本当は重複して実行される可能性のある/etc/network/if-*.dに配置するのはスマートじゃないけど、iptables/ipsetの設定はNICが認識されているかどうかに無関係に実行できるので、重複起動は気にしないことにしました。

他には/etc/rc2.d/なんかにスクリプトを配置することもできると思います。 ここら辺はdebianで標準的な場所がないので、ホストの使い方によって変化するかもしれません。

もしWorkstationならネットワークデバイスの初期化云々はそれほど重要ではないので、/etc/rc.local辺りで設定をするかもしれません。

常時接続のルータは意図せずiptables設定なしにネットワークに接続するのは嫌なので、if-pre-up.dを使いました。

iptables設定スクリプトと参照するファイル群

このスクリプトの配置場所はいくつかの候補の中から選択するしかありませんが、ファイル名と内容は自由に書けるので、内部でiptables-restoreコマンド等を実行するようにしました。

スクリプトの中身は次のようになっています。

/etc/network/if-pre-up.d/iptablesファイル全体

#!/bin/bash

PATH=/sbin:/usr/sbin
BASEDIR="$(dirname $0)"

ipset --restore < "${BASEDIR}/../ipset.restored"
iptables-restore < "${BASEDIR}/../iptables.restored"
ip6tables-restore < "${BASEDIR}/../ip6tables.restored"

スクリプトでは/etc/network/直下に3つのファイルがある事を前提にしています。

  • /etc/network/ipset.restored
  • /etc/network/iptables.restored
  • /etc/network/ip6tables.restored

今回はip6tablesは範囲外です。ipsetとiptablesの連携について書いていきます。

iptablesとの連携

直接"iptables.restored"ファイルを書く事もできますが、いろいろ危険なのでiptablesコマンドを使って設定した後に"iptables.restored"ファイルを保存しています。

ipsetとの連携は、まずiptables側で空のipsetルールを作成して、それを参照するiptablesルールを加えます。

ipset,iptablesコマンドを使った空のipsetルールを使ったルール作り

#!/bin/bash
PATH=/sbin:/usr/sbin:/bin:/usr/bin

## delete all rules
iptables -F
iptables -t nat -F
iptables -X
iptables -t nat -X
iptables -Z
ipset -F
ipset -X
...
ipset -N denyip iphash --hashsize 36864
ipset -N denynet nethash --hashsize 36864
iptables -A INPUT -m set --match-set denyip src -j DROP
iptables -A INPUT -m set --match-set denynet src -j DROP
iptables -A FORWARD -m set --match-set denyip src -j DROP
iptables -A FORWARD -m set --match-set denynet src -j DROP
iptables -A OUTPUT -m set --match-set denyip dst -j DROP
iptables -A OUTPUT -m set --match-set denynet dst -j DROP
iptables -A FORWARD -m set --match-set denyip dst -j DROP
iptables -A FORWARD -m set --match-set denynet dst -j DROP
...

このスクリプトを実行して、動きに問題がない事を確認してからiptables.restoredファイルを作成しておきます。

$ sudo /sbin/iptables-save > /etc/network/iptables.restored

次にipsetを使い、定義だけされている空のipsetルールに具体的な設定を加えていきます。

まず用意するのはボットネットに組み込まれていると思われるIPアドレスのリスト。

iptables.deny.outboundファイル抜粋

##
## comment string, this line should begin with the '#' char.
109.10x.23x.1xx
...
109.23x.22x.0/24
...

このファイルを処理する

#!/bin/bash
PATH=/sbin:/usr/sbin:/bin:/usr/bin
BASEDIR="$(dirname $0)"
OUTBOUND_BLOCK_FILE="${BASEDIR}/iptables.deny.outbound"

ipset -N tmpip iphash --hashsize 36864
ipset -N tmpnet nethash --hashsize 36864
if test -f "${OUTBOUND_BLOCK_FILE}"; then
  while read ipaddr
  do
    ( echo ${ipaddr} | egrep ^# > /dev/null ) && continue
    ip="$(echo ${ipaddr}|awk -F/ '{print $1}')"
    mask="$(echo ${ipaddr}|awk -F/ '{print $2}')"
    if test "${ip}" != "" -a "${mask}" = "" ; then
      ipset -A tmpip "${ipaddr}"
    else
      ipset -A tmpnet "${ipaddr}"
    fi
  done < "${OUTBOUND_BLOCK_FILE}"
fi
ipset -W denyip tmpip
ipset -W denynet tmpnet
ipset -X tmpip
ipset -X tmpnet

設定したipsetルールは--saveオプションを使って保存します。

$ sudo ipset --save > etc/network/iptables.restored

こういう形でスクリプトを分けたのにはいくつか理由がありますが、ipset/iptablesコマンドを利用して大量のIPアドレスを処理するルールを追加するのにはかなり時間がかかるので処理を分けたかったのが大きな理由です。

次はipsetを使ってみたかったということ。

iptablesを使う事も可能ですが、空のipsetルールを設定したように、空のchainを作成しておいて、後からそのchainに個別のIPアドレスをDROPするルールを追加していくのが良いでしょう。

そうしないと一連のiptablesコマンドの実行が完了するまでの間は、ネットワークに対して脆弱なまま接続する事になるかもしれません。

もちろん直接iptables-restoreコマンドが解釈するようなファイルを生成して時間を短縮することは可能です。

いずれの方法でも、テストを十分にして、いきなり起動時に読み込まれるファイルとして保存しない事が重要です。

ここでリストの挙げられているIPアドレスからの接続を拒否することよりも、そういったサイトへの接続を拒否する事の方が重要です。 もっとも接続してはいけないマスター系ノードのIPアドレスは変化するでしょうし、知られていないものがあるでしょうから、本当にこういうリストが有用なのかは少し疑問が残ります。

何もしないよりはましかな。

2010/12/02

DTIのServersMan@VPSでdebianを選択して最初にやったこと

以前から気になっていたDTIのServersMan@VPSでdebianがOSとして選択できるようになってしばらく経ちましたが、Alixより少しパワーが欲しかったのと、Debian Squeezeのテスト環境を兼ねて使ってみることにしました。

Debian LennyをSqueezeにする手順はまとめている方がいらっしゃるのと、それほど難しくないので、それ以前にやった事のメモを残しておきます。

初回ログインの第一印象

ssh経由とはいえ、rootユーザでのログインはなんだか斬新な感じです。

世界中からパスワードが分かればログインできるというのも、なんとなく不安な感じです。

ゆくゆくは作業用の一般ユーザを作るとして、それ以前にやった方がいい事がいくつかあったのでまとめておきます。

localesの設定

apt-getなどPerlを呼び出す場面ではロケール関連のエラーが表示されます。

perl: warning: Setting locale failed.
perl: warning: Please check that your locale settings:
	LANGUAGE = "ja_JP.UTF-8",
	LC_ALL = (unset),
	LANG = "ja_JP.UTF-8"
    are supported and installed on your system.
perl: warning: Falling back to the standard locale ("C").

ロケールが適切に設定されていない事が原因なので再設定します。

# dpkg-reconfigure locales

一覧からlocaleを選択しますが、おすすめは次の3つです。

  • en_US.UTF-8
  • ja_JP.EUC-JP
  • ja_JP.UTF-8

EUCは時代遅れですが、まだ古いrubyを使っていてEUCで動いているアプリケーションもあるので、念のため選択しています。

最終的に選択した3つのロケール

デフォルトロケールとしてen_US.UTF-8を選択しています。

パッケージ更新の前に/etc/apt/sources.listの調整

デフォルトの設定ではftp.debian.orgにアクセスしようとします。

日本国内にあるサーバから海外にアクセスするのは遅い上に無駄なので、これを修正します。

修正後の/etc/apt/sources.listファイル

deb http://ftp.jp.debian.org/debian/ lenny main
deb-src http://ftp.jp.debian.org/debian/ lenny main

deb http://ftp.riken.jp/Linux/debian/debian-security lenny/updates main
deb-src http://ftp.riken.jp/Linux/debian/debian-security lenny/updates main
#deb http://security.debian.org/ lenny/updates main
#deb-src http://security.debian.org/ lenny/updates main

deb http://ftp2.jp.debian.org/debian-volatile lenny/volatile main
deb-src http://ftp2.jp.debian.org/debian-volatile lenny/volatile main
#deb http://volatile.debian.org/debian-volatile lenny/volatile main
#deb-src http://volatile.debian.org/debian-volatile lenny/volatile main

volatileやsecurityパッケージは国内のミラーサーバからだと失敗した経験があるので、コメントアウトしたものも残しておきます。必要に応じて切り替えてください。

サーバ名は volatileパッケージのミラーsecurityパッケージのミラー(ftp.riken.jpを参照)の情報を参照して変更することもできます。

パス名が変更になる場合もあるので動いている設定とリストの記述をよくみてください。

不要なパッケージの削除

自分の目的にはdbusやlprngは不要なので、まとめて削除しました。

# apt-get remove lprng dbus sasl2-bin libnss-ldap
apacheを起動しないように設定

開いているポートの確認はnetstat -naなどで行ないますが、apacheはしばらく使わないので止めておきます。

# update-rc.d -f apache2 remove

起動時や停止時にapache2を操作する/etc/init.d/apache2スクリプトへのシンボクックリンクを/etc/rc?.d/*apache2シンボリックリンクを削除してくれます。

SSH経由でのログインを制限する

できればLinuxなどのクライアントの方が良いですが、ssh-keygenを使ってVPSログイン用のSSHの公開鍵と秘密鍵のペアを作ってSSHのパスワードログインは使わないようにします。

# ssh-keygen -t rsa
Generating public/private rsa key pair.
Enter file in which to save the key (/root/.ssh/id_rsa): /root/id_rsa_vpslogin
Enter passphrase (empty for no passphrase): xxxxxxxxxx
Enter same passphrase again: xxxxxxxxxx
Your identification has been saved in /root/id_rsa_vpslogin.
Your public key has been saved in /root/id_rsa_vpslogin.pub.
The key fingerprint is:
c7:a1:a3:ac:61:9b:1d:d0:d8:26:32:fe:0e:d7:aa:2e root@dti-vps-srv02
The key's randomart image is:
+--[ RSA 2048]----+
|                 |
|                 |
|          .      |
|     +   o .     |
|  o + + S o      |
| . o * . o       |
|  o + =          |
|E  = B .         |
| oooB .          |
+-----------------+

これで2つのファイルが手に入ります。

  • /root/id_rsa_vpslogin - 秘密鍵
  • /root/id_rsa_vpslogin.pub - 公開鍵
/root/id_rsa_vpslogin - 秘密鍵の取り扱い

VPSサーバでkeygenを実行した場合は、このファイルをクライアントマシンにコピーしてサーバからは削除します。

/root/id_rsa_vpslogin.pub - 公開鍵の取り扱い

このファイルは、VPSサーバ上の /root/.ssh/authorized_keys として配置します。

VPSサーバ上でkeygenを実行していればmvするだけです。

# mkdir -p /root/.ssh
# chmod 0700 /root/.ssh
# mv /root/id_rsa_vpslogin.pub /root/.ssh/authorized_keys
# chmod 600 /root/.ssh/authorized_keys
鍵ファイルを使ったログインテスト

クライアントマシンにある id_rsa_vpslogin ファイルを使って、VPSサーバにログインします。

$ ssh -i id_rsa_vpslogin root@127.x.x.x

パスワードを聞かれずにログインできれば終了です。

SSHでパスワードを使ったログインを禁止する前に

VPSの特徴として、リモートでログインできなくなったら終りというのがあります。

一般ユーザでログインして、sudoを使おうとした場合には、ホスト名とIPアドレスの変換が最低でも/etc/hostsを経由して行なえなければいけません。

DNSにも/etc/hostsにも記述のないホスト名を/etc/hostnameに記述すると、次回の再起動後にsudoが使えなくなります。

パスワードを使ったログインを禁止するのは簡単ですが、少なくともrootと一般ユーザの2つに別々のキーを作成しておき、ログインできるかどうかのテストを入念に行なう必要があります。

一般ユーザでログインできればsuコマンドでrootになれますが、いろいろ調子に乗って変更すると落とし穴にはまる可能性があるので注意が必要です。

最後にパスワードを使ったログインを禁止する

いろいろテストを入念にやった最後の最後にパスワードを使ったログインを禁止しておきます。

この作業は自信がなければ行なわずに、確信が持ててから行なう事が必要です。

ま、始めたばかりですから初期化すればいいんですけどね。

変更後の/etc/ssh/sshd_configファイル編集個所

# Change to no to disable tunnelled clear text passwords
PasswordAuthentication no

いろいろなオーケストレーションツールはrootでのログインとか、公開鍵を使ったssh経由でのログインを必要としますが、パスワードを設定できなかったりすると嫌ですね。

SSHを使えば安全というものでもないので、ssh-keygenで鍵を作成する時にはパスフレーズを必ず適当なフレーズで設定してあげてください。

さいごに

ServersMan@VPSでのdebianの選択は、経験というよりも責任を自分で取る覚悟がないと、お勧めできないですね。 パッケージの多さは魅力的なんですが、しばらくすると時代遅れになりますし、いざという時には自分の腕が頼りです。

自習目的ならいいですが、不用意にポートを開けて不幸を呼び込まないか心配な面もあります。

CentOSはパッケージの数が少ないですが、ビジネスユースならまずはRedHatベースのCentOSに慣れるべきだと思います。 まぁビジネスのためには「慣れるべき」とはいえ、CentOSを勧める理由は常に○×養成ギブス的な意味合いが強いのが、ちょっと悲しいところです。

ServersMan@VPSには、いろいろな変更を加えていますが、とりあえず最低限はこれぐらい必要でしょう。 できれば推測されにくい名前の一般ユーザでログインして、rootでのログインも禁止( PermitRootLogin yes on /etc/ssh/sshd_config)してください。