ArchLinuxでL2TP/IPsecなVPNへの接続を行う

2017/06/09 : 最新のArchの環境で、接続後正常に通信できない場合がある問題について追記しました。
2017/08/08 : libreswan 3.19(3.20が上手く動作しなかったので下げています)において、networkmanager-l2tpの動作を確認しました。libreswanとxl2tpdさえ正しくインストールされていれば、もうコマンドラインを叩かなくても良いようです。ちょっと嬉しい。
2018/08/27 : 古い記事への追記で恐縮ですが、筆者は現在、libreswanではなくstrongswanを利用しています。結果としてlibreswanよりも安定性が向上しました。一部libreswanとは設定ファイルの書き方が違いますが、ほとんど同じです。また、対向先が古い暗号化方式(3DES等)を用いている場合、明示的にそれを指定しなければなりません。例えばRTX1100が相手であれば、

ike=3des-sha1-modp1024
esp=3des-sha1

をstrongswanに読み込ませるconfに記述する必要があります。事前にike-scanで確認しておくとよいと思います。


冷遇されるL2TP/IPsecクライアント

先日、大須にて中古のThinkPad X220iを購入したのですが、折角なのでArchLinuxを導入することにしました。
順調にGNOMEも導入し、各種設定も終えたのですが、一つだけ上手く動作しない機能がありました。そう、L2TP/IPsecなVPNクライアントです。
私がArchLinux初心者ということもありますが、かなり骨が折れました。大学祭の最後、後夜祭のレーザーショー開始五分前に部室でようやく動作を確認できた瞬間は、本当に嬉しかったですね。私の精神状態がレーザーショーでした。
そんな訳で、NetworkManagerのL2TPプラグインから始まり、いくつもの方法を経て見つけ出した接続方法を、ブログにて共有したいと思います。

具体的な接続方法

まず、今回で使うものを軽く列挙しておきます。
※各種設定ファイルは、root権限で編集することを前提としています。
※事前にファイアウォールの設定等は済ませておいてください。
※どこか間違っていたり、不適切な部分があればご連絡ください。私自身いろいろ試しすぎて、全容を把握しきれていない部分もあるので……。

・libreswan : IPsecに必要なパッケージで、openswanの代替として必要なようです。 NetworkManagerのL2TPプラグインも試したのですが、上手く動作しませんでした。 (2017/08/08 追記 : 現在は修正されているようです)
また、ArchLinuxのwikiの通りに設定しても、openswanではエラーが出て処理が進みませんでした。また、strongswanも試しましたが、こちらではVPNサーバーへの接続が上手くいきませんでした。
・xl2tpd : L2TPに必要なパッケージです。今回はこいつの仕様に引っかかり、数時間悩み続けました。
・lsof : どうやらこれも必要なようです。

まず、これらのパッケージをインストールします。

yaourt -S libreswan
sudo pacman -S xl2tpd lsof

続いて、設定ファイルの編集に移ります。

まずは、IPsec (libreswan) の設定からです。
/etc/ipsec.confを以下のように編集します。

# /etc/ipsec.conf - Libreswan IPsec configuration file

# This file:  /etc/ipsec.conf
#
# Enable when using this configuration file with openswan instead of libreswan
#version 2
#
# Manual:     ipsec.conf.5

# basic configuration
config setup
	# which IPsec stack to use, "netkey" (the default), "klips" or "mast".
	# For MacOSX use "bsd"
	protostack=netkey
	#
	# Normally, pluto logs via syslog. If you want to log to a file,
	# specify below or to disable logging, eg for embedded systems, use
	# the file name /dev/null
	# Note: SElinux policies might prevent pluto writing to a log file at
	#       an unusual location.
	#logfile=/var/log/pluto.log
	#
	# The interfaces= line is only required for the klips/mast stack
	#interfaces="%defaultroute"
	#interfaces="ipsec0=eth0 ipsec1=ppp0"
	#
	# If you want to limit listening on a single IP - not required for
	# normal operation
	#listen=127.0.0.1
	#
	# Do not set debug options to debug configuration issues!
	#
	# plutodebug / klipsdebug = "all", "none" or a combation from below:
	# "raw crypt parsing emitting control kernel pfkey natt x509 dpd
	#  private".
	# Note: "crypt" is not included with "all", as it can show confidential
	#       information. It must be specifically specified
	# examples:
	# plutodebug="control parsing"
	# plutodebug="all crypt"
	# Again: only enable plutodebug or klipsdebug when asked by a developer
	#plutodebug=none
	#klipsdebug=none
	#
	# Enable core dumps (might require system changes, like ulimit -C)
	# This is required for abrtd to work properly
	# Note: SElinux policies might prevent pluto writing the core at
	#       unusual locations
	dumpdir=/var/run/pluto/
	#
	# NAT-TRAVERSAL support
	# exclude networks used on server side by adding %v4:!a.b.c.0/24
	# It seems that T-Mobile in the US and Rogers/Fido in Canada are
	# using 25/8 as "private" address space on their wireless networks.
	# This range has never been announced via BGP (at least upto 2015)
	#virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12,%v4:25.0.0.0/8,%v4:100.64.0.0/10,%v6:fd00::/8,%v6:fe80::/10
	virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12
	nat_traversal=yes
	oe=no

# For example connections, see your distribution's documentation directory,
# or https://libreswan.org/wiki/
#
# There is also a lot of information in the manual page, "man ipsec.conf"
#
# It is best to add your IPsec connections as separate files in /etc/ipsec.d/
include /etc/ipsec.d/*.conf

続いて、ipsec.secretsも同様に編集します。

include /etc/ipsec.d/*.secrets

設定ファイルからincludeする部分の編集を行います。
今回は/etc/ipsec.d/配下に、vpn1.conf, vpn1.secretsを作成します。ファイル名は適宜決めてください。

追記 : oruminさん (@kotatsu_mi)からご指摘をいただきました。NAT環境下だと、rightidあたりの設定も必要なようです。

rightid, leftidの指定方法はSS-NET様のページ 『 YAMAHA RTX1100 と OpenSwan で IPsec VPN 接続 』が参考になりますので、もしNAT環境下な方がいらっしゃった場合はSS-NET様のページも是非ご参照ください。 orumin様、ありがとうございました。

vpn1.confは以下の通りです。

conn vpn1
  authby=secret
  pfs=no
  auto=add
  keyingtries=3
  dpddelay=30
  dpdtimeout=120
  dpdaction=clear
  rekey=yes
  ikelifetime=8h
  keylife=1h
  type=transport
  left=%defaultroute
  leftprotoport=17/1701
  right=(VPNサーバーのIPアドレス)
  rightprotoport=17/1701

vpn1.secretsは以下の通りです。

%any (VPNサーバーのIPアドレス) : PSK "(IPsec事前共有鍵)"

設定が完了したら、重要なファイルをroot以外はファイルを読めないようにしておきます。所有者がrootとなっていることを確認して、以下のコマンドを実行します。
今回は念の為すべてのファイルに対して実行していますが、気になる場合は事前共有鍵を記述したsecretsファイルさえ700にしておけば何とかなると思います。
chmod 700 /etc/ipsec.conf /etc/ipsec.secrets /etc/ipsec.d/vpn1.conf /etc/ipsec.d/vpn1.secrets

続いて、xl2tp側の設定を行います。まず、/etc/xl2tpd/xl2tpd.confを編集します。vpn1の部分は適宜変更してください。
また、今回はサーバー側からの指定でCHAP認証を使用するためrequire chap = yesを入れています。この部分も、サーバーによって適宜変更してください。

VPNサーバーのIPは、数値とドットしか使ってはいけません。間違ってもダブルクオーテーションなどでくくらないように! 私はダブルクオーテーションでくくっていて、IPがホスト名として認識された結果数時間ハマってしまいました……。

[lac vpn1]
lns = (VPNサーバーのIP)
require chap = yes
require authentication = yes
ppp debug = yes
pppoptfile = /etc/ppp/options.l2tpd.vpn1
length bit = yes
redial = yes
redial timeout = 10
max redials = 3

次に、/etc/ppp/options.l2tpd.vpn1を編集します。vpn1の部分は適宜変更してください。
念の為、こちらでもCHAPの指定をしていますが、おそらくどちらか片方だけで動作するのではないかと思います。

2016/04/27 21:57 追記 : 最新のxl2tpd(恐らく1.3.7-1)に更新してから、以下の設定ファイルでは正常に動作しなくなりました。フォーラムにも報告が上がっているようです。 エラーを見つつ、 crtscts と lock をコメントアウトすることで再び動作するようになりましたが、あくまで暫定処置で、これが正しいのか分かりません。 もし詳しく知っている方がいらっしゃいましたら、是非Twitterなりコメント等でご教示いただけると幸いです。

ipcp-accept-local
ipcp-accept-remote
require-chap
refuse-pap
crtscts
noccp
noauth
idle 1800
mtu 1410
mru 1410
defaultroute
usepeerdns
debug
lock
connect-delay 5000
name (ユーザーのID)
password (ユーザーのパスワード)

ここに記載していれば大丈夫だと思うのですが、私は念の為 /etc/ppp/chap-secrets にもユーザー認証情報を記述しました。

# Secrets for authentication using CHAP
# client	server	secret			IP addresses
(ユーザーのID)		*		(ユーザーのパスワード)		*

例のごとく、設定ファイルの権限を700にしておきます。

chmod 700 /etc/xl2tpd/xl2tpd.conf /etc/ppp/options.l2tpd.vpn1 /etc/ppp/chap-secrets

続いて、ネットワーク関係でいくつか設定を行います。
今回は、/etc/sysctl.d/配下にsysctl.confを作成し、そこに設定を記述しました。

net.ipv4.ip_forward = 1
net.ipv4.conf.all.send_redirects = 0
net.ipv4.conf.all.accept_redirects = 0
net.ipv4.conf.default.send_redirects = 0
net.ipv4.conf.default.accept_redirects = 0
net.ipv4.conf.eth0.send_redirects = 0
net.ipv4.conf.eth0.accept_redirects = 0
net.ipv4.conf.lo.send_redirects = 0
net.ipv4.conf.lo.accept_redirects = 0

この設定を、以下のコマンドで反映させます。
sysctl --system

ここまで来ればもう少しです! 最終段階に入ります。以下のコマンドで必要なサービスをいくつか起動します。 systemctl start xl2tpd
systemctl start ipsec

ipsecの設定が正常かどうかをチェックします。以下のコマンドを実行して、結果に FAILED が出ていないことを確認してください。
ipsec verify
なお、下の方にエラーがいくつか見つかった旨のメッセージが出ていますが、FAILEDさえ出ていなければ少なくとも実害はないです。解決方法があればまた教えてください。

問題がなければ、いよいよ接続に移ります。
以下のコマンドで、IPsecの接続を開始します。vpn1の部分は適宜変更してください。
ipsec auto --up vpn1

IPsec SA established transport と出ればIPsecでの接続は成功です。
続いて、L2TP接続に移ります。以下のコマンドで、サーバーに接続します。vpn1の部分は適宜変更してください。
echo "c vpn1" > /var/run/xl2tpd/l2tp-control

ここで、ip aとするとpppX(Xは数値)というデバイスに、VPNサーバーからもらったIPがアサインされていると思います。
……ここでもし、このデバイスが表示されていない場合、journalctl -bでログを確認してみてください。私の場合、xl2tpdからホスト名解決エラーが出ていることに気づき、ハマりから脱出しました。恐らく設定ミスの類の可能性が濃厚です。

さて、ここまでなんの問題もなく、デバイスにIPがアサインされた皆様は、おめでとうございます。無事に接続成功でございます。
あとはルーティングだけです。Windowsのように、自動でルーティングを行ってくれるほど優しいものはないようです。手動で、きっちりルーティングしないと接続した意味がありません。

そんな訳で、ルーティングの設定を行います。幸いなことに、このあたりはArchLinuxのwikiの情報通りでOKです。wiki通りに設定してください。

以上で接続完了です。お疲れ様でした!

おまけ : 切断の方法

まず、ルーティングを元に戻します。これは簡単です。ルーティングを設定した逆の手順を行うだけで済みます。
そして、VPNからの切断は以下のコマンドで実現できます。vpn1の部分は適宜変更してください。
echo "d vpn1" > /var/run/xl2tpd/l2tp-control
ipsec auto --down vpn1
systemctl stop ipsec
systemctl stop xl2tpd

ここまで終えたら、ipコマンドで確認してみてください。無事に切断されているはずです。

どうしても切断方法が分からない場合、再起動を行うのも有効です。

2017/06/09 追記 : 最新のArchで接続後、正常に通信できない場合

環境によっては影響を受けない場合があるのかもしれませんが、少なくとも私のArch環境では、最新のカーネルにしていると『接続は正常に完了しpingも問題ないが、その他のTCP通信などが一切通らない』という問題が発生しました。
調べてみると同様の問題が出ている方がいらっしゃるようで、 https://bbs.archlinux.org/viewtopic.php?id=226523 の投稿を参考にLTSカーネルを導入、GRUBのcfgを再生成してLTSカーネルで起動し直したところ、正常に動作しています。
もっと良い解決方法が有るのかもしれませんが、もしカーネルの変更に抵抗がなく、かつこの問題に直面されている方がいらっしゃいましたら、上記方法で解決可能かもしれません。