2013年4月21日日曜日

OpenBlocks AX3でOpenVPN Serverを作る

GbEが4ポートもあるのならばVPNルータにしたいよなぁ、ということでOpenVPN サーバにしてみる。

ネットワーク構成

今回は、二つのサブネット(10.3.93.0/24, 10.39.3.0/24)の上に VPN(10.3.9.0/24)を構築する。

各ホストのハード・ソフトは以下の通りである。
  • server(OpenBlocks AX3)
    • Kernel: 3.0.6 #1 SMP Thu Apr 18 12:26:22 JST 2013 armv7l
    • OpenVPN: 2.1.3-2+squeeze1(Debian squeezeパッケージ)
  • hatsune
    • CPU: AMD Opteron(tm) Processor 3280
    • NIC: Intel Corporation 82574L Gigabit Network Connection
    • Kernel: 3.8.7-1-ARCH #1 SMP PREEMPT Sat Apr 13 09:01:47 CEST 2013 x86_64
    • OpenVPN: 2.3.0-2(Arch Linuxパッケージ)
  • kagamine
    • CPU: AMD E-450 APU with Radeon(tm) HD Graphics
    • NIC: Atheros AR8151 v2.0 Gigabit Ethernet (rev c0)
    • Kernel: 3.8.7-1-ARCH #1 SMP PREEMPT Sat Apr 13 09:01:47 CEST 2013 x86_64
    • OpenVPN: 2.3.0-2(Arch Linuxパッケージ)

鍵ファイルの生成

まず、認証に必要な公開鍵を作成する必要がある。OpenVPN公式にて用意して いる公開鍵基盤を管理するスクリプト群としてeasy-rsaが存在するので、これ を用いる。
easy-esaの各スクリプトを実行する前に、varsファイルを元に有効期限や証明 書の情報を環境変数に設定する。初期化する場合はclean-allスクリプトの実 行が必要である(clean-allを実行するとkeysディレクトリ以下の全ての鍵ファ イルが削除されるので注意)。
その後buildスクリプトを実行しCA鍵、サーバ鍵、クライアント鍵、DHパラメー タの生成を行う。ビルド作業はウィザード形式で行われるが、基本的にvarsファ イルと引数に渡した名前を元にデフォルト値が設定されているため、特に値を 指定し直す必要がある箇所はない。また、今回は秘密鍵にパスフレーズは付与 しない。
% git clone https://github.com/OpenVPN/easy-rsa.git
% cd easy-rsa/easy-esa/2.0
% vi vars
% source ./vars
% ./clean-all
% ./build-ca
...
% ./build-key-server server
...
% ./build-key hatsune
...
% ./build-key kagamine
...
% ./build-dh
...
生成した鍵ファイルはサブディレクトリkeys以下に全て保存される。 easy-rsaの詳細に関してはdoc/README-2.0やスクリプトのソースを参照すると よい。

サーバ設定

サーバのネットワーク設定とOpenVPNの設定ファイルの作成を行う。
miku@obsax3% sudo sysctl net.ipv4.ip_forward=1
miku@obsax3% sudo ip link set eth1 up
miku@obsax3% sudo ip addr add 10.3.93.1/24 dev eth1
miku@obsax3% sudo ip link set eth2 up
miku@obsax3% sudo ip addr add 10.39.3.1/24 dev eth2
OpenVPNサーバの最小限の設定ファイルは以下のようになる。
port  1194
proto udp
dev   tun0

ca         key/ca.crt
cert       key/server.crt
key        key/server.key
dh         key/dh2048.pem

server   10.3.9.0 255.255.255.0
ifconfig 10.3.9.1 255.255.255.0

client-to-client
client-config-dir ccd/
comp-lzo

keepalive 10 60
ping-timer-rem

persist-key
persist-tun

今回はクライアント毎にIPアドレスを固定で割り当てる為、 client-config-dirにて設定したディレクトリ(ccd)にCN毎のファイル (hatsune, kagamine)を置き、それぞれにIPアドレスの割り当てオプションを 記述する。
# hatsune
ifconfig-push 10.3.9.2 10.3.9.1
# kagamine
ifconfig-push 10.3.9.3 10.3.9.1

クライアント設定

hatsune

miku@hatsune% sudo ip link set enp4s0 up
miku@hatsune% sudo ip addr add 10.3.93.2/24 dev enp4s0
miku@hatsune% sudo ip route add 10.39.3.0/24 via 10.3.93.1
クライアントhatsuneの設定ファイルは以下の通りである。
client

dev tun0
proto udp
remote 10.3.93.1 1194

persist-key
persist-tun

ca   key/ca.crt
cert key/hatsune1024.crt
key  key/hatsune1024.key

ns-cert-type server
comp-lzo

kagamine

miku@kagamine% sudo ip link set enp2s0 up
miku@kagamine% sudo ip addr add 10.39.3.2/24 dev enp2s0
miku@kagamine% sudo ip route add 10.3.93.0/24 via 10.39.3.1
クライアントkagamineの設定ファイルは以下の通り。 hatsuneの設定ファイルとの違いは、リモートのIPアドレスと証明書・秘密鍵 のファイル名である。
client

dev tun0
proto udp
remote 10.39.3.1 1194

persist-key
persist-tun

ca   key/ca.crt
cert key/kagamine.crt
key  key/kagamine.key

ns-cert-type server
#comp-lzo
fragment 1472
mssfix 1472

各ホスト毎のファイルのリスト

各ホスト毎に必要なファイルは以下の通りである。
  • hatsune
    • client.conf (クライアント設定ファイル)
    • key/ca.crt (CA証明書)
    • key/hatsune.key (クライアント秘密鍵)
    • key/hatsune.crt (クライアント証明書)
  • kagamine
    • client.conf (クライアント設定ファイル)
    • key/ca.crt (CA証明書)
    • key/kagamine.key (クライアント秘密鍵)
    • key/kagamine.crt (クライアント証明書)
  • server
    • server.conf (サーバ設定ファイル)
    • key/ca.crt (CA証明書)
    • key/server.key (サーバ秘密鍵)
    • key/server.crt (サーバ証明書)
    • key/dh2048.pem (DHパラメータ)
    • ccd/hatsune (クライアントhatsune設定ファイル)
    • ccd/kagamine (クライアントkagamine設定ファイル)

デーモンの起動

各ホスト毎に先ほど準備したファイルを転送し、OpenVPNデーモンを起動する。 それぞれInitialization Sequence Completedとなれば接続が確立できている 筈である。
miku@obsax3% sudo openvpn server.conf
Fri Apr 19 22:19:05 2013 OpenVPN 2.1.3 arm-unknown-linux-gnueabi [SSL] [LZO2] [EPOLL] [PKCS11] [MH] [PF_INET6] [eurephia] built on Feb 21 2012
Fri Apr 19 22:19:05 2013 NOTE: OpenVPN 2.1 requires '--script-security 2' or higher to call user-defined scripts or executables
Fri Apr 19 22:19:05 2013 /usr/bin/openssl-vulnkey -q -b 2048 -m <modulus omitted>
Fri Apr 19 22:19:06 2013 TUN/TAP device tun0 opened
Fri Apr 19 22:19:06 2013 /sbin/ifconfig tun0 10.3.9.1 pointopoint 10.3.9.2 mtu 1500
Fri Apr 19 22:19:06 2013 UDPv4 link local (bound): [undef]
Fri Apr 19 22:19:06 2013 UDPv4 link remote: [undef]
Fri Apr 19 22:19:06 2013 Initialization Sequence Completed
Fri Apr 19 22:19:15 2013 10.3.93.2:1194 Re-using SSL/TLS context
Fri Apr 19 22:19:15 2013 10.3.93.2:1194 LZO compression initialized
Fri Apr 19 22:19:15 2013 10.3.93.2:1194 [hatsune] Peer Connection Initiated with [AF_INET]10.3.93.2:1194
Fri Apr 19 22:19:22 2013 10.39.3.2:1194 Re-using SSL/TLS context
Fri Apr 19 22:19:22 2013 10.39.3.2:1194 LZO compression initialized
Fri Apr 19 22:19:22 2013 10.39.3.2:1194 [kagamine] Peer Connection Initiated with [AF_INET]10.39.3.2:1194

性能測定

VPNクライアント間の通信が確立できていることを確認し、性能を測定する。 クライアントの1つ(hatsune)にて性能測定用のファイルを生成し、tmpfsがマ ウントされたディレクトリに置きHTTPとSCPでダウンロード可能な状態にして おく。(tmpfs上に置くのは、ディスクアクセス速度がボトルネックとならない ようにするため)
測定用ファイルの生成は以下のように行った。
miku@hatsune% dd if=/dev/urandom of=/tmp/dummy.img bs=1M count=1000
miku@hatsune% dd if=/dev/zero of=/tmp/zero.img bs=1M count=1000
今回は、VPNを用いずに通信した場合、VPN上にてLZO圧縮を有効にし通信した 場合、VPN上にてLZO圧縮を無効にし通信した場合について比較を行う。 LZO圧縮を無効にする場合は、サーバとクライアント全ての設定ファイルから comp-lzoオプションを取り除く。
SCPの場合、以下のように/dev/nullを宛先として指定する。
miku@kagamine% scp 10.3.9.2:/tmp/dummy.img /dev/null
dummy.img                               100% 1000MB   5.0MB/s   03:22
HTTPの場合もSCPと同様に、/dev/nullを宛先として指定する。
% wget -O/dev/null http://10.3.9.2:3939/dummy.img
--2013-04-19 23:07:34--  http://10.3.9.2:3939/dummy.img
10.3.9.2:3939 に接続しています... 接続しました。
HTTP による接続要求を送信しました、応答を待っています... 200 OK
長さ: 1048576000 (1000M) [application/octet-stream]
`/dev/null' に保存中

100%[============================>] 1,048,576,000 5.01MB/s 時間 3m 21s

2013-04-19 23:10:55 (4.98 MB/s) - `/dev/null' へ保存完了 [1048576000/1048576000]
それぞれ10回づつ計測を行った場合の平均は以下のようになった。
テスト内容非VPNVPNVPN(lzo)
転送(1GB, HTTP, ZERO)112MB/s5.0MB/s7.8MB/s
転送(1GB, HTTP, RANDOM)112MB/s5.0MB/s4.9MB/s
転送(1GB, SCP, RANDOM)16.7MB/s5.1MB/s5.0MB/s
ping rtt min/avg/max/mdev0.557/0.699/0.765/0.0801.471/1.520/1.582/0.0581.525/1.558/1.638/0.031
ping(-s 1472 -M do)0.628/0.802/0.846/0.0712.119/2.180/2.276/0.0771.544/1.689/1.737/0.050
予想以上に暗号化処理の負荷が大きいようで、VPN経由だと非VPN経由の1/24ま でスループットが低下した。ファイル転送の際には、OpenBlocks上のopenvpn デーモンのCPU使用率が100%に張り付いていた。
OpenVPNは今のところ単一プロセスでのSMP対応はされていないため、2core以 上を活かしたい場合はサーバ・クライアント双方を–remote-random等で分割 し利用できるよう準備する必要がある。
似た構成のIPSecだとどの程度になるのか気になるところ。

OpenVPNのバージョンを上げてみる

試しにOpenBlocks上にてOpenVPN-2.3.1を野良ビルドし比較してみたが、今回 のテストにおける速度に関してはほとんど同じだった。
野良ビルドの手順は以下の通り。
miku@obsax3$ aptitude install liblzo2-dev libssl-dev libpam0g-dev
miku@obsax3$ wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.1.tar.gz
miku@obsax3$ tar xzf openvpn-2.3.1.tar.gz
miku@obsax3$ cd openvpn-2.3.1
miku@obsax3$ ./configure --prefix=/usr/openvpn && make && sudo make install

beta版ファームウェア(wheezy)を試す

そうこうしているうちにdebian wheezyがOpenBlocks AX3に入ったようなので、 早速アップデートして比較してみる。wheezyでのカーネルのバージョンは3.2.36、OpenVPNのバージョンは2.2.1-8となっ ている。
テスト内容非VPNVPNVPN(lzo)
転送(1GB, HTTP, ZERO)112MB/s4.7MB/s7.6MB/s
転送(1GB, HTTP, RANDOM)112MB/s4.7MB/s4.7MB/s
転送(1GB, SCP, RANDOM)16.4MB/s4.7MB/s4.7MB/s
ping rtt min/avg/max/mdev1.096/1.596/1.767/0.2642.035/2.553/2.693/0.2022.052/2.589/2.863/0.208
ping(-s 1472 -M do)1.203/1.738/1.828/0.1822.694/3.109/3.285/0.2132.805/2.846/3.110/0.107
一気に速くなるのかなぁとわくわくしながら実行したのだが、結果は地味に遅くなってしまった。OpenVPN経由でない場合も遅くなっているようなので、 原因はOpenVPN以外(kernel側?)に存在する可能性が高そうである。

その他

kagamineのAtheros AR8151が、同時に蟹wlanを利用している状態である程度通 信すると突然死する謎の症状に悩まされる事があった。wlanを止めると死なな い。原因は不明。

2013年4月2日火曜日

feel6でIPv6(on Arch Linux)

プロバイダがPPPoEな固定IPv6サービスを始める気配がまったく無いので、久 しぶりにfeel6(http://start.feel6.jp/)を使ってみる。 ホスト環境はいつも通りArch Linux。

dtcpclientのビルド

dtcpclientのソースをダウンロードしてきてビルドする。FreeBSD用に書かれ ておりそのままではビルドできないため、オリジナルのMakefileを参考に直接 gccを叩く。

また、libbsdがインストールされていない場合は先にインストールしておく。

% wget http://www.imasy.or.jp/~ume/ipv6/dtcpclient-20060111.tar.gz
% tar xzf dtcpclient-20060111.tar.gz
% cd dtcpclient-20060111
% gcc -lbsd -lcrypto -Wall -DPREFIX=\"/usr/dtcp\" dtcpclient.c -o dtcpclient
% ./dtcpclient
usage: dtcpclient [-dDhlnU] [-b udpport] [-B naptport] [-e nickname]
[-f pidfile] [-m mtu] [-p port] [-s script] [-t tuntype] [-u username] server

起動

とりあえずfeel6にDTCPでログインできるか試してみる。 今回はNAT下で利用するため、-nオプションを付ける。-lは切断時の自動再接 続、-dはデバッグモードとなる。

% ./dtcpclient -d -l -n -t network -u ユーザ名 dtcp.feel6.jp 
no authinfo file found
password for hachune:
logging in to dtcp.feel6.jp port 20200
>>> +OK xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx FBDC TunnelBroker (version
0.2) Ready. <578926>:4096
<<< tunnel hachune yyyyyyyyyyyyyyyyyyyyyyyyyyyyyyyy network
>>> +OK 118.1.71.38 43.244.255.37 2001:03e0:0988::/48
sleep(60)
<<< ping
>>> +OK pong
sleep(60)

ネットワーク設定スクリプトを作成

ログインに成功しアドレスが取得できたことが確認できたので、早速ネットワー ク設定スクリプトを書きなおす。dtcpclientの-sオプションに渡すスクリプト は、ログイン完了時と切断時に引数に以下のように渡され起動されるので、そ れに合わせて記述する。

up dtcp.feel6.jp 10.39.39.37 network 118.1.71.38 43.244.255.37 2001:03e0:0988::/48

LinuxにてIPv6 over IPv4なトンネルを利用する場合は、sitインターフェース を利用する。

#!/bin/sh

DEV=sit0
STATUS=${1}
SERVER=${2}
NLOCAL=${3}
MODE=${4}
LOCAL=${5}
REMOTE=${6}
V6PREFIX=${7}

case ${STATUS} in
up)
        ip link add link ${DEV} type sit
        ip link set dev ${DEV} up
        ip address add `echo ${V6PREFIX} | sed -e 's|/48||'`1/64 dev ${DEV}
        ip -6 route add default via ::${REMOTE} dev ${DEV}
        ;;
down)
        ip -6 route delete default
        ip link delete ${DEV}
        ;;
esac

確認

最後に、通信が確立していることを確認する。プロバイダのDNSサーバを利用 している場合、AAAAフィルタが有効になっていてv6アドレスが引けないことが あるので注意する。

% ping6 -c 4 ipv6.google.com
PING ipv6.google.com(2404:6800:4004:802::1012) 56 data bytes
64 bytes from 2404:6800:4004:802::1012: icmp_seq=1 ttl=53 time=17.6 ms
64 bytes from 2404:6800:4004:802::1012: icmp_seq=2 ttl=53 time=29.9 ms
64 bytes from 2404:6800:4004:802::1012: icmp_seq=3 ttl=53 time=15.5 ms
64 bytes from 2404:6800:4004:802::1012: icmp_seq=4 ttl=53 time=15.8 ms

--- ipv6.google.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3005ms
rtt min/avg/max/mdev = 15.518/19.732/29.904/5.929 ms

(参考)AAAAフィルタ

AAAAフィルタが存在する場合

miku@hachune% dig @10.39.39.1 AAAA www.kame.net

; <<>> DiG 9.9.2-P2 <<>> @10.39.39.1 AAAA www.kame.net
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 58213
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 4000
;; QUESTION SECTION:
;www.kame.net.                  IN      AAAA

;; ANSWER SECTION:
www.kame.net.           71617   IN      CNAME   orange.kame.net.

;; Query time: 16 msec
;; SERVER: 10.39.39.1#53(10.39.39.1)
;; WHEN: Tue Apr  2 11:53:43 2013
;; MSG SIZE  rcvd: 62

AAAAフィルタが存在しない場合

miku@hachune% dig @8.8.8.8 AAAA www.kame.net

; <<>> DiG 9.9.2-P2 <<>> @8.8.8.8 AAAA www.kame.net
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 47873
;; flags: qr rd ra; QUERY: 1, ANSWER: 2, AUTHORITY: 0, ADDITIONAL: 1

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;www.kame.net.                  IN      AAAA

;; ANSWER SECTION:
www.kame.net.           21599   IN      CNAME   orange.kame.net.
orange.kame.net.        21599   IN      AAAA    2001:200:dff:fff1:216:3eff:feb1:44d7

;; Query time: 275 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Tue Apr  2 11:53:53 2013
;; MSG SIZE  rcvd: 90

2013年3月23日土曜日

NetBSD/RPiで遊ぶ(SDカードへの書き込み回数を気にしつつ)

流行りのRaspberry PiでNetBSDが動くようになったと聞いて、早速遊んでみる。 今回は、SDカードをread onlyにし、USBメモリに動的なファイルを書き出すこ とで、書き込み制限回数超過による不具合が起きにくく(起きても簡単に修復 可能)、かつSDカード側の更新が容易にできるようなシステムを目指す。

用意しておくもの

  • Raspberry Pi
  • Micro-USBケーブル(電源用)
  • キーボード, HDMI対応ディスプレイ, HDMIケーブル(可能ならRS-232C経由 でもOK)
  • SDカード(rootfs用、1GBで十分)
  • USBメモリ(unionfs用)
  • NetBSD環境(VMでも可)
  • はちゅねさん(監視役)

NetBSD/RPiのイメージを入手

NetBSD/rpiのHEADのイメージを入手する。もちろん自分でソースからbuild.sh してもよい。 今回は、てっとり早く済ませる為にNetBSD-dailyミラーから入手。 (NetBSD-daily/HEAD/日付/evbarm/binary/gzimg/rpi.img.gz) ftp://ftp.jaist.ac.jp/pub/NetBSD-daily/HEAD/201303201620Z/evbarm/binary/gzimg/rpi.img.gz

イメージの編集

ダウンロードしたイメージファイルを展開しSDカードに書き込み、NetBSD環境 にて編集する。今回は、SDカードとUSBメモリを直接NetBSDがインストールさ れている仮想マシン(KVM)に接続し編集を行う。それぞれの環境上で各デバイ スは以下のようになっているものとする。
デバイス用途ホストゲスト(NetBSD)RPi(NetBSD)
SDカードroot/dev/mmcblk0/dev/ld1/dev/ld0
USBメモリunion/dev/sdb/dev/ld2/dev/sd0
miku@hachune% gzip -cd rpi.img.gz | sudo dd of=/dev/mmcblk0 bs=1M
miku@hachune% sudo qemu-system-x86_64 -enable-kvm -m 512 \
> -drive file=/dev/mmcblk0,if=virtio \
> -drive file=/dev/sdc,if=virtio \
> -serial pty -nographic
まずはRasberry Pi用イメージ上のルートファイルシステムとなるファイルシ ステムを/mnt以下にマウントする。その中にunionfsの上のレイヤーとなるUSB メモリのマウントポイント/unionを作成しマウントする。また、/union以下に 各ディレクトリとのunionディレクトリを作成する。
nbsd# mount /dev/ld1a /mnt
nbsd# mkdir /mnt/union
nbsd# mount /dev/ld2a /mnt/union
nbsd# mkdir /mnt/union/usr /mnt/union/var \
> /mnt/union/etc /mnt/union/root /mnt/union/home
/mnt/etc/rc.confを編集する。今回ネットワークはdhcpcd任せとするが、もち ろん静的設定を行っても良い。また、swap領域をSDカード上に作成しては書き 込み回数を抑える事ができないためsavecoreと合わせて無効にしておく。
更に、mountcritlocalの時点で/varが書き込み可能な状態でマウントされるよ う、critical_filesystems_localを設定しておく。(これを行なっていないと、 /varに書き込めずsyslog等を正しく実行できない)
if [ -r /etc/defaults/rc.conf ]; then
        . /etc/defaults/rc.conf
fi
rc_configured=YES
hostname=negi.k.hachune.org
sshd=YES
dhcpcd=YES
wscons=YES
no_swap=YES
savecore=NO
critical_filesystems_local="/union /etc /var"
/etc/fstabを編集する。ここでは、swap領域のコメントアウトと/tmpのtmpfs の追加、unionfsの設定を行なう。
/dev/ld0a       /               ffs     rw,log,noatime  1 1
# /dev/ld0b       none            swap    sw      0 0
/dev/ld0e       /boot           msdos   rw      1 1
kernfs          /kern           kernfs  rw
ptyfs           /dev/pts        ptyfs   rw
procfs          /proc           procfs  rw
tmpfs           /tmp            tmpfs   rw,-m=1777,-s=67608576

/dev/sd0e       /union          ffs     rw,log,noatime  1 1
/union/usr      /usr            union   rw
/union/var      /var            union   rw
/union/etc      /etc            union   rw
/union/root     /root           union   rw
/union/home     /home           union   rw
最後に、ssh経由でログインできるようホスト側のパスワードファイル等をコ ピーし、ホームディレクトリを作成しておく。
nbsd# cp /etc/group /etc/passwd /etc/master.passwd /mnt/etc
nbsd# mkdir /mnt/home

カーネルのrebuild

残念ながら現在のRPIのカーネルはunionfsがサポートされていない(コメント アウトされている)ようで、そのままで起動するとunion mountに失敗し悲しい 状態に陥る。仕方ないのでカーネルだけ設定を変えてビルドしてみる。ついで に使いそうな機能も有効に。
通常のRPIカーネルと今回作成するNEGIPIカーネルの設定のdiffは以下の通り。
miku@hatsune% diff sys/arch/evbarm/conf/{RPI,NEGIPI}
43c43
< #file-system  UNION           # union file system
---
> file-system   UNION           # union file system
252c252
< #pseudo-device        carp                    # Common Address Redundancy Protocol
---
> pseudo-device carp                    # Common Address Redundancy
  Protocol
256,257c256,257
< #pseudo-device        ppp                     # Point-to-Point
  Protocol
< #pseudo-device        pppoe                   # PPP over Ethernet
  (RFC 2516)
---
> pseudo-device ppp                     # Point-to-Point Protocol
> pseudo-device pppoe                   # PPP over Ethernet (RFC 2516)
262,263c262,263
< #pseudo-device        tap                     # virtual Ethernet
< #pseudo-device        tun                     # network tunneling over tty
---
> pseudo-device tap                     # virtual Ethernet
> pseudo-device tun                     # network tunneling over tty
後はいつも通りbuild.sh。(クロスコンパイルがLinux上でも簡単にできるのは 非常にうれしい)
miku@hatsune% ./build.sh -O ../objarm -m evbarm -N0 -j9 -U tools kernel=NEGIPI
...
===> Kernels built from NEGIPI:
  /home/miku/netbsd/src/../objarm/sys/arch/evbarm/compile/NEGIPI/netbsd
===> build.sh ended:      Sat Mar 23 04:28:47 JST 2013
===> Summary of results:
         build.sh command:    ./build.sh -O ../objarm -m evbarm -N0 -j5 -U kernel=NEGIPI
         build.sh started:    Sat Mar 23 04:27:45 JST 2013
         NetBSD version:      6.99.17
         MACHINE:             evbarm
         MACHINE_ARCH:        arm
         Build platform:      Linux 3.8.4-1-ARCH-amd64 x86_64
         HOST_SH:             /bin/sh
         MAKECONF file:       /etc/mk.conf (File not found)
         TOOLDIR path:        /home/miku/netbsd/src/../objarm/tooldir.Linux-3.8.4-1-ARCH-amd64-x86_64
         DESTDIR path:        /home/miku/netbsd/src/../objarm/destdir.evbarm
         RELEASEDIR path:     /home/miku/netbsd/src/../objarm/releasedir
         Updated makewrapper: /home/miku/netbsd/src/../objarm/tooldir.Linux-3.8.4-1-ARCH-amd64-x86_64/bin/nbmake-evbarm
         Building kernel without building new tools
         Building kernel:     NEGIPI
         Build directory:     /home/miku/netbsd/src/../objarm/sys/arch/evbarm/compile/NEGIPI
         Kernels built from NEGIPI:
          /home/miku/netbsd/src/../objarm/sys/arch/evbarm/compile/NEGIPI/netbsd
         build.sh ended:      Sat Mar 23 04:28:47 JST 2013
===> .
miku@hatsune% ls -l ../objarm/sys/arch/evbarm/compile/NEGIPI/netbsd.bin
-rwxr-xr-x 1 miku miku 4637568  3月 23 04:28 ../objarm/sys/arch/evbarm/compile/NEGIPI/netbsd.bin
完成したカーネル(netbsdではなくnetbsd.bin)をSDカードのFAT領域に kernel.imgとしてコピーしておく。

起動

後はRaspberry PiにWrite protectスイッチをONにしたSDカードとUSBメモリを 挿し起動するだけ。所々カーネルがWARNINGを吐いているが、とりあえずは動 いているようだ。ssh経由だと結構サクサク動いているように感じる。

ハマりどころ

  • disklabelの扱いがamd64とevbarmで若干異なる
  • postfixが起動できない(unionfsでfcntlがコケる?, 未解決)
postfix/master[1087]: fatal: open lock file
/var/db/postfix/master.lock: cannot create file exclusively: Permission denied
negi# touch /var/db/postfix/master.lock
negi# chown postfix:postfix /var/db/postfix/master.lock
postfix/postfix-script: warning: not owned by postfix: /var/db/postfix
negi# chown postfix:postfix /var/db/postfix
postfix/master[1678]: fatal: fcntl: set non-blocking flag on: Operation not supported

dmesg

Copyright (c) 1996, 1997, 1998, 1999, 2000, 2001, 2002, 2003, 2004, 2005,
    2006, 2007, 2008, 2009, 2010, 2011, 2012, 2013
    The NetBSD Foundation, Inc.  All rights reserved.
Copyright (c) 1982, 1986, 1989, 1991, 1993
    The Regents of the University of California.  All rights reserved.

NetBSD 6.99.17 (NEGIPI) #2: Sat Mar 23 04:28:45 JST 2013
        miku@hatsune.k.hachune.org:/home/miku/netbsd/objarm/sys/arch/evbarm/compile/NEGIPI
total memory = 192 MB
avail memory = 183 MB
timecounter: Timecounters tick every 10.000 msec
cprng kernel: WARNING insufficient entropy at creation.
mainbus0 (root)
cpu0 at mainbus0 core 0: 700 MHz ARM1176JZ-S r0p7 (ARM11J V6ZK core)
cpu0: DC enabled IC enabled WB enabled LABT
cpu0: isar: [0]=0x140011 [1]=0x12002111 [2]=0x11231121 [3]=0x1102131, [4]=0x1141, [5]=0
cpu0: mmfr: [0]=0x1130003 [1]=0x10030302 [2]=0x1222100 [3]=0
cpu0: pfr: [0]=0x111 [1]=0x11
cpu0: 16KB/32B 4-way L1 Instruction cache
cpu0: 16KB/32B 4-way write-back-locking-C L1 Data cache
vfp0 at cpu0: VFP11
obio0 at mainbus0
bcmicu0 at obio0
bcmmbox0 at obio0: VC mailbox
vcmbox0 at bcmmbox0
bcmtmr0 at obio0 intr 3: VC System Timer
bcmpm0 at obio0: Power management, Reset and Watchdog controller
bcmrng0 at obio0: RNG
plcom0 at obio0 intr 57
plcom0: txfifo disabled
plcom0: console
genfb0 at obio0no data for est. mode 640x480x67
: switching to framebuffer console
genfb0: framebuffer at 0xc006000, size 1920x1200, depth 32, stride 7680
wsdisplay0 at genfb0 kbdmux 1: console (default, vt100 emulation)
wsmux1: connecting to wsdisplay0
wsdisplay0: screen 1-3 added (default, vt100 emulation)
sdhc0 at obio0 intr 62: SDHC controller
sdhc0: interrupting on intr 62
sdhc0: SD Host Specification 3.0, rev.153
sdmmc0 at sdhc0 slot 0
dotg0 at obio0 intr 9: USB controller
bcmspi0 at obio0 intr 54: SPI
spi0 at bcmspi0: SPI bus
bsciic0 at obio0 intr 53: BSC0
iic0 at bsciic0: I2C bus
bsciic1 at obio0 intr 53: BSC1
iic1 at bsciic1: I2C bus
usb0 at dotg0: USB revision 2.0
timecounter: Timecounter "clockinterrupt" frequency 100 Hz quality 0
timecounter: Timecounter "bcmtmr0" frequency 1000000 Hz quality 100
WARNING: module error: vfs load failed for `usbverbose', error 45
uhub0 at usb0WARNING: module error: vfs load failed for `usbverbose', error 45
: vendor 0x0000 DWC OTG root hub, class 9/0, rev 2.00/1.00, addr 1
uhub0: 1 port with 1 removable, self powered
ld0 at sdmmc0: <0x02:0x544d:SD04G:0x38:0xb0f6cf37:0x088>
ld0: 3780 MB, 1920 cyl, 64 head, 63 sec, 512 bytes/sect x 7741440 sectors
ld0: 4-bit width, bus clock 50.000 MHz
WARNING: module error: vfs load failed for `usbverbose', error 45
WARNING: module error: vfs load failed for `usbverbose', error 45
uhub1 at uhub0 port 1WARNING: module error: vfs load failed for `usbverbose', error 45
WARNING: module error: vfs load failed for `usbverbose', error 45
: vendor 0x0424 product 0x9512, class 9/0, rev 2.00/2.00, addr 2
uhub1: multiple transaction translators
uhub1: 3 ports with 2 removable, self powered
WARNING: module error: vfs load failed for `usbverbose', error 45
WARNING: module error: vfs load failed for `usbverbose', error 45
usmsc0 at uhub1 port 1
WARNING: module error: vfs load failed for `usbverbose', error 45
WARNING: module error: vfs load failed for `usbverbose', error 45
usmsc0: vendor 0x0424 product 0xec00, rev 2.00/2.00, addr 3
usmsc0:  Ethernet address b8:27:eb:a1:40:7b
ukphy0 at usmsc0 phy 1WARNING: module error: vfs load failed for `miiverbose', error 45
: OUI 0x00800f, model 0x000c, rev. 3
ukphy0: 10baseT, 10baseT-FDX, 100baseTX, 100baseTX-FDX, auto
WARNING: module error: vfs load failed for `usbverbose', error 45
uhidev0 at uhub1 port 2 configuration 1 interface 0
WARNING: module error: vfs load failed for `usbverbose', error 45
uhidev0: vendor 0x04d9 USB Keyboard, rev 1.10/3.90, addr 4, iclass 3/1
ukbd0 at uhidev0: 8 modifier keys, 6 key codes
wskbd0 at ukbd0: console keyboard, using wsdisplay0
uhidev1 at uhub1 port 2 configuration 1 interface 1
WARNING: module error: vfs load failed for `usbverbose', error 45
uhidev1: vendor 0x04d9 USB Keyboard, rev 1.10/3.90, addr 4, iclass 3/1
uhidev1: 2 report ids
uhid0 at uhidev1 reportid 1: input=6, output=0, feature=0
uhid1 at uhidev1 reportid 2: input=1, output=0, feature=0
umass0 at uhub1 port 3 configuration 1 interface 0
umass0: JetFlash Mass Storage Device, rev 2.00/1.00, addr 5
umass0: using SCSI over Bulk-Only
scsibus0 at umass0: 2 targets, 1 lun per target
sd0 at scsibus0 target 0 lun 0: <JetFlash, Transcend 4GB, 8.07> disk removable
sd0: fabricating a geometry
sd0: 3830 MB, 3830 cyl, 64 head, 32 sec, 512 bytes/sect x 7843840 sectors
boot device: ld0
root on ld0a dumps on ld0b
mountroot: trying nfs...
mountroot: trying msdos...
mountroot: trying ext2fs...
mountroot: trying ffs...
root file system type: ffs
WARNING: no TOD clock present
WARNING: using filesystem time
WARNING: CHECK AND RESET THE DATE!
warning: no /dev/console
init: copying out path `/sbin/init' 11
sd0: fabricating a geometry
WARNING: module error: vfs load failed for `compat', error 78
WARNING: module error: vfs load failed for `compat', error 78
WARNING: module error: vfs load failed for `compat', error 78
WARNING: module error: vfs load failed for `compat', error 78
WARNING: module error: vfs load failed for `compat', error 78
WARNING: module error: vfs load failed for `compat', error 78
WARNING: module error: vfs load failed for `com', error 78
WARNING: module error: vfs load failed for `com', error 78
nd6_dad_timer: called with non-tentative address 2001:c90:8405:1f9c:ba27:ebff:fea1:407b(usmsc0)
wsdisplay0: screen 4 added (default, vt100 emulation)

2013年3月21日木曜日

OpenBlocks AX3上のLXC用の最小構成Arch Linux rootfsを作る

前回構築したOpenBlocks用Arch Linuxコンテナには 不要なパッケージも多く含まれている。そこで、作成したコンテナを利用し最小構成 (systemdとsshdが上がりログインができる状態)のrootfs tarballを作成する。

基本的な構築方法は x86_64環境のArch LinuxでLXCコンテナ用rootfsを作成した時と同じであるが、 今回はpacstrap時にbaseを丸ごと入れるのではなく、systemdとopensshのみ導入する。

miku@arch% su
root@arch# pacman -S arch-install-scripts
root@arch# mkdir rootfs
root@arch# pacstrap -d rootfs pacman systemd openssh bash
root@arch# chroot rootfs /bin/bash
root@arch(chroot)# ln -s /usr/lib/systemd/system/sshd.service \
> /etc/systemd/system/multi-user.target.wants/sshd.service
root@arch(chroot)# ln -s /usr/lib/systemd/system/sshdgenkeys.service \
> /etc/systemd/system/multi-user.target.wants/sshdgenkeys.service
root@arch(chroot)# pacman -Sc
root@arch(chroot)# rm /var/cache/pacman/pkg/*
root@arch(chroot)# mkdir /dev/pts
root@arch(chroot)# passwd
root@arch(chroot)# groupadd -g 3939 miku
root@arch(chroot)# useradd -g miku -u 3939 -s /bin/bash -m miku
root@arch(chroot)# passwd miku
root@arch(chroot)# exit
root@arch# rm rootfs/root/.bash_history
root@arch# tar cJpf rootfs.tar.gz rootfs

今回作成した最小構成環境が正しく動作するか試したところ、/dev/consoleが 存在しないとのエラーが発生する。

miku@obs$ sudo /usr/miku/bin/lxc-start -n test -- /usr/lib/systemd/systemd
lxc-start: No such file or directory - stat(/proc/26644/root/dev//console)

これも/dev/ptsが存在しない問題と似た問題のようなので、/dev/consoleを作 成しておく。

root@arch(chroot)# mknod -m 600 mini/rootfs/dev/console c 5 1

LXC側で必要としている/dev/tty{1..4}等はLXC側で自動作成しているようなの で、LXC側で必要であるのに/dev/consoleを自動作成できていないのが原因だ と考えられる。

/dev/console作成後は想定通り動作するようになった。

miku@obs% sudo /usr/miku/bin/lxc-start -n test -- /usr/lib/systemd/systemd
<30>systemd[1]: Smack is not enabled in the kernel, not loading access rules.

今回作成したOpenBlocks用の最小構成のrootfs tarballは、以下からダウンロードできるよ うにしておいたので、試してみたい方はどうぞ。
http://repo.hachune.net/Linux/ArchLinux/rootfs/armv7h/2013.03.21/obs_rootfs.tar.xz