About the Site

This weblog is edited and run by members of reallyenglish, a company offering a total English learning solution based in London, Beijing, Shanghai and Tokyo. Visit our corporate site to know more about what we do.

Notes are posted by members from various cultural and geographical backgrounds, and the topics range from education, business and international communication to software development, the internet culture, and more.

Staff

Masatomo Nakano http://twitter.com/masatomon /m/mt-static/support/assets_c/userpics/userpic-2-100x100.png simonl davida jeremyw Go Kameda gavin b No name tomoyukis

 

Recent Comments

  • Tomoyuki Sakurai: we've been using vether(4) successfully since 4.7. http://old.nabble.com/kernel-6318:-arp-cache-problem-bridge%284%29-with-vether%284%29-td27635451.html (the bug read more
  • RofR: Hi everyone Where about to setup serveral OBSD 4.9 or read more
  • Tomoyuki Sakurai: the above configuration has been working fine since 4.6. read more
  • Jean Aumont: Hi Tomoyuki, If you capture the packets with tcpdump and read more
  • Tomoyuki Sakurai: you will not see OSPF packets on physical interface. > read more
  • Jean Aumont: Hi everyone, I have been trying to pass OSPF in read more
  • Anonymous: without any other information, all i can say is doing read more
  • Jean Aumont: I have a similar set-up, but my 2 end points read more
  • illouca: thank you for the patch !! read more
  • Go Kameda: Glad to hear that - im afraid i cannot really read more

November 2009 Archives

前回に引き続き、今回はFreeBSDのJailの簡単な説明と、実際にどのような感じで使えるのか、簡単なサンプルを交え紹介します。

「プログラマのための」について

前回書き忘れてしまったのですが、なぜ「プログラマのための」というのをタイトルに入れたかというと、

  • プログラマは自分の開発環境/テスト環境の構築ぐらい自分ですべし
  • でも、環境構築に時間をかけすぎるのはプログラマとしては本末転倒だよね

この二つをあっさりと解決してくれるのがFreeBSDのJailだと感じているからです。

それと、自分自身そこそこ長いことプログラマをやってますが、Jailは自分にとってなかなか衝撃的だった、というのもこのエントリを書くきっかけになっているというのもあります。

FreeBSDのJailとは

さて、まず基本的なFreeBSDのJailについて簡単に触れておきます。

FreeBSDのJailは仮想環境の一つの実装です。仮想環境にも色々ありますがJailはその中でもとてもシンプルな物です。一つの物理的なサーバ上で動いている一つのFreeBSD(以下Jailホスト)の上で、複数のFreeBSD(以下Jailゲスト)が動いているように見えるようにする仕組です。「見えるようにする」だけというのがポイントで、実際にはJailホスト上のカーネルの上ですべてのプロセスが動いているだけです。

また、Jailとchrootを同じようなもの、と考えている人もいるようですが、chrootがファイルシステムだけが対象なのに対し、Jailはファイルシステムに加えネットワークやプロセスといったものも管理下になるのが違います。Jailゲスト一つが独立したIP addressを持ちます。

外からネットワーク越しに見ると、Jailゲストは一つのFreeBSD OSのように見えます。しかし、実際には、Jailホスト上の1つのカーネルで、Jailゲスト上のすべてのプロセスが動いています。このことは、Jailホスト上のカーネルからJailゲスト上の各プロセスを普通にpsやtopコマンド等で確認することができます。

また、この仕組みがそのままいくつかのJail自体の制限になります。たとえば、違うバージョンのFreeBSDや、違うOSを仮想環境として入れるといったVMWareやXenといった他の仮想環境でできることができません。そして、(今のところ)各Jailゲストで動くプロセスに対してリソースの割当や制限をすることができません。ですので一つのJailゲストがリソースを食い過ぎてしまうと他のJailゲストに大きく影響を与えます。この辺は将来的には何かできるようになるかも、という話です。

実際に動いている環境での例を示します。

host-top

これは、実際に弊社で稼働中のJailホストでtopした結果です。”j”を押すと左から2列目にJID (Jail ID)というものが表示されます。これはそのプロセスがどのJailゲストで動いているかということを示します。このようにJailホストからは、Jailゲストのプロセスが普通に見ることができますし、またJailホスト上からJailゲストのプロセスのkillなどは普通にできます。

では、その中の一つのJailゲストに入り、同じようにtopコマンドを実行してみます。すると、以下のようにそのJailゲストのプロセスのみが表示されます。

guest-top

このJailゲストはPostgreSQL用のものなのでPostgreSQLに関連するプロセスとcronなどの基本的なプロセスだけが走っているのがわかります。Jailゲストの中からは、他のJailゲストやJailホストの情報は見えません。これはプロセスだけではなくてファイルシステムなどもそうです。

とてもシンプルです。そして、シンプルなだけにに仮想環境を動かすこと自体のオーバヘッドが少なく、無駄なく一台のハードウェアの資源を使うことができます。また9年前にリリースされたFreeBSD 4.0Rからの機能なので安定度も非常に高いです。

資源という面では、Jailゲスト同士でFreeBSDのユーザランド部分をファイルレベルで共有するのでディスクスペースもそれほど無駄になりません。どう作るかにもよりますが、大雑把に言うと、/etc, /usr/local, /var あたりはJailゲスト毎ですが、/usr 以下は共有されます。また、もちろんパッケージからインストールしたものはJail毎になります。これにより資源を節約できるだけなく、Jailゲストの数をたくさん増やしたとしてもFreeBSDとしてのベース部分のメンテナンスは1カ所で済むのも楽なところです。

また、Jailゲストで使うファイルもJailホストと同じファイルシステム上にあるので、簡単に直感的に扱うことができます。例えば、あるJailゲスト上で「/etc/pam.d/systemを壊してしまって、仮想環境に入れなくなってしまった」というトラブルが起きたとします。Jailホスト上から見ると、このファイルは、/foo/bar/jails/hogehoge.example.com/etc/pam.d/system にあります。Jailホストにとっても普通のファイルなのでお使いのエディタで簡単に修復できます。

Jailの導入

Jail自体はFreeBSDに標準で組み込まれているのですが、その他にいくつか設定が必要です。また、Jail単体だと管理が大変なので、packageまたはportsから管理ツールであるsysutils/ezjailも導入してください。

さて、普通ならここでJailシステムのインストールの仕方等を紹介するべきなのかもしれませんが、ちょっと大変だし、世の中にあるものより劣化したドキュメントを垂れ流すだけになりそうなので、どこか適当な情報を探してください

また、Jail自体についてはこの辺が詳しいです。

Jailを使用した運用例

以下の例ではJailの管理ツールであるezjailを使っています。私はezjailができる前のJail事情を知らないのですが、その時代は色々と大変だったみたいです。

例1: Jailの新規作成

Jailゲストを新しく作ります。JailゲストはFQDNをディレクトリ名として作成され、その下がそのJailゲストの/(root)ディレクトリになります。

$ sudo ezjail-admin create newjail.example.com 192.168.4.25
/usr/local/jails/newjail.example.com/./bin/usr/local/jails/newjail.example.com/./boot
/usr/local/jails/newjail.example.com/./dev
/usr/local/jails/newjail.example.com/./etc
/usr/local/jails/newjail.example.com/./etc/X11
/usr/local/jails/newjail.example.com/./etc/bluetooth
/usr/local/jails/newjail.example.com/./etc/bluetooth/hcsecd.conf
/usr/local/jails/newjail.example.com/./etc/bluetooth/hosts
/usr/local/jails/newjail.example.com/./etc/bluetooth/protocols
/usr/local/jails/newjail.example.com/./etc/defaults
(中略)
/usr/local/jails/newjail.example.com/./.cshrc
/usr/local/jails/newjail.example.com/./COPYRIGHT
/usr/local/jails/newjail.example.com/./basejail

この例では、192.168.4.25 というIP addressがこのJailゲストに設定されます。(Jailホスト側にも192.168.4.25というIP addressをaliasとしてふる必要もあります。)

作成したJailゲストを起動してみます。

$ sudo ezjail-admin start newjail.example.com
Configuring jails:.
Starting jails: newjail.example.com.

Consoleに入ります。

$ sudo ezjail-admin console newjail.example.com
Copyright (c) 1992-2009 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
     The Regents of the University of California. All rights reserved.

FreeBSD 7.2-STABLE (GENERIC) #0: Fri Aug  7 20:52:37 BST 2009

Welcome to FreeBSD!
(中略)
You may also use sysinstall(8) to re-enter the installation and
configuration utility.  Edit /etc/motd to change this login announcement.

newjail#

ここれでJailゲストが一つ作成され起動しました。newjail# のプロンプトが表示され、この以下の操作はJailゲストの仮想環境内の操作になります。この中からは他のJailゲストやJailホストの情報は全く見えません。この先は普通のFreeBSDと同じように好きなようにパッケージを入れたり設定したりできます。もちろんsshdを起動すれば外から直接newjailに入ってこれます。

このようにコマンド2、3個、所要時間1分未満で簡単に1つの仮想環境を作成することができます。

例2: Jailゲストのコピー

似たような環境を作るときにいちいち0から設定するのは大変です。こういうときは既にあるJailを簡単にコピーできます。

先ほど作成したnewjailをコピーし、newjail2を作成してみましょう。

いったんnewjailを停止。

$ sudo ezjail-admin stop newjail.example.com

コピー

$ sudo cp -a /usr/local/jails/newjail.example.com /usr/local/jails/newjail2.example.com

単純なファイルコピーなので、rsyncでもtarでもお好きなものでどうぞ。(パーミッションとかに気をつけて)

コピーしたファイルを元にnewjail2を作成します。(すでにあるファイルを使う場合は-xをつける)

$ sudo ezjail-admin create -x newjail2.example.com 192.168.4.26

これで、完了です。

先ほどと同じようにコンソールに入りコピーされていることを確認します。(起動していない場合にはconsoleコマンドでstartもします。)

$ sudo ezjail-admin console newjail2.example.com
Configuring jails:.
Starting jails: cms3-build.uk.reallyenglish.com.
Copyright (c) 1992-2009 The FreeBSD Project.
Copyright (c) 1979, 1980, 1983, 1986, 1988, 1989, 1991, 1992, 1993, 1994
     The Regents of the University of California. All rights reserved.

FreeBSD 7.2-STABLE (GENERIC) #0: Fri Aug  7 20:52:37 BST 2009

Welcome to FreeBSD!
(中略)
You may also use sysinstall(8) to re-enter the installation and
configuration utility.  Edit /etc/motd to change this login announcement.

newjail2#

これでコピーされたJailゲストが動きだしました。

ファイルのコピーにかかる時間は、もちろんその中のファイルの量によるので何とも言えませんが、実作業時間はこちらも数分といったところでしょう。

同じようなやり方で複数のJailホスト間でJailゲストをコピー(または、元のを消せば移動)することもできます。この場合コピー先のJailホストは同一のアーキテクチャのサーバ、同一のFreeBSDのバージョンのものにしておいた方が無難です。

今回のまとめ

とにかくJailは簡単です。よほど深いことをするのでない限りJail自体の知識はあまり必要となりません。普通のUNIX的な知識とFreeBSD的な知識があれば普段使いとしては十分です。

個人的な経験では、他の仮想環境はメンテナンス含め色々と手間がかかります。気づいたら動くなくなってた仮想環境というのも目にします。またメモリやディスクスペースのオーバヘッドも大きいので簡単にいくつも作ったりもできません。Jailはそういう意味でもとても軽いし堅いです。もし何らかの理由で動かなくなったとしても、上記で説明したようにとてもシンプルなのでわりと簡単に修復できますし、仮想環境の中のファイルを外から取り出すのも簡単です。

次回はもう少しだけ運用のTipsなどを紹介して最後にしたいと思っています。

それでは!

reallyenglish.com is geographically diverse. The HQ in UK, a few branches in Asia, maybe more in the future. Except for few exceptions, the employees expect universal services, such as source code repository, project management system and wiki. All of them must be protected by strong encryption. IPsec is a standard protocol designed for encrypting packets from one place to another. We extensively use IPsec between our offices.

As a sysadmin, whenever someone says "the Internet is down", I say "no, it isn't". The problem would be caused by networking issue, misconfiguration by someone, maybe his own fault or whatever. The Internet is fine. But, partially, he is right. The Internet is the network of networks. Different network is managed by different entity. As such, links between networks
cut off for various reason every day somewhere on the Internet. You just don't know it is happening. The Internet as a whole works somehow thanks to "dynamic routing".

What dynamic routing does is, in short, "if there are multiple paths to the destination, use the best path" and "tell neighbors about your directly connected networks so that others can understand the whole network map". Without dynamic routing, you have to teach every possible route to every single router. For our intranet, we're using OSPF.

Okay, for robust intranetworking, all you need is multiple meshed IPsec tunnels with OSPF. IPSec is a standard and mature protocol, and so is OSPF. Sounds easy? Not quite. What I don't really like about IPsec is, it wasn't designed with routing in mind. As Security Association is statically configured, you cannot specify multiple path to a destination. Moreover, it doesn't handle multicast packet. OSPF is a routing protocol and uses multicast for its communication.

One more thing to make this problem complicated is proprietary products, Netscreen security devices to be specific, we're still using. If you stick with a specific vendor, you will not have interoperability problem, but you're successfully vendor locked-in. What you can do is what that particular vendor implemented. If they don't, you cannot do anything with it. Anyway, I strongly prefer open standards and open platforms. The choice in this case is OpenBSD. However, there wasn't documentation about how to implement meshed, dynamically routed IPsec with OpenBSD and ScreenOS.

IPsec doesn't like multicast pakcet. Okay, use GRE, Generic Routing Encapsulation. By encapsulating multicast packet into GRE unicast packet, IPsec happily forward the packet to its peer. When the link to the peer goes down, ospfd(8) marks the link as unavailable and use alternative path to the destination. Sounds simple, isn't it? Again, not quite. You have to understand all the network layers involved. There would be 6 endpoints, or IP addresses, involved in this setup. IPsec endpoints, GRE tunnel endpoints and a /30 network for OSPF communication.

Let's configure OpenBSD first. Make sure both packet forwarding and GRE are enabled. Also, you better to disable pf(4) during the testing. You can enable it again after everything works. OpenBSD 4.6 and later enable pf by default.

# sysctl net.inet.gre.allow=1
# sysctl net.inet.ip.forwarding=1
# pfctl -d

Next, create GRE tunnel.

# ifconfig gre0 create
# ifconfig gre0 tunnel myglobal.ip.addre.ss peerglobal.ip.addre.ss (outer header)
# ifconfig gre0 inet mygre.ip.addre.ss peergre.ip.addre.ss netmask 0xffffffff link0 up (inner header)

The packets between mygre.ip.addre.ss and peergre.ip.addre.ss will be encapsulated by GRE unicast packets with the global IP addresses of the both endpoints as source and destination header. GRE packets are not encrypted, yet.

Then, configure IPsec. OpenBSD's newer ipsec.conf(5) makes IPsec configuration much easier than ever. The security policy would be "encrypt all packets between the endpoints with their global address". Due to performance limitation of the hardware, we use SHA1 and 3DES.

# vi /etc/ipsec.conf
mypeer = "peerglobal.ip.addre.ss"
me = "myglobal.ip.addre.ss"
mypassword = "password"
ike esp from $me to $mypeer peer $mypeer \ main auth hmac-sha1 enc 3des group modp1024 \ srcid $me/32 dstid $mypeer/32 \ psk $mypassword

Start isakmpd and tell it to read security policy from /etc/ipsec.conf.

# isakmpd -K
# ipsecctl -f /etc/ipsec.conf


NS 5GT's config is not so straight forward, but almost same you did above on OpenBSD.

set interface tunnel.1 zone untrust
set interface tunnel.1 ip mygre.ip.addre.ss/30 (inner header)
set interface tunnel.1 tunnel encap gre
set interface tunnel.1 tunnel local-if untrust dst-ip global.ip.addre.ss (outer GRE header, GRE endpoints)
set interface tunnel.1 tunnel keep-alive (optional, but useful to see GRE packet on the wire)
set ike gateway mypeer address peerglobal.ip.addre.ss main outgoing-interface "untrust" preshare password sec-level compatible
set vpn mypeer gateway jp proposal "nopfs-esp-3des-sha" 
set vpn mypeer bind interface tunnel.1
set vpn mypeer proxy-id local-ip global.ip.addre.ss/32 remote-ip peerglobal.ip.adre.ss/32 ANY

The gotcha was, I thought it wasn't possible for OpenBSD and 5GT to talk to each other in a setup like this because OpenBSD's GRE tunnel is point-to-point, 5GT's is a normal /30 subnet. I even didn't give it a try during the initial testing. In fact, it is. Now, you can ping the peer using GRE /30 IP address each other.


# ping peergre.ip.addre.ss
PING peergre.ip.addre.ss (peergre.ip.addre.ss): 56 data bytes
64 bytes from peergre.ip.addre.ss: icmp_seq=0 ttl=64 time=277.665 ms
...


You'll see ICMP packets on the GRE interface.
# tcpdump -tnei gre0 -c 10 icmp 
tcpdump: listening on gre0, link-type NULL
mygre.ip.addre.ss > peergre.ip.addre.ss: icmp: echo reply
peergre.ip.addre.ss > mygre.ip.addre.ss: icmp: echo request
...


Make sure the traffic is encrypted. Replace vr0 with your egress interface's name.
# ipsecctl -s all
FLOWS:
flow esp in from myglobal.ip.addre.ss to peerglobal.ip.addre.ss peer peerglobal.ip.addre.ss srcid myglobal.ip.addre.ss/32 dstid peerglobal.ip.addre.ss/32 type use
flow esp out from peerglobal.ip.addre.ss to myglobal.ip.addre.ss peer peerglobal.ip.addre.ss srcid peerglobal.ip.addre.ss/32 dstid myglobal.ip.addre.ss/32 type require

SAD:
esp tunnel from myglobal.ip.addre.ss to peerglobal.ip.addre.ss spi 0x1275cf8c auth hmac-sha1 enc aes
esp tunnel from peerglobal.ip.addre.ss to myglobal.ip.addre.ss spi 0x20eec763 auth hmac-sha1 enc aes

# tcpdump -tni vr0 -c 10
tcpdump: listening on vr0, link-type EN10MB
esp myglobal.ip.addre.ss > peerglobal.ip.addre.ss spi 0x61a862f2 seq 45586 len 372
esp peerglobal.ip.addre.ss > myglobal.ip.addre.ss spi 0x84cd621d seq 45973 len 132
Now that both IPsec and GRE tunnel worked, the last thing you need is enabling OSPF. ospfd.conf is very simple. Replace vr1 with your internal network interface.

# vi /etc/ospfd.conf
password="mypassword"
auth-md 1 $password
auth-type crypt
auth-md-keyid 1
area 0.0.0.0 {
 interface gre0 { }
 interface vr1 { passive }
}

Start ospfd(8) in debug and verbose mode.

# ospfd -dv
... lots of debug information ...

Do the same thing on 5GT.

set vr trust-vr protocol ospf enable
set interface tunnel.1 protocol ospf area 0.0.0.0
set interface tunnel.1 protocol ospf authentication md5 mypassword key-id 1
set interface tunnel.1 protocol ospf authentication active-md5-key-id 1
set interface tunnel.1 protocol ospf enable
set interface trust protocol ospf area 0.0.0.0
set interface trust protocol ospf passive
set interface trust protocol ospf enable

Now you'll see OSPF neighbor relationship is established.

# ospfctl show neighbor
ID                      Pri State      DeadTime Address                Iface     Uptime
peergre.ip.addre.ss     1   FULL/P2P   00:00:30 peergre.ip.addre.ss    vr1       00:00:23

run "ospfctl show rib" to see RIB and "ospfctl show fib" to see FIB. It should show you the network at the peer's end. If it doesn't work for you, make sure IPsec flow is established,  OSPF packet is flowing between both hosts. To make a meshed IPsec, simply repeat this procedure. Tedious? Well, for that matter, you have to replace all the proprietary boxes with OpenBSD and use some kind of automated configuration management system.

How I made my Flash dead silent

| No Comments

どうでも良い失敗談なのですが、先日.flaからswfをPublishしてもActionScriptが全く認識されずtraceもエラーも出力されず、本当にうんともすんともいわないという状態に陥りました。(Publishは成功するがActionScriptが全く認識されないという状態)

本当にうんともすんとも言わないので原因の手がかりが掴めず、classpath、document classのリンケージのチェック、ASO削除、TextMateでASファイルにBOMを加えてみるなどいろいろ試したんですが全然駄目で、数時間を無駄にしようとしていたそのとき、自分のミスに気がつきました。

Killer.png

画像のように、どうやら何かの拍子で誤ってLibraryのMovieClip Symbolのひとつに、(Base Classにではなく直接)flash.display.Spriteをリンケージしてしまっていたようです。

何故自分でもこんなことをやってしまったのかわかりませんが、これをやってしまうと上記のようにCS4(Mac版)だとpublishはするものの出力が完全沈黙するので、下手をするとはまります(因みにCS3で試したところIDEがクラッシュしました)。たぶんこんなアホなことをやるのは自分だけだろうと思いつつも、もし同じ症状に出くわしたら、一応各Symbolのリンケージをチェックしてみてください。。

This is one of my trivial horror stories - the other day I made changes on some Flash stuff I was working on and published the .fla as usual. However, it suddenly stopped working and even worse, it also stopped spitting out any trace/error messages at all. It published fine, but it's broken and dead silent. It seemed to stop recognizing all the ActionScript class files suddenly.

Since everything is dead silent I had no clue why it went wrong, I just blindly tried a couple of things I could think of, like checking class pathes/document class linkage, deleting ASOs, and trying to add UTF-8 BOM to the AS files (via TextMate). None of them worked. After wasting a couple of hours like this, I found my mistake.

Killer.png

Like the image above, somehow I mistakenly made a linkage to flash.display.Sprite from one of my hundreds of MovieClip symbol. I typed in flash.display.Sprite not in its Base Class field, but in the Class field. This was the cause of everything.

I had no idea why I did this, but anyway I wasted a couple of hours because of the mistake. Usually you don't do something like this but once you did it it may be hard to locate as Flash goes completely silent (In the case of CS4 Mac - when I tried the same on CS3 for testing, it simply crashed). I wrote this note hoping it might help someone who got into the same trap as I did. Perhaps no one else is ever gonna be as dump as me but anyways...