/home/tnishinaga/TechMEMO

日々行ったこと、面白かったことを書き留めます。

debian(wheezy)でtftpサーバーをたてた話

概要

著書「BareMetalで遊ぶ Raspberry Pi - 達人出版会」のプログラムをいちいちSDカードにコピーするのは面倒なので、U-Bootでネットワークブートさせたいです。

そのためにはまずTFTPサーバーを建てる必要があるのですが、他の人の方法では上手くいかなかったので、問題の調査過程と、問題解決の方法をメモしておきます。

 

TFTPサーバーのインストール

$ sudo aptitude -y install tftp tftpd-hpa

デフォルトの設定はこんな感じ

$cat /etc/default/tftpd-hpa 
# /etc/default/tftpd-hpa

TFTP_USERNAME="tftp"
TFTP_DIRECTORY="/srv/tftp"
TFTP_ADDRESS="0.0.0.0:69"
TFTP_OPTIONS="--secure"

今回はファイルの読み込みしかしないので、特に修正しないことにします。

TFTPサーバーが /srv/tftp にアクセスできるようにディレクトリの権限を変えておきます。

$ sudo chown -R tftp:nogroup /srv/tftp
$ sudo chmod -R 777 /srv/tftp

そしてhosts.allowに追加。

$ sudo sh -c "echo `in.tftpd:ALL` >> /etc/hosts.allow"

後は以下のコマンドでTFTPサーバーを再起動する。

$ sudo /etc/init.d/tftpd-hpa restart

TFTPサーバーの動作確認(問題発生)

U-Bootでチェックする前に、ローカルの環境から接続できるかテストします。

まずはテストのためにファイルを作っておきましょう。 作成後はアクセス権限を付与するのを忘れないように気をつけてください。

$ sudo sh -c "echo `hoge` >> /srv/tftp/hoge.txt"
$ sudo chown -R tftp:nogroup /srv/tftp
$ sudo chmod -R 777 /srv/tftp

ではこのhoge.txtをダウンロードしてみましょう。

$ tftp localhost

tftp> verbose
Verbose mode on.

tftp> trace
Packet tracing on.

tftp> get hoge.txt
getting from localhost:hoge.txt to hoge.txt [netascii]
sent RRQ <file=hoge.txt, mode=netascii>
sent RRQ <file=hoge.txt, mode=netascii>
sent RRQ <file=hoge.txt, mode=netascii>
sent RRQ <file=hoge.txt, mode=netascii>
sent RRQ <file=hoge.txt, mode=netascii>
Transfer timed out.

あれ…?うまく動かないですね。

xinetdを入れたり色々やってみましたが、状況が変わらないので、ちょっとまじめに調査してみます。

問題の調査

TFTPサーバーの起動確認

まずTFTPサーバーが動いているかを確認しましょう。

$ ps ax | grep tftp
 7832 ?        Ss     0:00 /usr/sbin/in.tftpd --listen --user tftp --address 0.0.0.0:69 --secure /srv/tftp

動いてますね。特に問題なさそうです。

アクセス権限の確認

次はアクセス権限の確認

$ ls -la /srv/tftp/
total 12
drwxrwxrwx 2 tftp   nogroup 4096 Apr 27 16:18 .
drwxrwxrwx 3 nobody nogroup 4096 Apr 27 00:18 ..
-rwxrwxrwx 1 tftp   nogroup    5 Apr 27 16:18 hoge.txt

これも特に問題なさそうです。

ネットワーク接続の確認

netstatを使って、TFTPサーバーの使用するUDP 69番ポートをチェックしてみます。

$ sudo netstat -tlnup | grep :69
udp        0      0 0.0.0.0:69              0.0.0.0:*      

これも特に問題なさそうです。

tcpdumpでパケットを覗く

どうにも原因がわからないので、tcpdumpでパケットを覗いて、TFTPクライアントがどのような要求を投げているか確認してみることにします。

もしかすると69以外のポートにアクセスしようとしているかもしれないので、SSHの22番ポート以外すべてをチェックします。

IPアドレスlocalhostで指定するとループバックインターフェースを使用するので、きちんと指定してあげましょう(実はこれにもハマりました)。

$ tcpdump -i lo not port 22
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on lo, link-type EN10MB (Ethernet), capture size 65535 bytes

この状態でもう1つ端末を開いて、そちらでtftpサーバーにアクセスしてみます。

$ tftp localhost

tftp> get hoge.txt

するとtcpdumpを立ち上げていた方に、以下の様なメッセージが出てきます。

21:50:36.734144 IP6 localhost.47887 > localhost.tftp:  20 RRQ "hoge.txt" netascii
21:50:36.734155 IP6 localhost > localhost: ICMP6, destination unreachable, unreachable port, localhost udp port tftp, length 76

どうやらIPv6でアクセスしようとして、失敗しているみたいです。 調べている過程で「IPv6でアクセスすると動かないから、 IPv4固定にしたほうがいいよー」と書いてあるところがあったので、IPv4を使うように指定してみましょう。

IPv4でアクセスしてみる

色々検証した結果、どうやらlocalhostで指定すると、IPv6アドレスの::1を見に行ってしまうようです。 IPv4で自身にアクセスするには、127.0.0.1を接続先に指定すれば良いです。

$ tftp 127.0.0.1

tftp> verbose
Verbose mode on.

tftp> trace
Packet tracing on.

tftp> get hoge.txt
getting from 127.0.0.1:hoge.txt to hoge.txt [netascii]
sent RRQ <file=hoge.txt, mode=netascii>
received DATA <block=1, 6 bytes>
Received 6 bytes in 0.1 seconds [480 bits/sec]

成功しました。 tcpdumpの結果も以下のようになっており、IPv4でアクセスできているみたいです。

22:03:08.299256 IP localhost.59555 > localhost.tftp:  20 RRQ "hoge.txt" netascii
22:03:08.300963 IP localhost.33201 > localhost.59555: UDP, length 10
22:03:08.301045 IP localhost.59555 > localhost.33201: UDP, length 4

おわりに

というわけで、やっとローカルからの動作確認が取れました。

まさかたったこれだけのことに、ほぼ1日じゅう調べ回ることになるとは……。

しかし今回いろいろ調べたお陰で、また同じような問題が起こった際に対処できるようになり、一歩前進したのでよしとします。

同じような問題に引っかかった人の助けになれば嬉しいです。