Linux
Debian

Linux上でのL2TP/IPSecのクライアント設定

Linuxを VPNサーバー にする話はよく見かけるのですが、 VPNクライアント にする話をなかなか見かけないのでそのメモ。

環境

VPNサーバー側

IDCFクラウドに付属のものを使いました。月500円(以下?)でまあ動くVPSだけでなく、VPNまでついてくるなかなかお得なサービスです。ただし向こうのルーターがたまに不具合を起こしたりすると再設定が必要になったりします。ほんとに重要な用途には向いていません。少なくとも現状のVPN周りとその対応を見る限りあんまり重要な用途には(ryまあ値段なりです。
VPNの方式としては、L2TP/IPSecになります。

VPNクライアント側

ディストリビューションはDebian GNU/Linux "sid"を使いました。クライアントソフトは、2016/7時点での最新版を使いました。

IPSecクライアント

strongSwan 5.5.0

L2TPクライアント

xl2tpd 1.3.6

合わせて、

$ sudo aptitude install strongswan xl2tpd

でおkです。(apt-getでも構いませんよ)
ネットワーク自動設定系のデーモン(WicdやNM)は無効にしておきます。というかpurgeしておくのがいいでしょう。aptitudeは文句言ってきそうですが。。。

L2TP/IPSecの概要

まずはL2TP/IPSecの概要をおさらいしておきましょう。WindowsやmacOSでてきとにやってる限り意識することはほとんどないのですけど、Linuxで設定する上では概要をわかっているかどうかはデバッグなどをする上で結構重要です。(まぁ、私もほんとにわかっているかどうかは自信ないですので、以下の理解に間違いがあったらこっそり教えて下さいね)

IPSec

IPSec XAuthとかではまた別なのですが、L2TP/IPSecの場合でのIPSecプロトコルが行っていることは、指定されたポートへの指定された通信の暗号化です。「セキュアトンネルを張る」という言い方がされることもあります。逆に言うと、VPNでは任意の通信へのトンネルを張らなくてはならないので、これでは不十分なわけですね。

L2TP

L2TPの正式名称は、"Layer 2 Tunneling Protocol"、つまりLayer 2の通信をトンネルによってエミュレートするためのプロトコルです。ここで言うLayer 2の通信とはすなわちPoint-to-Point Protocol, pppです。L2TPでは、udp 1701のポートを用いて、ppp通信をエミュレートします。ここでは暗号化に一切触れていないことに気をつけてください。つまり、(VPNレベルでの)セキュアな通信を行うためには、IPSecとの併用が必須である、ということです。

以上を踏まえると、L2TP/IPSecでは、IPSecが通信の暗号化を行い、L2TPはIPSecによって張られたセキュアトンネルを通してpppを提供する、ということができます。ですから、まずIPSecを確立し、その後L2TPを張るというのが順番です。

デバッギング

簡単なバグ(通信できていないなど)なら、Wiresharkでダンプを取ってみてください。ただ、IPSecを通したうえでのデバッギングはなかなか厄介ですので、そんな厄介な事態が起こらないように祈っておきましょう;)
あとはもちろんログファイルです。strongSwan, xl2tpdとも、ログは/var/log/syslogに吐かれていました。/var/log/xl2tpd.logみたいなファイルもあるんですが、何なんでしょうね。また、strongSwanについては、

$ sudo ipsec status

とすると、通信の状態が表示できます。

strongSwanの設定

それではまずstrongSwanの設定から。その前に、まずike-scanを使って、暗号化形式を調べておくとよいです。

$ sudo systemctl stop ipsec # strongSwanを止めておく
$ sudo ike-scan e.f.g.h
Starting ike-scan 1.9.4 with 1 hosts (http://www.nta-monitor.com/tools/ike-scan/)
e.f.g.h  Main Mode Handshake returned HDR=(CKY-R=xxxx) SA=(Enc=3DES Hash=SHA1 Auth=PSK Group=2:modp1024 LifeType=Seconds LifeDuration(4)=0x00007080) VID=xxxx(Openswan 2.6.37) VID=yyyy(Dead Peer Detection v1.0)

Ending ike-scan 1.9.4: 1 hosts scanned in 0.025 seconds (39.39 hosts/sec).  1 returned handshake; 0 returned notify

IDCFの場合、上記のように3des-sha1-modp1024!が暗号化形式であるとわかります。ということで、/etc/ipsec.confを次のように設定します。

/etc/ipsec.conf
conn %default
        keyingtries=0

conn idcf
        keyexchange=ikev1
        authby=secret
        right=e.f.g.h
        ike=3des-sha1-modp1024!
        esp=3des-sha1-modp1024!
        leftfirewall=yes
        auto=start
        left=%defaultroute
        leftprotoport=17/1701
        rightprotoport=17/1701
        type=transport

conf中のrightが接続先サーバー、leftが自分です。自分と相手のudp 1701番(17/1701)をつなげることを指定しています。また、自分がfirewallの内側にいるので、leftfirewallオプションをyesにしています。IDCFの場合、IPSec PSKなので、authby=secretにし、/etc/ipsec.secretにPSKを書き込んでおきましょう。

/etc/ipsec.secret
e.f.g.h : PSK "5c9597f3c8245907ea71a89d9d39d08e"

auto=startにしているので、strongSwanが起動するとともにこの接続先につなぎに行きます。
ということで、

$ sudo systemctl restart ipsec # 一応この後数秒待っておく
$ sudo ipsec status
Security Associations (1 up, 0 connecting):
        idcf[1]: ESTABLISHED 21 minutes ago, a.b.c.d[a.b.c.d]...e.f.g.h[e.f.g.h]
        idcf{2}:  INSTALLED, TRANSPORT, reqid 1, ESP in UDP SPIs: deadbeef_i cafebabe_o
        idcf{2}:   a.b.c.d/32[udp/l2f] === e.f.g.h/32[udp/l2f]

として、ちゃんと接続できているか確かめてください。

たまにあるエラー

$ sudo ipsec status
Security Associations (1 up, 0 connecting):
        idcf[1]: ESTABLISHED 21 minutes ago, a.b.c.d[a.b.c.d]...e.f.g.h[e.f.g.h]

だけ出て、その先が出ないことがなんかたまにあります。ログもなんか出ますが原因は正直良くわからないです(サーバー側?)。transportが確立できていないので、このままでは当然うまく行きません。
ikev1を一旦ikev2にして接続してみてから戻す、とかするとなぜかわかりませんがうまくいくことがあります。わけも分からず唱えるの、お祈りの儀式っぽい。

xl2tpdのセットアップ

ここまで来たらあと一息です。

/etc/xl2tpd.conf
[lac idcf]
lns = e.f.g.h
pppoptfile = /etc/ppp/options.l2tpd.client
length bit = yes
local ip = m.n.o.p
autodial = yes
redial = yes
redial timeout = 10
max redials = 6

lacはクライアント側ですので、idcfという名前のクライアント接続をセットアップしています。/etc/xl2tpd/l2tp-secretsにも適宜書き込みをお願いします。
pppの設定も書いておきます。

/etc/ppp/options.l2tpd.client
name xxxx
password yyyy
noauth
crtscts
mtu 1410
mru 1410
defaultroute
lock
persist

noauth??って思うかもしれませんが、これは相手の認証なのでOKです。

これで、xl2tpdを有効にしてみましょう。

$ sudo systemctl restart xl2tpd
$ ip addr
...
xx: pppX: <POINTOPOINT,MULTICAST,NOARP,UP,LOWER_UP> mtu 1410 qdisc pfifo_fast state UNKNOWN group default qlen 3
    link/ppp 
    inet p.q.r.s peer p.q.r.t/32 scope global pppX
       valid_lft forever preferred_lft forever
...

のようになっていれば成功です。

ゲートウェイの設定

設定(サーバーの?)によってはルート(route)の設定をうまくやってくれるようにもできるようなのですが、IDCFは残念ながらそうなっていません。そのため、

$ sudo route
...
p.q.r.t ... 255.255.255.255 ...
...

と、相手先ネットワークへの接続の設定ができていません。そこで、自分で設定してあげましょう。
/etc/ppp/ip-up.dに次のスクリプトを入れます。

/etc/ppp/ip-up.d/0001idcf
#!/bin/sh -e

if [ -n "`echo $1 | grep ppp`" ]; then
        ip route add p.0.0.0/8 via p.q.r.t dev $1
fi

exit 0

chmod 755を忘れずにかけてください。もっと複雑なことするならちゃんとスクリプトを書くことをおすすめします(笑)

すると、xl2tpdを再起動すれば、ちゃんとrouteが追加されていることがわかります。