ヘッドレスなBeagleBone Blackで取得IPアドレスを気にせずリモート接続する

BeagleBone Blackを持ち歩いて開発していると、たいていはヘッドレス運用でリモート接続なので、DHCP環境ではどのIPアドレスが割り当ったか知るすべはない。ブラウザでDHCP鯖の設定画面でも開けばわかるかもしれないが、手元のモバイルルーターでは、割り当てアドレスを知るすべもない。そんなときは、多少のブレはあっても数個の範囲内なので、pingでもして調べたらよいのだけど、それも面倒なので自動で名前解決できるように対策を講じる。
シリアル接続できる場合はこの限りではないのだけど、minicomでつなげるのがバックスクロールとかが微妙に不便なんだよね。
BeagleBone Blackの環境はUbuntu12.04。

mDNSでの名前解決

Appleの活用するBonjourで採用されている名前解決形式。
基本的には、サービス知りたいデバイスが、マルチキャストで「おーい!」っていうと、サービス持っている鯖が、「こんなサービスやってるよ!」と返すというシンプルな仕組み。
RFCにもなっているので、一般的だけど、思ったより使われていないのはどうしてか。Appleに背中から撃たれるのがイヤなのかな。
あと、.localで名前解決するのはイケてない気はするんだけどね。
http://tools.ietf.org/rfc/rfc6762.txt
ここでは使ってないけど、関連でこれも。
Dynamic Configuration of IPv4 Link-Local Addresses
http://tools.ietf.org/rfc/rfc3927.txt
zeroconf
http://www.zeroconf.org/

avahiのインストール

初期の頃は、Appleの提供するmDNSResponderが使われてたけど、なんかソースのライセンスに問題があるとかいうことで、コンパチ実装が出て来るようになった。その後、Appleのものはライセンスが変更されたりしたのだけど、その中で生き残ってスタンダードになったのがavahi。現在は、拡張されて他の用途にも使うようになっていたり。
さらに、mDNSを使って名前解決を行うことができるように、libnss-mdnsもインストールする。

ubuntu@ubuntu-armhf:~$ sudo apt-get install avahi-daemon libnss-mdns
Reading package lists... Done
Building dependency tree
Reading state information... Done
The following extra packages will be installed:
  bind9-host geoip-database libavahi-common-data libavahi-common3
  libavahi-core7 libbind9-80 libcap2 libdaemon0 libdns81 libgeoip1 libisc83
  libisccc80 libisccfg82 liblwres80 libxml2 sgml-base xml-core
Suggested packages:
  avahi-autoipd geoip-bin sgml-base-doc debhelper
The following NEW packages will be installed:
  avahi-daemon bind9-host geoip-database libavahi-common-data libavahi-common3
  libavahi-core7 libbind9-80 libcap2 libdaemon0 libdns81 libgeoip1 libisc83
  libisccc80 libisccfg82 liblwres80 libnss-mdns libxml2 sgml-base xml-core
0 upgraded, 19 newly installed, 0 to remove and 0 not upgraded.
Need to get 5294 kB of archives.
After this operation, 11.8 MB of additional disk space will be used.
(snip)

ホスト名の変更

ホスト名で名前解決するので、ホスト名を付ける。
デフォルトでは、ubuntu-armhfになっている。これは、長くて打ちにくい。

ubuntu@ubuntu-armhf:~$ cat /etc/hostname
ubuntu-armhf

黄色の丸シールが貼ってあるので、bbbyにする。設定後、再接続するとプロンプトも書き換わっている。

ubuntu@ubuntu-armhf:~$ sudo vi /etc/hostname
bbby
ubuntu@ubuntu-armhf:~$ sudo hostname bbby
ubuntu@ubuntu-armhf:~$ hostname
bbby
ubuntu@ubuntu-armhf:~$ exit
MacBook:~ kinneko$ ssh ubuntu@192.168.1.102
ubuntu@bbby:~$

しかし、ここは変わっていないな。

ubuntu@bbby:~$ cat /etc/hosts
127.0.0.1 localhost
127.0.1.1 ubuntu-armhf

avahiサーバーを再起動しておく。

ubuntu@bbby:~$ sudo /etc/init.d/avahi-daemon restart
Rather than invoking init scripts through /etc/init.d, use the service(8)
utility, e.g. service avahi-daemon restart

Since the script you are attempting to invoke has been converted to an
Upstart job, you may also use the stop(8) and then start(8) utilities,
e.g. stop avahi-daemon ; start avahi-daemon. The restart(8) utility is also available.
avahi-daemon stop/waiting
avahi-daemon start/running, process 1035

名前引きについては、nsswitch.confの変更を行う必要があるけれど、これはデフォルトで設定されている。

ubuntu@bbby:~$ cat /etc/nsswitch.conf | grep hosts
hosts:          files mdns4_minimal [NOTFOUND=return] dns mdns4

sshのサービスアナウンスを行う

bbby.localには、sshのサービスがあるよ、というお知らせを流せるようにする。
そのためのavahiの設定ファイルを作成する。

ubuntu@bbby:~$ sudo vi /etc/avahi/services/ssh.service
<?xml version="1.0" standalone='no'?>
<!DOCTYPE service-group SYSTEM "avahi-service.dtd">
<service-group>
    <name replace-wildcards="yes">%h ssh</name>
    <service>
        <type>_ssh._tcp</type>
        <port>22</port>
    </service>
</service-group>

avahiサーバーを再起動しておく。

ubuntu@bbby:~$ sudo /etc/init.d/avahi-daemon restart

設定の確認

bbby.localで名前引きできて、sshのサービスがアナウンスされているかどうか調べます。
まず、自前で確認するために、mdns-scanコマンドをインストールします。

ubuntu@bbby:~$ sudo apt-get install mdns-scan
ubuntu@bbby:~$ mdns-scan
+ bbby [90:59:af:5c:4d:b5]._workstation._tcp.local
+ bbby ssh._ssh._tcp.local

bbbyのホスト名と、sshサービスが動いていることが確認できます。


別のマシンからも確認してみます。

kinneko@BuildSV:~$ ping -c1 bbby.local
PING bbby.local (192.168.1.102) 56(84) bytes of data.
64 bytes from bbby.local (192.168.1.102): icmp_req=1 ttl=64 time=0.411 ms

--- bbby.local ping statistics ---
1 packets transmitted, 1 received, 0% packet loss, time 0ms
rtt min/avg/max/mdev = 0.411/0.411/0.411/0.000 ms

名前解決して、pingが届いています。

ポートセパレーターなどが設定されていると使えない

無線LANアクセスポイントでは、無線の盗聴を防ぐために、ポートセパレーターという機能が搭載されていて、無線クライアント同士での通信ができないようになっていることがある。この機能の名前は、メーカーによって違っていたりするので注意。
同様に、有線と無線の間で、マルチキャストが通じない設定になっていると使えない。
万能ではないのが残念。
今回の場合、無線接続のMacと有線のサーバー群との間では、マルチキャストが通過できなかった。

sshの鍵はIPアドレスに紐付けられている

sshは最初に接続すると、通信に使う鍵を生成して相互に自動保管する。
sshの鍵管理は、何も設定しないと、相手先のIPアドレスに紐付けられている。
つまり、DHCPで取得したIPアドレス変わると、参照する鍵も変わってしまう。
IPアドレスが変わってしまうと、また鍵を作らないと接続できなくなる。
この時、上書きしてくれればいいのだけど、すでに鍵があると接続できない。


この問題に対応するために、sshを公開鍵認証に変更しておく。
これは最初の一回はやらないといけないので、メンドクサイけどね。


普段、いろんなところに接続するために使っているので、鍵はすでに作成されている。
Macssh公開鍵をbbbyにコピーする。

MacBook:~ kinneko$ scp ~/.ssh/id_rsa.pub ubuntu@192.168.1.102:/home/ubuntu/.ssh/
ubuntu@192.168.1.102's password:
id_rsa.pub                                    100%  424     0.4KB/s   00:00

bbbyでは、これを登録する。登録後は削除しておく。鍵そのものは、テキストファイルなので、扱いが楽だ。

ubuntu@bbby:~$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
ubuntu@bbby:~$ rm ~/.ssh/id_rsa.pub

このままだと、誰でも読める状態になっているので、見られないように変更しておきます。

ubuntu@bbby:~$ ls -l ~/.ssh/authorized_keys
-rw-rw-r-- 1 ubuntu ubuntu 424 Mar 13 07:30 /home/ubuntu/.ssh/authorized_keys
ubuntu@bbby:~$ chmod 600 ~/.ssh/authorized_keys
ubuntu@bbby:~$ ls -l ~/.ssh/authorized_keys
-rw------- 1 ubuntu ubuntu 424 Mar 13 07:30 /home/ubuntu/.ssh/authorized_keys

Macから接続してみる。

MacBook:~ kinneko$ ssh ubuntu@192.168.1.102
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.8.13-bone30 armv7l)

 * Documentation:  https://help.ubuntu.com/
Last login: Thu Mar 13 05:45:06 2014 from buildsv.local

Macでは、特に認証なしにログインできた。


なんかIPアドレスでの接続だと、せっかくmDNS設定したのに、みっともないですな。
別のLinuxマシンからやり直し。

kinneko@BuildSV:~$ ls -l ~/.ssh/id_rsa.pub
-rw-r--r-- 1 kinneko kinneko 399 Mar 27  2013 /home/kinneko/.ssh/id_rsa.pub
kinneko@BuildSV:~$ scp ~/.ssh/id_rsa.pub ubuntu@bbby.local:/home/ubuntu/.ssh/
Warning: the ECDSA host key for 'bbby.local' differs from the key for the IP address '192.168.1.102'
Offending key for IP in /home/kinneko/.ssh/known_hosts:1
Matching host key in /home/kinneko/.ssh/known_hosts:8
Are you sure you want to continue connecting (yes/no)? yes
ubuntu@bbby.local's password:
id_rsa.pub                                    100%  399     0.4KB/s   00:00
ubuntu@bbby:~$ ls -l ~/.ssh/id_rsa.pub
-rw-r--r-- 1 ubuntu ubuntu 399 Mar 13 07:38 /home/ubuntu/.ssh/id_rsa.pub

ubuntu@bbby:~$ cat ~/.ssh/id_rsa.pub >> ~/.ssh/authorized_keys
ubuntu@bbby:~$ rm ~/.ssh/id_rsa.pub
kinneko@BuildSV:~$ ssh ubuntu@bbby.local
Warning: the ECDSA host key for 'bbby.local' differs from the key for the IP address '192.168.1.102'
Offending key for IP in /home/kinneko/.ssh/known_hosts:1
Matching host key in /home/kinneko/.ssh/known_hosts:8
Are you sure you want to continue connecting (yes/no)? yes
Enter passphrase for key '/home/kinneko/.ssh/id_rsa':
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.8.13-bone30 armv7l)

 * Documentation:  https://help.ubuntu.com/
Last login: Thu Mar 13 07:34:14 2014 from 192.168.1.100
ubuntu@bbby:~$ exit
logout
Connection to bbby.local closed.

以前sshで接続した実績から、IPでいうと1番目、キーで言うと8番目と一致するけど、続けるかどうか聞かれる。

kinneko@BuildSV:~$ ssh ubuntu@bbby.local
Warning: the ECDSA host key for 'bbby.local' differs from the key for the IP address '192.168.1.102'
Offending key for IP in /home/kinneko/.ssh/known_hosts:1
Matching host key in /home/kinneko/.ssh/known_hosts:8
Are you sure you want to continue connecting (yes/no)? yes
Enter passphrase for key '/home/kinneko/.ssh/id_rsa':
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.8.13-bone30 armv7l)

 * Documentation:  https://help.ubuntu.com/
Last login: Thu Mar 13 07:41:11 2014 from buildsv.local

毎回聞かれるのもウザイので、削除して再登録にする。削除した初回接続。

kinneko@BuildSV:~$ ssh ubuntu@bbby.local
The authenticity of host 'bbby.local (192.168.1.102)' can't be established.
ECDSA key fingerprint is 24:c4:b2:fe:9b:be:28:ec:85:86:f6:63:e1:62:3f:11.
Are you sure you want to continue connecting (yes/no)? yes
Warning: Permanently added 'bbby.local,192.168.1.102' (ECDSA) to the list of known hosts.
Enter passphrase for key '/home/kinneko/.ssh/id_rsa':
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.8.13-bone30 armv7l)

 * Documentation:  https://help.ubuntu.com/
Last login: Thu Mar 13 07:42:45 2014 from buildsv.local
ubuntu@bbby:~$ exit
logout
Connection to bbby.local closed.

一度切って再接続する。これが通常の画面になる。こちらはパスフレーズを要求される。

kinneko@BuildSV:~$ ssh ubuntu@bbby.local
Enter passphrase for key '/home/kinneko/.ssh/id_rsa':
Welcome to Ubuntu 12.04.4 LTS (GNU/Linux 3.8.13-bone30 armv7l)

 * Documentation:  https://help.ubuntu.com/
Last login: Thu Mar 13 07:44:48 2014 from buildsv.local
ubuntu@bbby:~$


鍵はどうやって作るのかって?
dsaで鍵を作ってみる。

ubuntu@bbby:~$ ssh-keygen -t dsa
Generating public/private dsa key pair.
Enter file in which to save the key (/home/ubuntu/.ssh/id_dsa):
Enter passphrase (empty for no passphrase):
Enter same passphrase again:
Your identification has been saved in /home/ubuntu/.ssh/id_dsa.
Your public key has been saved in /home/ubuntu/.ssh/id_dsa.pub.
The key fingerprint is:
9b:dc:f1:4f:52:e8:d8:14:02:53:a0:8d:8f:58:0e:9c ubuntu@bbby
The key's randomart image is:
+--[ DSA 1024]----+
|        +o.      |
|   . . + o       |
|    E + . . .    |
|     = o   . o   |
|    . o S . o .  |
|       . + B .   |
|        + o = .  |
|             +   |
|              .  |
+-----------------+

出来た。

ubuntu@bbby:~$ ls -l .ssh/id_dsa*
-rw------- 1 ubuntu ubuntu 751 Mar 13 07:53 .ssh/id_dsa
-rw-r--r-- 1 ubuntu ubuntu 601 Mar 13 07:53 .ssh/id_dsa.pub

id_dsaは秘密の鍵なので、管理には注意すること。
ファイル名は違うが、扱い方はid_rsaと同じ。

Windowsの人はどうすべきか?

LinuxMacは、これで問題ないけど、Windowsな人はどうするよ?と言われそう。
まぁ、わたしにはほとんど関係ないけどね。
iTunes入れたら?
と言いたいとこだけど、そんなめんどくさいもの入れたくないだろうね。
Safari入れても入るよな。
あ、開発やめたんだっけ... orz
そこで、これだ。
Bonjour Print Services for Windows v2.0.2
http://support.apple.com/kb/DL999


まぁ、こっちでもいいんだけど。ソースしか置いてないので。
https://github.com/jevinskie/mDNSResponder