2006-03-21 (Tue)

* ssh + bzip2 + gpg で bzip2 の internal error number 1007 エラー

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [ssh] [gpg] [ネットワーク] [PC]

毎日リモートにあるサーバのバックアップを ssh + tar + bzip2 + gpg で取っているのだが、7回に一回くらいの頻度で、tar の中から呼び出してる bzip2 が internal error number 1007 というエラーを出力してしまう。

クライアントは cygwin 環境。転送しているデータはだいたい数百メガバイトから数ギガバイトくらいのオーダー。下り 1.5Mbps の ADSL の回線で接続している。

bzip2/libbzip2: internal error number 1007.
This is a bug in bzip2/libbzip2, 1.0.3, 15-Feb-2005.
Please report it to me at: jseward@bzip.org.  If this happened
when you were using some program which uses libbzip2 as a
component, you should also report this bug to the author(s)
of that program.  Please make an effort to report this bug;
timely and accurate bug reports eventually lead to higher
quality software.  Thanks.  Julian Seward, 15 February 2005.


*** A special note about internal error number 1007 ***

Experience suggests that a common cause of i.e. 1007
is unreliable memory or other hardware.  The 1007 assertion
just happens to cross-check the results of huge numbers of
memory reads/writes, and so acts (unintendedly) as a stress
test of your memory system.

I suggest the following: try compressing the file again,
possibly monitoring progress in detail with the -vv flag.

* If the error cannot be reproduced, and/or happens at different
  points in compression, you may have a flaky memory system.
  Try a memory-test program.  I have used Memtest86
  (www.memtest86.com).  At the time of writing it is free (GPLd).
  Memtest86 tests memory much more thorougly than your BIOSs
  power-on test, and may find failures that the BIOS doesn't.

* If the error can be repeatably reproduced, this is a bug in
  bzip2, and I would very much like to hear about it.  Please
  let me know, and, ideally, save a copy of the file causing the
  problem -- without which I will be unable to investigate it.

エラーの内容は、bzip2/libbzip2 のバグか、メモリなどのハードウェア障害が考えられるというもの。散発的に発生するようなら ハードウェア障害の疑いがあるので、memtest86 などのメモリチェックツールで確認してとのこと。結構レアなエラーみたいだね。

私のマシンのメモリは 1GB * 2 の DDR-SDRAM ECC なし の Unbuffered なのがいけないの? でも、今までは問題なかった。もしかして私のマシン、壊れてきてるの? ネットワーク経由でやってるから、前段の ssh からうまくデータを受け取れてないとか? でもそれだったら bzip2 の内部エラーにはならず、もっと前の方でエラーになるだろうしなあ。

これだけじゃよくわからない。もっと詳細なログが必要だな。とりあえずログのレベルを上げた上でログを検分し、ハードウェアの交換も視野に入れた上で調査していこう。

2006-01-10 (Tue)

* rsync と ssh でミラーリングアップロード

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [ssh] [ネットワーク] [sonic64.com]

当サイト Landscape - エンジニアのメモのコンテンツのアップロードに、rsync を使うようにしてみた。

使ってみると、rsync は実に良くできた便利なツールであることがわかった。ちなみに今までは lftp を使っていた。詳しくは 2004-05-08 の「lftp を使った ftp ミラーリングと便利機能」を参照。さくらインターネットを使う前までは ftp しか許可されていなかったので仕方がないが、もっと早くから rsync に切り替えるべきだった。

- rsync でミラーリングアップロード

以下のコマンドで、ローカルで生成済みの Landscape のコンテンツをリモートのさくらインターネットのサーバに転送している。

rsync -t -r -z --include=*.html* --exclude=* -e "ssh -i $HOME/.ssh/sonic64.com_upload" $HOME/public_html/log.sonic64/ sonic64@sonic64.com:/home/sonic64/www/sonic64

コマンドの意味。
-t はファイルのタイムスタンプを転送先に反映させる。
-r はディレクトリを再帰的に転送する。
-z は圧縮を有効にする。

--include=*.html* --exclude=* はとりあえずあらゆるファイルとディレクトリを転送の対象外にして、その後 .html の拡張子を持つファイルのみ明示的に転送を許可している。要するに html だけ転送しているわけだ。$HOME/public_html/log.sonic64/*.html を転送対象に指定してもいいのだが、ファイル数が多すぎるために引数が長すぎるというエラーになってしまう。それを回避するため、$HOME/public_html/log.sonic64/ を転送対象として指定してから --include=*.html* --exclude=* で対象を *.html に絞っている。もっと上手いやり方もあると思うが、とりあえずこれで。

-e は ssh を使って接続を構成する。暗号化や公開鍵暗号による認証を利用できる。

ちなみに、ローカルに存在しないファイルをリモートから削除したい場合は、--delete オプションを指定する。私の場合はリモートにのみ存在するファイルやディレクトリがあるし、Landscape のコンテンツは増える一方で減ることはまずないので指定していない。

- rsync のデータ圧縮

rsync ではデータの圧縮をサポートしている。圧縮を使う場合は -z を指定する。テキストファイルを一気にミラーリングする場合などは、転送量を三分の一程度に減らすことができる。

$ rsync -W -v -t -r -z --include=*.html* --exclude=* -e "ssh -i $HOME/.ssh/sonic64.com_upload" $HOME/public_html/log.sonic64/ sonic64@sonic64.com:/home/sonic64/www/sonic64

sent 13460480 bytes  received 17636 bytes  45457.39 bytes/sec
total size is 43120469  speedup is 3.20

13460480 バイトしか送信していないのに、合計サイズが43120469 バイトになっている。これは圧縮の恩恵だ。

私の使っている回線のアップロード速度は、理論値で 512Kbps。実際の速度はだいたい秒間50KB くらいになる。 Landscape のコンテンツは合計で50MB 弱。圧縮せずに転送すると単純計算で1000秒、すなわち17分弱かかることになる。圧縮を有効にするだけで、17分が6分程度に短縮される。これは非常に便利だ。

ちなみに、-W オプションは 後述する「rsync アルゴリズム」を無効にするためのオプション。今回は圧縮による速度向上度合だけを計測したいので -W を指定したが、私の平常時の運用では指定していない。-v は詳細な転送情報を表示するためのオプション。

- rsync アルゴリズムと転送量の削減

rsync は独自の rsync アルゴリズムを使ってデータ転送量を削減している。しかもこれは圧縮と組み合わせることができる。

rsync アルゴリズムの良いところは、ファイルを一定サイズごとのブロックに分割して必要なブロックだけを転送している点にある。大きなファイルの一部分だけが変更されたとしても、変更を含むブロックだけを転送すればよいことになり、転送量を減らすことができる。

P2P ファイル共有ソフトの Winny でも類似の機能を実装している。2005-11-29 の「Winny の技術を読了」には詳しく書かなかったが、Winny はダウンロードに失敗しても、最初からダウンロードをやり直す必要はない。Winny は共有ファイルを64KB ごとのブロックに区切り、そのブロック単位でデータをやりとりするからだ。これと同じようなもの。

以下は記事を追加してミラーリングを行った場合。

$ rsync -v -t -r -z --include=*.html* --exclude=* -e "ssh -i $HOME/.ssh/sonic64.com_upload" $HOME/public_html/log.sonic64/ sonic64@sonic64.com:/home/sonic64/www/sonic64

sent 1771974 bytes  received 389842 bytes  40407.78 bytes/sec
total size is 43182507  speedup is 19.98

今の Landscape の HTML は、新規記事が追加されるとサイドバーに新規記事へのリンクなどが追加されるため、全ファイルが更新される。ftp だったら全ファイルを再アップロードする必要があるところだが、rsync は全ファイルの全データ分を転送するという挙動を見せていない。送っているのは 1771974 バイトだけ。ブロックの差分だけ転送している結果だ。このおかげで、通常の 19.98 倍という速度を達成している。素晴らしい。

ローカル生成 + サーバへ一括転送という仕組みのツールなら rsync は非常に有用だ。記事数2000くらいまでなら、今の仕組みのままでも大丈夫そうだ。rsync にはもっといろんな機能があるだろうから、しばらくは man rsync をじっくり読んでみることにする。

2004-11-22 (Mon)

* authorized_keysに書く no-pty と command="" の意味

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [ssh]

2004-11-17 に書いた「ssh scp sftp の正しい自動実行方法」の誤りについて指摘を頂いた。

ssh scp sftp の正しい自動実行方法 ぴろ日記
http://www.banana-fish.com/~piro/20041122.html#p01
> 下記は公開鍵の例。引用の際に改行を入れてしまっているが、実際は一行。
> from="*.example.com",no-port-forwarding,no-X11-forwarding, no-agent-forwarding,no-pty ssh-dss AAAAB3N...

えっと、authorized_keys自体を書き換えられる権限を、パスフレーズなしの鍵に与えてしまうと、結局ノーガードと同じことになってしまうです。悪い人の鍵でなんでもできるようにしたauthorized_keysをリモートにscpして一丁あがり。
あと、これも時々目にする勘違いだけど、「no-pty」は仮想端末とれなくなるだけで、シェルが取れなくなるわけじゃないので、仮想端末取らないで「ssh remotehost '/bin/sh' < 悪のスクリプト」とかやるだけの話。

指摘してくださってありがとうございます。穴を開けたまま運用するところでした。

確かに、上記のオプションのみに権限の限定を頼った場合、authorized_keys2 を上書きできてしまいますね。http://www.banana-fish.com/~piro/20040609.html#p06 に書かれてたことをスクリプトに反映できてない悪い見本になってました。2004-11-172004-11-18 の関連する部分に追記しました。なんで気づかなかったんだろう。

no-pty については誤解していました。なるほど、no-pty だけでは不十分というか、そもそも用途が違うわけですね。実行するコマンドを制限するなら、commmand="" を使わないと無意味だと。勉強になりました。実際に試してみたら楽勝で任意のコマンドをリモートで実行することができました。指摘を含め、2004-11-17 に追記しました。

2004-11-17 を書く前に、command="sleep 80000;" と no-pty をオプションに追加した公開鍵で scp を試していたのですが、sleep だけされてファイルの転送が全くなされないという結果に終わったため、command="" を外した権限の限定が不十分な公開鍵となったのでした。

その後は 2004-11-20 の以下のやり方を使うようにしています。
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="umask 077; f=backup`date +%F-%H%M%S`.encoded; echo $f; cat >/home/hiroaki/backup/$f;",from="*.example.com" ssh-dss AAAAB3N (略)

2004-11-20 (Sat)

* ssh + tar で安全なファイルコピー

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [シェルスクリプト] [ssh] [バックアップ]

2004-11-18 の「scp + tar + gpg で暗号化ネットワークバックアップ」について指摘を頂いた。

Misc Change Log 安全なファイルコピー
http://quasiquote.org/log/Memo/ssh_filecopy.html
http://sonic64.hp.infoseek.co.jp/2004-11-18.html#2004-11-18-1

ssh + tar じゃいかんのかいな。 rsh の時代からの基本だと思うのだが。

(cd path && tar cf - .) | ssh user@hostname "(cd path && tar xvfp -)"
暗号化したければ、送信側は tar の後、受信側は tar の前にいれてやればよい。何のために ssh 使ってるかわからないけど。

メンドイが、scp や sftp でもできなくはない。ヒントは mkfifo。でも本末転倒。だって scp も sftp も ssh のラッパーだから(少なくとも OpenSSH は。他の処理系はどうなのかな?)。

なんか変なこと書いてる?

ありがとうございます。恥ずかしながら、「rsh の時代からの基本」を知りませんでした。そもそも rcp や rsh は使ったことなかったりします。ssh + tar なら、出力を直接標準入力に渡したいという要件は満たしています。

2004-11-18 の「scp + tar + gpg で暗号化ネットワークバックアップ」を書いた後、FreeBSD QandA 2255 http://www.jp.freebsd.org/QandA/HTML/2255.html を読んでいて、ssh の標準入出力を使う方法があることを知って試してみてはいました。ただ、使い勝手とセキュリティの兼ね合いがまだできてなかったので公開してませんでした。

ローカルマシンで以下を実行し、tar + gpg したデータを ssh に渡してアップロードする。
echo $PASS_PHRASE | { tar --bzip2 -cf - $TAR_TARGET |gpg --batch -c --cipher-algo AES256 --force-mdc --passphrase-fd 3;} 3>&0 |ssh -i $HOME/.ssh/auto $REMOTE_SERVER -l $REMOTE_USER

上記コマンドで使っている公開鍵。
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,command="umask 077; f=backup`date +%F-%H%M%S`.encoded; echo $f; cat >/home/hiroaki/backup/$f;" ssh-dss AAAAB3N (略)

command="" と no-pty を使って安全性を高められるのは良いんですが、出力先ファイル名がリモート側で生成されることが不便。環境変数 SSH_ORIGINAL_COMMAND を使うか、それとも他にもっと良い方法ないかなーと探している状態でした。でもこれで ssh + tar + gpg + SSH_ORIGINAL_COMMAND で問題なさそうとわかったのでこの方法を使うことにします。ありがとうございました。

mkfifo は思いつきませんでした。なるほど、これなら中間ファイルを作らないというのは実現できますね。名前付きパイプって使ったことありませんでしたが、いろいろ面白いことができそう。

- ssh を使ってるのに、なぜわざわざ gpg でファイルを暗号化するのか

何のために ssh 使ってるかわからないけど。

ssh は経路の安全性と認証の安全性を確保するため、gpg はファイルの安全性を確保するために使っています。2004-11-18 において背景を書かずに、「このご時世に外部にデータを持ち出すなら、通信の暗号化とファイルの暗号化は必須だと思う。」で済ませてしまったのは言葉が足りませんでした。

今回の件では、遠隔地のファイルバックアップ用サーバにデータを送ることを想定していました。

共用のサーバであれば、パーミッションが甘いと他の一般ユーザにファイルを見られてしまいます。そんな事態は論外ですが。私だけが使える専用サーバだとしても、遠隔地にあるので管理者権限を持った人間が現地にいます。悪意を持った管理者ならファイルを見ることができてしまいます。

また、万が一マシンが盗難などにあうと、盗んだ人間にもデータの中身を見られてしまいます。もちろん、盗難などに備えて、設備管理者は防犯対策を、システム管理者はファイルシステムの暗号化などの対策はやっておくべきです。同じように、一般ユーザである私にできることがあるならやっておこう、という意味で GPG を使ったファイルの暗号化を施しています。

セキュリティは各担当者の積み重ねの結果確保できるものであって、各担当者が手を抜いた場合、手を抜かれた箇所に依存する部分の安全性が揺らいでしまいますしね。

- 訂正

追記。やっぱり変なこと書いてた。リモートマシンで pgp したいのか。全然読んでなかったorz

なら上のスクリプトを実行後、

ssh user@hostname "(cd path && find . -type f -exec gpg options {} \;)"
でどうよ? gpg は使ってないので知らない。ので、オプションは適当に。 tar ファイルで送ったものを単に gpg したいなら(多分これがお望みの方法だろう)、

(cd path && tar cf - .) | \
ssh user@hostname "(cd path && gpg options > filename.tar.gpg)"
さらに圧縮したいなら、

(cd path && tar cf - . | bzip2 -9) | \
ssh user@hostname "(cd path && gpg options > filename.tar.bz2.gpg)"
でいい罠。

いえ、ローカルで暗号化しないとデータの安全性を確保しにくいので、暗号化はローカルでやって暗号化したデータのみを外部に送信したいところです。なぜ「リモートマシンで pgp したいのか」と解釈なさったんだろう? あ、なるほど。2004-11-18 の以下の部分ですね。

もちろんこれに gpg を組み合わせれば、転送後のリモートマシン上でのファイルの暗号化も実現できる。

確かにこれだと「リモートマシンで gpg を実行したいと」解釈できますね。表現が良くなかったので以下のように改めます。

「ssh/scp/sftp のみを使った場合はデータが暗号化されるのは通信経路上だけだが、gpg を組み合わせればリモートマシンに送ったあともデータを暗号化された状態に保つことができる。」

2004-11-18 (Thu)

* scp + tar + gpg で暗号化ネットワークバックアップ

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [シェルスクリプト] [バックアップ] [ssh] [gpg]

scp + tar + gpg で経路とファイルを暗号化したネットワーク・バックアップをおこなう。

- 要するに 2004-03-19 の「ftp + tar + gpgで暗号化ネットワーク・バックアップ」の置き換え

2004-03-19 に「ftp + tar + gpgで暗号化ネットワーク・バックアップ」という記事を書いた。この方法だとファイル自体は gpg によって暗号化しているので、中身を解読される可能性は低い。しかし、ftp を使っているため 経路上で ID と パスワードを盗聴されるおそれがある。ファイルの安全とアカウントの安全は別の問題だ。

無料ホームページサービスのように ftp のみのサービスしているホストの場合は盗聴に対して有効な対策をとるのが難しい。しかし、ssh をサービスしているホストなら scp や sftp を使うことで通信の暗号化を実現できる。

ssh/scp/sftp のみを使った場合はデータが暗号化されるのは通信経路上だけだが、gpg を組み合わせればリモートマシンに送ったあともデータを暗号化された状態に保つことができる。このご時世に外部にデータを持ち出すなら、通信の暗号化とファイルの暗号化は必須だと思う。

- scp 用の鍵作成

2004-11-17 の「ssh scp sftp の正しい自動実行方法」のやり方で scp 専用かつ権限を限定した鍵を作成。これを使う。

2004-11-22 追記。
2004-11-17 に書いた、command="" の指定がない公開鍵を使った場合は権限の限定が不十分。command="" を使わずに scp 専用の鍵としたいならば、ファイル転送に特化したシェルを使うなどの対策を講じないと結果的にシェルへのアクセスを許してしまうおそれがある。詳しくは 2004-11-22 「authorized_keys に書く no-pty と command="" の意味」を参照。

- scp は標準入力からデータを読んでくれない

2004-03-19 の「ftp + tar + gpgで暗号化ネットワーク・バックアップ」の利点の一つに、gpg が出力したデータを直接 ftp の標準入力に渡してアップロードする、というものがある。これのおかげで余計な中間ファイルを作らずに済む。

scp でも同じ事をしようと思ったのだが、なんと scp には標準入力からデータを読んで直接アップロードという機能がない。scp の man page を読んでみたが、代替の機能は見つけられなかった。仕方がないので一度ファイルに書き出すことにした。

scp man scp.0
http://www.unixuser.org/~euske/doc/openssh/jman/scp.html

- scp + tar + gpg で暗号化ネットワークバックアップするシェルスクリプト

というわけでできたのが以下のスクリプト。これを cron で自動実行する。

#!/bin/sh

# setup
PASS_PHRASE="MY SECRET PASS PHRASE STRING"
TAR_TARGET="/home/hiroaki/log.txt /home/hiroaki/etc /cygdrive/s/cvsroot"
OUTPUT_FILE="backup`date +%F-%H%M%S`.tar.bz2.encoded"
OUTPUT_PATH="/home/hiroaki/tmp/$OUTPUT_FILE"
REMOTE_SERVER=backup.example.com
REMOTE_USER=hiroaki
REMOTE_UPLOAD_DIR=/home/hiroaki/backup

date
echo $TAR_TARGET
echo $PASS_PHRASE | { tar --bzip2 -cf - $TAR_TARGET |gpg --batch -c --cipher-algo AES256 --force-mdc --passphrase-fd 3;} 3>&0 >$OUTPUT_PATH

echo output to $OUTPUT_PATH
scp -oIdentityFile=$HOME/.ssh/auto $OUTPUT_PATH $REMOTE_USER@$REMOTE_SERVER:$REMOTE_UPLOAD_DIR
if [ $? -ne 0 ]; then
  echo "`date` scp error" >&2
  exit 1
fi
rm -f $OUTPUT_PATH

echo backup complete
date

- scp では今回の目的には力不足

やっぱり標準入力から渡したデータをアップロードしたい。gpg の生成したファイルのハッシュをチェックしたり、scp以外のプログラムでも gpg の出力を利用したり、ローカルにもファイルをため込んだりしたい場合は一度ファイルに出力する方がいいのだが、今回はそんなことはしないし。

また、ファイルをアップロードした後にパーミッションを落としておきたいんだけど、scp では chmod などを発行できないようなのでそれもできない。umask を 077 にしておくだけじゃなくて、アップロードしたファイルに 600 を明示的に指定したいんだけどなあ。

scp コマンドがバージョンアップして機能が強化される見込みもなさそうだし。

OpenSSH FAQ
http://www.ie.openbsd.org/openssh/ja/faq.html#2.10
2.10 - scp に (なにかの機能) を追加してくれない?
短い答え: だめです。

長めの答え: scp は標準化されていないのです。それにもっとも近いものは「rcp が何をやるか」という仕様だけです。これは接続の両側で同じコマンドが使われるため、機能やオプションを追加すると異なる実装の間で相互運用できなくなる危険性があります。

新しい機能は sftp のほうが追加されやすいでしょう。なぜならこのプロトコルは標準化されていますし (まあ、 ドラフト標準ですが)、クライアントとサーバが別々になっているからです。

今回の目的には scp はあまり適していないようだ。明日は sftp を試してみよう。

2004-11-17 (Wed)

* ssh scp sftp の正しい自動実行方法

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [ssh] [セキュリティ]

scp と sftp について調べていると、正しい自動実行についての文書を見つけた。cron から scp や sftp を自動実行しようと考えている私には役に立つ文書だ。

- 「専用のパスフレーズなしの鍵を作って権限限定」がベスト

正しいssh/scpの自動運転は ぴろ日記
http://www.banana-fish.com/~piro/20040609.html#p06
おねがいだからパスワード入力をexpectで自動化なんつーバッド・ノウハウをWebで広めないでくれ。(略)
あとcronとかからssh/scpするのにssh-agentでパスフレーズ入力を自動運転ってのもバッド・ノウハウな。

正しいssh/scpの自動運転は:

自動運転専用の鍵をパスフレーズなしで作成する。
でもって、その鍵を使ってやれることを、いかにして必要最小限の作業だけに制限するかを考える

が正解(現時点では)。

必要最小限の作業に制限する方法としては、

毎回完全に同じコマンド(引数含めて)しか実行しないなら、authorized_keysでcommand='...'を使って実行できるコマンドをそれだけに制限。
ファイル転送用途だけなら、scponlyとかの転送用途に限定されたシェルをリモートのアカウントのシェルに設定する。
上記2つのケースには該当しないけれど、特定のコマンドに実行を制限したい時はrestricted shellとか。
可能ならchroot patchをあてたsshdを使ってchroot環境作るのも良い。
あるいはauthorized_keysのcommand='...'機能を使って強制的に特定のコマンドを実行された場合に、本来リモートから(ssh host 'cmd...'等で)与えられたコマンドラインが環境変数SSH_ORIGINAL_COMMANDに保存されるのを利用して、SSH_ORIGINAL_COMMANDを自前で安全に処理するコマンドを作るとか。

とかって方法が考えられる。さらに、どうしても必要最小限のコマンドに制限できない場合は、接続元のホストを制限した上で接続元ホストの方を守るのと、実行されたコマンドのログをacct等で確実に取る(必要ならアラートも飛ぶようにする)。

なるほど、鍵でできることを限定することが先決か。あとは変なイベントが上がったときに検出する仕組みを作っておくってことね。

あと、意外に多い誤解が、「パスフレーズなしの秘密鍵は(パスワード認証における)パスワードなしと同じくらい危険」とか、(略)
秘密鍵のパスフレーズは秘密鍵ファイルを暗号化してるだけのもんです。逆に言うと秘密鍵ファイルを悪者に盗まれてしまったら、たとえパスフレーズが設定されていても、↑のCrack ( http://www.crypticide.com/users/alecm/ ) みたいなオフライン攻撃が可能、つまり悪者は手に入れた秘密鍵をどっか別の安心して作業ができるマシンでじっくり辞書攻撃なり総当り攻撃なり使ってパスフレーズを探すことができる。

なので、「秘密鍵を他人に渡さない」ということの方が、パスフレーズを設定することよりも遥かに重要。パスフレーズはいざという時の時間稼ぎでしかない。

それが分かれば、ssh-agentやkeychain使うより、いさぎよくパスフレーズなしにしちゃった方がいいってのも分かると思う(自動運転の場合ね)。だって、適切なパーミッションが設定されている秘密鍵ファイルを盗める人間(rootとか)なら、常駐しているssh-agent/keychainも乗っ取れるでしょ。パスフレーズ設定してる意味がない。「なんかの拍子にssh-agentのプロセスが死んじゃってて(めったにないけど)、自動運転に失敗した」とか、「サーバをリブートするたびに、パスフレーズ入力してssh-agent起動しないといけない(運用担当者全員にパスフレーズ教えないといけない)」とかって、余計な手間が増えるだけ。

確かに。再起動の度に ssh-agent 起動はやだなあ。ここでまた運用ミスが発生しかねないし。だったらパスフレーズ無しの方が理にかなってる。結局セキュリティは利便性とトレードオフになることが多い。今回の件では妥当な判断だと思う。

- 自動実行用の鍵作成

というわけで実際に権限を限定してみる。今回は authorized_keys2 レベルの話。ファイアウォールとか OS の話は別次元。そういうのは ssh に限らないレベルの話なのですべてやってあることが前提。

自動実行専用の鍵を作成。-N オプションでパスフレーズを指定できる。今回は空で作成した。
$ ssh-keygen.exe -t dsa -N "" -f ~/.ssh/auto_execute

生成した公開鍵 ~/.ssh/auto_execute.pub に from="*.example.com",no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty オプションを付加し、リモートサーバの ~/.ssh/authorized_keys2 に追加。

下記は公開鍵の例。引用の際に改行を入れてしまっているが、実際は一行。
# 2004-11-22 追記。
# 以下の公開鍵のオプション指定では権限を限定できていない。
# 権限を限定できている公開鍵の例は、
# 後述の「できることを限定した自動実行用の鍵で ssh 接続してみる」の項を参照。

from="*.example.com",no-port-forwarding,no-X11-forwarding,
no-agent-forwarding,no-pty ssh-dss AAAAB3NzaC1kc
3MAAACBAKZhqMdcujcJgGOCIsi+PrmkEEaAy/gpRPpB3Q5OA
wNG+PwTdU5O8/NPde64wNux4XNUB7XkV2eXWfaTZRYyYe0oC
XeJMh2LKZ/a/F3Wu283uuExSZhbkt3Dcv3+u6oyjBzIfNU+P
(以下略)

2004-11-22 追記。上記の鍵に付けたオプションだけでは無意味という指摘を頂いた。

ssh scp sftp の正しい自動実行方法
http://www.banana-fish.com/~piro/20041122.html#p01
えっと、authorized_keys自体を書き換えられる権限を、パスフレーズなしの鍵に与えてしまうと、結局ノーガードと同じことになってしまうです。悪い人の鍵でなんでもできるようにしたauthorized_keysをリモートにscpして一丁あがり。

あと、これも時々目にする勘違いだけど、「no-pty」は仮想端末とれなくなるだけで、シェルが取れなくなるわけじゃないので、仮想端末取らないで「ssh remotehost '/bin/sh' < 悪のスクリプト」とかやるだけの話。

指摘の通り、上記の鍵では ~/.ssh/authorized_keys2 に scp されることを防げないので意味がない。

また、command="" が無い場合、以下のようにシェルに直接コマンドを送り込むことができる。試したら authorized_keys2 の中身がローカルの端末に表示された。
$ echo "cat .ssh/authorized_keys2" |ssh -i /home/hiroaki/.ssh/auto remotehost.example.com -l hiroaki

結局、commnad="" を使えない場合は、「正しいssh/scpの自動運転は」 http://www.banana-fish.com/~piro/20040609.html#p06 で提示されていた方法で権限を限定する必要がある。

- 指定したオプションの説明

sshd.0
http://www.unixuser.org/~euske/doc/openssh/jman/sshd.html
authorized_keys ファイルの形式 から抜粋。
authorized_keys ファイルの形式

from="pattern-list"
        このオプションをつけると、公開鍵認証に加えて、クライアントのホス
        トをチェックできるようになります。カンマで区切ったリモートホスト
        名 (canonical name) のパターン列が指定できます (`*' および `?' が
        ワイルドカードとして使えます)。このリストには「〜でない」という否
        定 (negation) を入れることもできます。その場合はパターンの先頭に
        `!' をつけてください。否定つきのパターンにホストの canonical name
        がマッチした場合、この鍵は許可されません。このオプションはセキュ
        リティを上げるためにつけられました: 公開鍵認証それ自体は、(鍵を除
        いて) ネットワークやネームサーバ、その他ありとあらゆるものを信用
        しません。しかし、もし何物かが何らかの方法で鍵を盗むことができれ
        ば、その鍵を使って世界のどこからでもログインできてしまうことにな
        ります。このオプションは、そのような盗まれた鍵を使うことをより困
        難にします (もしこれを使おうとするなら、鍵のほかにネームサーバや
        ルータまでも手を入れなくてはならないからです)。

(略)

command="command"
        このオプションを使うと、認証にこの鍵が使われたときは必ずここで指
        定されたコマンドが実行されるようになります。ユーザが (訳注: クラ
        イアント側で) 指定したコマンドは無視されます。クライアント側が仮
        想端末を要求していれば、ここで指定されたコマンドは仮想端末上で実
        行されます。そうでなければ端末なしで実行されます。 8-bit クリーン
        な通信が欲しい場合は、仮想端末を要求してはいけません。あるいは
        no-pty オプションを使ってください。コマンド文字列中に引用符 (")
        を入れたいときは、バックスラッシュを前につけてください。このオプ
        ションは、ある公開鍵には特定の操作だけしかさせないようにするのに
        有効です。例として、リモートバックアップだけをさせて、それ以外な
        何もさせないような鍵がつくれます。クライアントの TCP/IP や X11 転
        送は、明示的に禁止されていない限り可能なので注意してください。こ
        のオプションはシェル、コマンドまたはサブシステムの実行に適用され
        ます。

no-port-forwarding
        認証にこの鍵が使われたときは TCP/IP 転送が禁止されます。クライア
        ントがポート転送を要求しても、すべてエラーになります。これはたと
        えば command オプションの指定されている接続などで使われます。

no-X11-forwarding
        認証にこの鍵が使われたときは X11 転送が禁止されます。クライアント
        が X11 転送を要求しても、すべてエラーになります。

no-agent-forwarding
        認証にこの鍵が使われたときは、認証エージェントの転送が禁止されま
        す。

no-pty  端末の割り当てを禁止します (仮想端末の割り当てが失敗するようにな
        ります)。

- できることを限定した自動実行用の鍵で ssh 接続してみる

前述の no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty を指定した scp/sftp 用の鍵を使い、putty で sshd に接続。TCP 接続はできるが、
Server refused to allocate pty
と表示されてシェルに入れなかった。no-pty の効果だな。ちなみに putty は CTRL + D で終了できた。

2004-11-22 追記。
前述の通り、上記は仮想端末が割り当てられていないだけで、シェルは使用可能となっている。できることを限定したければ、command="" を指定するか、scponly などのシェルを割り当てる必要がある。

今回は command="" を使う方を試してみた。以下は公開鍵の例。引用時に改行を入れているが、実際は一行。
no-port-forwarding,no-X11-forwarding,no-agent-forwarding,no-pty,
command="echo $SSH_ORIGINAL_COMMAND; umask 077; f=backup`date +%F-%H%M%S`.tar.bz2.encoded; echo $f; cat >/home/hiroaki/backup/$f;,from="*.example.com"
ssh-dss AAAAB3NzaC1kc
3MAAACBAKZhqMdcujcJgGOCIsi+PrmkEEaAy/gpRPpB3Q5OA
wNG+PwTdU5O8/NPde64wNux4XNUB7XkV2eXWfaTZRYyYe0oC
XeJMh2LKZ/a/F3Wu283uuExSZhbkt3Dcv3+u6oyjBzIfNU+P
(以下略)

ローカルから接続してみる。
$ echo "cat .ssh/authorized_keys2" |ssh -i ~/.ssh/auto $remote_host -l $remote_user
Pseudo-terminal will not be allocated because stdin is not a terminal.

backup2004-11-22-235811.tar.bz2.encoded

リモートに生成された backup2004-11-22-235811.tar.bz2.encoded の中身は以下のようになっていた。
cat .ssh/authorized_keys2

scp も試してみる。

$ scp -oIdentityFile=~/.ssh/auto file $remote_user@$remote_host:~/backup/test
scp -t /home/hiroaki/backup/test

command="" のおかげで、~/backup/test は生成されずに済んだ。

2004-10-01 (Fri)

* PuTTY のインストールと鍵作成・鍵管理

この記事の直リンクURL: Permlink | この記事が属するカテゴリ: [ssh] [ソフトウェア] [セキュリティ]

SSH を使ってリモートサーバにログインするために、PuTTY をインストールして環境設定するためのメモ。

PuTTY は今までも使っていたけど、LAN の中にあるサーバに接続するだけだったので、SSH じゃなくて Telnet をメインに使っていた。本当は LAN の中でも SSH を使う方が望ましいんだけど。

- ダウンロード

hdk の自作ソフトの紹介
http://hp.vector.co.jp/authors/VA024651/#PuTTYkj_top
executable files (PuTTY version 0.55 にパッチをあてた実行ファイル puttyjp.exe) をダウンロード。

PuTTY Download Page
http://www.chiark.greenend.org.uk/~sgtatham/putty/download.h ...
pageant.exe と puttygen.exe をダウンロード。putty-0.55-installer.exe の方がまとめてインストールされるので楽かも。

- PuTTY で SSH2 用の鍵を作成

puttygen.exe を起動し、RSA や DSA などの鍵タイプとビット数を指定して Generate を押す。プログレスバーの下の空欄でマウスを動かせ、という指示が出るのでマウスをテキトーに動かす。動かさないとプログレスバーは進まない。マウスを動かすと進む。これを利用して、「だるまさんがころんだ」みたいにして遊ぶこともできる。絶対勝てないけど。

鍵の生成が終わったら、パスフレーズを入力。"Save Public Key" と "Save Private Key" のボタンで公開鍵と秘密鍵を保存。この段階では puttygen.exe はまだ終了しないように。

- PuTTY で作成した鍵を OpenSSH 用の鍵に変換

PuTTY で作成した鍵は、そのままでは OpenSSH では使えないので変換する必要がある。そのままでは、
Server refused our key
などとサーバに拒否されてしまう。

ssh-keygen コマンドで変換しても良いし、テキストなのでコピーアンドペーストしてもいい。
今回はコピペを使う。puttygen.exe の Public key for pasting into OpenSSH authrized_keys file: と表示されている部分をコピーして、先ほど保存した公開鍵ファイルの中身を全部上書きする。

ssh-keygen コマンドを使った変換は、
@IT:鍵交換方式のsshでアクセスするには
http://www.atmarkit.co.jp/flinux/rensai/linuxtips/429usekeys ...
がわかりやすい。

- サーバに公開鍵を配置

接続先サーバのホームディレクトリにある .ssh ディレクトリに公開鍵 authrized_keys2 を配置する。ファイル名は authrized_keys2 にしておこう。authrized_keys2 のパーミッションは 600、.ssh のパーミッションは 700 にする。これ以外のパーミッションだと接続できない場合がある。

- PuTTY に使用する秘密鍵とログインIDを指定

PuTTY を起動し、PuTTY 設定ウインドウで「接続」を選び、「自動ログインのユーザ名」に接続先サーバのログインID を指定。「SSH」の「認証」を選び、「認証のためのプライベートキーファイル」に秘密鍵のパスを指定する。あとは「セッション」で接続先サーバ名とポートを選び、今回設定した内容に名前をつけて保存しておく。

- 相手先に接続

相手先サーバに初めて接続する場合、相手の鍵は既知の鍵ではないので、その鍵を信頼するか尋ねられる。今回は未知の鍵なので Yes を選択する。既知の鍵なのにこの警告が出たら、鍵がすり替えられているかもしれない。

あとは秘密鍵のパスフレーズを入力すればログイン完了。

- pageant.exe で鍵の管理とパスフレーズ自動入力

pageant.exe を使うと、パスフレーズが必要な場面で自動入力してくれる。pageant.exe を起動し、 Add Key ボタン押して秘密鍵ファイルを指定する。パスフレーズを聞いてくるので入力すると、pageant.exe に秘密鍵が登録される。この状態で先ほど設定したサーバに PuTTY で接続すると、自動的にログインできる。

秘密鍵ファイルの拡張子を pageant.exe に関連づけておけば、秘密鍵ファイルのダブルクリックで pageant を起動して pageant.exe に登録することができる。もちろんパスフレーズを尋ねられるけど。パスフレーズを Windows のスタートアップに登録しておくのも便利かも。

- 参考

@IT:Windowsからssh 2でLinuxにログインするには
http://www.atmarkit.co.jp/flinux/rensai/linuxtips/416usessh2 ...

@IT:鍵交換方式のsshでアクセスするには
http://www.atmarkit.co.jp/flinux/rensai/linuxtips/429usekeys ...

@IT:Linuxでsshの鍵を作成するには
http://www.atmarkit.co.jp/flinux/rensai/linuxtips/432makessh ...

あとは Google で検索すればどうにでもなる。スクリーンショット付きの解説ページもあるし。

すべての記事の見出し (全1029件)
全カテゴリの一覧と記事の数
カテゴリごとに記事をまとめ読みできます。記事の表題だけを見たい場合は、すべての記事の見出し (カテゴリ別表示) へ。

直近30日分の記事
2007-04-23 (Mon)
2007-03-07 (Wed)
2007-02-27 (Tue)
2007-01-17 (Wed)
2007-01-15 (Mon)
2007-01-14 (Sun)
2007-01-08 (Mon)
2006-12-01 (Fri)
2006-11-22 (Wed)
2006-11-20 (Mon)
2006-11-19 (Sun)
2006-09-30 (Sat)
2006-08-29 (Tue)
2006-08-04 (Fri)
2006-07-27 (Thu)
2006-07-23 (Sun)
2006-07-17 (Mon)
2006-07-10 (Mon)
2006-07-06 (Thu)
2006-07-03 (Mon)
2006-06-29 (Thu)
2006-06-28 (Wed)
2006-06-27 (Tue)
2006-06-25 (Sun)
2006-06-19 (Mon)
2006-06-18 (Sun)
2006-06-15 (Thu)
2006-06-11 (Sun)
2006-06-01 (Thu)
2006-05-30 (Tue)
プロファイル
斎藤 宏明。エンジニアです。宇都宮市に住んでいます。
リンク
RSS
スポンサードリンク
Powered by
さくらインターネット

© 斎藤 宏明 Saito Hiroaki Gmail Address
Landscape - エンジニアのメモ http://sonic64.com/
Landscape はランドスケープと読みます。
ひらがなだと らんどすけーぷ です。