Ubuntu 14.04 で OpenVPN

はじめに

f:id:takemaruhirai:20150527120840p:plain

この記事は、OpenVPNを使用して外部から内部ネットワークにアクセスする仕組みを構築する手順をメモしています。いろいろ他のサイトを参考にしています。

Business VPN | Next-Gen VPN | OpenVPN

ところで

公式サイトに行くと VPN Solution という項目があって、ここから OpenVPN Access Serverという管理ツールをダウンロードできるのですが、GUIが使えたりしていろいろ便利そうではあるのですが、有料製品のようです。今回は、あくまで無料でVPNサーバーを構築する予定ですので、こちらではなく。必要なドキュメント等は、Communityのほうにあります。

f:id:takemaruhirai:20150527120959p:plain

前提となる環境

今回、サーバーには、Ubuntu 14.04 LTS Server を使用しています。これは、すでにインストールされ、内部ネットワーク環境に置かれているものとします。 内部環境のネットワークアドレスは 192,168.1.0/24 とし、ゲートウェイ192.168.1.1VPNサーバーのアドレスは 192.168.1.10 としています。 外部のクライアントPCから、内部のAPサーバーに アドレス 192.168.1.20 でアクセスできるところまでが目標です。

f:id:takemaruhirai:20150527150813p:plain

iPhoneからも接続することを考えていますので、接続方式は ブリッジ ではなく NAT で、仮想ネットワークドライバは TAP ではなく TUN を使用します。

作業前に

以下の作業のほとんどは、root権限で行う必要があります。Ubuntuの場合、普段は sudo で実行しますが、面倒なのであらかじめ root 権限を取得して作業しました。

$ sudo -i

OpenVPNUbuntu にインストールする

まずは、レポジトリの情報を最新にアップデートします。

# apt-get update

そして、パッケージをインストールします。 *1

# apt-get install openvpn easy-rsa libssl-dev openssl

サーバー証明書を発行する

サーバー用に、公開鍵(.crt)、秘密鍵(.key)、証明書署名要求(.csr)、DHパラメータ(.pem)を作成します。

証明書作成用のディレクトリを作成

証明書発行用のディレクトリが必要になります。Ubuntuには専用のコマンド make-cadir が用意されているようなのでこれを使います。場所は、通常 /etc/openvpn の下に、easy-rsa ディレクトリを作成するようです。作成後、そのディレクトリに移動します。

# make-cadir /etc/openvpn/easy-rsa
# cd /etc/openvpn/easy-rsa
/etc/openvpn
│
└─ east-rsa       ←

Ubuntu Manpage: make-cadir - create certificates dir

f:id:takemaruhirai:20150527160828p:plain

証明書作成用の環境変数を設定する

移動先の easy-rsa ディレクトリに、vars というファイルがあります。このファイルの中に、必要な情報を入力していきます。

# vi ./vars
export KEY_COUNTRY="JP"                 # 国
export KEY_PROVINCE="Tokyo"             # 都道府県
export KEY_CITY="Shinjuku"              # 市区町村
export KEY_ORG="My Company Co.Ltd."     # 組織
export KEY_EMAIL="admin@my-company.com" # メールアドレス
export KEY_OU="Sales"                   # 組織単位

変更した varsファイルを読み込みます。

# . ./vars

サーバー証明書を作成する

以下のコマンド(実行可能ファイル)を順に実行してください。

# ./clean-all
# ./build-dh
# ./pkitool --initca
# ./pkitool --server server

keysディレクトリに移動し、TLS認証鍵を作成します。

# cd ./keys
# openvpn --genkey --secret

以上の作業で、keysディレクトリに以下の鍵ファイルが作成されていると思います。

/etc/openvpn
│
└─ east-rsa
    │
    └─ keys
       ca.crt       ←
       ca.key       ←
       server.crt   ←
       server.csr   ←
       server.key   ←
       dh2048.pem   ←
       ta.key       ←

これらのファイルを /etc/openvpn ディレクトリの下へコピーします。

# cp ca.crt server.crt server.keydh1024.pem ta.key /etc/openvpn
/etc/openvpn
│   ca.crt       ←
│   server.crt   ←
│   server.key   ←
│   dh2048.pem   ←
│   ta.key       ←
│
└─ east-rsa
    │
    └─ keys
       ca.crt
       ca.key
       server.crt
       server.csr
       server.key
       dh2048.pem    
       ta.key

OpenVPNを設定する

設定ファイルの作成

OpenVPNの設定を環境に合わせて変更していきます。設定ファイルは、まだ作成されていません。/usr/share/doc/openvpn にサンプル設定ファイルがありますので、以下のコマンドを実行してこれを server.conf として /etc/openvpn にコピーします。

# gunzip -c /usr/share/doc/openvpn/examples/sample-config-files/server.conf.gz > /etc/openvpn/server.conf
/etc/openvpn
│   ca.crt
│   server.crt
│   server.key
│   dh2048.pem    
│   ta.key
│   server.conf   ←
│
└─ east-rsa
    │
    └─ keys

この server.conf が設定ファイルになりますので、これを編集します。

# vi /etc/openvpn/server.conf

VPN通信の設定(規定値のまま)

f:id:takemaruhirai:20150527174357p:plain

ポート番号とプロトコルを指定します。必要がなければ、規定値のままで構いません。クライアント側のルーターで既定のポート番号が制限されている場合などに、tcp/443を使用することなどが可能とのことです。

port 1194
;proto tcp
proto udp

接続用の仮想ネットワークデバイスを指定します。今回の例では、iPhoneからの接続を考慮して TUN を選択しています。規定で TUN となっているので、変更は必要ありません。

;dev tap
dev tun

VPN通信に使用するネットワークアドレスを指定します。クライアント・サーバー間はこのアドレスで通信が行われ、サーバーで内部ネットワークアドレスに変換されます。今回の場合、規定値をそのまま使用しています。後の手順で、内部ネットワーク側のルーター設定でこのアドレスを指定する必要があります。

server 10.8.0.0 255.255.255.0

証明書の指定(規定値のまま)

  1. で作成した証明書を指定します。今回の場合、とくに変更は必要ありません。
ca ca.crt
cert server.crt
key server.key

DHパラメータの指定

  1. で作成した dh2048.pem を指定します。今回の場合、以下のように変更する必要があります*2
;dh dh1024.pem
dh dh2048.pem

アクセス先となる内部ネットワークの設定

外部からアクセスしたいネットワークのアドレスを入力します。push "route ..." の箇所を変更してください。今回の例 192.168.1.0/24 の場合は、以下のように指定します。

push "route 192.168.1.0 255.255.255.0"

次に、push "redirect-gateway ..."の箇所のコメントアウトを外して有効化します。これを有効にすることで、WebブラウジングDNS参照など、VPN ClientのすべてのトラフィックVPNサーバー経由にするそうです。

push "redirect-gateway def1 bypass-dhcp"

そして、DNSの設定を変更します。push "dhcp-option DNS..."の箇所を変更します。今回の例では、DNSサーバーとして192.168.1.1を指定します。

push "dhcp-option DNS 192.168.1.1"

TLSの設定

ファイルの末尾に以下の情報を追加します。

mode server
tls-server

TLS暗号化を有効化します。

tls-auth ta.key 0

通信暗号化の設定

サーバー・クライアント間で用いる暗号化の方式を指定します。ここで指定した方式を、クライアント側からも指定する必要があります。ここが、サーバーとクライアントで異なっていると、クライアントからの接続時にエラーとなります。

cipher AES-256-CBC

サービス実行ユーザーの変更

規定では、OpenVPN は root ユーザーとして動作するため、これを nobody:nogroup に変更し、セキュリティを高めておきます。

user nobody
group nogroup

その他のオプション

クライアント間通信の有効化

client-to-client

複数台のクライアントで、同じ証明書を使い回す(非推奨)。

;duplicate-cn

VPN通信の圧縮。今回、これを有効にするとiPhoneからの接続がうまくいかなかったため、コメントアウトしました。

;comp-lzo

設定の反映

server.conf を保存したら、openvpnサービスを再起動します。

# service openvpn restart

参考サイト

内部ネットワークの他のサーバーにアクセスするための設定をする

以上の設定のみで手順を進めると、クライアント側からOpenVPNサーバー自体(図の192.168.1.10あるいは10.8.0.1)にはアクセス可能となりますが、内部ネットワークの他のサーバー等(イントラネット上の業務アプリケーションや共有フォルダなど)にアクセスしようとしても、パケットが届かないためエラーとなってしまいます。そこで、OpenVPNサーバー上で、クライアントから 10.8.0.0/24 経由で来たパケットを 192.168.1.0/24 に転送する必要があります。

f:id:takemaruhirai:20150527180912p:plain

フォワーディングの有効化

まず、IPフォワーディングを有効にします。カーネルパラメータを変更しますので、sysctl.conf を開きます。

# vi /etc/sysctl.conf

そして、以下の行のコメントアウトを解除して保存します。

net.ipv4.ip_forward = 1

設定を即座に反映するために、以下のコマンドを実行します。

# sysctl -p

ルーティング設定の追加

そして、フォワーディングの設定をします。他のサイトでは ufw を使用した例が多く示されていますが、ここでは iptables を利用しています。なお、iptablesは、すべてACCEPTとなっており、とくにフィルタリング等は行われていない(ファイアウォール等は別途設けられている)ケースを想定しています。

まず、iptables の設定を永続化するためのツールを導入します。

# apt-get install iptables-persistent

次に、iptables に以下の設定を追加します。ifconfig コマンドで、物理ネットワークデバイスのデバイス名を確認しておいてください。

# ifconfig

eth0   Link encap:Ethernet  HWaddr 00:0B:CD:1C:18:5A
       inet addr:192.168.1.10  Bcast:192.168.1.255  Mask:255.255.255.0
       ...

lo     Link encap:Local Loopback
       inet addr:127.0.0.1  Mask:255.0.0.0
       ...

tun0   Link encap:UNSPEC  HWaddr 00-00-00-00-00-00-00-00-00-00-00-00-00-00-00-00
       inet addr:10.8.0.1  P-t-P:10.8.0.2  Mask:255.255.255.255
       ...

そのうえで、以下のコマンドを入力してください。今回は、仮想ネットワークデバイスが tun0(10.8.0.0/24)、物理ネットワークデバイス eth0(192.168.1.0/24)であるとします。

# iptables -t nat -A POSTROUTING -s 10.8.0.0/24 -o eth0 -j MASQUERADE

設定を保存します。

# service iptables-persistent save

参考サイト

ルーターを設定する

OpenVPNサーバー上での設定は以上ですが、内部ネットワークのゲートウェイとなっているルーター機器で、いくつか設定を行います。

ポート開放を許可する

外部から udp/1194へのアクセスを許可します。ルーターフィルタリングなどを使用します。

f:id:takemaruhirai:20150527194141p:plain

NTT OG410Xiの例

f:id:takemaruhirai:20150527193535p:plain

規定で、何もフィルタリングされていない場合は空欄。

外部からの udp/1194 宛てのパケットを VPNサーバーに送る

次に、外部のVPNクライアントからのアクセスを、VPNサーバーを経由するように設定します。ルーター静的IPマスカレードを使用します。

f:id:takemaruhirai:20150527223200p:plain

NTT OG410Xiの例

f:id:takemaruhirai:20150527193614p:plain

内部からの 10.8.0.0/24 宛てのパケットを VPNサーバーに送る

そして、内部から、10.8.0.0/24 に宛てたパケットがすべて VPNサーバーを経由するように設定します。ルータールーティングなどを使用します。

f:id:takemaruhirai:20150527193855p:plain

NTT OG410Xiの例

f:id:takemaruhirai:20150527193555p:plain

参考サイト

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

以上で、サーバー用の設定は完了です。あとは、外部から接続するクライアント端末ごとに、証明書を発行します。この証明書を用いて、各クライアントが内部ネットワークにアクセスします。ここでは、仮にアクセス先の グローバルIPアドレスが 123.456.78.9 であるとしています。

f:id:takemaruhirai:20150527204000p:plain

(ログアウトしていれば再度OpenVPNサーバーにログインし、)2. で作成した /etc/openvpn/easy-rsa ディレクトリに移動します。

# cd /etc/openvpn/easy-rsa
/etc/openvpn
│
└─ east-rsa       ←

作成済みの環境変数を読み込みます。

# . ./vars

作成したいクライアントの識別名を任意に命名します。ここでは、 client1 とします。以下のコマンドを実行してください。

# ./pkitool client1

もし、パスワードを設定したい場合には、--passオプションを使用します。証明書作成中にパスワードを聞かれますので、入力してください(確認を含めて2回)。ただし、4文字以上でないと怒られます。

# ./pkitool --pass client1

これで、keysディレクトリの中に、クライアント用の証明書が作成されているはずです。

/etc/openvpn
│
└─ east-rsa
    │
    └─ keys
       ca.crt
       ca.key
       server.crt
       server.csr
       server.key
       dh2048.pem    
       ta.key
       client1.crt  ←
       client1.csr  ←
       client1.key  ←

作成されたファイルのうち、client1.crtclient1.keyca.crtta.key を何らかの手段でクライアント端末に送ります。セキュリティに配慮して、できるだけ安全な方法で受け渡しをしてください。

/etc/openvpn
│
└─ east-rsa
    │
    └─ keys
       ca.crt       ←
       ca.key
       server.crt
       server.csr
       server.key
       dh2048.pem    
       ta.key       ←
       client1.crt  ←
       client1.csr
       client1.key  ←

VPNクライアントの設定(Windows

アプリケーションの入手

プラスシステムズ株式会社の提供するサイトから、vpnux Clientをダウンロードし、手順に従ってインストールします。*3こちらのソフトウェアの使用が、公式サイトでも推奨されているようです。

www.plum-systems.co.jp

設定

インストールが完了したら、vpnux Client を起動し、メニューの [プロファイル] → [追加]で設定画面を開きます。

f:id:takemaruhirai:20150527221517p:plain

f:id:takemaruhirai:20150527221533p:plain

上図のように設定をしたら、[保存]します。作成したプロファイルが、一覧画面に表示されたら完了です。

f:id:takemaruhirai:20150527221759p:plain

接続

起動時の画面から、作成済みのプロファイルを選択し、[接続]をクリックするだけです。非常に簡単です。

f:id:takemaruhirai:20150527221840p:plain

VPNクライアントの設定(iPhone

ovpnファイルの作成

新規に、テキストファイルを作成します。拡張子は .ovpnとしてください。ファイル名は仮に client1.ovpnとします。ファイルの内容は、以下のようなものになります。remoteの値には、接続先のグローバルIPアドレス、もしくはホスト名を入力します。 cipherの値を、2. で server.conf に指定した値と揃えることに注意してください。

tls-client
key-direction 1
remote 123.456.78.9
cipher AES-256-CBC
port 1194
proto udp
<ca>
-----      ca.crt の BEGIN CERTIFICATE ~ END CERTIFICATE までをペースト -----
</ca>
<cert>
----- client1.crt の BEGIN CERTIFICATE ~ END CERTIFICATE までをペースト -----
</cert>
<key>
----- client1.key の BEGIN ENCRYPTED PRIVATE KEY ~ END ENCRYPTED PRIVATE KEY までをペースト -----
</key>
<tls-auth>
-----      ta.key の BEGIN OpenVPN Static key V1 ~ END OpenVPN Static key V1 までをペースト -----
</tls-auth>

上記のようなファイルを作成したら、<ca><cert><key><tls-auth>各タグの中に該当する証明書(上記コメントのとおり)の鍵文字列を張り付けて保存します。

アプリの入手

iPhoneから App Store にアクセスし、OpenVPN Connect という無料アプリをダウンロードします。

OpenVPN Connect

OpenVPN Connect

設定のインポート

このアプリに、iTunes等の手段で、上記で作成した client1.ovpnを渡します。セキュアかどうか微妙なところですが、iPhoneのメールクライアントやファイラー等から .ovpnファイルを OpenVPN Connectで開くこともできます。

f:id:takemaruhirai:20150527212216p:plain

アプリでファイルを開くと、以下のような画面が表示されますので、+ボタンをタップします。これで、設定が完了します。

f:id:takemaruhirai:20150527224721p:plain

接続の開始

VPN接続を開始するには、下記の場所をタップしてください。

f:id:takemaruhirai:20150527215121p:plain

ステータスが Connected に変われば、接続完了です。

f:id:takemaruhirai:20150527215218p:plain

設定に問題がなければ、Safari等のブラウザやSMBに対応したファイラー等で、内部ネットワーク環境にアクセスできるはずです。下のアプリで、内部ネットワーク上の共有フォルダにアクセスることができました。

FE File Explorer: File Manager

FE File Explorer: File Manager

  • Skyjos Co., Ltd.
  • 仕事効率化
  • 無料

参考サイト

トラブルシューティング

もし、ステータスが接続済になっているにも関わらず、内部ネットワークにアクセスできない場合は、server.conf もしくは クライアントソフトウェア(あるいは client1.ovpn)の設定が間違っているか、ルーティングが正しく行われていないことが考えられます。

クライアント側の接続ログは、以下の場所から確認できますので、参考にしてください。

OpenVPN Connectの場合

f:id:takemaruhirai:20150527215232p:plain

サーバー側のログは、server.conf で何も設定を変更していなければ、システムログを確認します。

# view /var/log/syslog

以下に、私の引っかかったポイントをいくつか挙げておきます。

  • OpenVPNサーバーで、正しくIPフォワーディングの設定が出来ているか。とくに、sysctl.conf を変更し、反映したか。

    • VPNサーバー自体(192.168.1.10)にはアクセスできるが、他のサーバー(192.168.1.20)にはアクセスできない状態の場合、これが該当する可能性が高いです。
  • クライアントとサーバーで、暗号化方式を揃えたか。

    • サーバーで cipherAES-256-CBC としたなら、クライアント側でも同じにする必要があります。
  • 内部ネットワークからのレスポンスが正しく OpenVPNサーバーに戻ってくるか

    • ルーター 192.168.1.1 で、10.8.0.0/24 宛てのパケットを正しくルーティングする必要があります。

*1: 大抵の情報で上記のようになっていますが、 こちらのサイトだと、 libssl-devとopensslは指定していませんね。要調査。

*2:違いは、生成される鍵の長さだそうです。

*3:インストールせず、ポータブルな使い方もできるようです。