OpenVPN 経由で Azure SQL Database にプライベート接続してみた話

Azure

Azure SQL Database(PaaS SQL Server)へプライベートエンドポイント経由の接続をする際に OpenVPN を使用することがあったので備忘録として構築手順を残しておきます。

ネットワーク構成について

今回構築するネットワーク構成は大まかに以下の図の通りです。接続元のクライアントはオンプレミスサーバーでも Azure VM 上のサーバーでもその他クラウドサーバーでも問題ありません。

ゴールとしてはオンプレミスサーバーから OpenVPN 経由で Azure の仮想ネットワーク(VNet)にアクセスし、Azure SQL Database のプライベートエンドポイントへ接続します。

OpenVPN 経由で Azure SQL Database のプライベートエンドポイントへ接続するネットワーク構成

Azure リソースの作成

Azure リソースの作成と設定を行います。作成するリソースは以下の通りです。

  • 仮想ネットワーク(アドレス空間:10.1.0.0/16)
  • サブネット 2 つ(アドレス空間:10.1.0.0/24 と 10.1.1.0/24)
  • OpenVPN サーバー用 Azure VM(Ubuntu)
  • ネットワークセキュリティグループ(NSG)
  • Azure SQL Database(論理サーバーとデータベース)
  • プライベートエンドポイント(Azure SQL Database 用)

Azure 上に仮想ネットワーク(VNet)を作成し、サブネット(subnet)を Azure SQL Database 用と OpenVPN サーバー用に 2 つ作成します。

仮想ネットワークリソース
サブネットリソース

次に OpenVPN 用のサブネット上に Azure VM リソースを作成します。今回は Ubuntu Server 24.04 LTS を選択します。

OpenVPN サーバー用 Azure VM

Azure SQL Database(論理 SQL サーバー)とプライベートエンドポイントも作成します。この時プライベート DNS ゾーンと統合しておきます。

プライベートエンドポイント用のサブネット(10.1.1.0/24)上に作成し、10.1.1.4 がプライベートエンドポイント用の IP アドレスとして割り当てられました。

プライベートエンドポイントの DNS 設定

サブネットにネットワークセキュリティグループ(NSG)を設定し、必要なポートへの通信を許可します。今回は、OpenVPN 用に UDP 1194、ssh 用に TCP 22、Azure SQL Database 接続用に TCP 1433 ポートを許可します(適宜ソースを絞るように設定します。今回はテストのため任意のソースから許可します)。

以上で必要な Azure リソースは作成できたので、試しに OpenVPN サーバー用の Azure VM から Azure SQL Database へプライベート接続ができるか確認してみます。同一仮想ネットワーク上の異なるサブネット上に Azure VM と Azure SQL Database のプライベートエンドポイントを配置したので、この時点でプライベート接続が出来るはずです。

ssh で Azure VM に接続し、データベースへ接続するためのクライアントツール sqlcmd をインストールします。sqlcmd のインストール方法はこちらのドキュメントに記載があります。インストールが完了したら sqlcmd コマンドラインからデータベースへ接続します。

sqlcmd -S '<SQL サーバー名>.database.windows.net' -U '<ユーザー名>' -P '<パスワード>'

SELECT client_net_address
FROM sys.dm_exec_connections
WHERE session_id = @@SPID;

>10.1.0.4
→クエリの結果として接続元 Azure VM のプライベート IP が返ってくればプライベート接続ができています。

OpenVPN サーバー用の Azure VM から Azure SQL Database へのプライベート接続が確認できたら OpenVPN サーバーの設定作業に移ります。

OpenVPN サーバーの設定

認証キーの作成、OpenVPN サーバーのインストールと設定ファイル

ssh で OpenVPN サーバーに接続し、まずは openvpn や easy-rsa、net-tools をインストールします(net-tools は必須ではないです)。

$> sudo apt install openvpn easy-rsa net-tools -y

easy-rsa を使って CA や 証明書、認証キーを設定/作成しておきます。なお、今回はセキュリティ強化のため tls-auth も使用します(ta.key が tls-auth 用のキーです)。

$> make-cadir ~/ca
$> cd ~/ca
$> ./easyrsa init-pki
$> ./easyrsa build-ca

→任意の Pass phrase と common name の入力

$> ./easyrsa gen-dh
$> ./easyrsa build-server-full server nopass

$> cd pki
$> sudo cp ca.crt private/ca.key issued/server.crt private/server.key  /etc/openvpn
$> sudo openvpn --genkey secret /etc/openvpn/ta.key

キー等の作成が完了したら OpenVPN サーバー設定ファイル(/etc/openvpn/server.conf)を今回の環境用に設定します。

今回は、OpenVPN 用の Azure VM を配置したサブネットの範囲が 10.1.0.0/24 となるので、VPN 用のアドレス範囲を server 10.1.0.0 255.255.255.0 と記載します。また、OpenVPN のルーティング設定に 2 つのサブネット範囲(10.1.0.0/24 と 10.1.1.0/24)を設定しておきます(push “route 10.1.0.0 255.255.255.0”, push “route 10.1.1.0 255.255.255.0”)。

DNS 設定は Azure ネットワーク既定の Azure DNS のアドレスを設定しておきます(push “dhcp-option DNS 168.63.129.16″)。

$> sudo vi /etc/openvpn/server.conf

port 1194
proto udp
dev tun
ca ca.crt
cert server.crt
key server.key  # This file should be kept secret
dh none
auth SHA256
server 10.1.0.0 255.255.255.0
ifconfig-pool-persist /var/log/openvpn/ipp.txt
push "route 10.1.0.0 255.255.255.0"
push "route 10.1.1.0 255.255.255.0"
push "dhcp-option DNS 168.63.129.16"
push "redirect-gateway eth0"
keepalive 10 120
tls-auth ta.key 0 # This file is secret
cipher AES-256-GCM
user nobody
group nogroup
persist-key
persist-tun
status /var/log/openvpn/openvpn-status.log
log    /var/log/openvpn/openvpn.log
explicit-exit-notify 1
verb 3

設定ファイルの修正が完了したら OpenVPN を起動します。起動後に status を確認して “Started OpenVPN connection to server.” とログが表示されていれば起動できているはずです。

$> sudo service openvpn@server start
$> service openvpn@server status

Ubuntu のファイアウォールとルーティング設定

OpenVPN 側の設定を行いましたが、次に OS のファイアウォールやルーティング設定を行います。

ufw にポートを追加し有効化しておきます。OpenVPN サーバー用に UDP 1194、ssh 用に TCP 22、データベース接続用に TCP 1433 ポートを追加します。ufw を有効化する際に warning が表示されますが、ssh port を追加しているので y で有効化して問題ありません。

$> sudo ufw allow 1194/udp 
$> sudo ufw allow 22 
$> sudo ufw allow 1433 

$> sudo ufw enable
Command may disrupt existing ssh connections. Proceed with operation (y|n)? y

次に IP フォワーディングの設定を有効化します。/etc/default/ufw と /etc/ufw/sysctl.conf ファイルを以下のように修正します。

$> sudo vi /etc/default/ufw
DEFAULT_FORWARD_POLICY の値を ACCEPT に変更
---
DEFAULT_FORWARD_POLICY="DROP"
↓
DEFAULT_FORWARD_POLICY="ACCEPT"
---

$> sudo vi /etc/ufw/sysctl.conf
net/ipv4/ip_forward=1 のコメントアウトを解除
---
#net/ipv4/ip_forward=1
↓
net/ipv4/ip_forward=1
---

/etc/ufw/before.rules を修正して IP マスカレード設定を追記します。ファイルの最下部に *nat 以下を追加します。

※iptables コマンドにてマスカレード設定でもよいですが(sudo iptables -t nat -A POSTROUTING -o eth0 -s 10.3.0.0/24 -j MASQUERADE)、サーバー再起動で設定が失われるため永続化させておきます。

$> sudo vi /etc/ufw/before.rules
ここで指定する IP アドレスは OpenVPN サーバー用の Azure VM の subnet 範囲です。
---
# don't delete the 'COMMIT' line or these rules won't be processed
COMMIT

*nat
:POSTROUTING ACCEPT [0:0]
-A POSTROUTING -s 10.1.0.0/24 -o eth0 -j MASQUERADE
COMMIT
---

設定が完了したら ufw を再読み込みします。

$> sudo ufw reload

以上で OpenVPN サーバー側の設定は完了です。

クライアント用設定ファイルの作成

OpenVPN サーバー側の設定が完了したため、OpneVPN クライアント用の設定ファイルを作成します。

まずは easy-rsa を用いてクライアント用証明書とキーを作成します。

$> ./easyrsa build-client-full user nopass
$> sudo cp pki/issued/user.crt pki/private/user.key /etc/openvpn

次にクライアント用設定ファイル(ovpn ファイル)を作成する下準備をします。

ovpn ファイルの元となるヘッダー用ファイル(ovpn_head)を作成します。remote 項目にて OpenVPN 用の Azure VM に設定されたパブリック IP アドレスを指定します(クライアントから OpenVPN サーバーにアクセスする宛先のアドレスを指定する箇所です)。

$> vi ovpn_head

client
dev tun
proto udp
remote <OpenVPN サーバー用 Azure VM のパブリック IP アドレス> 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
key-direction 1
cipher AES-256-GCM
auth SHA256
verb 3
user nobody
group nogroup

ovpn ファイルにキー情報等を追記するために、スクリプトの作成と実行を行います(認証ファイルやキー等をクライアント側に転送して認証でも可)。

mkovpn.sh という名前のスクリプトを作成します。適宜環境を書き換えて使用ください。

$> vi mkovpn.sh

#!/bin/bash
ca_path=/home/<ローカルユーザーファイル名>/ca/pki
key_path=/home/<ローカルユーザーファイル名>/ca/pki/private
crt_path=/home/<ローカルユーザーファイル名>/ca/pki/issued
ta_path=/etc/openvpn/
if [ $# -ne 2 ]; then
       echo "mkovpn.sh HEADER CLIENT" 1>&2
       exit 1
fi
header=$1
target=$2
cat $header
echo '<ca>'
grep -A 30 'BEGIN CERTIFICATE' "$ca_path/ca.crt"
echo '</ca>'
echo '<key>'
cat "$key_path/$target.key"
echo '</key>'
echo '<cert>'
grep -A 30 'BEGIN CERTIFICATE' "$crt_path/$target.crt"
echo '</cert>'
echo '<tls-auth>'
grep -A 30 'BEGIN OpenVPN Static key V1' "$ta_path/ta.key"
echo '</tls-auth>'

先ほど作成した ovpn_head ヘッダーファイルとスクリプトを用いて ovpn を作成します。

$> sudo bash ./mkovpn.sh ovpn_head user > user.ovpn

以上でクライアント用の設定ファイルの作成が完了しました。

このクライアントファイル(user.ovpn)を VPN 接続を行いたいオンプレミスサーバー側に scp 等で転送しておきます。

クライアントマシンから VPN の接続

OpenVPN クライアントツールのインストールと設定

VPN 接続を行いたいオンプレミスサーバー側のクライアントマシンに接続します(今回は Windows を想定します)。

VPN 接続を行うクライアントツールである OpenVPN Connect をインストールします。OpenVPN Connect を開いたら Import Profile から先に作成して scp で転送してきたクライアントファイル(user.ovpn)を読み込ませます。

OpenVPN Connect

正しく設定が行えていれば以下図のように VPN 接続が確立できます。

OpenVPN Connect より VPN 接続

これでオンプレミスサーバーマシンから OpenVPN サーバーを経由して Azure 上のネットワークに接続することができました。

VPN 経由で Azure SQL Database へ接続

これまでの設定でオンプレミスサーバーマシンから Azure ネットワークに接続できたので、Azure SQL Database のプライベートエンドポイントへの通信経路も確保されました。

ただし、Azure SQL Database へ接続する際は完全修飾ドメイン名(FQDN:xxxx.database.windows.net)を用いて接続する必要があるため、このFQDN をプライベートエンドポイントの IP アドレスへ名前解決を行う必要があります。

DNS フォワーダーでも、自前の DNS サーバーのプライベート DNS ゾーンを用いて名前解決を行うことも良いですし、Azure DNS Private Resolver を用いて名前解決するのでもよいです。今回はテストのため、ローカルの hosts ファイルで名前解決を行います。

# Copyright (c) 1993-2009 Microsoft Corp.
#
# This is a sample HOSTS file used by Microsoft TCP/IP for Windows.
#
# This file contains the mappings of IP addresses to host names. Each
# entry should be kept on an individual line. The IP address should
# be placed in the first column followed by the corresponding host name.
# The IP address and the host name should be separated by at least one
# space.
#
# Additionally, comments (such as these) may be inserted on individual
# lines or following the machine name denoted by a '#' symbol.
#
# For example:
#
#      102.54.94.97     rhino.acme.com          # source server
#       38.25.63.10     x.acme.com              # x client host

# localhost name resolution is handled within DNS itself.
#	127.0.0.1       localhost
#	::1             localhost

10.1.1.4 <SQL サーバー名>.database.windows.net

SQL Server Management Studio(SSMS)からデータベースへ接続してみます。

SSMS で接続情報を入力

プライベート接続が行えていることも確認ができました。

接続元 IP アドレスを確認

以上でオンプレミスサーバーから OpenVPN を経由して Azure SQL Database のプライベートエンドポイントへ接続ができました。

おまけ

今回の設定だとクライアントマシンからのすべての接続が VPN サーバーを経由します。

特定の接続(Azure SQL Database への接続)のみに絞りたい場合は ovpn クライアントファイルに route-nopullroute でそのアドレス範囲を指定します。

Client
dev tun
proto udp
remote <OpenVPN サーバー用 Azure VM のパブリック IP アドレス> 1194
resolv-retry infinite
nobind
persist-key
persist-tun
remote-cert-tls server
key-direction 1
cipher AES-256-GCM
auth SHA256
verb 3
user nobody
group nogroup
route-nopull
route 10.1.1.0 255.255.255.0

さいごに

参考にさせていただいたサイトは以下の通りです。

Hardening OpenVPN Security | OpenVPN

Guide To Set Up & Configure OpenVPN Client/Server VPN | OpenVPN

ubuntu 20.04 LTS serverにOpenVPNをインストール #Ubuntu – Qiita

OpenVPNのインストールとセットアップからインターネット接続までのガイドブック

*本記事は公式の情報ではなく個人の投稿です。正式では無い情報を含む場合があります。

コメント

タイトルとURLをコピーしました