日曜日, 5月 29, 2005

Transfer-Encoding の chunked

HTTPプロトコル(protocol)の話です。
たぶん、かなりマニアック。

HTTPのヘッダーには「Transfer-Encoding」というものがあります。
どうやってコンテンツ部分を転送するかを指定するものです。サーバー側の環境変数でいうと「HTTP_TE」です。
特に値が指定されていなければContent-Lengthの数バイトがコンテンツとして転送されますね。

この値が「chunked」のときにはちょっと変わっています。
1. 最初の行の値が16進数で表した、これに続くコンテンツのバイト数
2. 上のバイト数が0ならここでリクエストの応答は終わりです。
3. 上のバイト数分のコンテンツ
4. 1に戻る
みたいな感じなので、「0」だけの行が出てくるまで読み続けるわけですね。

動的なコンテンツの場合にはパートごとに分けて作れるので便利なわけです。
ソケットを使って自分で読み取るプログラムをPerlで書いてみました。

---------------------------------------------------------------------
sub get_content {

my $sock = shift or die;
my $debug = shift;

my $header = '';
my $content_length;
my $chunked;
while ( <$sock> ) {
warn $_ if $debug;
$header .= $_;
$content_length = $1 if m/Content-Length: (\d+)/;
$chunked = 1 if m/Transfer-Encoding: chunked/;
last if m/^\r\n$/;
}

my $content = '';
if ( $chunked ) {
while ( <$sock> ) {
warn $_ if $debug;
last if m/^\r\n$/;
s/\r\n//;
my $content_length = hex($_) or last;
my $buff;
read $sock, $buff, $content_length;
$content .= $buff;
}
}
elsif ( $content_length ) {
my $buff;
read $sock, $buff, $content_length;
$content .= $buff;
}
else { die $header }

return wantarray? ( $content, $header ): $content;
}
---------------------------------------------------------------------

まあ、たまにはこんなこともしてみます。

金曜日, 5月 27, 2005

dnscache (djbdns) をやめよう

うちではDNS(のキャッシュサーバー)としてdnscache(djbdns)をローカルで使っていました。
ネットワーク越しにISPのキャッシュサーバーを使うよりは早いはず、と思っていたんですね。

そこで実際に応答の速度を計ってみると、、、なんと、ローカルの方が遅い!
といっても、ほとんど変わらないんですけど。断然早いと思っていたのでショックでした。
わざわざ自分で用意して、高負荷時にはもっと遅くなる可能性もある。なんて馬鹿らしいと考えて使うの止めました。
前に書いた、pop3の話でもそうですけど、管理の手間は極力少なくするほうがいいですしね。

ただ、キャッシュへの毒入れ(Cache poisoning)については多少不安がありますが。

木曜日, 5月 26, 2005

無料のPOP3サーバー(サービスとして)

ずばり、Gmailです!
でもよく考えたらYahooとかもやってますね。

そもそもなんでこんなことを言い出したのかというと、うちにはPOPサーバーがないんです。
Debianではデフォルトでインストールされないんですよ。そのほうがいいんですけどね。
まあ、それでも困らなかったんです。だって、メールボックスにあるファイルを直接読んだらいいですから。
ただ、それだとPCが増えたときに困るのもわかっていました。なので定番のPOPサーバーを探してインストールしようとしてたんです。そして衝撃が!

Gmailを使えばいいんだ!!

まだ普通っぽいですか?
ここのミソは”POPだけ使う”ことです。つまり、送信するときには自分で用意したSMTPを使うし、受信するときもこれを使います。そして、aliasを使ってGmailに転送します。
こうすると相手にはGmailを使っていることがわからない。自前でメールアカウントも用意できない程管理能力がない(または、貧乏)などと気づかれない!
これは、結構、すごいソリューションじゃないでしょうか。

利点は、
1. 対外的には自前で管理しているように見える
2. 内部的にもメーラーのPOPサーバーの設定をちゃんと見るような人間以外には気づかれない
3. 運用のコストがかからない
4. 専用のコンピューターを用意する必要がない(専用には用意しなさそうだけど)
5. もしPOPサーバーがLANの外側にあるなら、サーバー側の帯域の効率があがる(朝のピーク時を気にしなくていいから)
6. ディスクが少なくてもいい
7. Gmailはアカウントごとに2GB以上(しかも増え続ける)
8. そして、利用者が増えても増設の心配をしなくていい
9. おまけにバックアップも自動

気になる点は、
1. 安心(必要なものは自分で用意するべきなんて人が結構いる)
 → Google以上の稼働率を実現する自信がありますか? 僕はないです。
2. コンプライアンス
 → 第三者に情報を提供しないとPrivacy Policyには書いてあります。ただ、これをもって個人情報保護法案での情報の保護になるかはあやしい。ここから漏れるとは思えないけど。
3. 商用利用可能なのか?
 → これはちょっとわからないですね。誰か教えてください。

くらいでしょうか。全然問題ないですね。
激安メールシステムのコンサルタントができそうです。

水曜日, 5月 25, 2005

Filesystem Hierarchy Standard (FHS) について

FHSとはFilesystem Hierarchy Standardの略でして、Unixとその仲間たちのディレクトリやファイルの構成について決めたものです。
僕も経験があるんですが、Linuxを初めて触ったときってWindowsとディレクトリの構成が違ってて戸惑うんですよね。

おんなじことがUnix同士でもおきていて、それでこんな取り決めができたみたいです。
おおまかにはこんな感じ。

/ (ルートディレクトリ。根っこ。ここを切り倒せば木は倒れるわけですね)
├ /bin (基本コマンド。これがないとファイルも見れない)
├ /boot (起動に必要なファイル。下手にいじると再インストール)
├ /dev (デバイスファイル。なんでもファイルなUnixの真骨頂)
├ /etc (設定ファイル。rootになってする作業のほとんどはここをいじること)
├ /home (ユーザーのホームディレクトリ。ユーザーはみんな引きこもりなのでここから出られません)
├ /lib (共有ライブラリ。/binや/sbinのライブラリ、他のプログラムは別の場所のを使う)
├ /mnt (一時的なマウントポイント。さんざん乗っておいて、うまくいったら捨てられる)
├ /opt (追加アプリケーション。rpmとかdebとか)
├ /proc (プロセス情報など - Linux固有。ほんとになんでもファイル)
├ /root (root用ホームディレクトリ。王様は高台に住んでるわけですね)
├ /sbin (システム管理用コマンドなど。王様の兵隊たち)
├ /tmp (一時的なファイル。暴れたい時にはここで)
├ /usr (各種プログラムなど。ユーザーが使うアプリケーションなんかはここに)
└ /var (変更されるデータ。朝おっきくて、昼は小さい、暗くなるとまた大きくなるものなーんだ? 答え:影 下ネタ!?)

ほんとはもっと細かく決まってます。知りたい方はここのリンクからどうぞ。

まあ、これだけ分かればなんとなくすっきりしませんか?

火曜日, 5月 24, 2005

Debian GNU/Linux でSSLを利用する

SSLの設定です。
といっても openssl + Apache の場合ですのであしからず。

まずは乱数の種を作ります。
コンピュータでは完全な乱数(random)を作るのはなかなか難しいんですよね。それで乱数系列と同じ特性をもつ疑似乱数(pseudo-random)系列を生成するアルゴリズム(random number generator)が用意されてます。
ただ、アルゴリズムなので入力が同じなら当然結果も同じです。初期値を変えないと毎回同じ疑似乱数列が出力されてしまうわけですね。
そこで、種(seed)を用意するわけです。これは基本的になんでもいいんですが、ここでは/usr/binにあるファイル名を使います。
------------------------------------------------------
# openssl md5 /usr/bin/* > rand.dat
------------------------------------------------------
これで/usr/bin以下のファイル名とそのハッシュ値がrand.datに書き込まれます。

これを使って乱数を発生させて秘密鍵を作ります。
------------------------------------------------------
# openssl genrsa -rand rand.dat -des3 1024 > key.pem
------------------------------------------------------
"1024"は鍵の長さです。"-des3"は秘密鍵を暗号化する方法にTriple-DESを使うという意味です。

今度は秘密鍵を使ってCSR(署名要求 - Certificate Signing Request -)を作成します。しつこいですね。一度で全部作れよ!とか思います。ベルトコンベアなイメージです。
------------------------------------------------------
# openssl req -new -key key.pem -out csr.pem
------------------------------------------------------
国名(JP)、都道府県(Tokyo)、市区町村(Taito)、会社(*** Ltd.)、部署(system-1)を入力します。common nameにはSSLを使うドメインを入力します。あとの3つは何も入れなくてもいいです。
括弧の中は僕の使ったものです。部署は数字を入れておくと、あとでWebサーバを分散させるときに便利です。

あと、common nameにはワイルドカードが使える場合があります。
*.kumicho.net
のようなcommon nameにしておくとa.kumicho.netでもb.kumicho.netでも使える、といった感じです。便利ですね。
ただ、クライアントによっては「"*"と"a"が一致しない」なんて文句をいう場合があります。LDAPのクライアントはそう言ってました。IEやFirefoxは大丈夫みたいです。
あと、CAcertでは文句を言われなかったけど、Verisignなんかもそうなのかは知りません。

といった感じで作ったCSRを認証局に送れば証明書が送られてきます。証明書をcert.pemなんて名前にして保存。
Apacheの設定ファイルに
-------- sites-available/blogger --------------------
SSLCertificateKeyFile ssl/key.pem
SSLCertificateFile ssl/cert.pem
-----------------------------------------------------
なんて書けば使えるようになります。
起動時のパスフレーズの入力を省略したい方はこちら

ちなみに複数の証明書を使いたい場合には名前ベースではなく、IPベースのバーチャルホストを使わないといけません。
ApacheがSSLを使って接続するためには、どの証明書を使うか知るために名前を知らないといけない。けれど、そのHTTPリクエストの前にSSLでの接続が成立していなくてはいけない、なんてことが起こるからです。卵が先か、ニワトリが先か。。。

月曜日, 5月 23, 2005

Bookmarks Synchronizer を使う(FirefoxのExtension)

Bookmarks Synchronizerを使いましょう!
Web DAVの設定はこのためと言っても過言でないです。無茶苦茶便利です。

このExtensionは名前のとおり、ブックマークを同期させます。Firefoxを使っていればどこでも同じブックマークが使えるだけでなく、どこで更新してもそれが共有されます。
自宅で「このサイトは便利だなあ」とブックマークしておけば会社ですぐ見られるわけです。すばらしい。

使い方は、まずFirefox Extensionsのページに行きます。
BookmarksのカテゴリからBookmarks Synchronizerを選択してインストール。
設定を開いたら、HTTPSにチェックを入れて、サーバーの設定を書いていきます。
下にあるチェックボックスは最後にはチェックを入れず、上の3つはチェックするのがよいかと。

日曜日, 5月 22, 2005

Debian GNU/Linux で Web DAV を使う

WebDAV(Web-based Distributed Authoring and Versioning)を導入しました。
要はWeb(HTTP)を利用したファイルの共有です。実際にはHTTPの拡張として実装されています。

すでにApacheが起動していればほとんど手間がかかりません。

1./etc/apache2/mods-enabled/ にシンボリックリンクを作ってWebDAVの機能を取り込みます。これには専用のコマンドもあります。
---------------------------------------------------------------------------
# ln -s /etc/apache2/mods-available/dav.load /etc/apache2/mods-enabled/
# ln -s /etc/apache2/mods-available/dav_fs.conf /etc/apache2/mods-enabled/
# ln -s /etc/apache2/mods-available/dav_fs.load /etc/apache2/mods-enabled/
---------------------------------------------------------------------------
または
---------------------------------------------------------------------------
# a2enmod dav
---------------------------------------------------------------------------

2.WebDAVを使いたいDirectoryで機能を有効にします。下の"DAV On"がそうです。
-------- /etc/apache2/sites-available/default -----------------------------

SSLRequireSSL
DAV On
AuthName "Web DAV Area"
AuthType Basic
AuthLDAPURL ldap://ldap.kumicho.net/dc=kumicho,dc=net?cn
require valid-user

---------------------------------------------------------------------------

3.ついでに認証も付け加えます。実際にはほぼ必須です。

4.忘れがちなのがWebDAVで使うディレクトリに書き込み権限を与えることです。他のプログラムから操作する必要がなければ所有者を変えてしまいましょう。
---------------------------------------------------------------------------
# chown www-data /var/www/dav/
# chgrp www-data /var/www/dav/
---------------------------------------------------------------------------

5.最後にApacheを再起動します。
---------------------------------------------------------------------------
# /etc/init.d/apache2 restart
---------------------------------------------------------------------------

これでサーバーの設定は終わりです。
一応テストしたいときは、IEを開いて「ファイル」→「開く」とたどります。
「Webフォルダとして開く」にチェックを入れてURLを入力します。
あとは普通のフォルダのように利用できます。

木曜日, 5月 19, 2005

秘密鍵のパスフレーズ(passphrase)をなくそう

なんか、今更な感もありますが。

ApacheでSSLを使うときなんかはパスフレーズを消しておかないと再起動のたびに入力を求められて大変です。うちみたいに「いろはにほへとちりぬるを・・・」なんてパスフレーズにすると100回くらいキーを打たないといけません。再起動恐怖症になってしまいます。嘘ですが。
なので、普通はパスフレーズを空にして使います。

秘密鍵がkey.pemだとすると、
openssl rsa -in key.pem -out keynopass.pem
とするといいです。パスフレーズを聞かれるので入力すればパスフレーズなしの鍵ができます。
あとはkeynopass.pemの方を鍵として使うようにすればいいです。

火曜日, 5月 17, 2005

Debian の Exim4 でエイリアス(alias)の設定

たいしたことじゃないんですが、わかるまで結構時間がかかって悔しかったので。

うちのドメイン、kumicho.netに存在しないユーザー宛てのメールを僕が受け取る方法です。
/etc/aliases に
受け取りたい名前: 受け取るユーザー
を書きます。それだけ。

root宛のものなんかが僕のメールボックスにくるので、設定があるはずだと思って/etc/exim4のなかでgrep root しても見つからない。なんでだ、どうして?としばらく悩みました。まさかメールの設定の外にあるとは。。。sendmail互換なのか、それとも全然別の理由なのか、どちらにしても迷惑な話です。僕が睡眠不足になり、さらにうつ病になり、最後には仕事をやめて田舎で療養なんてことになったらDebianのせいですね。訴えてやる!

ちなみに、コンピュータに存在するユーザーがメールを転送するときには、ホームディレクトリの.forwardファイルを使います。
先頭の行に
# Exim filter
と書いて始めます。
次に
deliver gulliver@lilliput.fict.example
とか書くとそのあて先に転送できます。
このままだとローカルにメールが残らないので、ローカルのメールボックスに残す場合には
unseen deliver gulliver@lilliput.fict.example
とunseenをつけて安心です。ぷぷっ
他にもpipeコマンドでスクリプトに処理させることもできます。メールでブログに投稿したり、写真を掲載できるのはこういう機能を使ってるからなんですね、納得。

月曜日, 5月 16, 2005

Debian GNU/Linux でLDAPを使う

うちのサイトでもほんのちょっとだけパスワードかけたりしてるんですが、LDAPを使うように変更しました。
ちなみにLDAPはLightweight Directory Access Protocolの略です。名前の通り、軽量な、ディレクトリサービスにアクセスするためのプロトコルなんですね。

まず、いつものようにaptでslapd(これがLDAPサーバ)をインストールします。ついでにldap-utilsもインストールします。こっちはメンテナンスのために必要です。
Debianではインストール時に必要なことをインストーラーが聞いてきます。便利ですね。
最初にドメインを聞かれます。たとえばkumicho.netなんかにします。次に組織名を聞かれます。今回はWebのアクセス制御に使うのでWWW Usersなんかにします。このあたり、動作に問題はないのですが結構悩みます。このユーザーグループは組織(LDIFではoで表される)にすべきなのか組織単位(=ou)にするべきなのか。まあ、とりあえずあとでも変更できるので進めます。
最後に管理者用のパスワードを聞かれます。忘れなさそうな言葉を書いておきます。
これでインストールは終了。

次に情報を入力します。まず、こんなファイルを作ります。
-------- user.ldif --------
# user1, kumicho.net
dn: cn=user1,dc=kumicho,dc=net
objectClass: simpleSecurityObject
objectClass: organizationalRole
cn: user1
description: ここ説明です
userPassword: ****************
---------------------------
#で始まってる行はコメントです。
最初のdnっていうのは識別名。全データで一意である必要があります。
次の二つは、このデータオブジェクトのクラスを書きます。ここで選んだクラスによって使える属性が決まります。今回は認証に使うだけなので上の二つにしてあります。社員データベースを構築したい場合なんかだと、inetOrgPersonなんかを使うといいです。名前や住所、電話番号はもちろん、写真や認証鍵も管理できます。作るのが大変ですけどね。
次はcn(コモンネーム)、名前です。
次は説明なんですが、ここに書いてるように日本語も使えます。ただし、UTF-8じゃないといけません。
最後は見ての通り、パスワードです。隠してます。いやん。
もっと詳しく知りたいときは、/etc/ldap/schema以下のファイルを見ましょう。

で、こういうファイルを作ったら、
ldapadd -x -f user.ldif -D "cn=admin,dc=kumicho,dc=net" -W
こんな感じで入力します。パスワードを聞かれるので答えてくださいね。
ldapsearch -x -D "cn=admin,dc=kumicho,dc=net" -b "dc=kumicho,dc=net" -W
これでちゃんと入力されているか確認できます。
簡単に説明すると、-xは単純な認証を使う、-fは入力ファイル、-Dは操作を行う識別名、-bは検索のベース、-Wはパスワードの入力を促します。

うまくいったら、後はApacheを設定します。
認証をかけたいファイルやディレクトリの中で、
------------------------
AuthName "Private Area"
AuthType Basic
AuthLDAPURL ldap://ldap.kumicho.net/dc=kumicho,dc=net?cn
require valid-user
------------------------
こんな風に書きます。ファイルの指定の変わりにURLを指定するだけなので簡単ですね。?の前の部分は検索のベース、そのあとはIDに使う属性名です。デフォルトではuidという属性が使われますが、今回は登録していないのでcnを使います。

Apacheを再起動すればldapとの連携が使えるようになります。

あとは、ネットワークを超えて使用できるようにTLSの設定やIPアドレスによる制限をかけないといけないんですが、長くなるのでまた今度。
というか、今の使い方では必要ないからしないかも。普段ネットワークを越えて使わない→TLSいらない、WebはIPによる制限かけてない→総当り攻撃だったら制限かけてもWebを通してできる、ってことで。あ、でもWeb通して変更はできないし、slapdに脆弱性があること考えたらやっぱり必要か。。。