さくらVPSにEthernet BridgingなOpenVPNをインストールしてみました

出先から自宅のPCへ接続したいという動機からさくらVPS上のGentoo LinuxをOpenVPNサーバーとして構築しました。Ethernet Bridgeモードを使用して、BonjourやAvahiで名前解決できるようにしています。

ネットワーク構成

以下の3台のホストで構成されています:

  • Bowmore: さくらVPS上で動作するOpenVPNサーバー(Gentoo Linux)
  • Caolila: MacBook Air(OpenVPNクライアント、出先から接続)
  • PortEllen: VirtualBoxゲスト(OpenVPNクライアント、自宅ネットワーク上)

Single NICの問題

個人向けVPSの制約として、NICがグローバル接続用のもの1つしかなく、bridgeにこの唯一のNICを組み入れるとグローバル接続ができなくなってしまいます。この問題はLinuxカーネルに含まれるDummy net driverを使うことで対処できます。

OpenVPNセットアップ

パッケージインストール

[root@Bowmore] # emerge -pv openvpn
These are the packages that would be merged, in order:
[ebuild   R    ] net-misc/openvpn-2.2.2  USE="examples pam ssl -iproute2 -minimal -passwordsave -pkcs11 (-selinux) -static" 0 kB

認証局(CA)の設定

easy-rsaを使って証明書を生成します。varsファイルのKEY_*変数を編集します:

export KEY_SIZE=1024
export CA_EXPIRE=3650
export KEY_EXPIRE=3650
export KEY_COUNTRY="JP"
export KEY_PROVINCE="Tokyo"
export KEY_CITY="Suginami"
export KEY_ORG="BooMTown"
export KEY_EMAIL="openvpn@example.com"
export KEY_CN="ca.openvpn.example.com"
export KEY_NAME="Jhon Doe"
export KEY_OU="personal"

CA証明書の生成

[root@Bowmore] # cd /usr/share/openvpn/easy-rsa
[root@Bowmore] # . ./vars
[root@Bowmore] # ./clean-all
[root@Bowmore] # ./build-ca

これにより以下が生成されます:

  • ca.key: CA秘密鍵
  • ca.crt: CA証明書

サーバー証明書の生成

[root@Bowmore] # ./build-key-server bowmore

以下が生成されます:

  • bowmore.key: サーバー秘密鍵
  • bowmore.csr: 証明書署名要求
  • bowmore.crt: サーバー証明書

クライアント証明書の生成

[root@Bowmore] # ./build-key PortEllen
[root@Bowmore] # ./build-key Caolila

各クライアントに.key.csr.crtファイルが生成されます。

Diffie-Hellmanパラメータの生成

[root@Bowmore] # ./build-dh
Generating DH parameters, 1024 bit long safe prime, generator 2
[root@Bowmore] # ls -l /usr/share/openvpn/easy-rsa/keys/dh1024.pem
-rw-r--r-- 1 root root 245  /usr/share/openvpn/easy-rsa/keys/dh1024.pem

サーバー設定

/etc/openvpn/に以下をコピーします:

  • ca.crt
  • bowmore.key
  • bowmore.crt
  • dh1024.pem

/etc/openvpn/server.confを作成:

port 1194
proto udp
dev tap
ca ca.crt
cert server.crt
key server.key
dh dh1024.pem
server-bridge 172.16.255.1 255.255.255.0 172.16.255.16 172.16.255.31
client-to-client
duplicate-cn
keepalive 10 120
comp-lzo
persist-key
persist-tun
status openvpn-status.log
verb 4

シンボリックリンクを作成:

[root@Bowmore] # ln -s bowmore.crt server.crt
[root@Bowmore] # ln -s bowmore.key server.key

クライアント設定

各クライアントの/etc/openvpn/に以下をコピーします:

  • ca.crt
  • クライアント証明書(例: PortEllen.crt
  • クライアント鍵(例: PortEllen.key

/etc/openvpn/client.confを作成:

client
dev tap
proto udp
remote bowmore.example.com 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
ns-cert-type server
comp-lzo
verb 3

Ethernet Bridgeの設定

Dummy Net Driver

既に有効化されているか確認:

lsmod | grep -E '^dummy\s'
zcat /proc/config.gz | grep -E '^CONFIG_DUMMY=(y|m)$'

カーネルモジュールのビルド(必要な場合)

[root@Bowmore] # uname -a
Linux Bowmore 3.3.8-gentoo #2 SMP Sat Aug 4 09:57:38 JST 2012 x86_64
[root@Bowmore] # genkernel --menuconfig --no-clean --no-mrproper --lvm all

CONFIG_DUMMY=mに設定してビルドし、モジュールを読み込みます:

[root@Bowmore] # modprobe dummy
[root@Bowmore] # lsmod | grep dummy
dummy                   1946  0

bridge-utilsのインストール

[root@Bowmore] # emerge -pv bridge-utils
[ebuild   R    ] net-misc/bridge-utils-1.4  0 kB

ブリッジインターフェースの設定

IPフォワーディングの確認:

[root@Bowmore] # cat /proc/sys/net/ipv4/ip_forward
1

/etc/conf.d/netを編集:

config_dummy0=(null)
tuntap_tap0="tap"
config_tap0=("0.0.0.0 promisc")
bridge_br0="dummy0 tap0"
config_br0=(null)
depend_br0() {
  need net.dummy0 net.tap0
}

initスクリプトを作成:

[root@Bowmore] # cd /etc/init.d
[root@Bowmore] # ln -s net.lo net.dummy0
[root@Bowmore] # ln -s net.lo net.br0
[root@Bowmore] # rc-update add net.br0 default

テスト

ブリッジの起動

[root@Bowmore] # /etc/init.d/net.br0 start
 * Bringing up interface br0
 *   Creating bridge br0 ...
 *   Adding ports to br0
 *     dummy0 ...                                [ ok ]
 *     tap0 ...                                  [ ok ]

サーバーの起動

[root@Bowmore] # cd /etc/openvpn
[root@Bowmore] # openvpn server.conf
Mon Nov 26 01:21:04 2012 OpenVPN 2.2.2 x86_64-pc-linux-gnu [SSL] [LZO2] [EPOLL]
Mon Nov 26 01:21:04 2012 TUN/TAP device tap0 opened
Mon Nov 26 01:21:04 2012 Initialization Sequence Completed

サービスとして起動:

[root@Bowmore] # /etc/init.d/openvpn start
 * Starting openvpn ...                         [ ok ]

クライアントからの接続

サーバー側のログでクライアントの認証成功が確認できます:

Wed Dec 12 07:02:55 2012 [PortEllen] Peer Connection Initiated
Wed Dec 12 07:02:57 2012 MULTI: Learn: 66:de:0c:66:9d:56 -> PortEllen/113.xxx.yyy.zzz:51127

クライアント側のログ:

Wed Dec 12 07:02:36 2012 /bin/ifconfig tap0 172.16.255.18 netmask 255.255.255.0
Wed Dec 12 07:02:36 2012 Initialization Sequence Completed

MacBook Airからのテスト

MacBook Air(Caolila)からHomebrewでインストールしたOpenVPNを使い、iPhoneテザリング経由で接続テストを行い、無事接続できました!