Raspberry Pi」カテゴリーアーカイブ

Linux 同士の IPv6 IPsec 接続

個人的なことだが、自宅のフレッツ回線とプロバイダがIPv6ネイティブ方式 (IPoE) に対応したため、自宅内のノードに IPv6 グローバルアドレスを割り当てられるようになった。

これを利用して、自分で借りた「さくらの VPS」(こちらも IPv6 グローバルアドレスが付与される)と自宅内サーバの間に IPv6 IPsecトンネルを作成してみる。

前提環境:
・自宅サーバ: Raspbian 9.4 + strongswan
・VPS: CentOS 7.5 + strongswan
・認証方式: X.509 証明書

ネットワーク構成図

1. 証明書の作成

myserver1 上に CA のためのディレクトリと設定を準備する。
user@myserver1:~$ sudo mkdir /etc/ssl/CA
user@myserver1:~$ sudo mkdir /etc/ssl/newcerts
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/serial"
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/crlnumber"
user@myserver1:~$ sudo touch /etc/ssl/CA/index.txt
user@myserver1:~$ sudo vi /etc/ssl/openssl.cnf

/etc/ssl/openssl.cnfの抜粋:

dir		= /etc/ssl		# Where everything is kept
database	= $dir/CA/index.txt	# database index file.
certificate	= $dir/certs/ca1.crt 	# The CA certificate
serial		= $dir/CA/serial 		# The current serial number
crlnumber	= $dir/CA/crlnumber # the current crl number
                    # must be commented out to leave a V1 CRL
crl     = $dir/crl/crl.pem
private_key	= $dir/private/ca1.key

CA 鍵・証明書を作成する。
user@myserver1:~$ sudo openssl req -new -x509 -extensions v3_ca -keyout /etc/ssl/private/ca1.key -out /etc/ssl/certs/ca1.crt -days 3652
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:CA
Common Name (e.g. server FQDN or YOUR name) []:ca1.home.example.com
Email Address []:

myserver1 の秘密鍵を作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myserver1.key 2048
Enter pass phrase for myserver1.key:********
(後でパスワードを削除するので、パスワードはここでは適当に決める)
Verifying - Enter pass phrase for myserver1.key:********

秘密鍵ファイルのパスワードを削除しておく。
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myserver1.key -out /etc/ssl/private/myserver1.key
Enter pass phrase for myserver1.key:********
writing RSA key

myserver1 の CSR を作成する。
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myserver1.key -out /etc/ssl/cert/myserver1.csr
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:Server
Common Name (e.g. server FQDN or YOUR name) []:myserver1.home.example.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CA 鍵を使って CSR に署名する。
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myserver1.csr -config /etc/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/ca.key:********
(snip)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
(snip)
Data Base Updated

CA 証明書とホスト証明書・鍵を strongswan 用に配置する。
user@myserver1:~$ sudo cp /etc/ssl/certs/ca1.crt /etc/ipsec.d/cacerts/
user@myserver1:~$ sudo cp /etc/ssl/newcerts/01.pem /etc/ipsec.d/certs/myserver1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myserver1.key /etc/ipsec.d/private/

myvps1 用の証明書も同様に作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myvps1.key 2048
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myvps1.key -out /etc/ssl/private/myvps1.key
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myvps1.key -out /etc/ssl/cert/myvps1.csr
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myvps1.csr -config /etc/ssl/openssl.cnf

いま作成した myvps1 用のホスト証明書・鍵、CA証明書を myvps1 側にコピーする。
user@myserver1:~$ cp /etc/ssl/certs/ca1.crt .
user@myserver1:~$ cp /etc/ssl/newcerts/02.pem ./myvps1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myvps1.key .
user@myserver1:~$ sudo chown user myvps1.key
user@myserver1:~$ scp ca1.crt myvps1.crt myvps1.key myvps1:

myvps1 上で証明書・鍵を配置する。
[user@myvps1 ~]$ sudo cp ca1.crt /etc/strongswan/ipsec.d/cacerts/
[user@myvps1 ~]$ sudo cp myvps1.crt /etc/strongswan/ipsec.d/certs/
[user@myvps1 ~]$ sudo cp myvps1.key /etc/strongswan/ipsec.d/private/

作業用ファイルを削除する。
[user@myvps1 ~]$ rm ca1.crt myvps1.crt myvps1.key
user@myserver1:~$ rm ca1.crt myvps1.crt myvps1.key

2. VPS 側の IPsec 設定

strongswan をインストールする。
[user@myvps1 ~]$ sudo yum install epel-release
[user@myvps1 ~]$ sudo yum install strongswan

カーネルモジュールをロードする。
strongswan公式ドキュメントを参照して、必要なモジュールがロードされていない場合は手動でロードする。
[user@myvps1 ~]$ sudo modprobe xfrm6_tunnel

設定ファイルを編集する。
[user@myvps1 ~]$ vi /etc/strongswan/ipsec.conf

conn myhome-to-vps6
        authby=rsasig
        auto=add
        closeaction=clear
        dpdaction=clear
        leftid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.example.com"
        leftsubnet=2001:db8:abcd:efab:cdef:abcd:efab:cdef/128
        leftcert=myvps1.crt
        right=%any
        rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.home.example.com"
        rightsubnet=2001:db8:1234:5678::/64
        ike=aes256-sha512-modp8192!
        esp=aes256-sha512

[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

: RSA myvps1.key

strongswanサービス起動
[user@myvps1 ~]$ sudo systemctl enable strongswan
[user@myvps1 ~]$ sudo systemctl start strongswan

3. 自宅内サーバ側の設定

strongswanをインストールする。こちらは Raspbian なので apt コマンドで。
user@myserver1:~$ sudo apt install strongswan

必要なカーネルモジュールをロードする。
user@myserver1:~$ sudo modprobe xfrm6_tunnel
user@myserver1:~$ sudo modprobe esp6

設定ファイルを編集する。
user@myserver1:~$ sudo vi /etc/ipsec.conf

conn myhome-to-vps6
        authby=rsasig
        auto=start
        closeaction=restart
        dpdaction=restart
        leftid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.home.example.com"
        leftsubnet=2001:db8:1234:5678::/64
        leftcert=myserver1.crt
        right=2001:db8:abcd:efab:cdef:abcd:efab:cdef
        rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.example.com"
        rightsubnet=2001:db8:abcd:efab:cdef:abcd:efab:cdef/128
        ike=aes256-sha512-modp8192!
        esp=aes256-sha512

user@myserver1:~$ sudo vi /etc/ipsec.secrets

: RSA myserver1.key

strongswanサービスを起動する。
user@myserver1:~$ sudo systemctl enable strongswan
user@myserver1:~$ sudo systemctl start strongswan

Raspberry Pi で OpenVPN サーバを作成 (L2VPN編)

OpenVPN と tap インターフェイスを使って、自宅に接続できるレイヤー2 (ブリッジモード) VPNを作成する。Layer2モードだと、自宅外から VPN 接続したときに bonjour や Windows ネットワーク検索のようなサービスが、自宅内と同様に使えるのがメリット。

自宅内サーバ: Raspberry Pi 2 (Raspbian 9.x stretch)
環境は以下の図の通り。

この文書の手順以外に別途、インターネット接続ルータでサービスポートを外部公開 (スタティック NAT) しておく必要がある。

クライアント側の要件として、Apple iOS 系機器は tap デバイスに対応していないため、Layer2 VPN を利用できないので本稿のターゲットから外れる。Android 系も標準 API標準クライアントでは tap に対応していない(端末の root 権限があれば対応可能。また有料ソフトウェアの OpenVPN Client は tap に対応している)。Windows 用の OpenVPN GUI、Mac の Tunnelblick などは tap デバイスに対応している。

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

OpenVPN 本体と、ブリッジ設定に必要な bridge-utils をインストールする。

$ sudo apt install openvpn bridge-utils

2. Raspbian のネットワークインターフェイスを bridge 設定にする

サーバ側の eth0 デバイスを直接使わず、ブリッジデバイス br0 を使い eth0 をそのメンバーとするように設定する。OpenVPNサーバプログラムの使う tap0 デバイスも br0 のメンバーとして、ブリッジ接続できるようにする。

サーバの IP アドレスとしては、固定アドレスを設定する(自宅内のIPアドレスをルータのDHCPに任せているなら、DHCP配布範囲外のアドレスで固定する)。

マシン起動時に自動的にブリッジデバイスが有効になるよう、interfaces ファイルを編集する。

$ sudo vi /etc/network/interfaces

auto br0
iface br0 inet static
        address 192.168.100.20
        netmask 255.255.255.0
        network 192.168.100.0
        broadcast 192.168.100.255
        gateway 192.168.100.1
        dns-nameservers 192.168.100.1
        dns-search example.com
        bridge_ports eth0

もともと eth0 だったところを br0 にして、bridge_ports eth0 を追加するように編集する。

ここで一度再起動して、br0 に IP アドレスが付くことを確認する。
$ sudo shutdown -r now

起動したら IP アドレスの状況を確認する。br0 に IP アドレスが付いていれば OK。

$ ip a
1: lo: <loopback,up,lower_up> mtu 65536 qdisc noqueue state UNKNOWN group defaul
t qlen 1000
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
       valid_lft forever preferred_lft forever
2: eth0: <broadcast,multicast,up,lower_up> mtu 1500 qdisc pfifo_fast master br0
state UP group default qlen 1000
    link/ether 00:00:5e:00:53:11 brd ff:ff:ff:ff:ff:ff
3: br0: <broadcast,multicast,up,lower_up> mtu 1500 qdisc noqueue state UP group
default qlen 1000
    link/ether 00:00:5e:00:53:fe brd ff:ff:ff:ff:ff:ff
    inet 192.168.100.20/24 brd 192.168.100.255 scope global br0
       valid_lft forever preferred_lft forever</broadcast,multicast,up,lower_up></broadcast,multicast,up,lower_up></loopback,up,lower_up>

3. OpenVPN サーバ設定

OpenVPN サーバの設定ファイルを作成する。サンプル設定ファイルをコピーして、それをベースに編集する。

$ sudo mkdir -p /var/log/openvpn /etc/openvpn/ccd
$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz /etc/openvpn/server/
$ sudo gzip -d /etc/openvpn/server/server.conf.gz
$ sudo mv /etc/openvpn/server/{server,udp7231}.conf
$ sudo vi /etc/openvpn/server/udp7231.conf

port 7231
proto udp
dev tap
ca ca.crt
cert server.crt
key server.key
dh dh2048.pem
server-bridge 192.168.100.0 255.255.255.0 192.168.100.192 192.168.100.223
push "dhcp-option DNS 192.168.100.1"
push "dhcp-option DOMAIN example.com"
client-to-client
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-CBC
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append  /var/log/openvpn/openvpn.log
verb 3
explicit-exit-notify 1
crl-verify crl.pem

dev tap 設定にするところがブリッジ方式の要になる。server-bridge 設定には、VPN クライアントに配布する IP アドレスの範囲を指定する。自宅内ルータの DHCP では、この範囲を配布対象外にしておくこと。

トランスポート層プロトコルは UDP を利用する(TCP over TCP 問題を避けるため)。利用するポートは念のため標準の 1194 から変えておくこととして、適当にランダムで決める。今回は 7231 とした。

4. サーバ証明書の準備

easy-rsa パッケージを利用して CA を作成し、サーバ証明書・鍵を作成する。CA 作業用ディレクトリとして、/etc/openvpn/easy-rsa を作成する。

$ sudo make-cadir /etc/openvpn/easy-rsa
$ sudo -i
# cd /etc/openvpn/easy-rsa
# ln -s openssl-1.0.0.cnf openssl.cnf
# vi vars

以下のような設定をvarファイルに記述する。

export KEY_SIZE=2048
export KEY_COUNTRY="JP"
export KEY_PROVINCE="Aichi"
export KEY_CITY="Nagoya"
export KEY_ORG="Home"
export KEY_EMAIL="root@raspberrypi.example.com"
export KEY_OU="Server"

CA を作成し、サーバ鍵・証明書を作成する。

# . vars
# ./clean-all
# ./build-ca
# ./build-key-server server

TLS Static Key と DH Keyを作成する。DH Keyの生成にはかなりの時間がかかる(Raspberry Piでは10分以上)

# openvpn --genkey --secret /etc/openvpn/server/ta.key
# ./build-dh
# cp -p keys/ca.crt keys/server.crt keys/server.key keys/dh2048.pem /etc/openvpn/server/
# exit

5. OpenVPN サービスの有効化と起動

サーバ側 OpenVPN サービス用の systemd ユニットファイルは /lib/systemd/system/openvpn-server@.service である。@の後に、サーバ設定ファイルのドットより前の名前(今回の場合は “udp7231″)を指定して有効化・起動する。

サービスを有効化し、起動する。
$ sudo systemctl enable openvpn-server@udp7231
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-server@udp7231.service → /lib/systemd/system/openvpn-server@.service.
$ sudo systemctl start openvpn-server@udp7231

これだけだと、ブリッジデバイス br0 に tap0 デバイスが組み込まれず、VPN クライアントと LAN との相互通信ができない。/etc/systemd 以下に追加の systemd ユニットファイルを作成して、その中で tap0 を br0 に追加する処理を行う。

$ sudo vi /etc/systemd/system/openvpn-bridge.service

[Unit]
Description=OpenVPN bridge service
Requires=openvpn-server@udp7231.service
After=openvpn-server@udp7231.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/bin/sh -c '/sbin/brctl addbr br0 || /bin/true'
ExecStartPost=/bin/sh -c '/sbin/brctl addif br0 tap0 || /bin/true'
ExecStartPost=/sbin/ip link set tap0 up
ExecReload=/bin/true
ExecStop=/sbin/brctl delif br0 tap0

[Install]
WantedBy=multi-user.target

brctl addbr br0 の行は本来必要ないはず(br0 の立ち上げは /etc/network/interfaces に書いてあれば自動的に実行される)なのだが、タイミングの問題で openvpn サービス起動時にまだ br0 が無い場合があり、次の行の brctl addif br0 tap0 に失敗することがあるため、念のため加えている。

上記で作成した自作サービスを起動する。
$ sudo systemctl enable openvpn-bridge
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-bridge.service → /etc/systemd/system/openvpn-bridge.service.
$ sudo systemctl start openvpn-bridge

6. iptables 設定

ローカルファイアウォール設定で、OpenVPN の利用するポートを開けておく。

iptables の設定に iptables-persistent パッケージを利用している場合は、/etc/iptables/rules.v4 を編集して以下の行を加える。

-A INPUT -p udp -m udp --dport 7231 -j ACCEPT

設定を再読み込みする。
$ sudo netfilter-persistent reload

もしiptables直接ではなくufwを使っているのであれば、以下のコマンドでサービスポートを開ける。
$ sudo ufw allow 7231/udp
$ sudo ufw reload

ブリッジ設定の場合、パケットフォワーディングの設定(sysctl -w net.ipv4.ip_forward=1)は不要。

7. クライアント側設定テンプレートの作成

設定を複数のクライアントに配布するため、元となるテンプレートファイルを作成する。

$ sudo cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/client/client.template
$ sudo vi /etc/openvpn/client/client.template

client
dev tap
proto udp
remote 203.0.113.10 7231
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
key-direction 1
cipher AES-256-CBC
verb 3
<tls-auth>
ここに /etc/openvpn/server/ta.key ファイルの内容をペーストする。
</tls-auth>
<ca>
ここに /etc/openvpn/server/ca.crt ファイルの内容をペーストする。
</ca>
<key>
</key>
<cert>
</cert>

証明書・鍵ファイル等を別ファイルの形で配布しても良いが、設定ファイルの中に取り込む形にしてみる。設定を単一ファイルで配布できれば取り回しが良いため。

8. クライアント証明書の発行と設定ファイルの作成

テストクライアント用の設定を作成して、動作検証してみる。

まず、1番目のクライアント鍵・証明書 (client1と命名) を発行する。

$ sudo -i
# cd /etc/openvpn/easy-rsa
# . vars
# ./build-key client1
# exit

クライアント1のための設定ファイル (client1.ovpn) をテンプレートから作成する。

$ sudo cp /etc/openvpn/client/{client.template,client1.ovpn}
$ sudo vi /etc/openvpn/client/client1.ovpn

client1.ovpn ファイルの中の <cert>, <key> 各セクションの中に、作成したクライアント証明書 (client1.crt) と鍵 (client1.key) ファイルの内容をコピー&ペーストする。

作成した /etc/openvpn/client/client1.ovpn ファイルを配布して、クライアントデバイスにインストールして接続確認する。

接続成功するようなら、client2、client3、…と設定ファイルを同様に作成していく。

9. クライアント証明書の失効手続き

クライアントを使わなくなったら、証明書を失効させておく。client1を失効させるためには、以下のコマンドを実行する。

$ sudo -i
# cd /etc/openvpn/easy-rsa
# . vars
# ./revoke-all client1

Raspberry Pi 2にRaspbian jessieをインストール

注意

これは古い記事です。Raspbianの配布元からjessieが配布されるようになりました(2015/9現在)ので、そちらを使ってください。

1. 準備

OSイメージをダウンロードし、microSDカードに書き込む(以下はMac OS Xで作業した場合の手順)

$ unzip 2015-05-05-raspbian-wheezy.zip
$ sudo dd if=2015-05-05-raspbian-wheezy.img of=/dev/disk2 bs=4m

2. 起動直後の設定

USBキーボード、HDMIでモニタを接続して、さきほど書き込んだSDカードをRaspberry Piにさしかえて起動する。コンソール上でraspi-configが起動したら、以下の設定を実行する。

・Expand Filesystem
・Internationalisation Options -> Change Locale -> ja_JP.UTF-8 -> Default Locale -> ja_JP.UTF-8
・Internationalisation Options -> Change Timezone -> Asia -> Tokyo
・Internationalisation Options -> Change Keyboard Layout -> Generic 105-Key(Intel) PC -> Other ->  Japanese 
・Advanced Options -> SSH -> Enable

その後、raspi-config終了を選択すると、システム再起動がかかる。

piユーザでコンソールログインし、rootでのsshログインができるようパスワードを設定しておく(OSバージョンアップの際にroot権限で実行するため)。

pi$ sudo passwd root

ここからはネットワークで作業する。sshでログインしてみる。

$ ssh root@rasberrypi

OSバージョンアップ(wheezy->jessie)

OSバージョンアップのため、aptのsource行をjessieに書き換える。またjessieに対応していない行は使えないようにする。

# vi /etc/apt/sources.list
wheezy -> jessie
# cd /etc/apt/sources.list.d
# for i in *.list; do mv $i $i.orig; done

OSバージョンアップを実施する。

# apt-get update
# apt-get upgrade
# apt-get dist-upgrade

途中、「root での SSH パスワード認証を無効にしますか?」と聞かれるので「いいえ」を選択する。

パッケージアップデートが終了したら、必要ないパッケージをアンインストールして再起動する。

# apt-get autoremove
# shutdown -r now

初期設定・その他

さきほど有効化してしまった、rootでのsshログインを無効化する。

$ sudo vi /etc/ssh/sshd_config
PermitRootLogin no

自分に必要なユーティリティの類をインストールしておく。

$ sudo apt-get install dnsutils heirloom-mailx mlocate screen vim

Xが起動しないようにする。

$ sudo systemctl disable lightdm.service
$ sudo systemctl disable display-manager.service
$ sudo shutdown -r now

Raspberry Pi 2はARMv7になったんだし、慣れてるUbuntu入れるのが一番いいような気もするが…

Raspbianにstrongswan 5.xをインストール

Raspberry Pi model B+ を購入して VPN 箱にしようとしたが、Raspbian OS標準のstrongswan パッケージ (=debian wheezyのパッケージ) があまりに古い (4.5.2) ので、ソースから 5.x をインストールすることにする。

1. 標準パッケージのstrongswanをアンインストール

アンインインストールする前に、起動スクリプトをバックアップしておく。

$ sudo cp /etc/init.d/ipsec /tmp

その上で、標準のstrongswanをアンインストールする。

$ sudo apt-get purge libstrongswan strongswan \
strongswan-ikev1 strongswan-ikev2 strongswan-starter

2. ビルドに必要なパッケージをインストール

$ sudo apt-get install build-essential

3. 必要そうなライブラリをインストール

$ sudo apt-get install libgmp-dev libldap2-dev \
libcurl4-openssl-dev libpam0g-dev libkrb5-dev \
libfcgi-dev libgcrypt11-dev libxml2-dev libsqlite3-dev \
libcap-dev libldns-dev libunbound-dev libsoup2.4-dev \
libtspi-dev libjson0-dev libmysqlclient-dev libpcsclite-dev

4. ビルド・インストール

wheezy-backportsパッケージのrulesファイルを参考にしてconfigureオプションを決定する。インストール先が/usr/localではなくなるけど、まあいいでしょう…
$ wget https://download.strongswan.org/strongswan-5.2.2.tar.bz2
$ tar xjf strongswan-5.2.2.tar.bz2
$ cd strongswan-5.2.2
$ ./configure \
--disable-static \
--prefix=/usr \
--exec-prefix=/usr \
--sysconfdir=/etc \
--localstatedir=/var \
--libdir=/usr/lib \
--libexecdir=/usr/lib \
--with-tss=trousers \
--enable-addrblock \
--enable-agent \
--enable-attr-sql \
--enable-ccm \
--enable-certexpire \
--enable-cmd \
--enable-coupling \
--enable-ctr \
--enable-curl \
--enable-dhcp \
--enable-dnscert \
--enable-duplicheck \
--enable-eap-aka \
--enable-eap-aka-3gpp2 \
--enable-eap-dynamic \
--enable-eap-gtc \
--enable-eap-identity \
--enable-eap-md5 \
--enable-eap-mschapv2 \
--enable-eap-peap \
--enable-eap-radius \
--enable-eap-sim \
--enable-eap-sim-file \
--enable-eap-sim-pcsc \
--enable-eap-simaka-pseudonym \
--enable-eap-simaka-reauth \
--enable-eap-simaka-sql \
--enable-eap-tls \
--enable-eap-tnc \
--enable-eap-ttls \
--enable-error-notify \
--enable-farp \
--enable-gcm \
--enable-gcrypt \
--enable-imc-attestation \
--enable-imc-os \
--enable-imc-scanner \
--enable-imc-swid \
--enable-imc-test \
--enable-imv-attestation \
--enable-imv-os \
--enable-imv-scanner \
--enable-imv-swid \
--enable-imv-test \
--enable-integrity-test \
--enable-ipseckey \
--enable-ldap \
--enable-led \
--enable-load-tester \
--enable-lookip \
--enable-md4 \
--enable-mysql \
--enable-ntru \
--enable-openssl \
--enable-pkcs11 \
--enable-radattr \
--enable-soup \
--enable-sql \
--enable-sqlite \
--enable-systime-fix \
--enable-test-vectors \
--enable-tnccs-11 \
--enable-tnccs-20 \
--enable-tnccs-dynamic \
--enable-tnc-ifmap \
--enable-tnc-imc \
--enable-tnc-imv \
--enable-tnc-pdp \
--enable-unbound \
--enable-unity \
--enable-whitelist \
--enable-xauth-eap \
--enable-xauth-generic \
--enable-xauth-noauth \
--enable-xauth-pam \
--disable-blowfish \
--disable-des \
--with-capabilities=libcap
$ make
$ sudo make install

さすがにCPUの能力が低いので、ビルドには時間がかかる。

最初にコピーしておいた起動スクリプトを戻す。
$ sudo mv /tmp/ipsec /etc/init.d/
$ sudo update-rc.d ipsec defaults

自宅-VPS間でIPsec (strongswan X.509証明書認証)

前の記事と同じ構成で、認証に証明書を導入してみた。

ネットワーク構成は前の記事と同じで、以下の図のようになる。

前提:
・VPS の OS は CentOS 7.5、自宅側サーバは Raspbian 9.4 である。
・IPsec 実装には strongswan を利用する。
・証明書作成にはOpenSSLを使い、PEM ファイルの形で管理する。
・自宅側のIPsec端点 (ホスト名:myserver1) と同一のサーバに CA を作成しておき、この CA 上で両側の端点用の証明書を発行する。

1. strongswan インストール

user@myserver1:~$ sudo apt-get install strongswan
[user@myvps1 ~]$ sudo yum install epel-release
[user@myvps1 ~]$ sudo yum install strongswan

カーネルパラメータは前々回の記事と同一の設定をしておく。

自宅内サーバ側の設定。
user@myserver1:~$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #28行目のコメントを外す

user@myserver1:~$ sudo sysctl -p /etc/sysctl.conf

VPS の方にも同じ設定を実施する。
[user@myvps1 ~]$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #追記する

[user@myvps1 ~]$ sudo sysctl -p /etc/sysctl.conf

ファイアウォール(ufw)を閉じている場合は、UDP 500 と 4500 を空けておくこと。

2. 証明書の作成

myserver1 上に CA のためのディレクトリと設定を準備する。
user@myserver1:~$ sudo mkdir /etc/ssl/CA
user@myserver1:~$ sudo mkdir /etc/ssl/newcerts
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/serial"
user@myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/crlnumber"
user@myserver1:~$ sudo touch /etc/ssl/CA/index.txt
user@myserver1:~$ sudo vi /etc/ssl/openssl.cnf

/etc/ssl/openssl.cnfの抜粋:

dir		= /etc/ssl		# Where everything is kept
database	= $dir/CA/index.txt	# database index file.
certificate	= $dir/certs/ca1.crt 	# The CA certificate
serial		= $dir/CA/serial 		# The current serial number
crlnumber	= $dir/CA/crlnumber # the current crl number
                    # must be commented out to leave a V1 CRL
crl     = $dir/crl/crl.pem
private_key	= $dir/private/ca1.key

CA 鍵・証明書を作成する。
user@myserver1:~$ sudo openssl req -new -x509 -extensions v3_ca -keyout /etc/ssl/private/ca1.key -out /etc/ssl/certs/ca1.crt -days 3652
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:CA
Common Name (e.g. server FQDN or YOUR name) []:ca1.home.example.com
Email Address []:

myserver1 の秘密鍵を作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myserver1.key 2048
Enter pass phrase for myserver1.key:********
(後でパスワードを削除するので、パスワードはここでは適当に決める)
Verifying - Enter pass phrase for myserver1.key:********

秘密鍵ファイルのパスワードを削除しておく。
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myserver1.key -out /etc/ssl/private/myserver1.key
Enter pass phrase for myserver1.key:********
writing RSA key

myserver1 の CSR を作成する。
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myserver1.key -out /etc/ssl/cert/myserver1.csr
(snip)
Country Name (2 letter code) [AU]:JP
State or Province Name (full name) [Some-State]:Aichi
Locality Name (eg, city) []:Nagoya
Organization Name (eg, company) [Internet Widgits Pty Ltd]:Home
Organizational Unit Name (eg, section) []:Server
Common Name (e.g. server FQDN or YOUR name) []:myserver1.home.example.com
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

CA 鍵を使って CSR に署名する。
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myserver1.csr -config /etc/ssl/openssl.cnf
Enter pass phrase for /etc/ssl/private/ca.key:********
(snip)
Sign the certificate? [y/n]:y
1 out of 1 certificate requests certified, commit? [y/n]y
(snip)
Data Base Updated

CA 証明書とホスト証明書・鍵を strongswan 用に配置する。
user@myserver1:~$ sudo cp /etc/ssl/certs/ca1.crt /etc/ipsec.d/cacerts/
user@myserver1:~$ sudo cp /etc/ssl/newcerts/01.pem /etc/ipsec.d/certs/myserver1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myserver1.key /etc/ipsec.d/private/

myvps1 用の証明書も同様に作成する。
user@myserver1:~$ openssl genrsa -aes256 -out /etc/ssl/private/myvps1.key 2048
user@myserver1:~$ openssl rsa -in /etc/ssl/private/myvps1.key -out /etc/ssl/private/myvps1.key
user@myserver1:~$ openssl req -new -days 1826 -key /etc/ssl/private/myvps1.key -out /etc/ssl/cert/myvps1.csr
user@myserver1:~$ sudo openssl ca -in /etc/ssl/cert/myvps1.csr -config /etc/ssl/openssl.cnf

いま作成した myvps1 用のホスト証明書・鍵、CA証明書を myvps1 側にコピーする。
user@myserver1:~$ cp /etc/ssl/certs/ca1.crt .
user@myserver1:~$ cp /etc/ssl/newcerts/02.pem ./myvps1.crt
user@myserver1:~$ sudo cp /etc/ssl/private/myvps1.key .
user@myserver1:~$ sudo chown user myvps1.key
user@myserver1:~$ scp ca1.crt myvps1.crt myvps1.key myvps1:

myvps1 上で証明書・鍵を配置する。
[user@myvps1 ~]$ sudo cp ca1.crt /etc/strongswan/ipsec.d/cacerts/
[user@myvps1 ~]$ sudo cp myvps1.crt /etc/strongswan/ipsec.d/certs/
[user@myvps1 ~]$ sudo cp myvps1.key /etc/strongswan/ipsec.d/private/

作業用ファイルを削除する。
[user@myvps1 ~]$ rm ca1.crt myvps1.crt myvps1.key
user@myserver1:~$ rm ca1.crt myvps1.crt myvps1.key

3. strongswan の設定 (myserver1側)

設定ファイルを編集する。
user@myserver1:~$ sudo vi /etc/ipsec.conf

config setup セクションの後に以下の内容を追加する。

conn myhome-to-vps
	authby=rsasig
	auto=start
	closeaction=restart
	dpdaction=restart
	left=192.168.100.240
	leftsubnet=192.168.100.0/24
	leftcert=myserver1.crt
	right=203.0.113.180
	rightsubnet=203.0.113.180/32
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myvps1.vpsnet.example.com"

こちら側から接続を開始するため、auto=start を記述する。また接続が切れたときにはこちら側から再接続を実行するため、closeaction=restart と dpdaction=restart を記述する。

パスワードファイルには秘密鍵のファイル名を記述する。
user@myserver1:~$ sudo vi /etc/ipsec.secrets

: RSA myserver1.key

4. strongswan の設定 (myvps1側)

こちらも設定ファイルを編集する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.conf

以下の内容を追加する。

conn myhome-to-vps
	authby=rsasig
	auto=add
	closeaction=clear
	dpdaction=clear
	left=203.0.113.180
	leftsubnet=203.0.113.180/32
	leftcert=myvps1.crt
	right=%any
	rightsubnet=192.168.100.0/24
	rightid="C=JP, ST=Aichi, O=Home, OU=Server, CN=myserver1.home.example.com"

パスワードファイルには秘密鍵のファイル名を記述する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

: RSA myvps1.key

5. サービス起動と確認

サービスを起動する。

user@myserver1:~$ sudo service strongswan start
[user@myvps1 ~]$ sudo service strongswan start

接続できたかどうか、ip xfrm state コマンドで確認する。

user@myserver1:~$ sudo ip xfrm state
src 192.168.100.240 dst 203.0.113.180
	proto esp spi 0xbaef12dc reqid 1 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0x6bde34f03f729b5a3c1d93c112ea6a40bf312742 96
	enc cbc(aes) 0x4f2fa3876e41e825be32a4e710a5f193
	encap type espinudp sport 4500 dport 4500 addr 0.0.0.0
src 203.0.113.180 dst 192.168.100.240
	proto esp spi 0xbb4b32e0 reqid 1 mode tunnel
	replay-window 32 flag af-unspec
	auth-trunc hmac(sha1) 0x44b52fad2bf912e10b61706add1337f823ec344e 96
	enc cbc(aes) 0xaf32405118ac467efb02f5f76e59aad1
	encap type espinudp sport 4500 dport 4500 addr 0.0.0.0

自宅-VPS間でIPsec (strongswan)

自宅(動的IPアドレス)とVPS(固定IPアドレス)の間で、IPsec トンネルを常時接続してみる。これには、自宅のIPアドレスが変わっても、VPS 経由で自宅に入れるというメリットがある。

ネットワーク図

VPS の OS: CentOS 7.5
自宅サーバのOS: Raspbian 9.4 (Raspberry Pi)
IPsec ソフトウェア: strongswan

1. VPS 側

strongswan をインストールする。
[user@myvps1 ~]$ sudo yum install epel-release
[user@myvps1 ~]$ sudo yum install strongswan

通過パケットを転送できるように、カーネルパラメータを変更する。
[user@myvps1 ~]$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #追記する

[user@myvps1 ~]$ sudo sysctl -p /etc/sysctl.conf

ipsec.conf を編集する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.conf

conn myhome-to-vps
        authby=secret
        auto=add
        closeaction=clear
        dpdaction=clear
        left=203.0.113.180
        leftsubnet=203.0.113.180/32
        right=%any		#相手側IPアドレスは不明なので%anyにしておく
        rightsubnet=192.168.100.0/24

事前共有鍵を設定する。
[user@myvps1 ~]$ sudo vi /etc/strongswan/ipsec.secrets

: PSK "mypresharedkey"

サービスを起動する。
[user@myvps1 ~]$ sudo systemctl enable strongswan
[user@myvps1 ~]$ sudo systemctl start strongswan

2. 自宅側

strongswan をインストールする。
user@myserver1:~$ sudo apt install strongswan

通過パケットを転送できるように、カーネルパラメータを変更する。
user@myserver1:~$ sudo vi /etc/sysctl.conf

net.ipv4.ip_forward=1  #28行目のコメントを外す

user@myserver1:~$ sudo sysctl -p /etc/sysctl.conf

ipsec.conf を編集する。
user@myserver1:~$ sudo vi /etc/ipsec.conf

conn myhome-to-vps
        authby=secret
        auto=start		#自動的にこちらから接続する
        closeaction=restart
        dpdaction=restart
        left=192.168.100.240
        leftsubnet=192.168.100.0/24
        right=203.0.113.180
        rightsubnet=203.0.113.180/32

VPS 側と同じ事前共有鍵を設定する。
user@myserver1:~$ sudo vi /etc/ipsec.secrets

: PSK "mypresharedkey"

サービスを起動する。
user@myserver1:~$ sudo systemctl enable strongswan
user@myserver1:~$ sudo systemctl start strongswan

以上の設定で接続できる。NAPT を越えることが自動的に検出されて、IPsec パケットは NAT-Traversal でカプセル化される。iptables で UDP 4500 が閉じられている場合は、ACCEPT するように変更しておく。