Hello, world.

こつこつと

2008/11/28

KVM + Virtio on Gentoo

ひさしぶりに、更新。
今回は、KVM(Kernel Based Machine)を使ってみた。

発端は、久しぶりにPCを組んだこと。
なにかといじくるのに、今、性能の良いマシンが手元になかったので、一台、2年ぶりくらいに作ってみた。

構成は以下の通り。
  • CPU: Phenom X4 9950BE (x15に倍率変更して、3GHzで駆動)
  • Memory: DDR2-800 2GB x 4 = 8GB(UMAXの安いの)
  • MotherBoard: GIGABYTE GA-MA78GPM-DS2H
  • 電源:剛力プラグイン 450W
  • DISK: とりあえず、HGSTの500GB 5400rpmのやすいやつ。
  • ケース: DC-ACPCD/R(いわゆる、まな板)
これで、約45,000円、なんか価格に対する性能が半端ない気がします。
まな板 に組んでるので、家に普通に設置するには向きませんが、うちの会社の足下に今は放置されてます。
ちなみに、まな板とマザーは、マザー裏側につけられているファン固定用のプラスチックが干渉して、
ねじ止めできないことが発覚。なので、まな板の上に、置いているだけです。
また、5インチベイにマウントするなにかがあったほうがいいです。
まな板は、構造上、DVD-ROMドライブなどで、アクリル板を支えるようになっているようです。
とりあえず、私は、適当な雑誌で代替してます。

これくらいの性能のマシンだと、そのまま使っても性能使い切れないだろうなぁ、とおもったのが発端。
それで、ちょうどUPnPとかDLNAといった単語が飛び交う仕事もあったりしたので、
この手の環境つくるのに、物理的に複数マシンを用意するのは無駄だな、ってことで、
KVMをいれてみようということになりましたとさ。
んで、調べてると、CPUだけじゃなく、メモリ、ディスク、NIC、RTC?も準仮想かされているって記述があり。
そのへんをvirtioという形ですでに、kernelにマージされているらしいということで使ってみた。
virtioは、基本的に、ゲスト側もドライバが必要です。Windows向けも配布されてます。

まず、このマシンにGentoo 2008.0のinstall CDをもってきてインストールします。
ちなみに、インストールは、SD+USBのリーダーから行いました。このへん見れば、簡単にできます。
あ、メモリ8GBもつんでるし、ってことで、x86_64をインストールしてること前提。
まあ、i386でも、それほど差はないかも。amd64は、Portageで、MASKされまくってるので、むしろそっちのほうが楽?

こちらは、おそらく特に問題なく入るはず。
カーネルの設定は、
  • DISKは、BIOS設定で、とりあえず、全部AHCIにしとけば、カーネルもAHCI有効にしておけばOK。
  • TIMER関係は、virtioの性能向上のために、高精度、高頻度にしとくのが吉らしい。
  • Soundは、SB700は、Intel HD Audioで動く。
    (BIOSで無効にしてても、中途半端に認識する、が音(アナログ)は鳴らないので注意!これで、3時間くらいはまった。)
  • NICは、r8169なので、とくに問題なく動く。
  • Virtualizationから、KVMを有効にしとく。
これくらいで。あとは、手順通りにインストールすれば、すんなりいくはず。

肝心のKVM。
なんか今の環境は、いろいろ試行錯誤したので、結局、素でソース持ってきて、最新版(KVM-79)を使った。
でも、たぶん、Virtioとかはうごくので、PortageのKVM-78でいいかも。

ここからは、一応、Portage使うの前提で。
あ、手でKVMをコンパイルすると、
何故かKVMのconfigureスクリプトがフィルタ(enable/disableが含まれているものしか出さないようにしている?)して、
qemuのac97が有効にするオプション(--audio-cardlist)が./configure --helpで出てこないので、
$ ./qemu/configure --help

も実行してみて、KVMのconfigure実行時にほしいオプションは付け加えるが吉。
kqemuはたぶん、有効にしないほうが安全っぽい。

■Portageからのインストール
GentooのPortageから入れようとすると、~amd64は、Maskされている。
ので、Overlayを作る。
まず、/etc/make.confに
PORTDIR_OVERLAY=/usr/local/overlays

を追加。

# mkdir /usr/local/overlays
# mkdir /usr/local/overlays/app-emulation
# cp -a /usr/portage/app-emulation/kvm /usr/local/overlays/app-emulation/


で、KVMをコピーしてくる。
んで、kvm-78.ebuildのKEYWORDS="~amd64"となってるところを"amd64"(チルダを外す)だけ。
Digest作り直し。
# ebuild kvm-78.ebuild digest


そして、インストール。といきたいけど、道連れ(依存関係)でインストールされるqemuがこのままだとインストールできない。
gcc3系が必要だとのこと。
(ちなみに、KVM-79を手で落としてきて、x86_64なものだけをコンパイルするなら、gcc4.1.2でもいけた。)

なので、まず、
# emerge -av sys-devel/gcc:3.4

として、gcc3を入れる。gcc-3.4.6が入った。

んで、gccを変更。
# gcc-config -l

で、今使えるgccのリストが出る。gccって、こんな機能あったんだね、とひとりで感心。
余談ですが、crossdevで、クロスコンパイラ入れてると、それも出てきた。

左の添え字を指定すると切り替えれる。2がgcc-3.4.6だったら、
# gcc-config 2

んで、/etc/profileを読み直せ、と言われるので、
# source /etc/profile


この状態で、
# emerge qemu

とすると、インストールできるはず。

そして、gccをもとに戻す。
# gcc-config -l
# gcc-config 7


そして、
# emerge kvm

でインストールできるはず。

この後、kvmをロードする。AMD Phenomなので、
# modprobe kvm_amd

でいけた。

そして、Gentoo用のHDDイメージ作成とインストール
ここでも、試行錯誤の結果、virtio_blkを有効にして起動しちゃうと、ゲスト側のkernelが2.6.25以上じゃないと、
ディスクが認識されないので、だめぽ。
まあ、model=scsiとかを指定して、インストールすればいけるんですが、
それはちょっとカコワルイとか、意味のないことをおもったので、手順を軽く変更しました。

とりあえず、Gentooのインストール作業は、Linuxが動いていればそれなりにどうにかなるので、
Ubunto 8.10のインストールCDで起動してインストールしちゃいます。
てことで、適当に、ubuntuのインストールCDのISOイメージをダウンロードしてきます。

それに先だって、まずは、インストール先のHDDイメージ作成。
# kvm-img create -f qcow2 gentoo.img 60GB

で、qcow2という伸縮するimgができるみたい。とりあえず、60GBで作った。

そして、インストール用に以下のようなオプションで起動。(オプションの意味は、man qemuとかで。)
$ export QEMU_AUDIO_DRV=alsa
$ sudo kvm \
-m 2048m -monitor stdio -curses -vnc :0 \
-vga vmware \
-soundhw ac97 \
-drive file=hdd_image/gentoo.img,if=virtio,boot=on \
-localtime -k ja \
-net nic,vlan=0,model=virtio,macaddr=52:54:00:12:34:00 \
-net tap,vlan=0,ifname=tap0,script=scripts/ifup \
-cdrom install_image/ubuntu-ja-8.10-desktop-i386.iso \
-boot d


あ、ネットワークは、NATでなく、ブリッジで動かしてます。
なので、modprobe tunは実行しておく必要ありです。
また、ホスト側のマシンで、あらかじめブリッジを構築しておく必要があります。
それで、/dev/net/tunは、groupにrwの権限あたえたのですが、うまく動かなかったので、
sudoして、rootで動かしてます。これはどうにかしたい。

script/ifupは以下のような内容。
sudo /sbin/ifconfig $1 0.0.0.0 promisc up
sudo /sbin/brctl addif br0 $1

たしかこれは、どっかからぱくってきただけ。

んで、起動すると、Ubuntuがあがってくるはず。最悪、Xは起動しなくてもOK。コンソールだけでもインストールはできる。
そして、VNCクライアントを用意します。
これは、Windowsだと、UltraVNC、Macだと、Vine Viewerを使っています。(Chiken of VNCはうまく動かんかった。)

そして、通常と同じ手順でインストールをしていきます。
ただし、ディスクは、/dev/vdaとして認識されているので、注意。
カーネル構築時には、virtio関連を、Mではなく、yでカーネルに組み込みます。
はじめは、genkernelでinitramfsで起動しようとがんばってみたけど、
/usr/share/genkernel/x86/modules_load
に、virtio_blkを書いても、どうもうまくいかんかったので、挫折。なんでかはわからずじまい。

Grubインストールは、Gentooのstage3 tarball付属のでは、どうも/dev/vd*に対してのインストールは対応してない模様。
なので、苦肉の策で、Ubuntuのほうに、chrootな環境から抜けて、Ubuntuに付属のgrubでインストールをする。
そこでも、grub-installコマンドでは、どうもうまくいかんかったので、
# grub

で、とりあえず、コンソールにはいって、
# root (hd0, 0)
# setup (hd0,0)

なら、うまくいった。謎。
あ、あと、/boot/grub/device.mapもたぶん、(hd0,0) /dev/vdaとか手で書き加えた。
これで、一回、シャットダウンします。

そして、もう一回、qemu起動。
$ export QEMU_AUDIO_DRV=alsa
$ sudo kvm \
-m 2048m -monitor stdio -curses -vnc :0 \
-vga vmware \
-soundhw ac97 \
-drive file=hdd_image/gentoo.img,if=virtio,boot=on \
-localtime -k ja \
-net nic,vlan=0,model=virtio,macaddr=52:54:00:12:34:00 \
-net tap,vlan=0,ifname=tap0,script=scripts/ifup


cdrom関連のオプションを外して、起動します。
これで、うまく起動できたら、成功。
あとは、通常のGentooとして使えます。

うちの環境だと、
ディスクは、90MB/s前後出ています。快適。
ネットワークも、100Mbps前後は出ているようです。

ちなみに、Ubuntuだとこんな苦労なしに、さくっと入ります。
でも、Gentooをがんばっていれてみたかったので、楽しかったです。

次回があれば、このVM上で、CoherenceというDLNAサーバを動かしてみる話を書くかも。

2008/09/17

iphoneでirc

iPhoneでIRCを使うべく、Webをさまよったけど、どうもIRCクライアントはよさそうなのがない。
というわけで、アプリはあきらめて、mobircのiPhone対応がされているみたいなので、
ブラウザ(Safari)経由で使うことにした。

インストールは以下に書くけど、基本はこのページでまとめられているので、そっち見た方がはやいかも。

もともと、tiarraは使っているので、そこは割愛。

基本的に、mobircがすでにiphone対応も取り込んでいるみたいなので、
CodeReposからsvnでさくっとダウンロード。
$ svn checkout http://svn.coderepos.org/share/lang/perl/mobirc/trunk/ mobirc


サンプルの設定ファイルをコピーする。
$ cp config.yaml.sample config.yaml

設定を適当にいじる。iphoneから使えればそれでいいので、以下みたいなシンプルなものに。
tiarraをjisで動かしていたので、incodeはjisにした。 utf-8にして、LimeChatもutf-8のほうがいいのかなぁ。
plugin:
- module: IRCCommand::TiarraLog
- module: Authorizer::Cookie
config:
password: xxxx
- module: Authorizer::BasicAuth
config:
username: xxxx
password: xxxx
- module: MessageBodyFilter::IRCColor
config:
# no_decorate: 0

- module: Component::IRCClient
config:
server: 127.0.0.1
port: 6660
nick: ku
desc: ku
username: ku
password: xxxxx
# incode: utf-8
incode: jis

- module: Component::HTTPD
config:
port: 6661


んで、
$ perl mobirc

と実行してみたが、モジュールがかなり足りないみたい。
参照ページのコメントの通り、
$ sudo -H sh -c "eval PERL_MM_USE_DEFAULT=1 cpan -H App::Mobirc"
で、CPANからmobircに必要なものをがっつり入れる。
PERL_MM_USE_DEFAULTは、設定しないほうが無難みたいですが、
入るモジュール量が半端なく、perlには無頓着な私はこのままいれちゃいました。

んで、
$ perl mobirc &

で、起動しました。

iphoneからも、ajaxで軽快にみれるようです。ただ、5秒に1回リロード?されるようで。
これ、電池すげーくいそうかも、と思いつつ、これでちょっとの間使ってみます。

私は、参照先のページと同様に、screenで動かしっぱなしですが、
ちゃんとdaemonっぽく動かすなら、daemontools(svtools)を使うといいかも。
たぶん、tiarraはrunっていうスクリプトがあるので、そのまま動くんじゃないかな(試してないけど)
$ supervise tiarra &

とか実行すれば、たぶん。
logとかちゃんととるなら、multilogとかも設定が必要?

mobircは、簡単なrunスクリプトが必要ですね。
単に、起動するだけで大丈夫じゃないかな。
#!/bin/sh
exec ./mobirc

とか。

2008/09/13

FlickrとPicasaへの画像アップロード

お仕事でいろんな写真サイトに手元の写真をアップロードするというのをやる予定です。
それに先駆けて、APIも整備されていて有名なところということで、FlickrとPicasaに挑戦してみた。

基本的に、作るのはDjangoのWebApplicationです。
WebApplicationの場合は、Flickr,Picasaとも、基本的に、ユーザからそれぞれのサイトの
ユーザ名とパスワードを預かるのは、さすがに、なんか気持ち悪いですよね、
というのに対処された認証になっているようです。
なんか世の中には、意外にその手のサンプルが少ないようなので、書いてみる。
まあ、ドキュメント読めば、普通に書いてるんだけど。

FlickrとPicasa(というか、Google)は、どちらもトークンというものを
ユーザ操作によって取得し、それを使ってユーザの画像を操作できます。
#Googleは、OAuthにも対応しているようですが、ライブラリが対応していないっぽいので、
#実績もあるしー、とかいう弱腰で、AuthSub方式を使いました。

とりあえず、どちらのサイトも、流れは以下になるようです。
・まず、各サイトへの認証URLを生成する
・そのURLへのリンクをクリックさせるか、リダイレクトする
・そのサイトで、このアプリから認証を要求されてるけど、承認するか?ページが表示される
・Cookieとかで認証済みなら、ボタン押すだけか、認証画面からログイン
 すると、自分のアプリサイト(事前に指定済み)のURLへリダイレクトされる
 そのとき、GETの引数として、トークンかそれに準ずるもの(flickrでは、frobというらしい)が渡される
・それを使って、永続的に利用できるトークンを取得する(昇格させる)
・それ以降は、それを使って、アップロード等の操作を行う

こっからは、実際のPythonででっちあげたサンプルコード(Djangoでサイト構築をした場合です。)
Flickrは、flickrpyを利用しました。
いまいち、これ以外に、トークンを使った認証にうまく対応しているライブラリを
見つけられませんでした。

とりあえず、FlickrでAPI Keyを取得します。
そのときに、認証後の戻り先のURL指定があるので、
http://xxx.xxx.xxx.xxx/flickr/gotFrob
というようなURLを指定しておきます。このURLでfrobを取得します。

とりあえず、viewだけ貼り付け。urlconfとかは適当に書く必要がもちろんあります。
あとは、Photoというモデルをつかってるけど、たいしたものでないので、省略。
とりあえず、やっつけこーど。さらに、!!!とか書いてるところはチョー適当。
ほんとは、生成したfrobをちゃんと覚えといて、ユーザとひも付けしないとだめだけど、
そこは適当に今は、渡されたfrobからtokenを取得して、ファイルに保存してるだけ。


from flickrapi import FlickrAPI

FLICKR_TOKEN = u'xxxx'
FLICKR_TOKEN_FILE_PATH = u'flickr_token.txt'
FLICKR_API_KEY = u'yyyy'
FLICKR_API_SECRET = u'zzzz'
FLICKR_PERMISSION = u'delete'

def get_flickr_api(token=None):
if token is None:
return FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, format='etree')
else:
return FlickrAPI(FLICKR_API_KEY, FLICKR_API_SECRET, token=token, format='etree')


def flickr_redirect_to_login(request):
flickr = get_flickr_api()
response = flickr.auth_getFrob()
frob = None
if response.attrib['stat'] == u'ok':
frob = response.findtext('frob')
else:
# !!!
return HttpResponse('Error')

return HttpResponseRedirect(flickr.auth_url(perms='delete', frob=frob))

def flickr_got_frob(request):
if request.method == 'GET':
frob = request.GET['frob']
flickr = get_flickr_api()
response = flickr.auth_getToken(frob=frob)
token = None
if response.attrib['stat'] == u'ok':
token = response.findtext('auth/token')
else:
# !!!
return HttpResponse('Error')

token_file = file(FLICKR_TOKEN_FILE_PATH, 'w')
token_file.write(token)
token_file.close()

return render_to_response('flickr/flickr_got_token.html',
dict(frob=frob, token=token))

def flickr_upload(request):
if request.method == 'GET':
photo_id = request.GET['photo_id']
photo = Photo.objects.all().filter(photo_id=photo_id).get()
token_file = file(FLICKR_TOKEN_FILE_PATH, 'r')
FLICKR_TOKEN = token_file.read()
token_file.close()
flickr = get_flickr_api(token=FLICKR_TOKEN)
response = flickr.upload(filename=photo.get_photo_url().encode('utf-8'), title=photo.caption)
flickr_photo_id = None
if response.attrib['stat'] == 'ok':
flickr_photo_id = response.findtext('photoid')
else:
# !!!
return HttpResponse('Error')

return render_to_response('flickr/flickr_upload.html',
dict(photo_id = photo_id, flickr_photo_id = flickr_photo_id))


流れは、
ユーザ操作によって、flickr_redirect_to_loginが呼び出されます。
すると、flickrの認証画面にとばされます。
んで、flickr_got_frobに帰ってきて、frobを使って、flickrからtokenを取得します。
んで、それを使って、flickr_uploadをつかって、アップロードする。

次は、Picasaの場合、同様にDjango前提。
gdata-python-clientで、AuthSubを利用します。
Picasaの場合は、事前にAPI等を取得するわけではなく、URL生成時に戻り先を指定する。
なんかアプリを事前に登録することで、
アプリ名とかがちゃんとGoogle側でも表示されるらしいので、やったほうがいいかも。
Picasaの場合は、frobのようなものはなく、1回限りのtokenという扱いで、それをsessionトークンに昇格させる。

ポイントは、これはバグだろーみたいな投稿もGoogle Codeであったけど、
Picasaの場合は、対アルバムにしかアップロードできないので、
InsertAlbumをとりあえずやってアルバムを作ってやろうとするけど、
こいつが対象のURLを生成する際に、self.emailを利用しようとする。
これは、ClientLogin()を使う場合は、email,passwordを指定しているから問題ないのだけど、
事前取得済みのsession tokenを使う場合、emailはわからない場合が普通。
そういうときは、Googleでは、'default'をURLとして指定すると、ユーザを勝手にGoogle側で決めてくれるようだ。
(これを調べるのに、ずいぶん手間取った。。。)
というわけで、本来なら、ライブラリ側のコード自体を、emailがNoneなら、defaultにするみたいするべきだけど、
ちょっとめんどくさかったので、emailに'default'をさくっと呼び出す前に代入した。
これで、とりあえず、うまくいくようにはなった。ただ、これはあまりにもやっつけすぎるかも。


import gdata.photos.service

PICASA_TOKEN = ''
PICASA_TOKEN_FILE_PATH = u'picasa_token.txt'

def picasa_redirect_to_login(request):
gd_client = gdata.photos.service.PhotosService()
auth_url = gd_client.GenerateAuthSubURL(next='http://xxx.xxx.xxx.xxx/picasa/got_token',
scope='http://picasaweb.google.com/data/',
secure=False, session=True)
return HttpResponseRedirect(auth_url)

def picasa_got_token(request):
if request.method == 'GET':
token = request.GET['token']
gd_client = gdata.photos.service.PhotosService()
gd_client.SetAuthSubToken(token)
gd_client.UpgradeToSessionToken()
token_file = file(PICASA_TOKEN_FILE_PATH, 'w')
token_file.write(gd_client.GetAuthSubToken())
token_file.close()
return HttpResponse('session token is %s' % (gd_client.GetAuthSubToken()))
else:
# !!!
return HttpResponse('Error')

def picasa_upload(request):
if request.method == 'GET':
photo_id = request.GET['photo_id']
import sys
photo = Photo.objects.all().filter(photo_id=photo_id).get()
gd_client = gdata.photos.service.PhotosService()
PICASA_TOKEN = file(PICASA_TOKEN_FILE_PATH, 'r').read()
gd_client.SetAuthSubToken(PICASA_TOKEN)
# bad techs
gd_client.email = 'default'
response = gd_client.InsertAlbum('test', 'test')
album_url = response.GetFeedLink().href
response = gd_client.InsertPhotoSimple(album_url, photo.caption, photo.comment, photo.get_photo_url())
return HttpResponse('picasa photo link is here' % response.GetSelfLink().href)
else:
# !!!
return HttpResponse('Error')


長くなったので、これでやめとこう。
とりあえず、こんな感じ。

iPhone 2.1

評判通り、いろいろよくなってますね。
・日本語入力は、確かにすげーサクサク!
・バックアップも確かにはやくなった
・電波状況の表示は、
 自宅は基本的に1本だったのが、基本5本に変化
 ソフトバンクさん、3Gエリアの改善要求とか送ってごめんw
 しかし、これ、電波の捕まえ具合がよくなったのか、
 表示がかわっただけなのか。

で、一つ解決されない疑問が、
・SMS 着信時の警告音繰り返し機能(2 回まで追加可能)
って、どこで設定するのだろう。。。
2chで何回か質問されてるみたいなんだけど、
見事なまでのスルーにちょっと笑った。
うちは、SMSでのやりとりが多いから、
この機能は是非使いたいんだけどなぁ。

【追記】
設定はなくて、SMSがきてるのに、なにも操作せずに放置すると、
5分後にもう一度、警告音が鳴るということだそうです。
なろほど。

2008/09/12

MacBookPro 再インストール

どうも動きがもっさりしてきていろいろ怪しい動きをするようになったので、再インストールした。

入れたもの
・ATOK 2008
 →とりあえず、これがないと始まらない。

・MobileMe
 →とりあえず、これでMail.appとかアドレスブックとかの内容を復元。
  メールアカウントとキーチェーンが復元されるのは、かなり楽でいい。
・Plaxo
 →主な目的は、iCal→GoogleCalendarの同期
  GoogleCalendarで最近対応した
  CalDavでがんばってみようと試みたけど、
  iPhoneと同期がOTAじゃ無理だった。
  ポイントは、
  PlaxoはGoogleCalendarの複数のカレンダーに対応できない。
  そのため、カレンダーごとに別のアカウントを作って、
  メインのアカウントに編集権限を与える形にする。
  Plaxoに同期エンドポイントを作るときには、
  作ったアカウントを登録しておく。
  これで、iCalをhubにして、
  iPhone,MobileMe,iCal,GoogleCalendarで予定の同期ができて便利。

・SSHまわりをレストア
 →鍵とかをなくすと、いろんなところに入れなくなる。
・MacFUSE,MacFusion
 →最近、開発はsshfs経由で編集しかしないので、ほぼ必須。
・DropBox
 →マシンが変わっても、ローカルにSyncしてくれる。
  いざというときには、Webから古い世代にもどしたり、
  削除したものを復活させられるのが便利。
  仕事用のドキュメントとかを入れている。

・Growl
 →特に、設定は変えないけど、
  IRCとかGmailとかのnotifyのために入れる。
・GmailStatus
 →未読チェック用。

・FireFox(lzycビルド)
 →FEBEでバックアップをとったつもりだったが、
  ProfileをRestoreしようとしたら、
  CPU 100%で暴走したまま固まる。。。
  泣く泣くextensionを手で入れ直した。
  ・Delicious Bookmarks これがないとなにもできない
  ・BetterGmail, BetterGCal
  ・FireBug 一応、Web屋さんなので
  ・GreaseMonkey 主に、LDRのため
   →UserScriptはもうなにを入れてたか覚えてないので、最低限入れた
    ・LDR Dedupe Entries
    ・LDR Full Feed
    ・Backx2 Livedoor Reader
    ・Shift+zっぽいことを自動的にしてくれるやつ

・SubEthaEdit
 →開発はこれで基本的にやってる
  特に、ここがイイ!っていうのはないけど、
  Pythonハイライトとかデフォルトで入ってるし。慣れ。
・ターミナル
 →元から入ってるやつ、これで結構いける。
  設定はProをベースにちょっと変えて使ってる。

・iCal
 →Plaxoから予定を復元。
  あとは、GoogleCalendarに社長とか会社の人の予定が入ってるので、
  それをCalDav経由で読み込む。
  GoogleAppsの別アカウントで認証が必要でも、
  CalDav経由ならちゃんと読めるのが便利。

・BathyScaphe
 →2ch.新・Mac,iPhone,AV機器あたりを板追加して終わり。
・夏ライオン
 →Twitterクライアントはシンプルなので、これをつかってる。
・iChat
 →Adiumとか使ってる人がおおいようだけど、
  必要なのが、MobileMeとGTalkなので、これで十分。
  インターフェースがかなり好き。
・Skype
 →打ち合わせ用。特に設定は変えない。
・LimeChat OSX
 →自宅サーバに、tiarraが入ってるので、最低限の設定をするだけ。
  基本的に、常に、ウインドウは出していないので、
  Growlで発言があったら、Notifyウインドウをだすようにしている。

・MPlayer OS Extended
 →とりあえず、ほとんどの動画が再生できるので、入れている。
・Flip4Mac
・Perian
 →まあ、念のため、という位の感じ。

・OnyX
・Secret
 →Finder、Dock,メニューバーあたりの設定を結構いじった。
  隠しファイル表示、
  ネットワークドライブでは、.DS_Storeつくらない、
  半透明なし、Dockに隙間つくる等

実は、再インストールが意外に大変ってことがわかった。
クラッシュ!とかなら、TimeMachineで復元ができるんだけど、
怪しいから再インストール→復元したら、
だめじゃん、みたいに気づいてちょっと鬱な感じ。
TimeCapsule未だ活用されず。。。

2008/09/08

iPhone買った

au W53CAからのMNP。スパボ一括。本体たけー。
絶対、2年とか使わないと確信してるので一括にした。

雑感。

i.softbank.jpの使いづらさに絶望。
MobileMeメインで使うのが、無難そう。
me.com→gmailの転送はやめずに、gmail側でフィルタ作って、
Inboxには入れずに、ラベルつけて、Archiveに直行させることにした。

とりあえず、メアド変更のお知らせメール送ったら、
i.softbank.jpも、me.comもPCメールと判定されるから、
結構、携帯以外のメール拒否ってる人から軒並み弾かれて帰ってきた。
me.comは仕方ないとしても、i.softbank.jpは一応、携帯の仲間に入れてくれないのか。

SMSがiChatっぽくて、慣れ親しんだ感じで楽しい。
これで、ほかのキャリアも使えればいいのに。

電話帳もMNPの場合は、自力で移行するしかない。
普通の携帯なら、赤外線で全件送信とかで、自力&無料で移行とか簡単にできる。
意外にこの方法使ってる人少ない気がする。
ソフトバンクショップのPCとかでがんばるよりは、楽だと思うんだけど。
とりあえず、ヨドバシ アキバのPCは軒並み故障とかで並んでる人がいっぱいいて、疑問に感じた。

結局、携帯から全部、携快電話使って、vCardで書き出して、Macでアドレスブックに読み込んだ。
よみがな入れないと、ソートがダメダメな感じなので、
手打ちでがんばった。30分くらいかかった。しんどかった。
これも、SoftBank内の機種変なら、なんか電話帳移行サポートみたいなページがあるんだけどねぇ。。。
そっちならうまくいくのかしら。

2008/09/06

MuninでTimeCapsuleのトラフィックを見る

TimeCapsuleは、SNMPに対応してるみたいなので、
我が家のルータとして、どれくらいがんばってるのかをグラフにしてみた。

使うのは、Munin
debianなので、
# aptitude install munin munin-node

これだけで、apacheがはいってたら、cronで5分ごとに、htmlが
/var/www/muninに生成されるようになるみたい。
使えるpluginとかは、munin-node-configureとか実行しなくても、
ローカルホスト分は、インストール時に設定してくれるらしい。

ただ、ホスト名が、localhost.localdomainで格好悪いので、
/etc/munin/munin-node.conf で

host_name xxx

を、適切に設定しておく。

んで、本題のTimeCapsule向けの設定追加。
ここで、ちょっと混乱したのは、Muninの動作の仕方。
ここまで、簡単に設定できすぎたので、よくわかってなかったのだけど、
Muninは、munin-nodeに接続して、各種情報を取得し、HTMLを生成するという形らしい。
つまり、SNMPを直接読むようなことにはならない。
ということで、SNMPから値を取得して、gateway的に動くmunin-nodeが必要ということらしい。
これがわかってなくて、munin.confのaddressの設定を直接TCのIPにして動かなくて、5分くらいはまった。

というわけで、気を取り直して。
まず、snmp周りのプラグインを有効にするためにも、
# munin-node-configure-snmp [TCのIPアドレス]
と実行すると、シンボリックリンクを張るためのコマンドが表示される。
注意は、実行されるわけじゃないこと。
# munin-node-configure-snmp [TCのIPアドレス] | sh
とかやるほうがいいかも。
うちの設定では、gec0, wlan0, vlan0のtraffic,errorsが追加された。
snmpwalkで見る限り、TimeCapsuleには、

1 gec0
2 mv0
3 pflog0
4 lo0
5 wlan0
6 vlan1
7 pppoe0
8 bridge0

という8つのIFがあるように見える。
なんで、上の3つだけ選ばれたのかは、謎。

うちのTimeCapsuleは、PPPoEでセッション張ってるので、
pppoe0
だけは、手動で追加した。
# ln -s /usr/share/munin/plugins/snmp__if_ /etc/munin/plugins/snmp_tc_if_7
# ln -s /usr/share/munin/plugins/snmp__if_ /etc/munin/plugins/snmp_tc_if_err_7
/etc/munin/pluginsのファイル名は、上のコマンドで実行されたものにあわせる。
最後の数字は、SNMPから取得できるintを使う。(上のリストアップの数字と一緒)

んで、/etc/munin/munin.confの設定。
以下を追加。munin-nodeが動いているホストのIPをaddressで設定。
バーチャルなノードなので、ノード名とホスト名はちがうので、use_node_nameはnoで。

[tc]
address 127.0.0.1
use_node_name no


とりあえず、これで、munin-nodeが動いているホスト以外にも,
tcというのができるはず。

gec0 -> 有線LAN(internal)
wlan0 -> 無線LAN
vlan1 -> 有線LAN(external)
pppoe0 -> PPPoE

かなぁ、とトラフィックを眺めて想像してみたけど、あってるかなぁ。。。
まあ、とりあえず、ウチのルータであるTimeCapsuleが
どれくらいトラフィック食っているかが、一目瞭然になって楽しい。
そして、Muninのほかのプラグインも試してみたくなるくらい簡単ですばらしいすな。

2008/09/02

debianにsshguard & 結果

自宅のサーバにも、sshguardを入れてみた。
こいつは、公開鍵での認証しか受け付けないのだけど、
まあ、一応、ということで入れてみた。

iptablesは周りは一緒。
syslogのままで最初設定しようとしたけど、どうもうまく動かず断念。

心機一転、syslogは実は重い、とか言われてる記憶とかもあって、
syslog-ngに変更してみた。
# aptitude install syslog-ng
で、さっくりとsyslogに変わってインストールされた。

んで、/etc/syslog-ng/syslog-ng.confの編集

filter sshlogs { facility(auth, authpriv); };
destination sshguardproc {
program("/usr/sbin/sshguard"
template("$DATE $FULLHOST $MESSAGE\n"));
};
log { source(s_all); filter(sshlogs); destination(sshguardproc); };


sourceが、サンプルでは、sourceという名前だけど、
debianでは、s_allとして定義されているので、そこだけ変更。

これで、動き始めた。

そして、結果。
1日に、3~4回、アタックを検知して、iptablesのルールを追加しているようだ。
大抵はうまく動いている。

しかし、本日のアタックは、なんとアクセスごとにsrcIPが違う。。。
いわゆる、botnetってやつですかね。
あきらかに、4アクセス/1secくらいの勢いで、違うユーザでログインを試みられているので、
連動しているとしか思えないのですが。。。
とりあえず、以下のようなコマンドで、IPを数える。
# grep ssh /var/log/messages | grep Invalid | gawk '{ print $10 }' | sort -u | wc -l

めっちゃ適当だけど、Invalid user guest from xxx.xxx.xxx.xxx
ていう感じの行を補足して数えてみると、350くらいのIPがある。

こういう場合は、現状、sshguardでは防ぎようがないっすねぇ。
単純に、IP縛りを外して、n秒間にm回以上ログインが失敗したら、で
ある程度の検知はできるかもしれんけど、そのあとのブロックのしようがないか。
全部、はじくわけにいかんもんねぇ。
過去に遡及して、失敗してるアドレス追加する?くらいかなぁ。
ちょっと改造してみようかな。。。

2008/08/29

sshguard

SSHでの総当たり攻撃がウザすぎるので、対策をしてみた。

根本的には、パスワード認証やめれ、とか、ポート変えろ、とかあるんだろうけど、他ユーザへの告知がめんどくさいとかいろいろあるので、がんばってみた。

はじめは、このへんのページを見ながら、iptablesのip_recentをつかって対処をしてみたんだけど、n秒間にm回以上、”アクセス”があったらというのが、どうもこわいなぁ、と。
FileZillaとか設定次第では、平気でSSHコネクション複数張ろうとしたりするので、この制限にさくっとひっかかりそうなので、やめた。

んで、探してみた。
Gentooなので、portageになにかないかと探してみたら、sshguardというのが出てきた。
SSHへのログイン失敗をログからカウントして、勝手に、iptablesへルールを追加してくれる。
(ペナルティ時間がおわったら、ルールの削除も。)
#iptables以外にも、PFやipfwとかにも対応してるみたい。

とりあえず、インストール。

# emerge sshguard

んで、設定。
環境次第のようだが、ウチは、openssh, syslog-ng, iptablesの組み合わせなので、
/usr/share/doc以下のドキュメントにどんぴしゃの設定がある。

まずは、iptablesにsshguard用のチェインを追加。

# iptables -N sshguard
# iptables -A INPUT -p tcp --dport 22 -j sshguard


次に、ログを検知させるために、syslog-ngの設定(/etc/syslog-ng/syslog-ng.conf)追加。

# pass only entries with auth+authpriv facilities that contain sshd
filter sshlogs { facility(auth, authpriv) and match("sshd"); };
# pass to this process with this template (avoids prefixes)
destination sshguardproc {
program("/usr/local/sbin/sshguard"
template("$DATE $FULLHOST $MESSAGE\n"));
};
log { source(src); filter(sshlogs); destination(sshguardproc); }

んで、killall -HUP syslog-ngで設定リロード。

これで、あとは、網にかかるのを待つだけ、
オプションでn(-p)秒間にm(-a)回失敗すると、とかを設定できる。
まあ、デフォルトでとりあえず動かしてみます。

今日は、何回かうまくはじいてるみたい。よかよか。

2008/01/07

うが

眠い。。。

有閑倶楽部がくだらなくて意外におもしろい

twistedでtwitterクライアントってすげー簡単なのね、感動。
twistedはすばらしいけど、わかりづれー

2007/11/15

InspIRCd

InspIRCdをいじり中。

このサーバはすごく綺麗に作られていて、拡張も考慮されています。
それ以外にも、epoll、kqueueとかにも対応していて、
大量の接続もさばけるようになっています。

たとえば、過去ログをログインした時に/NOTICEで送って欲しければ、
src/modules以下に、m_kakolog.cppというファイルを作って、
Moduleクラスを継承したクラスで、

OnUserMessageをオーバーライドして、
/PRIVMSG,/NOTICEが飛んできたら、発言を保存するSQLを発行。

OnUserJoinをオーバーライドして、
過去ログを/NOTICEとしてがばっと送る。

というのをとりあえず作ってみた。

基本は、src/modules/extra/m_sqllog.cppが
IRC全体での各種動きを保存するモジュールとなっているので、
これをパクれば、2時間くらいでできました。

あとは、SQLもAPIとして標準化されている(ついでに、非同期に動きます)ので、
MySQL,Psql,sqlite3であれば、コードを書き換えることなく使えます。
(m_sqlv2.so,m_sqlutils.soを有効にする必要アリ。)

うわぁ、楽しくなってきた!
仲間内IRCはこれをベースなおうちサーバに移行しようかしら。
bot置いておいて、過去ログとかAutoOperとかより
全然スマートにサーバサイドだけその手の処理ができる、ってのは良い気が。