CentOS 6.0 で L2TP-VPN サーバを構築する

SERVER


CentOS 6.0 で L2TP-VPN サーバーを構築する

L2TP (Layer 2 Tunneling Protocol) とは、VPN (Virtual Private Network) を実現するためのプロトコルのひとつで、これを利用することによって、遠い場所にあるコンピューターやネットワークを LAN のように結ぶことができる仕組みです。

IPsec などにより通信経路を暗号化することで、途中でインターネットを経由しても通信内容が第三者に漏れないよう予防することもできるようになっているようです。

 

VPN の構築については、以前にも Linux を PPTP サーバとして稼動する でお話したように PPTP を使って実装したことがありましたけど、PPTP の場合には GRE プロトコルも使用する都合、どうやら NAPT (IP Masquerade) を使ってインターネットアクセスを実現している同一ネットワーク環境下では、同時に 1 台からしか PPTP-VPN を利用できない感じでした。

そこで、同一 NAPT 内から複数のデバイスが同時接続できる VPN 接続はできないものかと調べてみたところ、L2TP には NAPT を考慮した NAT トラバーサルの機能もあるようでした。

これならもしかすると理想的な環境を作れそうな感じだったので、この L2TP を CentOS 6.0 上に実装してみることにしました。

 

L2TP のインストール

CentOS 6.0 で L2TP を利用するに当たり、平成 23 年 11 月 25 日現在、EPEL リポジトリを使用するのが良いようでした。

EPEL リポジトリを利用できるようにするための方法については CentOS 6.0 に EPEL リポジトリを追加する に記していますので、そちらの方を確認してください。

xl2tpd のインストール

EPEL リポジトリの利用準備が整ったら、L2TP を実現するためのパッケージ "xl2tpd" をインストールします。

yum install xl2tpd

"xl2tpd" パッケージをインストールすると、平成 23 年 11 月 25 日現在では、次の設定ファイルがインストールされたようでした。

  • /etc/xl2tpd/xl2tpd.conf
  • /etc/xl2tpd/l2tp-secrets
  • /etc/ppp/options.xl2tpd

/etc/xl2tpd/xl2tpd.conf の設定

まずこのうちの "/etc/xl2tpd/xl2tpd.conf" を調整してみます。

[lns default]

ip range = 192.168.1.128-192.168.1.254

local ip = 192.168.1.99

require chap = yes

refuse pap = yes

require authentication = yes

ppp debug = yes

pppoptfile = /etc/ppp/options.xl2tpd

length bit = yes

既定では、上記のような設定内容になっていました。

つまり、L2TP でこの Linux に接続すると、この Linux 自身の "192.168.1.99" と、"192.168.1.128" から "192.168.1.254" とが割り当てられた接続クライアントの間で VPN 通信が行われるといった感じでしょうか。

/etc/ppp/options.xl2tpd の設定

また、上の設定ファイル "pppoptfile" で指定した "/etc/ppp/options.xl2tpd" では、PPP 制御に関する設定を記載します。

# この接続に名前を付けます。

name xl2tpd

 

# 認証を必要とします。

# mschap-v2 を要求し、他は禁止しています。

auth

refuse-pap

refuse-chap

refuse-mschap

require-mschap-v2

 

# ハードウェアフロー制御 (RTS/CTS) を使用します。

crtscts

 

# 相手側をゲートウェイとするディフォルト経路を追加します。

defaultroute

 

# UUCP 形式のロックファイルを生成します。

lock

 

# 最大受信単位 (MRU) と最大転送単位 (MTU) を指定します。

mtu 1410

mru 1410

 

# Windows クライアントに DNS 情報と WINS 情報を渡します。

ms-dns 192.168.1.1

ms-dns 192.168.1.2

ms-wins 192.168.1.1

ms-wins 192.168.1.2

 

# ネットマスクを指定します。リモート IP アドレスとの論理和(より小さいネットワーク)が採用されるそうです。

netmask 255.255.255.0

 

# 接続切断時に再接続を試みます。

persist

 

# Proxy ARP により接続してきたホストがローカルネットワークに在るように見せます。

proxyarp

 

# ログファイルの保存場所を指定します。

logfile /var/log/xl2tpd.log

ここでまず "name" として、この接続に名前をつけています。ここでつけた名前は、接続アカウントを "/etc/ppp/chap-secrets" に登録するときに使用します。

それと、ネットワーク環境に合わせて、VPN クライアントに割り当てたい DNS サーバーを "ms-dns" で、WINS サーバーを "ms-wins" で指定します。

また、"noccp" で CCP (圧縮制御プロトコル) での接続を無効化、"crtscts" でハードウェアフロー制御を有効化、"nodefaultroute" でこの接続をディフォルトゲートウェイとして使用しない、"proxyarp" で ARP 情報を交換してそれぞれが異なるネットワークに存在していてもそれらを LAN として認識させる、といった設定が行えます。

詳細は "man pppd" として pppd のドキュメントを参照することで、各オプションの意味についてを調べることができるようでした。

Openswan のインストール

L2TP の通信を暗号化するための IPSec もインストールしておく必要があるようでした。

仕組みとしては L2TP と IPSec とは切り離して考えられているらしいのですけど、Windows 7 や iPhone 4 で L2TP 接続を行ってみようとすると、xl2tpd だけでは IPSec の証明書が見つからないということでエラーとなってしまいました。

いろいろと設定すれば上手く行く方法もあるのかもしれないですが、今回は IPSec 環境についても整えてみようと思います。

 

IPSec を実現するためのパッケージ "Openswan" を、次のようにしてインストールします。

yum install openswan

 

/etc/ipsec.conf の設定

Openswan がインストールされたら、まずは "/etc/ipsec.conf" の内容を調整します。

version 2.0

 

config setup

protostack=netkey

nat_traversal=yes

virtual_private=%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12

oe=off

nhelpers=0

 

include /etc/ipsec.d/*.conf

初期設定では "include /etc/ipsec.d/*.conf" という記載が "#" がついてコメントアウトされているようなので、その行を有効化して、次のような内容の設定ファイルに調整しました。

また、NAT トラバーサルを考慮して、virtual_private の値に "%v4:10.0.0.0/8,%v4:192.168.0.0/16,%v4:172.16.0.0/12" を設定しておきます。

/etc/ipsec.d/l2tp-psk.conf の設定

続いて L2TP に必要な設定ファイルを、次のような内容で "/etc/ipsec.d/l2tp-psk.conf" というファイルを作成します。

conn L2TP-PSK

type=transport

ike=3des-md5

esp=3des-md5

forceencaps=no

authby=secret

pfs=no

rekey=no

keyingtries=3

left=%defaultroute

leftnexthop=%defaultroute

leftprotoport=17/1701

right=%any

rightprotoport=17/%any

auto=add

dpddelay=5

dpdtimeout=20

dpdaction=clear

"authby" を "rsasig" とすることで、電子証明書による暗号方式を採用することもできるらしいですが、とりあえず今回は共有暗号鍵を使う方向で設定して行きたいと思います。

 

また、ここで "forceencaps" に "no" を指定していますが、こうしないと Windows Server 2008 R2 から接続できない様子でした。

ちなみにこの "forceencaps" オプションというのは、ESP プロトコルを強制的にカプセル化するかどうかのオプションのようです。Windows ではレジストリを書き換えないと NAT トラバーサルを利用できないという話をどこかで目にしたので、もしかするとそれと関係があるのかもしれません。

 

それともうひとつ、詳細は iOS で L2TP-VPN への再接続に失敗する に記しましたが、iPhone や iPad 等で L2TP 接続する場合には、2 度目の接続で失敗してしまわないように "dpddelay", "dpdtimeout", "dpdaction" も設定すると良さそうです。

/etc/ipsec.d/default.secrets の設定

そして、"/etc/ipsec.d/default.secrets" というファイルを作成し、その中に共有暗号鍵を設定します。

: PSK "password"

なお、このファイルにはパスワードが記載されていますので、念のため次のようにして、root アカウント以外が参照できないようにしておくと良いかもしれません。

chmod go-rwx /etc/ipsec.d/default.secrets

 

L2TP の起動と設定ファイルの最終調整

L2TP を起動する

設定ファイルをひととおり調整したら、L2TP の起動を行います。

service ipsec start

service xl2tpd start

これで Openswan (ipsec) と xl2tpd が起動されました。

 

これらの機能を Linux 起動時に自動起動されるようにするには、次のコマンドを実行します。

chkconfig ipsec on

chkconfig xl2tpd on

これで Linux 起動時に ipsec と xl2tpd が自動的に起動するようになりました。

Openswan の動作確認と設定調整

ここで、Openswan のセットアップと起動が完了したので、次のコマンドを実行して動作状況を確認します。

ipsec verify

すると、次のような感じで Openswan の動作状況が画面にレポートされました。

Checking your system to see if IPsec got installed and started correctly:

Version check and ipsec on-path [OK]

Linux Openswan U2.6.24/K2.6.32-71.29.1.el6.x86_64 (netkey)

Checking for IPsec support in kernel [OK]

NETKEY detected, testing for disabled ICMP send_redirects [FAILED]

 

Please disable /proc/sys/net/ipv4/conf/*/send_redirects

or NETKEY will cause the sending of bogus ICMP redirects!

 

NETKEY detected, testing for disabled ICMP accept_redirects [FAILED]

 

Please disable /proc/sys/net/ipv4/conf/*/accept_redirects

or NETKEY will accept bogus ICMP redirects!

 

Checking for RSA private key (/etc/ipsec.secrets) [OK]

Checking that pluto is running [OK]

Pluto listening for IKE on udp 500 [FAILED]

Cannot execute command "lsof -i UDP:500": そのようなファイルやディレクトリはありません

Pluto listening for NAT-T on udp 4500 [FAILED]

Cannot execute command "lsof -i UDP:4500": そのようなファイルやディレクトリは ありません

Checking for 'ip' command [OK]

Checking for 'iptables' command [OK]

Opportunistic Encryption Support [DISABLED]

この中から [FAILED] とレポートされたものに焦点を当てて、そのエラーを解消させて行きます。

 

まず、次の [FAILED] として通知された内容について見て行きます。

NETKEY detected, testing for disabled ICMP send_redirects [FAILED]

これについては "/etc/sysctl.conf" で、次のような設定を行うことで回避できるようでした。

設定としては、各インターフェイスについて "send_redirects" および "accept_redirects" を 0 にします。存在するすべてのインターフェイスについて行っておくのが良いようです。

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.lo.send_redirects = 0

net.ipv4.conf.lo.accept_redirects = 0

net.ipv4.conf.eth0.send_redirects = 0

net.ipv4.conf.eth0.accept_redirects = 0

net.ipv4.conf.eth1.send_redirects = 0

net.ipv4.conf.eth1.accept_redirects = 0

これらの設定を行ったら、次のようにして設定内容を有効化します。

sysctl -p

これで ICMP まわりの FAILED が通知されなくなるようでした。

 

続いて、次の [FAILED] と通知された内容です。

Pluto listening for IKE on udp 500

Pluto listening for NAT-T on udp 4500 [FAILED]

これは単純に lsof" というコマンドがインストールされていないことが原因でした。

これは CentOS 6.0 であれば、次のようにしてインストールすることが可能です。

yum install lsof

これで [FAILED] とレポートされたものは全て [OK] になりました。

 

残すところ、次の [DISABLED] の通知です。

Opportunistic Encryption Support [DISABLED]

これは "/etc/ipsec.conf" の中で "oe=off" としているため、この Opportunistic Encryption Support が無効になっていることを意味しているようです。

Opportunistic Encryption Support を直訳すると "ご都合主義の暗号化サポート" になるのでしょうか。

IKE (Internet Key Exchange) と IPsec を使って、事前準備がなくても暗号化された接続を実現するための機能のようですが、まずは無効のままにしておくことにします。

ちなみに "oe=on" にしたときに、"host" コマンドが見つからないというエラーが出た場合には、"yum install bind-utils" を実行して "bind-utils" パッケージをインストールします。

 

L2TP-VPN 接続用のアカウントを用意する

xl2tpd と Openswan で構築した L2TP-VPN では、接続の際に使用するアカウントは PAP 認証であれば "/etc/ppp/pap-secrets" に、CHAP 認証であれば "/etc/ppp/chap-secrets" に登録しておく必要があります。

今回は MS-CHAPv2 認証を使用するので "/etc/ppp/chap-secrets" に次のように記載しました。

# アカウント    接続名    パスワード    IPアドレス

"vpn-account"    "xl2tpd"    "vpn-password"    *

これで、アカウントが "vpn-account" で、パスワードが "vpn-password" のアカウントを作成できました。

接続名には "/etc/ppp/options.xl2tpd" の "name" で設定した名前を指定しているので、このアカウントは今回の L2TP-VPN 用のアカウントになります。IP アドレスのところには、接続元の IP アドレスを指定することができるようでしたけど、今回は "*" として無制限とします。

他にもいくつかアカウントを登録したい場合には、行を変えて同じように登録します。

 

ちなみにこのアカウントファイルは、編集するとすぐにそれが有効になります。

接続中のものについては影響ありませんが、ipsec や xl2tpd を再起動しなくても、次からの接続の時には新しい設定での認証になるので注意して設定するようにします。

 

ルーティングを有効にする

ルーティングを有効にしないと、L2TP クライアントは接続したサーバーとしか通信ができないようです。

特に Proxy ARP を利用した場合など、L2TP サーバーと同一のネットワークや、それを経由した別のネットワークと通信を行いたい場合には、この L2TP をセットアップした Linux 側で ip_forward を有効化する必要があります。

 

CentOS 6.0 の場合には、"/etc/sysctl.conf" の "net.ipv4.ip_forward" の値に 1 を指定します。

net.ipv4.ip_forward = 1

設定ファイルを更新したら、次のコマンドを実行して、設定を有効化します。

sysctl -p

これで IP ルーティングが有効になり、この L2TP サーバーを経由したネットワーク通信が可能になりました。

 

L2TP への接続について

上記のように L2TP サーバーの準備が完了したら、これで L2TP-VPN の利用準備はひとまず整いました。

接続の際には、"/etc/ppp/chap-secrets" で登録したアカウントとパスワードと、"/etc/ipsec.d/default.secrets" ファイルに記載した IPsec の事前共有キーを指定します。

Windows 7 での具体的な設定方法については L2TP-VPN に Windows 7 で接続する に、Linux での接続設定については CentOS 6.0 で L2TP-VPN に接続する に、それぞれ記してみましたので、必要に応じてそちらの方をご覧ください。

また、パケットフィルター等のファイアーウォールで保護された環境に L2TP-VPN サーバーを設置するには、L2TP-VPN で使用するポートを開放する で記した通信を許可してあげる必要があるようでした。