Desire(Android)からVPN(L2TP/IPSec)で家のLinuxサーバに接続したときのメモ。
構築・設定
Linuxサーバには、L2TPサーバとして、xl2tpd、IPSecのスタックとしてopenswanを使った。
2.6系列だとカーネルレベルでIPSecがサポートされているのでそちらを使っても良いと思うのだが、情報量的が多かったopenswanを使った。
構築は さくらのVPSでiPhone用の野良WiFi通信傍受対策のL2TP/IPSec(VPN)を設定したメモ – nori_no のメモ を参考にさせて貰った。
Android側のVPNの設定として注意すべきことは「L2TPセキュリティ保護を有効」のチェックボックスは空にしておく。
接続
構築後、U300のSIMが入っているDesireからVPN(L2TP/IPSec)張ってみると、サーバ側で以下のエラーを出してVPNが切断される。
Apr 24 01:13:30 myserver xl2tpd[14929]: Maximum retries exceeded for tunnel 20276. Closing.
Desire側では大体検知できず、ネットが繋がらなくなって気づくことがほとんど。
解析
xl2tpdのソースを見てみると、L2TPの(キープアライブのための)HELLO電文の応答でリトライアウトしていた。
xl2tpdの実装を見ると、60秒毎にHELLO電文をサーバ側から送信し、5秒の間にHELLO電文の応答がない場合、先述のエラーとなりサーバ側で回線を解放していた。3Gのような無線ネットワーク、なおかつ、U300のようにレイテンシの高い回線だと、通常時でも応答を返すまでに5秒以上かかることがあるようで、接続状態が安定しないようだ。
上記については、xl2tpdの設定ファイルでは変更できなくて、ソースにハードコーディングしてあった。そのパラメタを以下のように書き換えて再コンパイルした結果、かなり安定するようになった。
l2tp.h
//#define HELLO_DELAY 60 /* How often to send a Hello message */ #define HELLO_DELAY (10*60) /* How often to send a Hello message */ //#define DEFAULT_MAX_RETRIES 5 /* Recommended value from spec */ #define DEFAULT_MAX_RETRIES 60 /* Recommended value from spec */
HELLO電文の送信間隔を10分とし、リトライ回数を60回とする
network.c:248
// tv.tv_sec = 1;
tv.tv_sec = 10;
HELLO電文のリトライ間隔を1秒から10秒とする
注意
rfc2661によると、hello電文の間隔について「おすすめは60秒」となっていたので、それを伸ばすことにより、他のクライアントに影響がある可能性があります。