2013年5月31日

RaspberryPiをWiFiでつなぐ(2) 任意のAPに接続

前回はRaspberryPiの起動時に予め指定したデフォルトの暗号化されたWiFi APに接続できるようにした。今回はSSIDを指定して任意のAPに接続する。

方法はいたって簡単で、まず
  • 接続したいAPを記述したwap_supplicantファイル
  • それを指し示すinterfacesファイル
を作る。ファイルの置き場所はどこでもよいが、一応デフォルトのディレクトリに入れることにする。

注意:wpa_supplicantファイルは平文のPSKを含むので、必ずオーナをスーパーユーザにしてオーナ以外の読み出しを禁止すること。
pi@raspberrypi$ sudo cat /etc/wpa_supplicant/wpa_supplicant-my_ssid2.conf
network={
    ssid="my_ssid2"
    proto=RSN
    key_mgmt=WPA-PSK
    pairwise=TKIP
    group=TKIP
    psk="yyyyyyyy"
}

pi@raspberrypi$ ls -l /etc/wpa_supplicant/wpa_supplicant-my_ssid2.conf
-r-------- 1 root root 218 May 20 17:09 /etc/wpa_supplicant/wpa_supplicant-my_ssid2.conf
pi@raspberrypi$ sudo cat /etc/network/interfaces.my_ssid2
iface wlan0 inet dhcp
wireless-essid my_ssid2
wpa-conf
/etc/wpa_supplicant/wpa_supplicant-my_ssid2.conf

ifdownで現在の接続を終了する。
pi@raspberrypi$ sudo ifdown wlan0
Internet Systems Consortium DHCP Client 4.2.2
Copyright 2004-2011 Internet Systems Consortium.
All rights reserved.
For info, please visit https://www.isc.org/software/dhcp/

Listening on LPF/wlan0/80:1f:02:86:f6:ef
Sending on   LPF/wlan0/80:1f:02:86:f6:ef
Sending on   Socket/fallback
DHCPRELEASE on wlan0 to 192.168.0.1 port 67

まだデーモンプロセスが動いていると現在の接続を完全に終了できないので、それらを殺し、念のためifconfigでwlan0をディセーブルしてクリーンな状態にする。
pi@raspberrypi$ sudo kill `ps ax | grep wlan0 | grep -v grep| awk '{print $1}'`
pi@raspberrypi$ sudo ifconfig wlan0 down

あとはwlan0をもう一度イネーブルして、ifupの-iオプションで先ほどのinterfacesファイルを指定してやればOK。

pi@raspberrypi$ sudo ifconfig wlan0 up
pi@raspberrypi$ sudo ifup -i /etc/network/interfaces.my_ssid2 wlan0

次は、wlan0がAPに接続されていない時にスキャンで得られたAPと自分の知っているAPのリストを照合して自動的に候補のAPにつなぐこと。たぶんシェルスクリプトで可能だと思うが…。

2013年5月24日

RaspberryPiをWiFiでつなぐ

RaspberryPiを車載のデータレコーダとして使用し、帰宅して車庫に入ったり外出先でホットスポットなどでWiFiがつながれば自動的にデータをアップロードするようなアプリケーションを考えている。

まず一番最初に実現することは、自宅のWiFi LANに接続できるようにすること。

ハードウェア

Edimax EW-7811Unという802.11nをサポートするUSBの超小型ドングルを使ってうまく行った。$10程度と値段も手頃。

ソフトウェア

こちらのサイトをパクらせていただいた。

我が家のWLANはWPA2-PSK-TKIPでSSIDのブロードキャストなし。

まず、何もしない状態から。
pi@raspberrypi$ lsusb
Bus 001 Device 001: ID 1d6b:0002 Linux Foundation 2.0 root hub
Bus 001 Device 002: ID 0424:9512 Standard Microsystems Corp.
Bus 001 Device 003: ID 0424:ec00 Standard Microsystems Corp.
Bus 001 Device 004: ID 7392:7811 Edimax Technology Co., Ltd EW-7811Un 802.11n Wireless Adapter [Realtek RTL8188CUS]

pi@raspberrypi$ iwconfig wlan0
wlan0     unassociated  Nickname:"<WIFI@REALTEK>"
          Mode:Managed  Frequency=2.412 GHz  Access Point: Not-Associated 
          Sensitivity:0/0
          Retry:off   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality:0  Signal level:0  Noise level:0
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0

受信できるWiFiのAPを探してみる。
pi@raspberrypi$ iwlist wlan0 scan | grep ESSID
                    ESSID:""
                    ESSID:""
                    ESSID:"NETGEAR16"
「NETGEAR16」は隣の家のAPのようだ。我が家のAPのSSIDは見えない。

iwconfigで秘密のSSIDを指定してやる。
pi@raspberrypi$ sudo iwconfig wlan0 essid "my_ssid"
pi@raspberrypi$ iwlist wlan0 scan | grep ESSID
                    ESSID:"my_ssid"
                    ESSID:""
                    ESSID:"NETGEAR16"

pi@raspberrypi$ iwconfig wlan0

wlan0     IEEE 802.11bg  ESSID:"my_ssid"  Nickname:"<WIFI@REALTEK>"
          Mode:Managed  Frequency:2.412 GHz  Access Point: D8:EB:97:B1:33:99  
          Bit Rate:54 Mb/s   Sensitivity:0/0
          Retry:off   RTS thr:off   Fragment thr:off
          Power Management:off
          Link Quality=100/100  Signal level=65/100  Noise level=0/100
          Rx invalid nwid:0  Rx invalid crypt:0  Rx invalid frag:0
          Tx excessive retries:0  Invalid misc:0   Missed beacon:0
見えなかった秘密のSSIDが見えるようになり、WLANのリンク層(APのMAC)も見えるようになった。

次はWPAの認証と接続。前述のサイトの指示に従って、WPA2-PSK-TKIP用のwpa_supplicant.confファイルを作る。/etc/wpa_supplicant/wpa_supplicant.confはすでに存在しているが、ファイルの内容が余りにも違うので、別にファイルを作ることにする。
注意:このファイルは平文のPSKを含むので、必ずオーナをスーパーユーザにしてオーナ以外の読み出しを禁止すること。
pi@raspberrypi$ sudo cat /etc/wpa_supplicant/wpa_supplicant-my_ssid.conf
network={
    ssid="my_ssid"
    proto=RSN
    key_mgmt=WPA-PSK
    pairwise=TKIP
    group=TKIP
    psk="xxxxxxxx"
}
 
pi@raspberrypi$ ls -l /etc/wpa_supplicant/wpa_supplicant-my_ssid.conf
-r-------- 1 root root 218 May 20 17:09 /etc/wpa_supplicant/wpa_supplicant-my_ssid.conf

ごのファイルで認証と接続を実行する。
pi@raspberrypi$ sudo wpa_supplicant -i wlan0 -c  /etc/wpa_supplicant/wpa_supplicant-my_ssid.conf
rfkill: Cannot open RFKILL control device
rfkill: Cannot open RFKILL control device
ioctl[SIOCSIWAP]: Operation not permitted
ioctl[SIOCSIWENCODEEXT]: Invalid argument
ioctl[SIOCSIWENCODEEXT]: Invalid argument
wlan0: CTRL-EVENT-DISCONNECTED bssid=00:00:00:00:00:00 reason=0
ioctl[SIOCSIWENCODEEXT]: Invalid argument
ioctl[SIOCSIWENCODEEXT]: Invalid argument
wlan0: Trying to associate with d8:eb:97:b1:22:88 (SSID='my_ssid' freq=2412 MHz)
wlan0: Association request to the driver failed
wlan0: Associated with d8:eb:97:b1:33:99
wlan0: WPA: Key negotiation completed with d8:eb:97:b1:33:99 [PTK=TKIP GTK=TKIP]
wlan0: CTRL-EVENT-CONNECTED - Connection to d8:eb:97:b1:33:99 completed (auth) [id=0 id_str=]
^Z
[1]+  Stopped                 sudo wpa_supplicant -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant-my_ssid.conf
pi@raspberrypi$ bg
[1]+ sudo wpa_supplicant -i wlan0 -c /etc/wpa_supplicant/wpa_supplicant-my_ssid.conf &
rfkillioctlが何だか文句をつけるが、wpa_supplicantが異常終了しなければうまく行っている。このままでは接続中はずっとwpa_supplicantが走り続けるので、バックグラウンドに追いやる。

ここでifconfigを実行してみると、あ~ら不思議、dhcpもちゃんと動いてWLANが使えるようになっている。
pi@raspberrypi$ ifconfig wlan0
wlan0     Link encap:Ethernet  HWaddr 80:1f:02:86:07:e0 
          inet addr:192.168.0.115  Bcast:192.168.0.255  Mask:255.255.255.0
          UP BROADCAST MULTICAST  MTU:1500  Metric:1
          RX packets:0 errors:0 dropped:450574 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:73019668 (69.6 MiB)  TX bytes:729719 (712.6 KiB)

以上の操作をシステム起動時に自動的に実行させる。私はDebian系のRCファイルはまったく分からないが、前述のサイトの指示にしたがって/etc/network/interfacesを変更してみた。空色の部分が変更・追加した所。
pi@raspberrypi$ cat /etc/network/interfaces
# $Header: /etc/network/RCS/interfaces,v 1.2 2013/05/21 00:17:33 root Exp $
auto lo

iface lo inet loopback
iface eth0 inet dhcp

allow-hotplug wlan0
# Disabled by h
##iface wlan0 inet manual
##wpa-roam /etc/wpa_supplicant/wpa_supplicant.conf
##iface default inet dhcp


# Added by h
# http://www.youchikurin.com/blog/2007/06/linuxlan_1.html
auto wlan0
iface wlan0 inet dhcp
wireless-essid my_ssid
wpa-conf /etc/wpa_supplicant/wpa_supplicant-my_ssid.conf
リブートすると自動的にWLANに接続される。ifupifdownが使えるのでWLANを任意に接続・切断できる。

これで自宅のWLANに常に接続できるようになった。次は、現在見える(あるいは見えない)SSIDから予め登録された「安全なホットスポット」のリストを照合して自動的に接続する方法を見つけるあるいは作ることだが、それは次回に…。

2013年5月15日

Cygwinからネットワークドライブ・シェアをアクセス

Windowsでネットワークドライブとしてマウントしてあるネットワークシェアは、Cygwinからは/cygdrive/<ドライブレター>としてアクセスできる(はず)。
h@cygwin:~$> ls -l /cygdrive
total 0
drwxrwxr-x+ 1 Administrators root     0 2013-05-14 04:13 c/
drwxrwxr-x+ 1 ????????       ???????? 0 2013-05-14 03:02 r/
ここは、//readynas312/backup-cygwin というNASのシェアをR:にネットワークドライブとしてマウントしてある。

ところで、このネットワークドライブ(シェア)はパス(UNC)を明示的に使ってアクセスすることもできる。
h@cygwin:~$> ls -l //readynas312
total 0
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-09 21:33 Backup/
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-13 13:28 Documents/
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-09 20:42 Music/
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-09 20:42 Pictures/
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-14 03:02 backup-cygwin/
-rw-r--r--  1 h        None     0 2006-11-30 16:00 backup-garlic

実はこのNASにはbackup-cygwin以外にも、上に見られるように
  • Backup
  • Documents
  • Music
  • Pictures
  • backup-cygwin
  • backup-garlic
というシェアがあるのだが、これらのうち、BackupDocumentsMusicPicturesは「guest」のオーナシップで誰でもアクセスでき、backup-cygwinbackup-garlicはそれぞれ同じ名前のアカウントがオーナである。ところが、backup-garlicはこのホスト(cygwin)からアクセスのためのクレデンシャルを設定していないので本来ならディレクトリに見えるはずが通常ファイルに見えている
 
ただしguestがオーナでないネットワークドライブが/cygdrive/<ドライブレター>あるいはUNCでアクセスできるのは、Cygwinの走るホスト上でローカルに実行した場合のみ

sshでリモートから同じことをしようとしても上手く行かない
h@linux:~$ ssh cygwin
Last login: Tue May 14 11:26:08 2013 from linux
Fanfare!!!
You are successfully logged in to this server!!!
h@
cygwin:~$> ls -l /cygdrive
total 0
drwxrwxr-x+ 1 Administrators root     0 2013-05-14 04:13 c/
h@cygwin:~$> ls -l //readynas312
total 0
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-09 21:33 Backup/
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-13 13:28 Documents/
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-09 20:42 Music/
drwxrwxr-x+ 1 ???????? ???????? 0 2013-05-09 20:42 Pictures/
-rw-r--r--  1 h        None     0 2006-11-30 16:00 backup-cygwin
-rw-r--r--  1 h        None     0 2006-11-30 16:00 backup-garlic
/cygdriveからはR:が消え、//readynas312上のguestがオーナでないシェアはディレクトリとして見えない。

sshでCygwinにログインすると、ネットワークシェアにアクセスクレデンシャルを渡せないようだ

そんならcronからはどうか、とジョブを登録してみたが、やはりクレデンシャルが必要な、guestがオーナでないシェアはディレクトリとして見えないようだ。残念!

Cygwinでパス名を扱うときはスラッシュの扱いに気をつけなければならない。通常、Linuxではスラッシュがいくつ重なっていても単一のスラッシュと同じに扱われ、例えば「//aa/bb/cc」と「/aa/bb/cc」は同じことで、「ルートディレクトリの中のディレクトリaaの下のサブディレクトリbbの下のcc」だが、CygwinではWindowsのUNCと同じ解釈をして「ホストaaのシェアbbのトップディレクトリcc」をアクセスしようとする(そして失敗してもLinux風の重複スラッシュ無視にはフォールバックしない)。実はここで使ったNETGEARのNASは、ssh経由のrsyncで外部パスを指定するとホスト名とファイルパスを無造作に「:/」で結合していたので、例えば「host」の「/dir」を指定すると「host://dir」がrsyncに渡され、「:」の後ろがそのままCygwinに渡されるのでUNCと解釈されおかしなことになっていた(バグとして修正済み)。