2014年2月7日金曜日

Mac OS XでVPN接続が切れたら自動的に再接続する

先日構築したSoftEther VPNによるVPN環境で、遠隔地のMacでVPNを接続しておいたはずが、いつの間にか接続が切れているという問題が度々発生していた。

OS XのL2TPクライアントにKeep-Aliveの機能はついてないみたいだし、かと言ってSSHみたいに接続先のターミナル上で定期的になにか出すというわけにもいかない。

じゃあ、接続を切れないようにするんじゃなくて、切れたら再接続するようにできればいいんじゃないか、と思って探したらあった。

Mac OS X起動時にVPNで自動接続&途切れても再接続するように設定できる : ライフハッカー[日本版]

なるほど。しかし上記リンク先のコードはなぜかインデントが全角空白になってて面倒だと思うので、直したコードを以下に貼っとく。なお"VPN Service Name"の部分は接続したいVPN接続設定の名前に置き換えること(「システム環境設定」の「ネットワーク」に表示されている名前)。あと接続有無の監視間隔が120秒だったのを60秒に変更してある。

on idle
  tell application "System Events"
    tell current location of network preferences
      set myConnection to the service "VPN Service Name"
      if myConnection is not null then
        if current configuration of myConnection is not connected then
          connect myConnection
        end if
      end if
    end tell
    return 60
  end tell
end idle

AppleScriptエディタを開いて上記コードを貼り付け、メニューの「ファイル>保存...」を選択する。ダイアログで
  • ファイルフォーマットは「アプリケーション」を選択
  • オプションの「ハンドラの実行後に終了しない」にチェック
して保存する。


あとは保存したアプリケーションを実行すれば接続が開始され、60秒間隔で接続の有無を監視してもし接続が切れていたら自動的に再接続してくれる。

実際先日構築したVPN環境で試したら、接続が切れた時にちゃんと再接続してくれていたことが確認できた。これでVPNが落ちてないか心配せずに済む。

ちなみに、起動時に自動的にVPNに接続させるには、「システム環境設定>ユーザとグループ」でユーザを選び「ログイン項目」に追加しておけばいい。さらに実行中にDockにアイコンを出さない方法も上のリンク先に書いてあるので必要なら参照のこと。僕の場合、実行されているのが明示的にわかったほうがいいと思ったのでアイコン消す設定はしてない。

Apple Script も極めれば色々自動化できそうで面白そうだな。また機会があったら調べてみよう。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。

2014年2月6日木曜日

Keep-AliveとNATテーブルの関係

SSHなんかで外部のサーバに接続していて、しばらく何もせずに放置しておくと通信できなくなることがあったりする。対策を立てていないと頻繁に起きる。

これの原因は、接続の途中にあるルータ。ルータはプライベートIPアドレスの領域とグローバルIPアドレスの領域の境目では、アドレスを変換してやりとりする(プライベートIPアドレスをもつパケットはインターネットに出るとすぐに破棄されてしまうので)。その際変換元のプライベートIPアドレスと返還後のグローバルIPアドレスの対応関係を記憶しており、これがNATテーブルと呼ばれる。

もっとも、最近は単なるNATではなく複数のプライベートIPアドレスをポート番号を変えつつ通信することで1つのグローバルIPアドレスと対応させるNAPT(IPマスカレード)の方が多いと思う。
(参考 → NAT - ネットワークエンジニアを目指して)

まあ、NATにしてもNAPTにしても、プライベートIPアドレスとグローバルIPアドレスの対応一覧表を内部に持っているわけだ。

で、NATテーブルにしろNAPTテーブルにしろ、無限に記録するわけには行かない。だから記録できる数の上限もあるし、一定時間使わなければ破棄していく。

で、接続を確立してから一定時間以上通信がないと、接続経路の途中にあるルータのNATテーブル(またはNAPTテーブル)が破棄されてしまい、いざ通信しようとしたらできない、ということになるわけだ。

で、対策としては、一定間隔で何か通信するということになる。一定間隔でデータが流れていれば、NATテーブルやNAPTテーブルの該当レコードはクリアされない。このような、接続を維持するために一定間隔でデータを流す行為や機能をKeep-Aliveと呼ぶわけね。

例えば簡易な方法としてはSSHではログインした端末でpingをlocalhost宛に打ったりとかする。他にもクライアントソフトが定期的に無害なパケットを流すなど、対策方法はいくつかある。
(参考 → keep-alive for ssh)

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。

2014年2月5日水曜日

Mac OS X で TUN/TAP 仮想ネットワークデバイス

仮想ネットワークデバイスを Mac OS X で試してみたくて調べてた。TUN/TAP は共に仮想ネットワークデバイスの仕組みで、名前自体は知ってたけれど違いがよく分かってなかったので改めて調べてみると、

TAP : データリンク層を操作する仮想デバイス
TUN : ネットワーク層を操作する仮想デバイス

ていうことらしい。TAPはソフトウェアルータ、TUNはソフトウェアブリッジに使える、っていう理解でいいのかな。

Mac OS X 用の TUN/TAP ドライバは下記からダウンロードできる。
http://tuntaposx.sourceforge.net/

インストールは特に難しいことはなくて、インストーラの指示に従えば完了する。

インストールが完了しても、システム設定画面などに変化はない。ただ、/dev を見てみると、tun0〜tun9 と tap0〜tap9 のデバイスが新たに作られているのが分かる。

ごく簡単な使い方の例としてはこんなスクリプトを見つけた。
http://lakm.us/logit/2013/01/handy-tap-interface-mac-osx/

上記リンク先からちょっと引用しよう。

#!/usr/bin/python
 
import os
while 1:
 try:
  file_path = '/dev/tap1'
  dev_file = os.open(file_path, os.O_RDWR)
  interface = 'tap1'
  while 1:
   pass
 except:
  print "tap interface is closing"
  exit()
  break

これを setup-tap1.py として保存したら、

[root]# ./setup-tap1.py &
 

て感じでバックグラウンドで実行する。
すると ifconfig で tap1 が出現するようになるので、IP アドレスの設定なども可能。

と、この辺まで調べたあたりで、TUN/TAP 仮想ネットワークデバイスとは別の方法を検討し始めたので今回はここまで。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。

2014年2月4日火曜日

SEもプログラマもエディタで空白文字表示してくれ(Vim,Eclipse設定例付)

今日仕事でちょっと気になったのが、設定ファイルやソースコードに全角空白が明らかに意図しない位置に紛れ込んでいること。

実際の動作に支障があるわけではない。しかし、構築や開発を進める上で、例えばバッチファイルや自動処理プログラムに思わぬ形で影響することがある。今日も他人が書いた設定ファイルとソースコードに全角空白が紛れ込んでいて、それで変な動作をするので原因を調べていて、少し時間を余計に取られてしまった。コマンドライン上ではパッと見ではわからないからなぁ。

地味な話だけれど、エディタで全角空白を表示する設定にしていれば気づくはずだ。なお全角空白に限らず、空白文字は表示させておくことを強くお勧めする。インデントにスペースとタブが混在するとか、行末に余計な空白があるとか、そういうのは後々ミスの原因になりかねないんで。

ちなみに僕がよく使うエディタは Vim と Eclipse 内蔵のテキストエディタなので、設定方法を書いておく。参考になれば。

Vim の場合

~/.vimrc(Windows では Vimをインストールしたフォルダの _vimrc )に次のように記述する。

set listchars=tab:>\ ,trail:-                            " 特殊文字の代替文字(タブと行末のスペース)
highlight SpecialKey ctermfg=darkgray                    " タブの色
highlight NonText ctermfg=darkgray                       " 改行の色
highlight ZenkakuSpace cterm=underline ctermfg=darkgray  " 全角スペースの色
match ZenkakuSpace / /                                  "スラッシュの間に全角スペース

Eclipse の場合

メニューから「ウィンドウ>設定」を選択し、設定ダイアログで「一般>エディター>テキスト・エディタ」の画面を出し、「空白文字の表示」にチェックを入れる。その横の「可視性の構成」をクリックすると表示する文字をカスタマイズできる。下の画像参照。


他のエディタについてはよく知らないけれど、大抵ついてる機能だから調べれば見つかると思う。というより、SE・プログラマは空白文字表示できないエディタは頼むから使わないで。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。

2014年2月3日月曜日

エンジニアは上司の言うことを素直に聞くな

これは IT エンジニアに限った話ではないと思うんだけれど、エンジニアは上司に言われたからといって素直に言われた通り受け入れるようではダメだと思うんだ。

というのは、エンジニアというのは技術で仕事上の貢献をしているわけで、その分野の技術に関しては誰にも負けないと思えるのが理想だよね。それは相手が上司だろうが関係ないわけ。技術的に自分のほうがより良い案を持っていると思ったら、相手が上司でも、それは堂々と主張すべきなんだよね。人間関係の調整がいくら上手なろうが、技術的に改善できることがあるのに、それを自ら抑えこんでしまってはダメなんだ。

もちろんそのためには技術的な面で日々自分のスキルアップをし続けなければいけないと思うし、そうしなければハイハイと言うことを聞くだけになる。エンジニアにとって学ぶべき知識なんて無限にあるし時代とともに技術は常に新しくなっていくわけで、上司だってそんなに網羅できているわけがない。その意味では少なくとも自分の今担当している部分に関する知識を徹底的に追求すれば、そんなに長い期間かからずに上司より詳しく慣れる可能性は高いわけだ。

たとえ技術の話以外のことだったとしても、仕事の進め方や組み立て方の話だったら、それだって結局自分なりの考え方を持っているべきなんだよね。まあ IT の分野ではマネジメントすら技術の一部という扱いになってるし、その意味では全部が技術の話と言えなくもないけど。ともかく少なくとも、自分の考え方の主張はしてみて、その上で上司の言うことに従うかどうか決めるべきであって、ただ言われるがままに仕事をするってのは良くないと思うんだ。

エンジニアは技術というモノサシがあるおかげで、上司・部下などの組織の上下関係に関係ない基準を持って話ができる。だから「課長が白と言ったら白、でも部長が黒と言えば黒」みたいな状態とは基本的には無縁であるべきなんだ。だからエンジニアは上司の言うことを素直に聞くなって言ってるわけ。結果的に言うことを聞くことになったとしても、そういう考え方が前提にあるかどうかで全然違うわけだからね。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。

2014年2月2日日曜日

SoftEther VPNでLinux上にVPNサーバ立てて遠隔地と手元のMacで画面共有

Mac OS X にはデフォルトで画面共有の機能がついていて、これがなかなかに使いやすくていい。この画面共有は同じネットワーク内にある Mac にはアカウント名とパスワードさえ分かれば接続することができる。

一方、遠隔地にある Mac に対しては同一の Apple ID を設定して「どこでも My Mac」機能を利用すれば接続はできるけれども、ちょっと事情があって同一の Apple ID を設定していない Mac にも画面共有で接続したかった。

で、以前は LogMeIn の Free 版を使っていたんだけど、なんと有料化されるとのこと。(参照: リモートアクセス「LogMeIn」無料版が突如終了、完全有料制に - ITmedia ニュース)うーむ、これは困った。

実はこの件とは別に自分用にパブリッククラウドサービスを契約してて、仮想サーバを立てて CentOS を入れて運用している。そこにはグローバルIPも割り当ててある。じゃあそれを VPN サーバにしてしまおうと思いついた。それなら新たに費用が発生することもないし。

てことでフリーの VPN サーバを探したら、SoftEther VPN ってのがあるそうで。OpenVPN よりも速いという謳い文句つきだ。これをインストールして使ってみることにした。

SoftEther VPN  Server のダウンロード

SoftEther VPN  のダウンロードページから VPS サーバをダウンロード。コンポーネントは「SoftEther VPN  Server」を選ぶ。

SoftEther VPN  Server のインストール

インストール方法は公式ドキュメントの「7.3 Linux へのインストールと初期設定 - SoftEther VPN プロジェクト」に従えば OK 。

管理者パスワードの設定

管理者パスワードを設定します。サーバ付属の vpncmd で「ServerPasswordSet」コマンドを実行する。マニュアル通りにインストールしたのなら vpncmd のパスは  /usr/local/vpnserver/vpncmd になる。

仮想ハブの作成

仮想ハブを作成するか、最初に「DEFAULT」という名前の仮想ハブができているので、それも使える。今回は「DEFAULT」を使うことにするので、新たに作成はしない。

ユーザの作成

仮想ハブにユーザを作成する。vpncmd で「Hub DEFAULT」コマンドを実行して「DEFAULT」仮想ハブを管理対象とした後「UserCreate」コマンドを実行する。

IPSec 機能の有効化

L2TP over IPsec を使えるようにする。vpncmd で「IPSecEnable」コマンドを実行する。有効にするのは L2TP over IPsec だけでいい(暗号化なしの L2TP と EtherIP / L2TPv3 over IPSec はいらない)。

SecureNAT 機能の有効化

SecureNAT 機能は、簡易 DHCP サーバ機能と仮想 NAT 機能の2つからなる機能。vpncmd で「SecureNatEnable」コマンドを実行する。なお、このコマンド実行後に簡易 DHCP サーバ機能と仮想 NAT 機能は両方とも自動的に有効化される。

簡易 DHCP サーバ機能の設定

SecureNAT 機能のうち、簡易 DHCP サーバ機能を使うので設定を確認する。今回はデフォルトのまま使うので設定変更しないけれど、確認はしておく。vpncmd で「DhcpGet」コマンドを実行する。デフォルトでは 192.168.30.10〜192.168.30.200 の範囲のIPアドレスが配布される設定なっている。

仮想 NAT 機能の無効化

今回は仮想 NAT 機能は使わないので無効化しておく。vpncmd で「NatDisable」コマンドを実行する。

VPN サーバのファイアウォールで必要なポートを開ける

Mac 側からは L2TP over IPSec で接続するので、UDP 500 番と UDP 4500 番のポートの通信が VPN サーバのファイアウォールを通過できるようにしておく。

Mac の VPN 接続設定及び接続実行

ここまでできたら、Mac から VPN に接続できる。この操作は接続元である手元の Mac と接続したい遠隔地の Mac の両方で行う必要がある。もちろん遠隔地の Mac は VPN に接続したままの状態にしておく。公式ドキュメントの「Mac OS X からの接続方法 - SoftEther VPN プロジェクト」に従えば OK 。
なお公式ドキュメントでは「すべてのトラフィックを VPN 接続経由で送信」オプションにチェックを入れるよう書いてあるが、VPN 経由でインターネットに出る経路がない場合はこれにチェックを入れるとインターネットにつながらなくなる。画面共有が用途の場合は画面共有したいマシンとしか VPN 経由で通信しないのでチェックを入れなくてもいいだろう。
ちなみに遠隔地の Mac で VPN 接続が切れたら自動的に再接続させる方法はこちら。

DHCP テーブルを確認

ここからは、遠隔地の Mac へ手元の Mac から接続する時の手順になる。あらかじめ両方の Mac が VPN に接続されていること。まず VPN サーバにログインして DHCP テーブルを確認する。vpncmd で「DhcpTable」コマンドを実行する。割り当てられた IP アドレスとクライアントホスト名の対応が分かるので、接続したい遠隔地の Mac に割り当てられた IP を把握しておく。

画面共有を実行

接続元の Mac で Finder を起動して、メニューからの「移動>サーバへ接続...」を選択する。「サーバへ接続」ダイアログが表示されたら「サーバアドレス」欄に「vnc://(遠隔地の Mac の IP アドレス)」を入力して「接続」ボタンをクリック。

これで接続できるはず!僕の環境では、LogMeIn を使っていた時よりもはるかに快適に画面をリモートから操作できた。予想以上に反応速度が改善されてびっくり。スクロールとかもスムーズにできるし。

「グローバル IP の付与された Linux サーバを持っいてなおかつ root  権限を使える」という条件があるけれども、もし当てはまる方はぜ SoftEther VPN による VPN サーバ構築をぜひ試してみては。

※2014/02/03 VPNサーバのファイアウォールのポート開けについて追記。
※2014/02/05 VPNサーバの IPSec 機能有効化について追記。
※2014/02/07 MacのVPN接続設定部分に追記。

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。

2014年2月1日土曜日

[ruby] Sinatra + Cucumber + Capybara が良さそうな感じ

さて、最近新しいプロジェクトで Web インターフェースを作っていくにあたり、どの言語でどのフレームワーク使うかについて検討している。

やっぱ言語は ruby だな。コード書いてて一番楽しそうだし、読みやすいからメンテしやすそうだし。となるとフレームワークをどうするか。

で、ruby の軽量フレームワーク Sinatra について調べてた。Rails でももちろんいいし、実際僕は Rails 使ったことないので興味もあるんだけど、関わってる製品の事情で軽量なフレームワークの方が良さそうなんで Sinatra が第一候補になった。

そしてせっかくフレームワーク使うなら、テストが効率よくできる仕組みがすごく重要。やっぱりテスト駆動で開発したいもんで。初めてテスト駆動を実際に仕事で使った時は衝撃だったなぁ。それ以来テスト駆動開発のファンになった。

さて、Sinatra の公式ページを読むと、テストについては基本的には Rack ベースらしい 。Rack は Webアプリケーションインターフェースって言葉だけ聞くとなんじゃそりゃって感じですが、要するに「こういうリクエストが来たらこうレスポンスを返すっていう決まりを書く時の形式を共通化するもの」って理解でいいかな。

で、実際テストを書く時には
・テストケースを書く → Cucumber を使う
・テストの中身を書く → Capybara を使う

という感じに組み合わせれば良さそうな感じ。

Cucumber を使うとテストケースを自然言語に近い形式で書ける。設定すれば日本語も使えるらしい。まあ実際に日本語を使ってテストケースを書くかどうかは別としても、直感的に見て分かりやすいテストケースを書けるのは、テスト駆動開発を行う上でも助かりそうだ。

Capybara は Web アプリケーションの実際のテストの中身を描くのに便利な機能を提供してくれる。例えばレスポンス中の HTML のある要素に特定の文字列が入っていることを確認したい、なんてときに自力でレスポンスボディから要素を抽出するのは面倒だが、それを XPath や CSS セレクタの形式で抽出できるようにするメソッドを提供してくれたりする。同じようなもので Webrat というのもあるらしいが、Capybara のほうが後発らしく使いやすいみたい。

あと、Capybara はテストを Webkit 経由で実行できるドライバが用意されていて、なんと Javascript のテストも一緒にできるらしい。すごい。以前 Javascript のテストは QUnit でやってて分離してたから効率は良くなかったけど、これできたらテスト効率もアップしそうだな。

参考サイト:
Testing Sinatra with Rack::Test
jnicklas/capybara · GitHub
ASCIIcasts - “Episode 257 - request specとCapybara”
あーありがち - 実はCapybaraってよく分からないんです
第21回 Railsアプリの受け入れテストをCucumberで書こう:Ruby Freaks Lounge|gihyo.jp … 技術評論社

※この記事について指摘・意見・提案・感想などありましたら下のコメント欄にどうそ。