OpenVPN(ブリッジ)
20150110

確認環境
 CentOS7.x
⇒CentOS6.x以下の場合はOpenVPN(ブリッジ CentOS6.x以下)ページにて。
⇒リプレイス中でのメモ書きのため、誤りがある場合はご一報下さい。

概要
 1.SSL/TLS-VPNのサーバーを構築する。
 2.L2レベルでの通信が可能なブリッジモードを使用する。
 3.通信スループット20mbps以上を目指す。
 →暗号化処理の問題で、サーバーのハードウェアスペック(特にCPU)によって大幅に変わってきます。
 →当環境では、地デジ放送のデータ程度(15-18mbps)であればリアルタイムに転送出来る事を確認。
  CPU「A-10 5700(AES-NI未使用)」/メモリ「DDR3-2000-4096MB」/仮想環境OS /

トンネルモード(L3)VPNを構築する場合は「OpenVPN」を参考(CentOS7.x非対応)
 ※iphoneやandroidで接続する場合は上記トンネルモードで構築すること
⇒L3モードはNW機器上で実装していく方針としたため、以降更新予定無し。このページとCentOS6.xのページで構築は可能

OpenVPNブリッジモードによるメリット
 ルーティング設定が不要
 TCP/IP以外のプロトコルを使用可能
 →通常の内部ネットワークと同様に、NetBIOSによるファイル転送やDLNAが使えます。

OpenVPNブリッジモードによるデメリット
 アクセス制御の実装が面倒
 →基本的には「client-to-client」のコメントアウトをしない限り、VPNサーバ側内部ネットワークに属する
  システム全てと通信が可能な為、アクセス制限の方法が限られてしまう。
 →内部ネットワーク用NICが増えたと認識する(ようなもの)という点でトンネルモードと大きな違いがあります。
以下の仕様に基づいて設定をしています。

 VPNサーバ環境(Linux/ネットワークインターフェース/IPアドレス)
  IPアドレス : 192.168.0.3
  サブネットマスク  : 255.255.255.0(/24)
  ネットワークアドレス  : 192.168.0.0
  ブロードキャストアドレス : 192.168.0.255
  物理ネットワークインターフェース名 : eth0 ←環境によって違うので、ifconfigなりで確認すること
  ブリッジ用ネットワークインターフェース名 : br0
  TAPインターフェース名 : tap0

 VPNサーバ仕様
  サーバーアドレス : ry.tl
  ポート : UDP 1194
  VPNクライアントIPアドレスプール : 192.168.0.64 〜 192.168.0.127

 VPNクライアント
  OS : Windows
  ブリッジインターフェース名 : tap
  →「ローカルエリア2」 とかになっているアダプター名

 鍵強度
  RSA鍵 : 4096bit
  →パフォーマンスへの影響は限定的です。
  →各種鍵作成時間の増加。(最初のお星様作成時間の増加が著しい)
  →1時間に1回のSSL/TLSの再ネゴシエーションの時間の増加。
  対称鍵 : AES(128bit)
  →サーバースペックによりますが、パフォーマンスに直結します。
  →対応CPUであれば「AES-NI」を実装すると劇的な向上が見込めます。
◆インストール
 [root@Server ~]# yum -y install openssl-devel lzo-devel pam-devel
 [root@Server ~]# wget http://swupdate.openvpn.org/community/releases/openvpn-2.3.6.tar.gz
⇒2.3.6の部分は最新のバージョンに置き換えるなりしてください。
 http://openvpn.net/index.php/download/community-downloads.html

 [root@Server ~]# rpmbuild -tb --clean openvpn-2.3.6.tar.gz
 [root@Server ~]# yum -y localinstall ~/rpmbuild/RPMS/x86_64/openvpn-2.3.6-1.x86_64.rpm
 [root@Server ~]# rm -f ~/rpmbuild/RPMS/x86_64/openvpn-*
 [root@Server ~]# rm -f openvpn-2.3.6.tar.gz
⇒CentOS6.xまでとかなり違う
◆CA証明書作成
 [root@Server ~]# wget https://github.com/OpenVPN/easy-rsa/archive/master.zip
 [root@Server ~]# unzip master.zip
 [root@Server ~]# cp -r easy-rsa-master/easyrsa3/ /etc/openvpn/
 [root@Server ~]# rm -rf easy-rsa-master/
 [root@Server ~]# rm -f master.zip
⇒環境導入

 [root@Server ~]# cd /etc/openvpn/easyrsa3
 [root@Server easyrsa3]# vi vars

以下を設定
# Organizational fields (used with 'org' mode and ignored in 'cn_only' mode.)
# These are the default values for fields which will be placed in the
# certificate. Don't leave any of these fields blank, although interactively
# you may omit any specific field by typing the "." symbol (not valid for
# email.)

set_var EASYRSA_REQ_COUNTRY "JP" ←国名
set_var EASYRSA_REQ_PROVINCE "OSAKA" ←都道府県
set_var EASYRSA_REQ_CITY "OSAKA" ←市町村
set_var EASYRSA_REQ_ORG "ry.tl" サーバーアドレス
set_var EASYRSA_REQ_EMAIL "root@ry.tl" 管理者メールアドレス

# Choose a size in bits for your keypairs. The recommended value is 2048. Using
# 2048-bit keys is considered more than sufficient for many years into the
# future. Larger keysizes will slow down TLS negotiation and make key/DH param
# generation take much longer. Values up to 4096 should be accepted by most
# software. Only used when the crypto alg is rsa (see below.)

set_var EASYRSA_KEY_SIZE 4096

 [root@Server easyrsa3]# source vars
 [root@Server easyrsa3]# ./easyrsa init-pki
 [root@Server easyrsa3]# ./build-ca
Note: using Easy-RSA configuration from: ./vars
Generating a 4096 bit RSA private key
.............................++
................................................................................................................................................................................................................................................................................................................++
writing new private key to '/etc/openvpn/easyrsa3/pki/private/ca.key'
Enter PEM pass phrase:xxxxxxxx ←ここにパスワード入れる。後ほど証明書作る時に聞かれるパスワード
Verifying - Enter PEM pass phrase:xxxxxxxx ←確認用に同じパスワード入力
-----
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Common Name (eg: your user, host, or server name) [Easy-RSA CA]:ry.tl ←ドメイン入力

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/etc/openvpn/easyrsa3/pki/ca.crt

 [root@Server easyrsa3]# cp -pr pki/ca.crt /etc/openvpn/
⇒所定の位置へとコピーします。

◆サーバー証明書作成
 [root@Server easyrsa3]# ./easyrsa build-server-full server nopass
Note: using Easy-RSA configuration from: ./vars
Generating a 4096 bit RSA private key
................................................................................................++
............................++
writing new private key to '/etc/openvpn/easyrsa3/pki/private/server.key'
-----
Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf
Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:xxxxxxxx ← CA証明書作る時に入れたパスワードを入力
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :PRINTABLE:'server'
Certificate is to be certified until Dec 25 04:52:08 2024 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated


 [root@Server easyrsa3]# cp -pr pki/issued/server.crt pki/issued/server.key /etc/openvpn/
⇒所定の位置へコピーします。

◆DHパラメータ作成
 [root@Server easyrsa3]# ./easyrsa gen-dh
⇒お星様がいっぱい出てくるので終わるのを待つ。サーバースペックにもよるが、4096bitだと凄い時間掛かる。

 [root@Server easyrsa3]# cp -pr pki/dh.pem /etc/openvpn/
⇒所定の位置へコピーします。

◆TLS用の鍵作成
 [root@Server easyrsa3]# openvpn --genkey --secret /etc/openvpn/ta.key

◆クライアント証明書(「mobile」アカウント用)
 [root@Server easyrsa3]# ./easyrsa build-client-full mobile nopass
Note: using Easy-RSA configuration from: ./vars
Generating a 4096 bit RSA private key
.................................................................................++
.....................................................................................................................................................................................................................................................................................................................................++
writing new private key to '/etc/openvpn/easyrsa3/pki/private/mobile.key'
-----
Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf
Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:xxxxxxxx ←CA証明書のパスワード
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :PRINTABLE:'mobile'
Certificate is to be certified until Dec 25 05:27:26 2024 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated

〜パス付きを作る場合〜
[root@Server easyrsa3]# ./build-key-pass test
 Enter PEM pass phrase: パスワード
 Verifying - Enter PEM pass phrase:パスワード

◆最後にもろもろをコピー(とりあえず1個ずつ「/root」にでも。)
 [root@Server easyrsa3]# mkdir /root/key

 [root@Server easyrsa3]# cp -pr /etc/openvpn/easyrsa3/pki/private/ca.crt /root/key/
 [root@Server easyrsa3]# cp -pr /etc/openvpn/easyrsa3/pki/private/mobile.crt /root/key/
 [root@Server easyrsa3]# cp -pr /etc/openvpn/easyrsa3/pki/private/mobile.key /root/key/
⇒クライアント端末への受け渡し方法には気をつける。
◆サーバーコンフィグを編集
 [root@Server ~]# vi /etc/openvpn/server.conf
→サンプルConfigのパス「/usr/share/doc/openvpn-*/sample-config-files/server.conf」

----------------------------------------------------------------------------------------------------
# サーバー用コンフィグ
# Ver 20130114

# 使用するポートの指定(必須)
port 1194

# プロトコルの指定。TCPかUDP(必須)
proto udp

# TAPインターフェース指定(必須)
dev tap0

# 認証用鍵ファイルのパス(必須)
ca ca.crt
cert server.crt
key server.key
tls-auth ta.key 0

# 鍵強度
dh dh.pem
cipher AES-128-CBC

# 配布するIPアドレスのテーブル(任意)
# 固定化する際に用いる
ifconfig-pool-persist ipp.txt

# VPNサーバーのアドレスと、VPNクライアントのアドレスの幅指定(必須)
server-bridge 192.168.0.3 255.255.255.0 192.168.0.64 192.168.0.127

# 以下のローカルネットワークにアクセスする場合、VPNサーバーを経由する。(推奨)
push "route 192.168.0.0 255.255.255.0"

# DNSサーバー/WINSサーバーの設定(任意)
push "dhcp-option DNS 192.168.0.3"
push "dhcp-option DNS 192.168.0.1"
push "dhcp-option WINS 192.168.0.3"

# クライアント同士の通信を許可(推奨)
client-to-client

# キープアライブの設定(推奨)
keepalive 10 120

# LZO(圧縮)の有効化(推奨)
comp-lzo

# ユーザー権限(必須)
user nobody
group nobody

# 読み込み関係(不明)
persist-key
persist-tun

# ログ関係(必須)
status /var/log/openvpn-status.log
log /var/log/openvpn.log
log-append /var/log/openvpn.log

# ログ取得レベル(必須。レベルは任意)
verb 3

# 下記設定については動作の保証は出来ません。
# うまく行けばスループット向上を見込めます。(当環境でNetBIOSを用いたファイル送信で20-25mbps前後)
# ※TAPアダプターが10Mbps接続となっている場合がありますが、実際にはそれ以上の速度で通信も可能です。

# 以下、通信最適化

# MTUを指定(VPN及びL2ヘッダを付与する必要がある為、データサイズを小さくするとオーバーヘッドが減ると予想)
link-mtu 1400
# MSSを指定(上記の通り)
mssfix 1300
# UDPのみ。断片化を防止する為に変更(MTU-28の値を指定)
fragment 1372

# AES-NI対応CPUであれば下記設定を有効にして下さい。
#engine aesni

# エラーが出る場合の対処
replay-window 128
----------------------------------------------------------------------------------------------------

※環境によって変更する事。

◆クライアントに対するIPアドレス配布を固定にする場合(一部のみでも可)
 [root@Server ~]# vi /etc/openvpn/ipp.txt
test,192.168.0.64
test2,192.168.0.120
◆サーバー用ブリッジのインストール
 [root@Server ~]# yum -y install bridge-utils ←最初から入ってるかも

◆サーバー用ブリッジの設定(起動用スクリプトの作成)
 [root@Server ~]# vi /etc/openvpn/bridge-start

#!/bin/bash

# 20150110

# ブリッジインターフェース名
br="br0"

# TAPアダプター(インターフェース)名
tap="tap0"

# 物理ネットワークインターフェース名
eth="eth0" ←インターフェース名に注意
# ひとつ上の物理ネットワークインターフェースのIPアドレス
eth_ip="192.168.0.3"
# サブネットマスク
eth_netmask="255.255.255.0"
# ブロードキャストアドレス
eth_broadcast="192.168.0.255"
# デフォルトゲートウェイアドレス
eth_gw="192.168.0.1"

# 以降設定不要
for t in $tap; do
openvpn --mktun --dev $t
done

brctl addbr $br
brctl addif $br $eth

for t in $tap; do
brctl addif $br $t
done

for t in $tap; do
ifconfig $t 0.0.0.0 promisc up
done

ifconfig $eth 0.0.0.0 promisc up

ifconfig $br $eth_ip netmask $eth_netmask broadcast $eth_broadcast

route add default gw $eth_gw

※IPアドレス部分を環境に合わせて設定する事。
※書き換える際はインターフェース名に注意

 [root@Server ~]# chmod +x /etc/openvpn/bridge-start
→実行権限を付与

◆サーバー用ブリッジの設定A(停止用のスクリプトの作成)
 [root@Server ~]# vi /etc/openvpn/bridge-stop

#!/bin/bash

# 20110129

# ブリッジインターフェース名(ifconfig等で要確認)
br="br0"

# TAPアダプター(インターフェース)名
tap="tap0"

# 以降設定不要
ifconfig $br down
brctl delbr $br

for t in $tap; do
openvpn --rmtun --dev $t
done

※環境に合わせて設定する事。
※書き換える際はインターフェース名に注意

 [root@Server ~]# chmod +x /etc/openvpn/bridge-stop
→実行権限を付与
◆ネットワークとOpenVPNの起動と終了の設定
起動順としては「ネットワークの起動→ブリッジ起動→OpenVPNの起動」
終了順としては「OpenVPNの終了→ブリッジ終了→ネットワークの終了」
これらを実装するために設定を行う。

 [root@Server ~]# vi /etc/rc.d/init.d/network ←ifconfig入れてる点に注意
----------------------------------------------------------------------------------------------------

びふぉー
  touch /var/lock/subsys/network
  [ -n "${NETWORKDELAY}" ] && /bin/sleep ${NETWORKDELAY}
  ;;
  stop)
  # Don't shut the network down if root is on NFS or a network
  # block device.
  rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/" && $3 != "rootfs") { print $3; }}' /proc/mounts)
  rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)

  if [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev|_rnetdev" ]] ; then
  exit 1
  fi
----------------------------------------------------------------------------------------------------

あふたー
  touch /var/lock/subsys/network

  /bin/bash /etc/openvpn/bridge-start
  /bin/bash /etc/rc.d/init.d/openvpn start


  [ -n "${NETWORKDELAY}" ] && /bin/sleep ${NETWORKDELAY}
  ;;
  stop)
  # Don't shut the network down if root is on NFS or a network
  # block device.

  /bin/bash /etc/rc.d/init.d/openvpn stop
  /bin/bash /etc/openvpn/bridge-stop


  rootfs=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/" && $3 != "rootfs") { print $3; }}' /proc/mounts)
  rootopts=$(awk '{ if ($1 !~ /^[ \t]*#/ && $2 == "/") { print $4; }}' /etc/mtab)

  if [[ "$rootfs" =~ "^nfs" ]] || [[ "$rootopts" =~ "_netdev|_rnetdev" ]] ; then
  exit 1
  fi

※システムのアップデートで本ファイルの内容が初期化される場合があります。
 その場合の症状としては、起動時に自動でopenvpnが立ち上がらなくなり、
 openvpnデーモンを起動しても接続は出来るがホストとの通信が出来ないといった不具合が発生します。
 この症状が見られた場合は本ファイルを一度見直して下さい。

◆上記対策の為、一日一回本ファイルの中身を調査するスクリプトを作成(任意)
 [root@Server ~]# vi /etc/cron.daily/openvpn_network.sh

#!/bin/sh
export LANG=ja_JP.UTF-8

# Ver 20111214

# ネットワークスクリプトファイル
FILE="/etc/rc.d/init.d/network"

# 検索キーワード
KEY="openvpn"

# メール送信先アドレス。(デフォルトroot宛)
MAILADDRESS="root"

# 以降設定不要
if grep $KEY $FILE > /dev/null 2>&1 ; then
:
else echo -e "「$FILE」内にて、「$KEY」の文言を確認出来ません。\nOpenVPNの動作に支障が出る可能性がありますので、確認して下さい。\n参考「http://ry.tl/openvpn.html」"| mail -s "ネットワークスクリプト内容の変更を確認" $MAILADDRESS
fi

 [root@Server ~]# chmod +x /etc/cron.daily/openvpn_network.sh
→実行権限を付与

→cronにて実行され、問題があればメールにて通知されてきます。
◆IPフォワードの設定その1
 [root@Server ~]# echo 1 > /proc/sys/net/ipv4/ip_forward

◆IPフォワードの設定その2
 [root@Server ~]# vi /etc/sysctl.conf
  # Controls IP packet forwarding
  net.ipv4.ip_forward =0

 これを以下に変更する。無かったら追記する

  # Controls IP packet forwarding
  net.ipv4.ip_forward =1
◆iptablesの設定を変更(firewalldを無効化の上、iptablesを導入しています)
 [root@Server ~]# iptables -A FORWARD -s 192.168.0.0/255.255.255.0 -j ACCEPT
内部アドレスからの通過を許可する。

 [root@Server ~]# iptables -A INPUT -p udp --dport 1194 -j ACCEPT
VPNに使用するポートへのアクセスを許可する。(ルータでも行う事)
----------------------------------------------------------------------------------------------------

インターフェース名からIPアドレスを取得して設定している場合は「eth0」から「br0」に変更する必要があります。
 →CentOSで自宅サーバー構築様のiptables設定を用いている場合を想定して記します。

文字は変更/文字は追記。試していないので動作の保証は出来ません。

# インタフェース名定義
LAN=br0

# 外部からのUDP1194番ポート(OpenVPN)へのアクセスを日本からのみ許可
# ※OpenVPNサーバーを公開する場合のみ
iptables -A INPUT -p udp --dport 1194 -j ACCEPT_COUNTRY

# 内部からの通過をすべて許可
iptables -A FORWARD -s $LOCALNET -j ACCEPT


どうしても構築がうまく行かない場合はFW(iptables)で引っかかっている場合が多いので、一度無効化して問題の切り分けしてみて下さい。
◆OpenVPNの起動
初回は終了する際に、存在しないブリッジインターフェースを終了させようとしてエラーが発生しますが、問題はありません。
 [root@Server ~]# /etc/rc.d/init.d/openvpn stop
 [root@Server ~]# /etc/openvpn/bridge-stop
 [root@Server ~]# /etc/rc.d/init.d/network start
 [root@Server ~]# /etc/openvpn/bridge-start
 [root@Server ~]# /etc/rc.d/init.d/openvpn start
◆クライアント作業
先ほど「/root/key」にコピーした鍵一式と「client.ovpn」をC:\Program Files\OpenVPN\config\に保存。
◆クライアント作業(Windows64bitの場合)
先ほど「/root/key」にコピーした鍵一式と「client.ovpn」をC:\Program Files (x86)\OpenVPN\config\に保存。

補足として鍵一式
 ca.crt
 test.crt
 test.key
 ta.key
◆クライアント作業(「client.ovpn」をメモ帳などで開きます。)
# クライアント用コンフィグ
# Ver 20130114

# モード
client

# ネットワーク接続のデバイス名(コントロールパネルなりから確認設定をしてから変更)
dev-node tap

# プロトコル(サーバー側と合わせる。)
proto udp

# サーバーアドレス+ポート番号
remote ry.tl 1194

# 名前解決関係
resolv-retry infinite

# 特定のローカルポートを確保しない。
nobind

# Man-in-the-Middle攻撃対策
ns-cert-type server

# 読み込み関係
persist-key
persist-tun

# キーとかのパス(クライアント毎にファイル名などの変更が必須)
ca ca.crt
cert test.crt
key test.key
tls-auth ta.key 1

# 鍵強度
cipher AES-256-CBC

# LZO(圧縮)の有効化。サーバー側とあわせる必要がある。
comp-lzo

# ログ取得レベル
verb 3

# OpenVPNサーバからパラメータを受け取るための設定らしい。
pull

# OpenVPNサーバからIPアドレスを受け取るための設定らしい。
float

# 下記設定については動作の保証は出来ません。
# うまく行けばスループット向上を見込めます。(当環境でNetBIOSを用いたファイル送信で20-25mbps前後)
# ※TAPアダプターが10Mbps接続となっている場合がありますが、実際にはそれ以上の速度で通信も可能です。

# 以下、通信最適化

# MTUを指定(VPN及びL2ヘッダを付与する必要がある為、データサイズを小さくするとオーバーヘッドが減ると予想)
link-mtu 1400
# MSSを指定(上記の通り)
mssfix 1300
# UDPのみ。断片化を防止する為に変更(MTU-28の値を指定)
fragment 1372

# AES-NI対応CPUであれば下記設定を有効にして下さい。
#engine aesni

# エラーが出る場合の対処
replay-window 128
----------------------------------------------------------------------------------------------------

※環境によって変更する事。
〜運用後の操作〜
◆追加で使用するクライアント用の認証鍵を作成する場合。
 [root@Server ~]# cd /etc/openvpn/easy-rsa/
 [root@Server easyrsa3]# source vars

 [root@Server easyrsa3]# ./easyrsa build-client-full mobile2 nopass
Note: using Easy-RSA configuration from: ./vars
Generating a 4096 bit RSA private key
.................................................................................++
.....................................................................................................................................................................................................................................................................................................................................++
writing new private key to '/etc/openvpn/easyrsa3/pki/private/mobile2.key'
-----
Using configuration from /etc/openvpn/easyrsa3/openssl-1.0.cnf
Enter pass phrase for /etc/openvpn/easyrsa3/pki/private/ca.key:xxxxxxxx ←CA証明書のパスワード
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :PRINTABLE:'mobile2'
Certificate is to be certified until Dec 25 05:27:26 2024 GMT (3650 days)

Write out database with 1 new entries
Data Base Updated

〜パス付きを作る場合〜
[root@Server easyrsa3]# ./build-key-pass test2
 Enter PEM pass phrase: パスワード
 Verifying - Enter PEM pass phrase:パスワード


最後に
 OpenVPNは下記のように「conf」ファイルを複数用意する事によって、同一サーバー上にて複数のVPNサーバーを立てる事が出来ます。
 ブリッジモードとトンネルモードの両方を同一サーバー上で構築する事も可能です。
  /etc/openvpn/server.conf
  /etc/openvpn/server2.conf

 使用するポート番号の重複は出来ませんので、注意して下さい。

 また、クライアントについても同様の設定で複数サーバーへの接続が可能です。
 この場合、トンネル用インターフェースの増設が必須となる点に注意(パッチが用意されています。)

以上