L2TP/IPsec VPNサーバの構築

VPNサーバの構築 - koba::blog で構築した PPTP VPN サーバを長いこと使っていたのだが、最近のOSでは PPTP VPN がサポートされなくなってきている*1ので、L2TP/IPsec VPN サーバを構築することにした。

PPTP VPNCentOS 5 上に構築していたのだが、すでに yum のサポートも停止しているのでまず CentOS 7 にアップグレードした。

CentOS 7 の場合、

に完全なスクリプトがあるが、人の書いたスクリプトを信用してroot権限で実行するのもよろしくないので、1つ1つ理解しながら手作業で実行する。

1. パッケージのインストール

以下のパッケージを yum でインストールする。

$ sudo yum update -y
$ sudo yum install -y xl2tpd libreswan

xl2tpd は yum の標準のリポジトリにはないので拡張パッケージの EPEL からインストールする。そのため、まず EPEL をリポジトリに追加する必要があるらしいのだが、さくらVPSの標準OSの CentOS 7 ではすでに追加済みであった。また、lsof も必要らしいがこちらもすでにインストール済み。

インストールされたバージョンは以下の通り。

$ rpm -q xl2tpd libreswan lsof
xl2tpd-1.3.8-2.el7.x86_64
libreswan-3.15-8.el7.x86_64
lsof-4.87-4.el7.x86_64

2. L2TP の設定

以下の設定ファイルを修正する。

  • /etc/xl2tpd/xl2tpd.conf
  • /etc/ppp/options.xl2tpd
  • /etc/ppp/chap-secrets
(1) /etc/xl2tpd/xl2tpd.conf
diff -u -r1.1 xl2tpd.conf
--- xl2tpd.conf	2017/08/03 14:54:20	1.1
+++ xl2tpd.conf	2017/08/04 10:23:18
@@ -15,7 +15,7 @@
 ; will be used by xl2tpd as its address on pppX interfaces.
 
 [global]
-; listen-addr = 192.168.1.98
+listen-addr = 93.184.216.34
 ;
 ; requires openswan-2.5.18 or higher - Also does not yet work in combination
 ; with kernel mode l2tp as present in linux 2.6.23+
@@ -29,8 +29,8 @@
 ; debug tunnel = yes
 
 [lns default]
-ip range = 192.168.1.128-192.168.1.254
-local ip = 192.168.1.99
+ip range = 192.168.0.101-105
+local ip = 192.168.0.1
 require chap = yes
 refuse pap = yes
 require authentication = yes

listen-addr
サーバの外部IPアドレス
local ip
サーバの内部IPアドレス
ip range
クライアントに払い出す内部IPアドレスの範囲

(2) /etc/ppp/options.xl2tpd
diff -u -r1.1 options.xl2tpd
--- options.xl2tpd	2017/08/03 15:15:56	1.1
+++ options.xl2tpd	2017/08/10 10:16:55
@@ -1,19 +1,20 @@
 ipcp-accept-local
 ipcp-accept-remote
 ms-dns  8.8.8.8
+ms-dns  8.8.4.4
 # ms-dns  192.168.1.1
 # ms-dns  192.168.1.3
 # ms-wins 192.168.1.2
 # ms-wins 192.168.1.4
-noccp
+# noccp
 auth
-crtscts
+# crtscts
 idle 1800
-mtu 1410
-mru 1410
+mtu 1200
+mru 1200
 nodefaultroute
 debug
-lock
+# lock
 proxyarp
 connect-delay 5000
 # To allow authentication against a Windows domain EXAMPLE, and require the
@@ -24,3 +25,10 @@
 # You need to join the domain on the server, for example using samba:
 # http://rootmanager.com/ubuntu-ipsec-l2tp-windows-domain-auth/setting-up-openswan-xl2tpd-with-native-windows-clients-lucid.html
 
+name xl2tpd
+refuse-pap
+refuse-chap
+refuse-mschap
+require-mschap-v2
+persist
+logfile /var/log/xl2tpd.log

ログファイルはあらかじめ作成しておく。

$ sudo touch /var/log/xl2tpd.log
(3) /etc/ppp/chap-secrets
diff -u -r1.1 chap-secrets
--- chap-secrets	2017/08/03 22:21:16	1.1
+++ chap-secrets	2017/08/03 22:31:19
@@ -1,2 +1,3 @@
 # Secrets for authentication using CHAP
 # client	server	secret			IP addresses
+"user"		"xl2tpd"	"password"		*

ユーザとパスワードを設定する。PPTP VPN を運用している場合はすでにユーザ登録済みかもしれない。サービス毎にパスワードを変える場合は第2項目の設定が必要。その場合 /etc/ppp/options.xl2tpd の name の設定に合わせる必要がある。

3. IPsec の設定

以下の設定ファイルを修正する。

(1) /etc/ipsec.conf

include の行を有効にする必要があるようだが、すでに有効になっていたため修正なし。*2

(2) /etc/ipsec.d/l2tp-ipsec.conf

以下の内容で新規作成。

conn L2TP-PSK-NAT
    rightsubnet=0.0.0.0/0
    dpddelay=10
    dpdtimeout=20
    dpdaction=clear
    forceencaps=yes
    also=L2TP-PSK-noNAT
conn L2TP-PSK-noNAT
    authby=secret
    pfs=no
    auto=add
    keyingtries=3
    rekey=no
    ikelifetime=8h
    keylife=1h
    type=transport
    left=93.184.216.34
    leftprotoport=17/1701
    right=%any
    rightprotoport=17/%any

left
サーバの外部IPアドレス

(3) /etc/ipsec.d/default.secrets

以下の内容で新規作成。

: PSK "psksecrets"

psksecrets は「事前共有鍵」。クライアント側の設定では「シークレット」などと呼ばれている項目にあたる。

4. firewalld の設定

CentOS 7 から iptables が firewalld に置き換わっている*3のでこれを使って IPsec まわりのパケットを通すようにする。

$ sudo firewall-cmd --permanent --add-service=ipsec
$ sudo firewall-cmd --permanent --add-port=1701/udp
$ sudo firewall-cmd --permanent --add-port=4500/udp
$ sudo firewall-cmd --permanent --add-masquerade
$ sudo firewall-cmd --reload

5. sysctl の設定

CentOS 7 からカーネルパラメータを変更する場合は /etc/sysctl.conf を修正するのではなく、 /etc/sysctl.d/ 配下に目的毎にファイルを置くようになった。/etc/sysctl.d/ 配下のファイルはファイル名順に読み込まれ、設定が競合した場合は後から読み込まれたものが有効になる。

IPsec に関する変更は /etc/ipsec.d/sysctl に記述し*4、/etc/sysctl.d/60-ipsec.conf としてリンクした。

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

設定した内容を反映する。/etc/sysctl.d/ 配下のファイルを全て読み込む場合は従来の -p ではなく、 --system オプションを使う。

$ sudo sysctl --system

6. サービスの再起動

CentOS 7 からサービスの管理は systemctl コマンドを使うようになった。ipsec と xl2tpd を有効にし、再起動する。

$ sudo systemctl enable ipsec
$ sudo systemctl enable xl2tpd
$ sudo systemctl restart ipsec
$ sudo systemctl restart xl2tpd

2017-08-12 追記

VPN接続が安定しなかったため、/etc/ppp/options.xl2tpd の MTU/MRU のサイズを 1200 に調整してみました。時々切断される場合はあるものの概ね問題なく接続できています。

*1:iOS 10 とか macOS Sierraとか

*2:nat_traversal=yes を設定している例もあるが…

*3:実際には firewalld は iptables のフロントエンドとして動作しているようだが、直に iptables を操作すると設定が混乱するので firewalld のみを使うのが吉

*4:ファイル名はsysctl.conf にしたかったのだが、そうすると /etc/ipsec.conf から include されてしまう