Windows PCをOpenVPNサーバーにして複数拠点のPCをVPN接続する

ネットワーク VPN 自宅サーバ

サーバー設置拠点1か所とクライアント設置拠点3か所の、合計4拠点程度を同一VPNに参加させる想定の構成。 OpenVPNサーバーはWindows PCで稼働し、Raspberry PiはOpenVPNサーバーではなくDDNS更新のみを担当する。

接続先は共通で <vpn-hostname>(例: vpn.example.org:1194/UDP) とし、既存のインターネット通信は各拠点の通常回線を使い、VPNは 10.77.0.0/24 のみをトンネル経由で流すスプリットトンネル構成とする。

全体構成

                             Internet
                                |
                      vpn.example.org
                            UDP 1194
                                |
                       Server-site Router
                                |
                         Windows PC (OpenVPN Server)
                            10.77.0.1
                     /        |         \
                    /         |          \
         10.77.0.11   10.77.0.12   10.77.0.13
         client-01     client-02     client-03

Raspberry Pi:
- サーバー拠点の動的グローバルIPv4を監視
- XServerのAレコード更新(DDNS)のみ

1. DNS運用方針(VPNホスト)

vpn.example.org はWebサイト用のDNS設定とは分け、OpenVPNサーバー拠点のグローバルIPv4を指す独立したAレコードとして設定する。

DNS
親ドメインAレコード185.199.108.153 / 185.199.109.153 / 185.199.110.153 / 185.199.111.153
vpn.example.org Aレコードサーバー拠点の現在IP(以下 <サーバー拠点のグローバルIPv4>
TTL300

2. XServer DNSをDDNSとして使う

利用するネームサーバーは XServer (ns1.xdomain.ne.jp / ns2.xdomain.ne.jp / ns3.xdomain.ne.jp)。 Raspberry Pi 上でAPIを叩いて vpn.example.org のAレコード更新を行うが、毎回APIを呼ばない

systemd timer は5分間隔。更新ロジックは次のようにする。

  1. 現在のグローバルIPv4を取得する
  2. /var/lib/xserver-ddns/last_ip と比較する
  3. 変更なしならAPI呼び出しせず終了
  4. 変更ありならAPIでAレコード更新
  5. 成功時のみ last_ip を更新

確認コマンド:

sudo cat /var/lib/xserver-ddns/last_ip
systemctl list-timers xserver-ddns.timer
journalctl -u xserver-ddns.service -n 30 --no-pager

Windows側からは名前解決だけ確認する。

Resolve-DnsName vpn.example.org -Type A

3. OpenVPNサーバー(Windows)設計

サーバー条件

OpenVPN Community Edition 2.7系、サブネット 10.77.0.0/24 を採用。
OpenVPNサーバーアドレスは 10.77.0.1

Server: 10.77.0.1/24
Client-to-client: 有効

構築手順とサーバー設定

Windows PCへOpenVPN Community Edition 2.7系をインストールし、サーバーは OpenVPNService から起動する。構築は次の順で行う。

  1. サーバー設定へVPNサブネットとUDP待受を設定する
  2. PCごとに異なるCommon Nameでクライアント証明書を発行する
  3. Common Nameと同じ名前のCCDファイルを作成する
  4. クライアントごとの .ovpn を作成する
  5. OpenVPNService を起動して待受とログを確認する

サーバー設定のうち、ネットワークに関する部分は次の構成とする。

port 1194
proto udp
dev tun
topology subnet
server 10.77.0.0 255.255.255.0
client-config-dir ccd
client-to-client
persist-key
persist-tun
verb 3

topology subnet を明示することで、CCDの ifconfig-push は「クライアントIPとサブネットマスク」の組み合わせになる。client-config-dir のパスは、実際にCCDを配置したディレクトリに合わせる。

スプリットトンネルを維持するため、redirect-gateway は設定せず、クライアントへもpushしない。これにより、VPNサブネット 10.77.0.0/24 宛の通信だけがトンネルへ入り、通常のインターネット通信には各拠点の既定ルートが使われる。

クライアント固定IP(CCD)

同じ .ovpn を使い回すのではなく、クライアントごとに証明書を分け、ccd で固定IPを固定する。

client-01         ifconfig-push 10.77.0.11 255.255.255.0
client-02         ifconfig-push 10.77.0.12 255.255.255.0
client-03         ifconfig-push 10.77.0.13 255.255.255.0

CCDファイル名は、各クライアント証明書のCommon Nameと一致させる。例えばCommon Nameが client-01 なら、ccd ディレクトリ内の client-01 に対応する ifconfig-push を記述する。

クライアント設定のネットワーク部分は次の構成とする。

client
dev tun
proto udp
remote vpn.example.org 1194
nobind
persist-key
persist-tun
verb 3

各PCのプロファイルには、そのPC用に発行したクライアント証明書を対応させる。

Windows側はサービス登録して起動させる。
確認は次。

Get-Service OpenVPNService
Get-NetUDPEndpoint -LocalPort 1194

正常起動時、C:\ProgramData\OpenVPN\Log\server.log

Initialization Sequence Completed

が出るのを確認する。

4. Windowsクライアント運用

クライアントは OpenVPN GUI で手動接続/切断する運用とする。
Windowsサービスによる自動接続とGUI接続を同時に有効にすると二重接続になるため避ける。

運用手順:

  • OpenVPN GUI を起動
  • Connect
  • 必要な作業
  • Disconnect

クライアントログの必要部分例:

VERIFY OK
Peer Connection Initiated
ASSIGN_IP,,10.77.0.11
Initialization Sequence Completed
CONNECTED,SUCCESS,10.77.0.11

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

client-to-client を有効にして、VPN内の端末間通信を許可する。

10.77.0.11 ↕ 10.77.0.12 ↕ 10.77.0.13

ただし到達可否は各端末のWindows Firewall方針にも依存する。

6. RDP・Ping・任意ポートの開放

VPN経由でOpenVPNサーバー 10.77.0.1 のRDPを使う例。

Test-NetConnection 10.77.0.1 -Port 3389

期待結果(要点):

RemoteAddress    : 10.77.0.1
RemotePort       : 3389
SourceAddress    : 10.77.0.11
TcpTestSucceeded : True

RDP実行:

mstsc /v:10.77.0.1

Windows Firewallでは、既存のLAN向けRDPルールを残し、VPN用に追加ルールを追加する。
既存のローカルLANルールを消すと誤って利用域を狭めるため注意。

New-NetFirewallRule `
    -DisplayName "RDP from OpenVPN" `
    -Direction Inbound `
    -Protocol TCP `
    -LocalPort 3389 `
    -RemoteAddress 10.77.0.0/24 `
    -Action Allow `
    -Profile Any

VPN内のみICMP許可:

New-NetFirewallRule `
    -DisplayName "ICMPv4 from OpenVPN" `
    -Direction Inbound `
    -Protocol ICMPv4 `
    -IcmpType 8 `
    -RemoteAddress 10.77.0.0/24 `
    -Action Allow `
    -Profile Any

追加ポート例(例: TCP 8080):

New-NetFirewallRule `
    -DisplayName "TCP 8080 from OpenVPN" `
    -Direction Inbound `
    -Protocol TCP `
    -LocalPort 8080 `
    -RemoteAddress 10.77.0.0/24 `
    -Action Allow `
    -Profile Any

7. ルーター設定(公開)

OpenVPNを外部から接続可能にするため、ルーター側には以下を設定する。

Protocol: UDP
External Port: 1194
Internal Port: 1194
Destination: OpenVPN Server PC のLAN IP

UDP 1194 をOpenVPNサーバーへ転送する必要がある。

8. 運用上のセキュリティルール

運用時の前提として次を明文化しておく。

  • 各PCごとに異なるクライアント証明書を発行
  • .ovpn の使い回し禁止(利用PCごとに1枚)
  • 利用停止時は証明書失効で除外
  • ルータ/サーバーの公開ポートは最小化(1194/UDPのみ)

9. 途中で証明書を外す場合

一時停止ではなく完全除外する場合は、revoke で証明書を失効し CRL 更新する。

運用イメージ:

  1. 該当端末の運用終了を決定
  2. 該当クライアント証明書をサーバー側で失効
  3. CRLを再発行/反映
  4. 再接続を再試行して失効反映を確認

10. ルーター固有トラブルについて

今回使用したTP-Link Deco X20ではポートフォワーディングに関する問題が発生した。
詳細な切り分けは別記事を参照。