FreeBSD on Raspberry Pi 3(以下ラズパイ3)でL2TP+IPsecのVPNサーバーを構築したので、ここに覚書を記したいと思います。
注意点
現在接続を確認しているクライアントOSは
- iOS/iPadOS(13)
- macOS(Catalina)
- Android(8.0)
- ChromeOS
です。
(Windowsはモバイル環境がなく、ローカル接続のみ確認していてインターネット側からの接続・通信は未確認)
きっかけ
すでにNUC(Celeronの安いの)でracoon+mpd5(OSはFreeBSD 9.x)によるVPNを構築していましたが、iOS/macOS以外のクライアント(Android等)で接続できない問題を抱えていました。
今回、ラズパイ3を入手したことと、VPNサーバーのさらなる省電力化およびクライアントOSの選択肢を広げるため、ラズパイ上にVPNサーバーを構築することにしました。
Racoon→StrongSwanに変えた理由ですが、Linuxでも使われていて情報量が多いかなと思ったからです。
今回の目標
- 事前共有鍵(PSK)方式でL2TP/IPsecのVPNが張れ、内部のネットワークが参照できること
前提環境
ハードウェア
- ルーター(静的NAPT設定ができ、かつVPNパススルーをサポートしているもの)
- Raspberry Pi 3 Model B+microSDカード
- SDに書き込む・接続テスト用PC
- L2TP/IPsec接続をサポートしているスマートフォン・タブレット・ノートPC
ソフトウェア
- FreeBSD 12.1
- StrongSwan
- mpd5
その他前提
- グローバルIPを直に割り当てられたインターネット接続があること
- DDNSが設定済みで、FQDNから上記のグローバルIPが引けること
- ルータ内はプライベートIP
- ルータ自身のプライベートIPは192.168.x.1
- ラズパイ3のIPは192.168.x.2
- VPNサーバで割り当てるIPアドレスの範囲は192.168.x.yから192.168.x.zまで
手順
FreeBSDのSDカードイメージをダウンロード
ここから”RPI3”のイメージをダウンロードします。
https://www.freebsd.org/ja/where.html
microSDカードにイメージを書き込む
macOS/UNIX系OSの方はここら辺をご参考に。
https://qiita.com/s_mitu/items/ecfcab3826fee2c873d9
Windows・ChromeOSな方は適当にググってください。
microSDをラズパイ3に差し、OS起動
特に手順が間違っていなければ、OSが起動すると思います。起動したら、一般ユーザの作成・IPアドレス・sshの設定などをします。ここでは手順割愛。
StrongSwan・mpd5をインストール
今回はpkgを利用してインストールします。
pkg install strongswan
pkg install mpd5
StrongSwanの設定
参考文献を参照して作って、そこからいろいろ試行錯誤しましたが、最終的には以下の形になりました。
config setup
## 各機能に関するデバッグレベルを2に設定(デフォルトは1)
charondebug = "dmn 4, mgr 4, ike 4, cfg 4, knl 4, net 4, esp 4"
conn %default
ike=aes256-sha1-modp1024,aes128-sha1-modp1024,3des-sha1-modp1024!
esp=aes256-sha256,aes256-sha1,3des-sha1!
conn L2TP-PSK-NAT
type=transport
authby=secret
leftprotoport=udp/l2tp
left=192.168.x.2
leftsubnet=0.0.0.0/0
leftauth=psk
right=%any
rightsubnet=0.0.0.0/0
rightprotoport=udp/%any
rightauth=psk
auto=add
setupのログレベルの設定はお好みで。
conn %defaultの暗号化方式の指定は必須です。これがないとつながるものがつながりません。
leftauth, rightauth, authbyの指定はPre-shared keyにするためのものです。全部はいらないような気もしますが、とりあえずこれで動いているので。
LeftprotopointはL2TPで使うプロトコル・ポートなので指定が必要です(結局これがないと動かない?)。
: PSK "事前共有鍵”
事前共有鍵は文字列をそのまま指定します。この文字列をできる限り複雑にしておくこととこのファイルのパーミッションは600にしておきましょう(オーナーはroot)。
mpd5の設定
参考文献を参照して新しく作り直しました。
startup:
log +ipcp +ipv6cp +lcp +link +auth +ecp +ccp
default:
load l2tp_server
l2tp_server:
set ippool add pool_l2tp 192.168.x.y 192.168.x.z
create bundle template B_l2tp
set iface enable proxy-arp
set iface enable tcpmssfix
set iface group ng
set iface route default
set ipcp ranges 192.168.x.2/24 ippool pool_l2tp
set ipcp dns 192.168.x.1
set ipcp enable vjcomp
set bundle enable compression
set ccp enable mppc
set mppc enable e40
set mppc enable e128
set mppc enable stateless
create link template L_l2tp l2tp
set link action bundle B_l2tp
set link mtu 1354
set link keep-alive 10 60
set link no pap chap eap
set link enable chap-msv2
set link enable chap
set link enable multilink
set link enable acfcomp protocomp
set auth enable system-acct
set l2tp self 192.168.x.2
set l2tp enable length
set l2tp disable dataseq
set link enable incoming
ユーザー名 "パスワード"
ユーザー名もできるだけ複雑にしておいた方がいいと思います。
(パスワードは言わずもがな)
そしてこのファイルのパーミッションも600にしておきます(オーナーはroot)。
rc.confの設定
たいした設定はなく、以下を追記するだけです。
strongswan_enable=“YES”
mpd5_enable=“YES”
gateway_enable=“YES”
サービス起動
service strongswan start
service mpd5 start
クライアントから接続してみる(内部)
ここまでできたら、まずルータ内部から接続してみましょう。
macOSを例に説明します。
- 「環境設定」を起動し、「ネットワーク」を開きます。
- 左下の”+”を押します。
- インターフェースは”VPN”、VPNタイプは”L2TP over IPSec”を選択、名前は適当に入れて「作成」。
- 「構成」欄で「構成を追加…」を選び、適当な名前を入れて「作成」。
- サーバ欄はラズパイ3のIPアドレス、アカウント名はmpd.secretで設定したユーザー名を入れ、「認証設定」を押す。
- 「パスワード」が選択されていることを確認してmpd.secretで設定したパスワードを入力。
- 「共有シークレット」が選択されていることを確認してipsec.secretsで設定した事前共有鍵を入力。
- 「グループ名」は空欄のまま。
- 「OK」を押して戻る。
- 「適用」を押して設定完了。
- あとは「接続」を押して、VPN接続ができて送受信状態が表示されればOK!
ルーターの設定変更
概要のみ書きます。
- UDPのポート500, 1701, 4500の穴を空け、ラズパイ3に向ける
- ESPも同様
- ルーターに「VPNパススルー有効/無効」の設定があれば「有効」にする。
クライアントから接続してみる(外部)
先ほどの内部の接続テストの環境を流用します。
- とにかく自宅セグメントの範囲外に出ます。面倒なのでここではMacを無線LANを使ってモバイルLTEルータに接続します(当然接続先はLTEのネットワークです)。
- 「環境設定」を起動し、「ネットワーク」を開きます。
- 左ペインで先ほど作ったVPNを選択します。
- サーバアドレスをDDNSのFQDNに変更して、「適用」を押します。
- 「接続」を押して、VPN接続ができることを確認する。
- 接続したまま、内部ネットワークの機器(ルータなど)が見えることと、そこから自宅外のサイトが見えるかを確認する。
感想
構築のきっかけはmacOS/iOSのPPTPサポート終了だったのですが、racoonの時と比べて意外と時間がかからずにできてしまったなー感はあります。どちらかというとこの記事を作ることに時間がかかりすぎた感じです。
詰まったところ
mpd5自身が立ち上がらない
参考文献から設定を持ってきていたのですが、service mpd5 startしてstatusを確認すると立ち上がっていない…
調べた結果、mpd.confに “#”でコメントを書いているとどうもエラーになるようで、面倒なので以下のコマンドでコメントを削除しました。いや日本語のコメントがNGなのかも。
sed -e ’s/#.*$//‘ mpd.conf mpd.conf.new
mv mpd.conf.new mpd.conf
VPN接続するとDNSの名前が引けない
VPN接続しないうちはいいのですが、接続している間、クライアントはもちろんのこと、ラズパイ3自身もDNSの名前が引けなくなる現象が発生しました。
調べると、ルータへのDNSクエリーが正常に動作していないようです。しかし、他の機器からは正常に引けている。VPN接続を切るとDNSが引けるようになる。
原因はmpd.confのset ipcp rangesの第1パラメータをラズパイ3のIPアドレスではなくルータのIPアドレスを指定してしまっていました。やはり参考文献から設定を持ってくる際に勘違いしてしまったようです。
スループット
ラズパイ3なのであまり期待しない方がいいと思います…
参考文献
https://blog.c6h12o6.org/post/freebsd-l2tp-ipsec-ipsec/
https://blog.c6h12o6.org/post/freebsd-l2tp-ipsec-l2tp/
終わりに
持っているルーターがNVR500なので、実はこれ単体でL2TP/IPsec通信ができることが以前実験していたときに判明してしまいました。
しかし、NVR500のL2TP/IPsec VPNは
- PSKのみ(証明書は未サポート)
- PSKの事前共有鍵は32文字まで
という制限があるので、将来的に証明書認証に乗り換えるのであればこの記事は役に立つのではないかなーと。自分もその1人ですが。
もう1つ、NVR500のNATはSymmetric NATなので、Full cone NATのルータに買い換えようかな…と思っていることもあります。
(Symmetric NATだといろいろ制約もあるのですよ…例えばスマートフォンを使ったリモートでの動画再生とか…)
あとラズパイ3用のpkgはx64のPoudriere環境を別途構築しているのでそちらから取ってくるようにしています。これについては需要があれば別途記事を上げたいと思います。