2013年7月31日

AndroidでOpenVPNとVNCクライアントを走らせる

Barnes & NobleのNOOKというAndroidタブレットを買った。もともと同社のe-Readerとして開発・発売されたが、B&N社が電子本事業のビジネスモデルの見直しにあたって、Androidの一切の制約を外してGoogle Playの使えるフルのオープンな比較的安値($149)のAndoidタブレットになったので買ってみた。ちょうど配偶者が仕事先にタブレットを持って行きたがっていたので好機だという事情もあった。

配偶者の期待する主なタブレットの用途は現場での簡単な報告書作りだが、複雑なことは自宅でPCでじっくり行うとしても、表計算とかプレゼンテーションも将来的にはできるにこしたことはない。Android Market Placeを探すと数は少ないもののフルフィーチャーのオフィスツールスイートが売られているが、それらに飛びつく前に先ずはタブレットからVPNで自宅のLANに繋いでVCNでPCを操作できるようにしてみた。こうすれば外から自宅のPC上で編集や転送などのファイルの操作ができ、将来的にもインフラとして役立つと考えたから。ファイル転送に関してはDropBoxなどの商用クラウドを使う手もあるが、何時の間にかUIが変わっていたりとか、プライベートなファイルの運命を100%他人に委ねることは個人的にあまり好きではないので、商用クラウドも使ってはいるが限定的。こちらも半プロだからバックアップとかセキュリティとかにはかなりの労力を使っていて、今のところうまく行っている。

VPN経由のVCNによるLAN上のPCアクセスには次の4段階のネットワーク操作が必要。
  1. タブレットを現場のWiFiに接続
  2. ダイナミックDNSでタブレットの現在のグローバルIPアドレスからの接続を自宅のファイアウォールに許可させる
  3. ファイアウォールとの間でVPNを接続
  4. ターゲットのPCにVCNでアクセス
1)は言うまでもない。タブレットのWiFi機能を使う。

2)は我が家独特のセキュリティ強化のための動的なIPパケットフィルタリング。ここでは詳しくは触れない。

3)は商用サービスではなく、我が家でいろいろな外部ホストからのアクセスで実績・経験のあるOpenVPNを使って、ファイアウォールをVPNサーバに仕立てた。

4)のVNCで自宅のPCのデスクトップが操作できる。

OpenVPN

Android用OpenVPNのappは数種類出回っているが、ここではrootアクセスが不要なOpenVPN Connectを選ぶ。OpenVPN ConnectはP-t-P接続のtunインタフェースのクライアント専用で、*.ovpnというファイルから設定をインポートする。*.ovpnファイルは、OpenVPNの*.conf設定ファイルとほぼ同じだが、PEM形式の鍵や証明のデータをXML風のタグで内蔵している。

OpenVPNの鍵や証明データの生成方法は別項を参照。

クライアント側の*.confファイルタをブレット用にカスタマイズし、nook-vpn.confと名付ける。カスタマイズは基本的に以下の数ヶ所だけ。
  • サーバのアドレス(ドメイン名可)とポート番号
  • 鍵や証明ファイルのパス(相対パス可)

もしTLSを使う時は、
  • サーバ側:「tls-auth ta.key 0
  • クライアント側:「tls-client」「tls-auth ta.key 1
の行が存在しなければならない。実はこれがよく分からない。iOS(iPhone)のクライアントを使ったときはこれがあるとダメだった。もし接続がTLSエラーで拒否されるようなら、多少セキュリティが落ちるがサーバとクライアントの両方で「tls-auth」をコメントアウトすればよい。

もしTLSを使うなら、「方向」を合わせなければならない。通常はサーバ側は「0」すなわち入力側、クライアント側は「1」すなわち出力側とする。このとき、後で述べるようにclient.confからクライアントにインストールするclient.ovpnを生成とき、TLS(ta.key)を組み込むのと同時に
key-direction 1
と言う行を追加してクライアント側の方向を示さないとハンドシェークができない。

tunインタフェースしかサポートしていないので、複数のAndroidクライアントをサポートするにはクライアントの数だけ別のポート番号でサーバを動かさねばならず、少々面倒。さらに、ドキュメントでは不明な以下の問題がある。
  • サーバの*.confファイルに設定するVPNエンドポイントアドレスのネットマスクは最低でも255.255.255.248(/25)
  • サーバ側のVPNエンドポイントアドレスはccd/*の指定に関わらず常に一番小さいアドレス、すなわち上記で指定したネットアドレス+1
例えば、nook-server.conf
server 10.0.0.32 255.255.255.248
を指定すると
  • サーバは必ず10.0.0.33
  • クライアントは10.0.0.34~10.0.0.39のいずれか
になる。クライアント側も固定アドレスの方がうれしいので、ccd/nook-vpn
# Force client and server addresses
ifconfig-push 10.0.0.34 10.0.0.33
のように指定してやる。こちらのサイトではサーバとクライアントのアドレスが上記とは逆になるような設定を紹介しているが、我が家では動作しなかった。ただしこのサイトにリストされているtunのエンドポイントアドレスの組み合わせは守らねばならない。

 *.ovpnファイルは*.confファイルに鍵や証明データを取り込んで生成する。一々手でやるのは面倒なのでスクリプトを書いたので使ってください。
[root@gateway ~]# ls -F
conf2ovpn.sh*
[root@gateway ~]# cd /etc/openvpn/nook-server-keys
[root@gateway ~]# ls -F
01.pem  ca.key        nook-vpn.conf  nook-vpn.key   server.key
02.pem  conf2ovpn.sh* nook-vpn.crt  
server.crt     ta.key
ca.crt  dh1024.pem    nook-vpn.csr   server.csr

[root@gateway/etc/openvpn/nook-server-keys]# ./conf2ovpn.sh nook-vpn.conf >nook-vpn.ovpn

生成した*.ovpnファイルは、(マイクロ)SDカードにコピーし、タブレットに挿入する。タブレット上でOpenVPN Connectを起動し、メニュー(右上の八卦見のような「三」のようなアイコン)を開き、「SDカードからインポート」を選ぶ。デフォルトでは/sdcardディレクトリに飛ぶが、NOOKの場合/sdcardは内部SDカードに使用済みで挿入した外部SDカードは/mnt/ext_sdcardにマウントされる(Chromoでも同じことが起きたので、NOOK限ったことでないようだ)ので、ディレクトリを移動してから*.ovpnファイルを選択する。

と言うより、*.ovpnファイルをメイルの添付ファイルとしてタブレット自身に送り、添付ファイルを保存すると「SDカードからインポート」ですぐ見えるのでそこでインポートすればよい。またはタブレットをUSBでホストに接続して、一時的にUSBドライブとして見せて、そこで見えるタブレット側のディレクトリ(例えば「Download」)にコピーしてもよい。
 
後はサーバ側でOpenVPNを起動し、タブレット側のUIで簡単な設定をするとVPNが開通する。

ここで露見したのは、クライアント(Android)側がすべてのネットワークトラフィックをVPN経由にしてしまうらしいこと。つまり、まるっきりLANの中に入ったようになる。このままでは外のインターネットに接続できないので、サーバのiptablesのNATでVPNからの接続も外のインターネットに行けるようにする。すべてのトラフィックがVPNサーバ経由になるのでパフォーマンスが低下するが、クライアントのオプションを探しても他に解決手段が見つからなかった。

だから、OpenVPNに接続するのは必要な時だけにして、使い終わったら切断するように心がけなければならない。したがって、「Boot時に自動的に接続」のオプションは選んではいけない。

NOOK以外のタブレットによっては(例えばChromo)、tun.koカーネルモジュールがないと騒ぐが、慌てずPlayStoreに行って「TUN.KO Installer」をダウンロードして実行するとインストールされるはず、と思ったが、カーネルモジュールをインストールするためにはこのデバイスを「root」つまりスーパユーザの特権を得なければならず、rootのやり方はデバイスによってさまざまらしいので面倒くさくなってやめてしまった。

VNC

VNCもいくつかのappが出回ってるが、bVNC Freeを使って好結果を得た。こちらはOpenVPNと違ってインストールにあたっての特別なトリックは必要ないが、以下の二点で多少の時間を費やした。
 

DNS

OpenVPNの設定が悪いのか、タブレットからVPN(LAN内)のDNSが使えないので、VCNでアクセスするPCのIPアドレスを直接入力する必要があった。我が家のLAN上のホストは固定アドレスのDHCPにしているので大きな問題ではない。
 

日本語入力

タブレット側で日本語キーボードを使って入力したテキストは、VNCサーバ(PC)が受け付けない。VNC経由でリモートホストの日本語入力は、タブレット側ではデフォルトの英語キーボードのままにして、リモートのPC側の日本語入力機能を使い、タブレット上のローカルの日本語入力は日本語キーボードと使い分けが必要。タブレットの仮想キーボードでしか試していないが、近々入手する予定のBluetoothの外部キーボードでも同じと期待される。

VPNとVNCで最低限のことができるようになった。これから、AndroidのオフィススイートだとかDropBoxだとかのツールを少しづつ加えていくつもりだ。

2013年7月5日

DNSをオーバライドする(Windows)

我が家のインターネットファイアウォールはOpenVPNのサーバとして機能する。普段は仕事先のUbuntuのワークステーションから定常的にtunで接続しており、仕事先から家庭内のLANをアクセスしている。更に、WindowsのラップトップにもOpenVPNのクライアントをインストールしてあり、こちらはWindowsの仕様上tapインタフェースだが、旅行中に滞在先のホテルから家庭内のLANをアクセスするのに重宝している。例えば、旅行中に撮影した写真をラップトップにコピーすると、Genieというバックアップデーモンが自動的に我が家のバックアップサーバにバックアップを作成してくれるし、旅行中に使った金の記録もLAN上の家計簿用マシンに直接記録できる。

今フィリピンを旅行中で、最初のホテルではVPNで快適に家庭内LANをアクセスできていたのだが、二軒目のホテルでは最初の1時間ぐらいはよかったものの、突然動作がおかしくなってしまった。さてはWindowsお得意の要リブート状態かとリブートしてみたが復活しない。調べてみると、DNSに問題が発生していた。このホテルのネットワークはDOCOMO interTouchとやらなのだが、こいつのDNSサーバが特異な動作をしていることが分かった。

そもそも、VPNとは既存のTCP・UDPレイヤの上にIPをトンネリングさせる技術だが、通常DNSはベースつまりUDPを提供しているレイヤのDNSに優先権があり、ベースのDNSが解決できないとVPN上のDNSサーバに解決を委ねるようになっているらしい。だからウチのVPN-LANの場合、外からは見えないLAN内のドメインはベースすなわちホテルのLANのDNSサーバには解決できず、VPN上の我が家の内部DNSサーバにお鉢が廻ってLAN上のプライベートドメインが解決できるはずなのだ。

ところが、このDOCOMO interTouchのDNSサーバは、自分が解決できないドメインをすべて自分自身に解決してしまうようになっているらしい。つまり、ありとあらゆる、出鱈目なドメインを含むグローバルインターネット上に見えないドメインはニセのホストに解決されてしまう。理由はよくわからないが、多分マルウェアによる不正なリダイレクトを防ぐためではないかと想像する。この結果、VPN上の我が家のDNSサーバの出番はなくなり、結果的にVPNで接続された我が家のLAN上のドメインは実質解決できなくなってしまう。最初の1時間ほどが上手く行っていたのは、多分前日に宿泊したホテルで正常に解決できていたものがキャッシュに残っていたのだと思う。

このDOCOMO interTouchのDNSサーバの余計な振舞いを阻止するには、Windowsクライアント上に固定のhostsファイルを置くしかない。hostsファイルの在り処はUnix/Linuxなら/etc/hostsだが、Windowsでは%SystemRoot%\system32\drivers\etc\hostsで、通常はC:\Windows\system32\drivers\etc\hostsとなる。Windowsのhostsファイルの文法はUnix/Llinuxのそれとは異なり、「IPアドレス ホスト名」である。

取り敢えず必要なLAN上のホストをhostsファイルに書き込んでみたところ上手く行った。

今後LAN上のDNSに変更があるたびに一々手でWindowsクライアントのhostsファイルをアップデートするわけにもいかないので、cronで定期的に自動アップデートを実行、すなわち我が家のプライベートDNSの解決データをキャッシュするスクリプトを書こうと思ったが、このWindowsラップトップにインストールしてあるCygwinのsshdがdllファイルの一つが足りなくて動作しないことが分かった。Cygwinは個別のパッケージを管理するツールがないようで、setup.exeですべてをインストールし直し(あるいはすべてをアップデート)することになり、ホテルの低速インターネットで明日の朝までに完了するかどうかは分からない。