カテゴリー別アーカイブ: ネットワーク

ネットワーク技術に関すること

Linux 同士の IPv6 IPsec 接続

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

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

前提環境:
自宅サーバ: Raspbian stretch + strongswan
自宅内グローバルIPv6アドレス範囲: 2001:db8:1234:5678::/64
自宅サーバIPv6アドレス: 2001:db8:1234:5678:9012:3456:7890:1234
VPS: CentOS 7.4 + strongswan
VPS グローバル IPv6 アドレス: 2001:db8:abcd:efab:cdef:abcd:efab:cdef
認証方式: X.509 証明書

1. 証明書の作成

オレオレ CA を作成して証明書を発行する。IPv4で構築した時の記事を参照のこと。

2. VPS 側の設定

strongswan をインストールする。

$ sudo yum install epel-release
$ sudo yum install strongswan

カーネルモジュールをロードする。
strongswan公式ドキュメントを参照して、必要なモジュールがロードされていない場合は手動でロードする。

$ sudo modprobe xfrm6_tunnel

設定ファイル
/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.jp"
        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.example.com"
        rightsubnet=2001:db8:1234:5678::/64
        ike=aes256-sha512-modp8192!
        esp=aes256-sha512
        keyexchange=ikev2

/etc/strongswan/ipsec.secrets:

: RSA myvps1.key

strongswanサービス起動

$ sudo systemctl enable strongswan
$ sudo systemctl start strongswan

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

strongswanをインストールする。こちらは Raspbian なので apt コマンドで。

$ sudo apt install strongswan

必要なカーネルモジュールをロードする。

$ sudo modprobe xfrm6_tunnel
$ sudo modprobe esp6

設定ファイル
/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.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.jp"
        rightsubnet=2001:db8:abcd:efab:cdef:abcd:efab:cdef/128
        ike=aes256-sha512-modp8192!
        esp=aes256-sha512
        keyexchange=ikev2

/etc/ipsec.secrets:

: RSA myserver1.key

strongswanサービスを起動する。

$ sudo systemctl enable strongswan
$ sudo systemctl start strongswan

OpenVPN で L2VPN を作成する

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

サーバ: Raspberry Pi 2 (Raspbian 9.0 stretch)
環境は以下の図の通り。

この文書の手順以外に別途、外部接続ルータでサービスポートを外部公開しておく必要がある。

Apple iOS系デバイスはtapに対応していないため、Layer2 VPNを利用できないので注意。Android系もroot権限なしの標準APIとそれを利用する標準クライアントではtapに対応していない(有料ソフトウェアのOpenVPN Clientはtapに対応している)。

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

$ sudo apt install openvpn bridge-utils

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

eth0デバイスを直接使わず、ブリッジデバイスbr0を使ってeth0をそのメンバーとするように設定する。IPアドレスはDHCP範囲外の固定IPアドレスを利用することとする。

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 home.private
        bridge_ports eth0

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

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

3. サーバ設定

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
client-config-dir ccd
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-SEARCH home.private"
client-to-client
keepalive 10 120
tls-auth ta.key 0
cipher AES-256-CBC
comp-lzo
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log-append  /var/log/openvpn/openvpn.log
verb 3

トランスポート層プロトコルは 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.home.private"
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 である。@の後にサーバ側 conf ファイルのドットより前の名前(今回の場合は “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

これだけだと、ブリッジデバイスに tap0 デバイスが組み込まれず、通信できない。/etc/systemd 以下に追加の systemd ユニットファイルを作成し、tap0 デバイスをブリッジに追加する。

$ 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
comp-lzo
<tls-auth>
ここに/etc/openvpn/server/ta.keyファイルの内容をペーストする。
</tls-auth>
<ca>
ここに/etc/openvpn/server/ca.crtファイルの内容をペーストする。
</ca>
<key>
</key>
<cert>
</cert>

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

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

まず1番目のクライアント用の鍵・証明書を発行する。

$ 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、…と設定ファイルを同様に作成していく。

openswan vs strongswan vs libreswan

IPsec の実装として、openswan / strongswan / libreswan どれを使えばいいの?というお話。

どの実装もかつてのFreeS/WAN IPsecの末裔であって、似た設定で動作するのだけど微妙に書式が違う、というやっかいなことになっている。

openswan:
もうメンテされていない古い実装。Ubuntu 18.04 LTS も CentOS 7 もパッケージを用意していないので、あえて使う理由がない。
libreswan:
openswanのフォークで、現状メンテされている。RedHat/CentOS系は標準パッケージで用意されている。Debian/Ubuntu系にはパッケージなし。
strongswan:
ご先祖から大幅に書き直されたもの。Debian/Ubuntu系OSの場合は標準パッケージで用意されている。RedHat/CentOS系はepelレポジトリに入っている。

Fedora の場合は strongswan / libreswan どちらもパッケージが用意されている。

ということで、openswan は使わないものとして、あとは OS によってパッケージがある方を選んでおけば良いのではないか。

※2018/04/12追記: メジャーなディストリビューションのうち、現時点で Debian 9.x (stretch) についてはまだ libreswan パッケージが無く、openswan が残っている。Debian stretch の場合は、strongswan を使っておくのが良いだろう。

参考:
IPsec for Linux – strongSwan vs Openswan vs Libreswan vs other(?)

DNSSEC ルートゾーン KSK ロールオーバーについて

DNSSECのルートゾーンKSKロールオーバーについて、ロールオーバー前後でDNSの検索に支障が出ないよう、各所から通達が出ている。

ルートゾーンKSKロールオーバーによる影響とその確認方法について (JPRS)
KSKロールオーバーについて (JPNIC)

(2017/10月予定だった切り替えが延期され、現在は 2018/10/11 に予定されています)

1. 管理下の DNS キャッシュは DNSSEC 検証をしているか

DNS キャッシュサーバーを管理している場合は、一応気を付けたほうが良い。管理下の DNS キャッシュサーバーに対して、dig コマンドでDNSSEC 対応済みドメイン (例: jprs.jp) の情報を検索したときに、回答に ad フラグが付いていたら「キャッシュサーバーでDNSSEC署名検証が有効になっている」状態なので、更新後の鍵を設定してやる必要があるかもしれない。

adフラグが付いている例:

$ dig jprs.jp. @mydns.example.com

; <<>> DiG 9.10.3-P4-Ubuntu <<>> jprs.jp.
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 26772
;; flags: qr rd ra ad; QUERY: 1, ANSWER: 1, AUTHORITY: 4, ADDITIONAL: 9
...

(参考: DNSSECチュートリアル~実践編~)

2. RHEL 7 / CentOS 7 + BIND の場合

named.confにデフォルトで以下の設定が入っていて、DNSSEC署名検証が有効になっている。

options {
...
        dnssec-enable yes;
        dnssec-validation yes;

        /* Path to ISC DLV key */
        bindkeys-file "/etc/named.iscdlv.key";

        managed-keys-directory "/var/named/dynamic";
...
};
...
include "/etc/named.root.key";

対処法1. パッケージアップデート

/etc/named.iscdlv.key と /etc/named.root.key に、ルートゾーンの鍵が入っている。パッケージバージョンがbind-9.9.4-38.4以降であれば、上記2ファイルに新しい鍵が追加されるので、bindのパッケージをアップデートしてしまうのが一番手っ取り早く安心できる方法ではある。

対処法2. 自動更新に任せる

9.9.4-38.3以前のパッケージを使っている場合でも、RFC5011 の自動更新に対応している。named を起動すると更新後の鍵は /var/named/dynamic/managed-keys.bind{,.jnl} として自動保存される。このため、特に何かをする必要はない。

# とはいえ、CVE-2017-3142、CVE-2017-3143への対処が9.9.4-38.5以降で行われているので、パッケージを更新した方が良い。

3. RHEL 7 / CentOS 7 + Unbound の場合

デフォルトの /var/lib/unbound/root.key には古い鍵しか入っていないが、/etc/unbound/unbound.conf に以下の記述があり、自動更新が有効になっている。

server:
...
        auto-trust-anchor-file: "/var/lib/unbound/root.key"
...

unbound のデーモンを起動すると、/var/lib/unbound/root.key に新しい鍵が追加される。

このため、これらの設定を変更していなければ、特に対処の必要はない。

4. 確認、その他

EDNS0を無効化していないこと、経路上でTCP53が通ること、フラグメントパケットが通ることも確認しておく。

大きなサイズの DNS 応答に対応できているかどうかは、DNS-OARCが確認用のレコードを用意してくれているので、以下の dig コマンドで確認できる。

$ dig +bufsize=4096 +short rs.dns-oarc.net txt

非対応のキャッシュサーバだと、以下のような回答が返ってくる。

rst.x476.rs.dns-oarc.net.
rst.x485.x476.rs.dns-oarc.net.
rst.x490.x485.x476.rs.dns-oarc.net.
"203.0.113.1 DNS reply size limit is at least 490"
"203.0.113.1 lacks EDNS, defaults to 512"
"Tested at 2017-08-31 01:19:47 UTC"

さくらのVPS上のUbuntuでIPv6

IPv6アドレスの設定方法 | さくらのVPS | さくらインターネット公式サポートサイト
CentOSをそのまま使っているなら上記の通りなんだけど、Ubuntuに入れ換えている場合のメモ。

1. VPSホームにログインして、自分のVPSに割り当てられたIPv6グローバルアドレスを調べる。

2. Ubuntuにログインして/etc/network/interfacesを編集。

iface eth0 inet6 static
	address 2001:db8:ffff:ffff:203:0:113:15
	netmask 64
	gateway fe80::1

3. ifdown; ifup で行けると思うけど、念のため再起動。

iOS/Android 端末からの L2TP/IPsec 接続 (strongswan+xl2tpd)

iOSやAndroid端末、あるいは Windows PC などからもリモートアクセスできるよう、VPS マシンに VPN 接続を設定しておく。

PPTPについては既に脆弱性が発見されており、OSによってはサポート対象外になっているため、VPN プロトコルとしては L2TP/IPsec を使う。

前提:
対象サーバはVPSのUbuntu 14.04。

IPsec 実装としては strongswan、L2TP 実装としては xl2tpd を利用する。

ネットワーク図は以下の通り。
05

1. インストール

myvps1:~$ sudo apt-get install strongswan xl2tpd

カーネルパラメータをパケット転送できるよう設定する。

myvps1:~$ sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1  #28行目のコメントを外す
# 以下、追記する
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.eth0.accept_redirects=0
net.ipv4.conf.eth0.send_redirects=0
net.ipv4.conf.lo.accept_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv6.conf.eth0.accept_redirects=0
net.ipv6.conf.lo.accept_redirects=0
myvps1:~$ sudo sysctl -p /etc/sysctl.conf

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

2. ipsec.confの設定

myvps1:~$ sudo vi /etc/ipsec.conf

以下の内容を追記する。

conn L2TP-PSK
        authby=secret
        auto=add
        closeaction=clear
        dpdaction=clear
        type=transport
        rekey=no
        left=203.0.113.180
        leftprotoport=17/1701
        right=%any
        rightprotoport=17/%any

IPsec はトランスポートモードを使用する。ペイロードに L2TP を通すので、ルーティングはそちらに任せる。

再接続等はクライアント側に任せたいため、こちらからは何もしない設定である。接続が切れた場合はセッションをクリアする。

3. IPsecの事前共有鍵の設定

myvps1:~$ sudo vi /etc/ipsec.secrets

事前共有鍵を平文で記述する。

: PSK "mypresharedkey"

4. xl2tpd.conf の設定

myvps1:~$ sudo vi /etc/xl2tpd/xl2tpd.conf

以下の設定を追記する。

[global]
port = 1701

[lns default]
ip range = 172.16.1.11-172.16.1.30
local ip = 172.16.1.254
length bit = yes
require chap = yes
refuse pap = yes
require authentication = yes
name = myvps1.vpsnet.example.jp
ppp debug = no
pppoptfile = /etc/ppp/xl2tpd-options

接続クライアント側には、172.16.1.11 から 30 の間でアドレスが割り振られる。

5. xl2tpd-options の設定

myvps1:~$ sudo vi /etc/ppp/xl2tpd-options

L2TPの設定を記述する。

ipcp-accept-local
ipcp-accept-remote
ms-dns 172.16.1.254  (myvps1:172.16.1.254にキャッシュDNSサーバが立っている前提)
noccp
auth
crtscts
idle 1800
mtu 1300
mru 1300
nodefaultroute
lock
connect-delay 5000
refuse-pap
refuse-chap
refuse-mschap
require-mschap-v2

6. chap-secrets の設定

myvps1:~$ sudo vi /etc/ppp/chap-secrets
username	*	"l2tppassworddesu"	*

一般ユーザで読めない権限にしておく。

7. デーモンの起動

myvps1:~$ sudo service strongswan restart
myvps1:~$ sudo service xl2tpd restart

この状態で、iPhoneなどから接続してみる。
iPhoneであれば「設定」→「VPN」→「VPN構成を追加…」で「L2TP」を選択して設定を追加する。
サーバ欄にはVPSのホスト名(IPアドレス)、アカウントにはL2TPユーザ名、パスワードにはL2TPパスワード、シークレットにはIPsec事前共有鍵を設定する。

クライアント機器が、公衆無線LANなどのプライベートネットワーク中に居る状態も想定しなければならない。その場合は NAT-Traversal を使うことになるが、Ubuntu 14.04 の strongswan は標準でNAT-Traversal を自動検出してくれるようなので、特別な設定をしなくても接続できる (ただし、UDP 4500番ポートについてファイアウォールが空いている必要はある)。

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

IPsecトンネルの認証に証明書認証を導入する検証を実施してみたが、Ubuntu 14.04 標準パッケージの openswan では trusted_ca returning with failed というエラーが出てうまくいかなかった。

strongswan で試したところ成功したので、この設定を以下に説明する。(strongswanとopenswanの比較はこちら)

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

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

1. strongswan インストール

myserver1:~$ sudo apt-get purge openswan
myserver1:~$ sudo apt-get install strongswan
myvps1:~$ sudo apt-get purge openswan
myvps1:~$ sudo apt-get install strongswan

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

vpn1:~$ sudo vi /etc/sysctl.conf
net.ipv4.ip_forward=1  #28行目のコメントを外す
# 以下、追記する
net.ipv4.conf.default.send_redirects=0
net.ipv4.conf.all.send_redirects=0
net.ipv4.conf.eth0.accept_redirects=0
net.ipv4.conf.eth0.send_redirects=0
net.ipv4.conf.lo.accept_redirects=0
net.ipv4.conf.lo.send_redirects=0
net.ipv6.conf.eth0.accept_redirects=0
net.ipv6.conf.lo.accept_redirects=0
vpn1:~$ sudo sysctl -p /etc/sysctl.conf

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

2. myserver1上にCAのためのディレクトリと設定を準備する

myserver1:~$ sudo mkdir /etc/ssl/CA
myserver1:~$ sudo mkdir /etc/ssl/newcerts
myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/serial"
myserver1:~$ sudo sh -c "echo '01' > /etc/ssl/CA/crlnumber"
myserver1:~$ sudo touch /etc/ssl/CA/index.txt
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

3. CAの証明書・鍵を作成する

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
Email Address []:

4. myserver1ホストの秘密鍵を作成する

myserver1:~$ openssl genrsa -aes256 -out myserver1.key 2048
Enter pass phrase for myserver1.key:********
(後でパスワードを削除するので、パスワードはここでは適当に決める)
Verifying - Enter pass phrase for myserver1.key:********

秘密鍵ファイルのパスワードを削除しておく

myserver1:~$ openssl rsa -in myserver1.key -out myserver1.key
Enter pass phrase for myserver1.key:********
writing RSA key

5. CSRを作成する

myserver1:~$ openssl req -new -days 1826 -key myserver1.key -out 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
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:

6. CA鍵を使って署名する

myserver1:~$ sudo openssl ca -in 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

7. CA証明書とホスト証明書・鍵を /etc/ipsec.d にコピーしておく

myserver1:~$ sudo cp -p /etc/ssl/certs/ca1.crt /etc/ipsec.d/cacerts/
myserver1:~$ sudo cp -p /etc/ssl/newcerts/01.pem /etc/ipsec.d/certs/myserver1.crt
myserver1:~$ sudo cp myserver1.key /etc/ipsec.d/private/

8. myvps1用の証明書も同様に作成する

myserver1:~$ openssl genrsa -aes256 -out myvps1.key 2048
myserver1:~$ openssl rsa -in myvps1.key -out myvps1.key
myserver1:~$ openssl req -new -days 1826 -key myvps1.key -out myvps1.csr
myserver1:~$ sudo openssl ca -in myvps1.csr -config /etc/ssl/openssl.cnf

9. myvps1 にホスト証明書・鍵、CA証明書をコピーする

myserver1:~$ cp /etc/ssl/certs/ca1.crt .
myserver1:~$ cp /etc/ssl/newcerts/02.pem ./myvps1.crt
myserver1:~$ scp ca1.crt myvps1.crt myvps1.key myvps1:

myvps1:~$ sudo cp ca1.crt /etc/ipsec.d/cacerts/
myvps1:~$ sudo cp myvps1.crt /etc/ipsec.d/certs/
myvps1:~$ sudo cp myvps1.key /etc/ipsec.d/private/
myvps1:~$ rm ca1.crt myvps1.crt myvps1.key
myserver1:~$ rm ca1.crt myvps1.crt myvps1.key

10. strongswan の設定 (myserver1側)

設定ファイルを編集する。

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.jp"

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

パスワードファイルには秘密鍵のファイル名を記述する。

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

/etc/ipsec.secrets:

: RSA myserver1.key

11. strongswan の設定 (myvps1側)

こちらも設定ファイルを編集する。

myvps1:~$ sudo vi /etc/ipsec.conf

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

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"

パスワードファイルには秘密鍵のファイル名を記述する。

myvps1:~$ sudo vi /etc/ipsec.secrets

/etc/ipsec.secrets:

: RSA myvps1.key

12. サービス起動と確認

サービスを起動する。

myserver1:~$ sudo service strongswan start
myvps1:~$ sudo service strongswan start

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

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

myserver1:~$ sudo ip xfrm policy
src 203.0.113.180/32 dst 192.168.100.0/24 
	dir fwd priority 1827 
	tmpl src 203.0.113.180 dst 192.168.100.240
		proto esp reqid 1 mode tunnel
src 203.0.113.180/32 dst 192.168.100.0/24 
	dir in priority 1827 
	tmpl src 203.0.113.180 dst 192.168.100.240
		proto esp reqid 1 mode tunnel
src 192.168.100.0/24 dst 203.0.113.180/32 
	dir out priority 1827 
	tmpl src 192.168.100.240 dst 203.0.113.180
		proto esp reqid 1 mode tunnel
(snip)

自宅-VPS間でIPsec (openswan)

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

ネットワーク図 (IPアドレスは例示用)
03

OS: Ubuntu 14.04 LTS
ソフトウェア: openswan

1. VPS側
ipsec.confを編集する。

myvps:~$ sudo vi /etc/ipsec.conf

/etc/ipsec.conf:

config setup
	protostack=netkey #autoから変更
(snip)
conn myhome-to-vps
    authby=secret
    auto=add
    left=203.0.113.180
    leftsubnet=203.0.113.180/32
    right=%any
    rightsubnet=192.168.24.0/24
    rightid=192.168.24.252

事前共有鍵を設定する。

myvps:~$ sudo vi /etc/ipsec.secrets

/etc/ipsec.secrets:

: PSK "mypresharedkey"

2. 自宅側
ipsec.confを編集する。

myvps:~$ sudo vi /etc/ipsec.conf

/etc/ipsec.conf:

config setup
	protostack=netkey #autoから変更
(snip)
conn myhome-to-vps
    authby=secret
    auto=start
    left=192.168.24.252
    leftsubnet=192.168.24.0/24
    right=203.0.113.180
    rightsubnet=203.0.113.180/32

VPS側と同じ事前共有鍵を設定する。

myvps:~$ sudo vi /etc/ipsec.secrets

/etc/ipsec.secrets:

: PSK "mypresharedkey"

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

自宅グローバルIPアドレスは不定のため、IPsecのピアIDとしては適当な文字列(ここではプライベートIPアドレス)を使う。通常、片側の端点が動的IPアドレスの場合は Aggressive モードを使うものだが、上記の設定であれば Main モードでつながるようだ。このへんの仕組みがよくわからない…

また、上記は事前共有鍵による認証を使っているが、OpenSSLで生成したRSA証明書認証を設定しようとするとうまくいかない。このあたり試行錯誤が必要だ。
(※追記: openswanだとうまくいかないので、strongswanに切り替えました。strongswanとopenswanの比較はこちら)