strongSwanでLet’s Encrypt証明書を使ったIKEv2 VPNサーバーを作る

この世界が誕生する前から、実はowner203はこの世界(のサーバー)をVPNアクセスポイントとして使っていました。owner203は家の外でインターネットを使うことが多く、VPNを使うのはもちろんセキュリティのためです。特にフリーWi-Fiを使うときはなおさらです。ConoHaの回線速度はとても早いので、常時VPNをオンにしても速度は落ちません。

VPNにはいろんなタイプがありますが、安全性とクライアントの設定しやすさを考慮したうえで、やはりIKEv2に他なりません。iOS、macOSとWindowsではアプリ不要で設定できるし、Wi-Fiとモバイルデータの切り替えでも切断しないなど、他のタイプより優秀だと考えました。

IKEv2接続は必要条件としてサーバー証明書が必要です。自己署名の証明書を使うマニュアルが多くありますが、自己署名の場合、クライアントが手動で証明書を導入する(ルート認証局を信頼設定にする)必要があるなど、面倒くさいです。クライアントでの接続を簡単化するため、Let’s Encrypt発行の証明書を使います。英語の参考資料を読みながら設定したが、自分が理解できるようにここで整理しておきます。サーバーOSはUbuntu 18.04です。

Apacheの導入

すべての作業の前に、まず普通にWEBサーバーを建てて、ドメインでサーバーにHTTP接続ができるようにしておきます。後ほどLet’s Encryptの証明書を取得するために必要なので、先にインストールしておきます。

sudo apt update
sudo apt install apache2

インストールしたら、ufwで使うポートを開けます。

sudo ufw allow 'Apache Full'
sudo ufw status #確認する

Let’s Encryptの導入

まずApache用のCertbotを入れます。

sudo apt install python-certbot-apache

もしこれでダメだったらCertbotのPPAを入れてからもう一度試します。Ubuntu最新版では不要のはずです。

sudo add-apt-repository ppa:certbot/certbot  #最新版では不要

証明書を取得する前に、まずApacheでドメインのconfファイルを設定します。複数ドメインをバーチャルホストでホストしていない(000-default.confしかホストしない)場合は省略可能です。

sudo vi /etc/apache2/sites-available/owner203.com.conf
/etc/apache2/sites-available/owner203.com.conf

#次の行を追記する
ServerName owner203.com;
sudo apache2ctl configtest  #設定ファイルをテストする
sudo systemctl reload apache2 #設定ファイルをリロードする

これから証明書を取得します。基本的に表示内容を従えれば大丈夫です。

sudo certbot --apache -d owner203.com -d www.owner203.com  #もっとドメインがあれば-dで追加する

Let’s Encryptの証明書は有効期限が短いので、定期的に更新しないといけません。このCertbotで証明書を取得した場合は自動的に/etc/cron.d/で自動更新の設定が済んだはずです。ここで自動更新のテストをやってみます。

sudo certbot renew --dry-run

strongSwanの導入

いよいよ本題に入ります。IKEv2の作成にはstrongSwanを使います。Androidでも公式クライアントAppを入れることでIKEv2接続ができます。strongSwanのインストールはとても簡単です。

sudo apt install strongswan

次にstrongSwanの設定ファイルを編集します。設定内容が多いので、オリジナルの設定ファイルをバックアップして書き直します。

sudo mv /etc/ipsec.conf{,.orig}
sudo vi /etc/ipsec.conf
/etc/ipsec.conf

config setup
    charondebug="ike 1, knl 1, cfg 0"
    uniqueids=no

conn ikev2-vpn
    auto=add
    compress=no
    type=tunnel
    keyexchange=ikev2
    fragmentation=yes
    forceencaps=yes
    ike=aes256-sha1-modp1024,3des-sha1-modp1024!  #iOSを対応するために暗号化メソッドをaes256-sha1-modp1024に指定する
    esp=aes256-sha1,3des-sha1!  #上の行と順番を一致する
    dpdaction=clear
    dpddelay=300s
    rekey=no
    left=%any
    leftid=@owner203.com
    leftcert=fullchain.pem  #この行ではIKEv2で使用するサーバー証明書を指定したが、後ほどCertbotで取得した証明書ファイルをstrongSwanのフォルダにコピーしなければならない
    leftsendcert=always
    leftsubnet=0.0.0.0/0
    right=%any
    rightid=%any
    rightauth=eap-mschapv2
    rightsourceip=10.10.10.0/24
    rightdns=8.8.8.8,8.8.4.4
    rightsendcert=never
    eap_identity=%identity

次にIKEv2接続で使う認証情報を設定します。

sudo vi /etc/ipsec.secrets
/etc/ipsec.secrets

#以下の行を追記する
: RSA "privkey.pem"  #IKEv2で使うクライアント証明書を指定する
vpn_username : EAP "vpn_password"  #複数ユーザーを設定する場合は行を追加して設定する
#追記はここまで

strongSwanを再起動して、設定を有効にする。

sudo systemctl restart strongswan

ファイアーウォールに関する設定

これからは、クライアントがVPNで接続してサーバーのインターネットを使うために、ufwでポートを開けて、IPv4のデータ転送を設定します。

まず、IKEv2とIPSecが使う500番ポートと4500番ポートを開きます。

sudo ufw allow 500,4500/udp

次の操作へ進む前に、サーバーが使うネットワークインターフェース名を確認しなければなりません。これはサーバーをログインした直後に表示されるSystem informationで確認できます。ConoHaの場合はeth0でした。

Output

System information as of Xxx Xxx 00 00:00:00 JST 2019
System load: 0.0 Processes: 000
Usage of /: 00.0% of 00.00GB Users logged in: 0
Memory usage: 00% IP address for eth0: 000.000.000.000
Swap usage: 0%

またip routeコマンドでも確認できます。

ip route | grep default
Output

default via 000.000.000.1 dev eth0 proto dhcp src 000.000.000.000 metric 100

もしeth0ではない場合、次の操作でeth0の箇所を自分のサーバーが使うインターフェース名に変更します。

それではufwが使うフィルターファイルを編集します。

sudo vi /etc/ufw/before.rules
/etc/ufw/before.rules

#以下の行を追記する
*nat
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -m policy --pol ipsec --dir out -j ACCEPT
-A POSTROUTING -s 10.10.10.0/24 -o eth0 -j MASQUERADE
COMMIT

*mangle
-A FORWARD --match policy --pol ipsec --dir in -s 10.10.10.0/24 -o eth0 -p tcp -m tcp --tcp-flags SYN,RST SYN -m tcpmss --mss 1361:1536 -j TCPMSS --set-mss 1360
COMMIT
#追記はここまで

*filter
#中略...
#以下の行を追記する
-A ufw-before-forward --match policy --pol ipsec --dir in --proto esp -s 10.10.10.0/24 -j ACCEPT
-A ufw-before-forward --match policy --pol ipsec --dir out --proto esp -d 10.10.10.0/24 -j ACCEPT
#追記はここまで

#後略...
sudo vi /etc/ufw/sysctl.conf
/etc/ufw/sysctl.conf

#前略...
#次の行のコメントマークを解除する
net/ipv4/ip_forward=1

#中略...
#次の行の設定を確認する
net/ipv4/conf/all/accept_redirects=0

#中略...
#以下の行を追記する
net/ipv4/conf/all/send_redirects=0
net/ipv4/ip_no_pmtu_disc=1
#追記はここまで

#後略...

ufwを再起動して、設定を有効にします。

sudo ufw disable
sudo ufw enable

証明書ファイルの配置

strongSwanの設定で証明書ファイルを指定したが、これから実際に証明書ファイルをstrongSwanの証明書フォルダにコピーします。

sudo cp -f /etc/letsencrypt/live/owner203.com/fullchain.pem /etc/ipsec.d/certs/fullchain.pem
sudo cp -f /etc/letsencrypt/live/owner203.com/privkey.pem /etc/ipsec.d/private/privkey.pem

Let’s Encryptの証明書は自動更新されますが、更新された証明書ファイルが自動でstrongSwanの証明書フォルダにコピーされるよう、cronを設定します。

sudo crontab -e
/crontab

#次の行を追記する
0 4 10 * * root cp -f /etc/letsencrypt/live/owner203.com/fullchain.pem /etc/ipsec.d/certs/fullchain.pem && cp -f /etc/letsencrypt/live/owner203.com/privkey.pem /etc/ipsec.d/private/privkey.pem && ipsec rereadall

owner203は、毎月の10日午前4時に最新の証明書を自動コピーして上書きする、という設定にしました。必要に応じて数値を変更できます。

中間証明書の取得

ここまで設定をしたら、iOS、macOSとAndroidではもう接続できます。ただWindowsからの接続には、サーバーで中間証明書を入れなければなりません。サーバーで次のコマンドを実行して、中間証明書を入れます。

sudo wget https://letsencrypt.org/certs/lets-encrypt-x3-cross-signed.pem -O \
/etc/ipsec.d/cacerts/lets-encrypt-x3-cross-signed.pem

これで、iOS、Android、WindowsのクライアントはIKEv2でサーバーに接続して、サーバーのネット回線とIPアドレスを使うことができるようになりました。

クライアントの設定

iOSとmacOS

iOSとmacOSクライアントの設定はとても簡単です。新規でVPN接続を作成して必要項目を設定します。

タイプIKEv2
説明
任意
サーバ自分のドメイン
リモートID自分のドメイン
ローカルID空欄
ユーザ認証ユーザ名
ユーザ名設定したVPNユーザー名
パスワード設定したVPNパスワード

Android

Androidクライアントから接続するには、strongSwanのAppをインストールする必要があります。Google Playからダウンロードできます。ADD VPN PROFILEからVPNプロファイルを作成して、以下の項目を設定します。

Server自分のドメイン
VPN TypeIKEv2 EAP (Username/Password)
Username設定したVPNユーザー名
Password設定したVPNパスワード
Show advanced settingsチェックを入れる
IKEv2 Algorithmsaes256-sha1-modp1024

Windows

Windowsクライアントの設定は少しややこしいですが、Windows 10 Version 1809を例として説明します。

まず通常通りにVPN接続を追加します。場所は「設定」「ネットワークとインターネット」「VPN」「VPN接続を追加する」です。

VPNプロバイダーWindows (ビルドイン)
接続名任意
サーバー名またはアドレス自分のドメイン
VPNの種類IKEv2
サインイン情報の種類ユーザー名とパスワード
ユーザー名 (オプション)まだ空欄のままでいい
パスワード (オプション)まだ空欄のままでいい

次に、作成したVPN接続を編集します。「関連設定」にある「アダプターのオプションを変更する」から、先ほど作成したVPN接続で右クリックして、「プロパティ」を開きます。「セキュリティ」タブで、「データの暗号化」に「最強の暗号化 (サーバーが拒否する場合は切断します)」を選択します。「ネットワーク」タブで、「インターネット プロトコル バージョン 6 (TCP/IPv6)」のチェックを外します。「インターネット プロトコル バージョン 4 (TCP/IPv4)」を選択して、「プロパティ」をクリックします。それから「詳細設定」を開いて、「リモート ネットワークでデフォルト ゲートウェイを使う」をチェックします(これを設定しないと、WindowsクライアントはVPNサーバーのインターネット回線を使いません)。「OK」をクリックしてすべて保存して閉じます。

最後に接続します。ユーザー名とパスワードを正しく入力しても弾かれます。それからパスワードだけを要求するダイアログボックス(ユーザー名が編集不可状態)で正しいパスワードを入力して「OK」をクリックすると、今度は問題なく接続できます。