さくらのVPSでL2TP/IPsec
前回さくらのVPSを構築しました、今回はこのVPSとローカルにあるPCをVPN(Virtual Private Network)で接続する方法を覚書として残したいと思います。
覚書を作っているうちに、後半にあるstrongSwanの設定記述は非推奨だという事が判明しました。strongSwanのviciインターフェースによる設定方法は「strongSwanの新しい設定方法(vici)」にて紹介します。
サーバーはDebian10でxl2tpdとstrongSwanを利用して、Window10に付属の標準のVPN(L2TP/IPsec 事前共有鍵)で接続できるようにします。
IPsec
これから設定する項目は、IPsecについて理解していると何をやっているのかわかりやすいと思います。そこでまずIPsecから把握していきます。
IPsecはデータセキュリティを担うプロトコルです。セキュリティの仕組みではSSLが有名ですが、これとの違いはSSLはOSI参照モデルのセッション層で稼働するセキュリティとなっているのに対し、IPsecがネットワーク層で稼働します。
またバージョンも1、2、3とあります。
IPsecの構造
IPsecは次のプロトコルで構成されています。
- カプセル化
AH(Authentication Header)と呼ばれる改ざん防止用のプロトコル、ESP(Encapsulated Secury Payload)と呼ばれる改ざん防止と暗号化のプロトコルがあります。それぞれを単独で使う場合と両方を使う場合がありますが、最も一般的なのはESPだけを使うパターンです。 ESPを改ざん防止で使う場合はESPの暗号化範囲+ESPヘッダだけが改ざん防止の対象になるのに対し、AHを利用するとデータ全体をチェックすることができます。そのためAH+ESPという併用の仕方があります(その分負荷は上がります)。
- ハッシュ
改ざんを検知するためのハッシュにはMD5やSHAが使えることになっています。MD5よりSHAの方が強度が強いです。さらにSHAの中でも種類があり強度が違います。
- 鍵交換
IKE(Internet Key Exchange)プロトコルによって、暗号化の方法(DES,3DES,AES)などを決め、鍵の交換をします。鍵交換の部分はDH(ディフィー・ヘルマン鍵共有)が用いられます。これもバージョンが複数あります。
トンネルモードとトランスポートモード
カプセル化の方法にAHとESPまはたその両方があると先に紹介しましたが、それぞれにおいてカプセル化の範囲も変えることができます。その違いを「トンネルモード」と「トランスポートモード」として表します。
トンネルモードでは最終的な宛先(IPヘッダ)をAHやESPヘッダによってカプセル化します。
トランスポートモードではIPヘッダの内側にAHやESPヘッダを挿入します。
ESPを改ざん防止にも利用する場合は、最後にチェック用データが付与されます。もともとESPには長さをそろえるためのパディングがありますが、チェック用データはその後ろに付与されます。
トンネルモードにおいてデータは次のように並びます。
[new IP Header][AH][IP Header][Data]
ESP
[new IP Header][ESP][IP Header][Data][ESP Padding][ESP Check]
AH+ESP
[new IP Header][AH][ESP][IP Header][Data][ESP Padding]
トランスポートモードでは次のようになります。
[IP Header][AH][Data]
ESP
[IP Header][ESP][Data][ESP Padding][ESP Check]
AH+ESP
[IP Header][AH][ESP][Data][ESP Padding]
AH+ESPではAHがデータの改ざんチェックを行うので[ESP Check]は含まれません。
こちらはネットワークエンジニアとして:「IPsec - Transport mode / Tunnel mode」を参考にさせていただきました。
IKE(Internet Key Exchange)
ここまで見てきたように、いろいろなプロトコルを合わせて構成されるIPsecです。柔軟なところはいいのですが、実際に通信するとなると多くの設定の中から相手に合わせた選択をする必要があります。その手間のかかる作業を自動でやってくれるのがIKEです。
これもバージョンが1と2が存在します。1はISAKMP/Oakleyと呼ばれたりすることもあります。
バージョンで違いはありますが、基本的に暗号鍵を交換するために暗号化通信を構築し、DHによって暗号鍵を交換します。その後IPsecによる暗号化通信が始まります。
アプリのインストールと設定
アプリのインストールと設定は技術メモの壁:「自宅-VPS間でIPsec (strongswan)」を参考にさせていただきました。
VPS側は固定IPアドレスが割り振らています。ここでは仮に123.456.789.1とします。ローカル側はNATの内側にありグローバルアドレスは動的配布になっています。
VPSとローカルともにDebian10をOSとして使っていることにします。
インストールはどちらも共通です。
...
# apt update
...
# apt install strongswan
...
インターフェース間のパケットの転送を許可する設定をします。この方法も共通です。
/etc/sysctl.conf
...# コメントアウトを外します
net.ipv4.ip_forward=1
...
OS再起動をかけてもいいですが、次のようにすると再起動なく設定を反映させられます。
これは設定をデフォルトの/etc/systctl.confから読み込むコマンドです。pの後にファイルパスを指定するとそこから読み込むこともできます。
次にPSK(Pre Shared Key)を設定します。どちらも同じにする必要があるのでこの方法も両者で共通です。
/etc/strongswan/ipsec.secrets
...: PSK "password" ...
:の前に宛先IPアドレスを入力すると接続毎にPSKを変更できます。他この設定ファイルの詳細はstrongSwan:「ipsec.secrets」にあります。
アプリの設定ファイル修正します。これはぞれぞれ少し違います。まずVPS側の設定です。
/etc/ipsec.conf
config setup conn ipsec-test # VPSのIPアドレス(グローバルアドレス) left=123.456.789.1 # VPSのサブネット(単体接続) leftsubnet=123.456.789.1/32 # 接続先のアドレス「%any」ですべてを意味します right=%any # ローカルサブネットを指定しません rightsubnet=0.0.0.0/0 # 接続が閉じられた際終了 closeaction=clear # Dead Pear Detection時終了 dpdaction=clear # PSKを使ったIPsec authby=secret # 起動時に待ち受け状態に auto=add
このファイルはconfig setupに全接続の共通設定を記述しますがここでは何も記載しません。参考サイトではnat_traversal=yesを設定していましたが、現在は非推奨という事で、なくてもNAT越えはできます。そのあとに「conn 名前」の後に接続毎の設定を記述します。名前は自由にいくつも設定でき「also=名前」とすることで記述した設定を読み出すこともできます。
このファイルの記述方法の詳細はstrongSwan:「ipsec.conf」にあります。
次にローカル側の設定です。
/etc/ipsec.conf
config setup conn ipsec-test # ローカルのIPアドレス(プライベートアドレス) left=192.168.1.1 # ローカルのサブネット(プライベート側) leftsubnet=192.168.1.0/24 # 接続先(VPSのIP) right=123.456.789.1 rightsubnet=123.456.789.1/32 # 接続が閉じられた際再接続 closeaction=restart # Dead Pear Detection時再接続 dpdaction=restart # PSKを使ったIPsec authby=secret # 起動時に接続しにいく auto=start
ファイアウォールの設定
IKEで使われるudpの500ポートと、4500ポートに対して許可を設定します。AHやESPはTCPやUDP、ICMP等と同じようにIPの上の階層のプロトコルなのでポート番号というものがありません。
iptablesでは-pオプションでプロトコル番号を使った設定ができるので、AHなら51(またはah)、ESPなら50(またはesp)を設定します。ちなみにほかのプロトコル番号はTCP(6)、UDP(17)、ICMP(1)となっています。
また今回インストールしたstrongswanではAH+ESPが利用できないので、通常利用するのは暗号化のあるESPとなります。そのため利用されないAHのファイアウォール設定はしません。
-A INPUT -p udp --dport 500 -j ACCEPT -A INPUT -p udp --dport 4500 -j ACCEPT
systemctl restart strongswanを両側で実行した後、ipsec statusで接続先のアドレスが表示されていればIPsec通信は成功しています。
L2TP
L2TPとはL2、OSI参照モデルの第二階層でトンネルを作成するプロトコルです。本来別のネットワークになる二つの場所をつなげることができます。このプロトコルは暗号化されませんが、先に設定したIPsecの中を通すことでそれを実現します。この方法はL2TP/IPsecと呼ばれます。
L2TP接続用のアプリであるxl2tpdをVPSにインストールします。今度は接続相手をWindowsにしてみます。
これらの方法は技術メモの壁:「Debian 9でL2TP/IPSecのVPNサーバーを構築する」を参考にさせていただきました。
# apt install xl2tpd ...
まずはサーバー側からの設定です。
L2TPはL2TPでユーザー名とパスワード認証をするようにします。
xl2tp用の設定ファイルとして/etc/xl2tpd/l2tp-secretsというファイルも存在しますが、ここではpppdがデフォルトで使用する/etc/ppp/chap-secretsファイルにサーバーに接続しにくるユーザー名とパスワードの設定をします。ユーザー名、サーバー名、ユーザーパスワード、ユーザーIPアドレスの順に記述します。
この時*(半角アスタリスク)にしておくとどんな値でも受け付けます。
/etc/ppp/chap-secrets
username * password *xl2tpdのメインの設定ファイル(/etc/xl2tpd/xl2tpd.conf)を修正します。このエントリーはすべてコメントアウトしてあるので利用するセクション(;[global]と;[lns default]部を忘れずに) と、エントリーのコメントアウトを外して修正します。
/etc/xl2tpd/xl2tpd.conf
[global] # ファイルの場所を変更します auth file=/etc/ppp/chap-secrets ... [Ins default] # IPアドレス払い出し ip range = 192.168.200.2-192.168.200.32 # サーバーのIPアドレス local ip = 192.168.200.1 # Lengthビットを立てL2TPオプションのLengthを使う length bit = yes # 認証プロトコルの可否 refuse pap = yes refuse chap = yes require authentication = yes # ホスト名 hostname = xl2tpd
払い出すIPアドレスやサーバーのIPアドレスは、既存で利用されているネットワークに重複しないように設定する必要があります。
L2TPの予備知識
IPsec通信をとにかく開通させることが使命の方は読み飛ばしてもらって構いません。ここで少し寄り道をしてL2TPについて理解を深めます。そうすることで、トラブル解決能力が少しは上がるのではないかと思っています。
L2TPプロトコルの外側にはIPsecによりカプセル化されていることには触れました。そして、この内側には、PPPプロトコルが含まれています。PPPプロトコルは「Point To Point」の意味で、1対1でネットワークを構築するプロトコルです。
またL2TPにおいては、接続しに行こうとする端末のことをLAC(L2TP Access Concentrator)、ここで設定しているサーバー端末のことをLNS(L2TP Network Server)と呼びます。
xl2tpd.confの設定はほかにもあり、man xl2tpd.confとすることで参照することができます。そのひとつにpppoptfileというものがあります。
これは、xl2tpdがPPPを呼び出すときに利用する追加設定ファイルを指定するものです。
Debianにおいてはpppdを利用するようなので、man pppdとすることで主なオプション値を確認でききます。/etc/ppp/optionsがそのサンプルファイルとなっているようです。筆者の環境ではオプションファイル自体を指定しないでも問題ありませんでした。)逆にサンプルオプションを指定すると稼働しませんでした)
参考にさせていただいたページでは次のような設定がされていましたので、項目の補足説明を入れながら紹介します。
# 認証で使われる名前 name xl2tpd # 相手からのローカルIPアドレスの指定を受け入れる ipcp-accept-local # 相手からのリモートIPアドレスの指定を受け入れる ipcp-accept-remote # 認証プロトコルの可否 refuse-pap refuse-chap refuse-mschap※1 require-mschap-v2※1 # 接続先をデフォルトルートとしない nodefaultroute # 圧縮を使用しない nobsdcomp # MTU/MRU mtu 1372※3 mru 1372※3 # シリアルデバイスの排他制御 lock※2 # ログファイル logfile /var/log/xl2tpd.log※1 # DNS通通知 ms-dns 8.8.8.8※0 # ネットマスク指定 netmask 255.255.255.0※0 # 切断時に再接続 persist※4
筆者の環境では
※0のオプションは利用していません。
※1のオプションは、man pppdに存在しませんでしたが稼働しました。
※2のオプションは、man pppdに存在しますが稼働しませんでした。
※3のオプションは、設定値が大きすぎる場合は修正してくれるようです。
※4のオプションは、おかしな接続が残ると以降接続できないような現象が見受けられたので、筆者はこの設定を消しました。またマニュアルでは、これを利用する際に「idel 秒数」オプションでアイドル時の切断設定をする事を推奨していました。
ログに「autonegotiation is unset or enabled, the speed and duplex are not writable.」という表示がでていました。リンク速度・二重半二重の設定はしていませんが、これらを設定したい場合は systemd.linkの設定で、AutoNegotiaionを切ることができるようです。
ipsec.conf
strongSwan(IPsec)に戻ります。次はVPS側のipsec.confを次のように修正します。
/etc/ipsec.conf
left=123.456.789.1 leftprotoport=udp/1701 right=%any rightsubnet=0.0.0.0/0 rightprotoport=udp/%any type=transport closeaction=clear dpdaction=clear dpddelay=30 dpdtimeout=120 auto=add authby=secret forceencaps=no
アンダーライン部が修正を加えた箇所になります。ポートの指定をL2TPのものであるudp/1701に設定しています。L2TPは発信ポートは定まっていないので、right側はanyとしています。またトランスポートモードを明示しました。forceencapsはnoにするとWindows10の標準のVPN接続からの接続が可能になります。
L2TP接続を加えたのでファイアウォールの修正をします。/etc/iptables/rules.v4に次の行を加えます。
このmオプションで指定されているpolicy拡張はIPsecのパケットを処理するものです。--dir inで入力方向、--pol ipsec でIPSecのデータを抽出します。詳しくはman iptables-extensionsから確認できます。全体で、IPSecかつudpの1701番ポート(L2TP)を許可する設定となっています。
Windows10のVPNから接続できるかチェックします。「スタートメニュー」→「設定」→「ネットワークとインターネット」→「VPN」→VPNを追加すると進めていきます。
表示されるウインドウに設定項目を入れていきます。
- VPNプロバイダ
Windowsビルトイン
- 接続名
自由につけられます
- サーバー名またはアドレス
- VPNの種類
- 事前共有化キー
ipsec.secretsファイルに設定したPSK
- ユーザー名
chap-secretsファイルに記述したユーザー名
- パスーワード
chap-secretsファイルに記述したパスワード
VPSのIPアドレスを入力します
事前共有キーを使ったL2TP/IPsec
「保存」ののち「接続」から接続できたら成功です。
参考にさせていただいたサイトの皆様ありがとうございました。