Ubuntu ServerでOpenVPNサーバーを構築する

自宅に立ち上げたUbuntu Serverを経由して、自宅の外から安全に自宅内のネットワークに接続できるようにVPN (Virtual Private Network)環境を構築します。OpenVPNを使うと、SSL/TLSによるSSL VPN環境を構築できます。

ufwが有効の場合、iptablesコマンドを使ったOpenVPNのルーティング設定はうまく動きませんでした。しかし、ufwの設定ファイルにルーティング設定を追加することでOpenVPNクライアントから自宅内のネットワークやインターネット接続ができるようになりましたので、その設定方法についても紹介します。

IP forwardingの設定

/etc/sysctl.confを変更してIP forwardingを有効にします。

sudo nano /etc/sysctl.conf

net.ipv4.ip_forward行の先頭にある#を削除して、コメントを解除して上書き保存します。

# Uncomment the next line to enable packet forwarding for IPv4
net.ipv4.ip_forward=1

変更した設定を再読み込みします。

sudo sysctl -p /etc/sysctl.conf

OpenVPNのインストール

aptでOpenVPNとeasy-rsaをインストールします。

sudo apt update
sudo apt install openvpn easy-rsa

PKI(公開鍵基盤)のセットアップ

OpenVPNはPKI(公開鍵基盤)を使って証明書による認証を行います。クライアントはサーバー証明書を認証し、サーバーはクライアント証明書を認証します。

  • サーバーとクライアントの証明書に署名するために使用される、マスター認証局(CA)の証明書(公開鍵)と秘密鍵
  • サーバーの証明書と秘密鍵
  • 各クライアントの個別の証明書と秘密鍵

認証局(CA)のセットアップ

以下のコマンドでeasy-rsaディレクトリを作成します。

make-cadir ~/easy-rsa

easy-rsa/varsファイルを変更して証明書のDN(識別名)情報に含める国・県・市・組織・部署の名前を入力することもできますが、varsファイルの説明を読むと、デフォルトの「cn_only」ではこれらの名前は無視されてCN、つまりCommon Nameのみを使用するとのこと。

easy-rsaディクレトリの中に移動し、以下のコマンドを実行します。build-caでCommon Nameが尋ねられたらEnter キーを押してデフォルト値のまま進めます。

cd ~/easy-rsa
./easyrsa init-pki
./easyrsa build-ca nopass

CA証明書(pki/ca.crt)と秘密鍵(pki/private/ca.key)がeasy-rsaディレクトリの中に作成されます。

~/easy-rsa$ ./easyrsa init-pki

init-pki complete; you may now create a CA or requests.
Your newly created PKI dir is: /【ホームディレクトリのパス】/easy-rsa/pki

~/easy-rsa$ ./easyrsa build-ca nopass
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
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]:【Enterキーを押す】

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/【ホームディレクトリのパス】/easy-rsa/pki/ca.crt

~/easy-rsa$ ls -l pki/*.crt
-rw------- 1 xxx xxx 1204  x月 xx xx:xx pki/ca.crt
~/easy-rsa$ ls -l pki/private/*.key
-rw------- 1 xxx xxx 1704  x月 xx xx:xx pki/private/ca.key

サーバー証明書と秘密鍵の作成

easy-rsaディクレトリの中で、以下のコマンドを実行します。

./easyrsa gen-req server nopass

Common Nameが尋ねられたらデフォルトのままEnterキーを押します。証明書要求(pki/reqs/server.req)と秘密鍵(pki/private/server.key)が作成されます。

~/easy-rsa$ ./easyrsa gen-req server nopass
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
............+......+..........+.....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+...+.......+........+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*......+...............+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
.+..+.+..+....+...+..+....+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*.+..+.+......+...+...+.....+....+...+...+...+.....+......+..........+...+..+....+..+..........+..+...+.......+..+.+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++*...+.+.....+.+...+.........+..+.+...+.........+..+...+.+..............+......+.......+..+.......+...........+............+...+..........+..............+...+...+.......+.....+.+.....+.+........+.+......+...+...+..............+....+............+..+.............+...+...........+.+...+......+........+...............+......+.........+......+.+......+..+......+...............+.......+.....+.......+..+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
-----
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) [server]:【Enterキーを押す】

Keypair and certificate request completed. Your files are:
req: /【ホームディレクトリのパス】/easy-rsa/pki/reqs/server.req
key: /【ホームディレクトリのパス】/easy-rsa/pki/private/server.key

~/easy-rsa$ ls -l pki/reqs/*.req
-rw------- 1 xxx xxx 887  x月 xx xx:xx pki/reqs/server.req
~/easy-rsa$ ls -l pki/private/*.key
-rw------- 1 xxx xxx 1704  x月 xx xx:xx pki/private/ca.key
-rw------- 1 xxx xxx 1704  x月 xx xx:xx pki/private/server.key

続けて、以下のコマンドを実行します。

./easyrsa sign-req server server

サーバー証明書(pki/issued/server.crt)がeasy-rsaディレクトリの中に作成されます。2023年5月現在のUbuntu 22.04.02 LTS上ではerrorが発生していますが、このまま操作を続けていきます。

~/easy-rsa$ ./easyrsa sign-req server server
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)

You are about to sign the following certificate.
Please check over the details shown below for accuracy. Note that this request
has not been cryptographically verified. Please be sure it came from a trusted
source or that you have verified the request checksum with the sender.

Request subject, to be signed as a server certificate for 825 days:

subject=
    commonName                = server


Type the word 'yes' to continue, or any other input to abort.
  Confirm request details: 【yesと入力する】
Using configuration from /【ホームディレクトリ】/easy-rsa/pki/easy-rsa-xxxxx/tmp.xxxxx
40275399217F0000:error:0700006C:configuration file routines:NCONF_get_string:no value:../crypto/conf/conf_lib.c:315:group=<NULL> name=unique_subject
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName            :ASN.1 12:'server'
Certificate is to be certified until xxx xx xx:xx:xx xxxx GMT (825 days)

Write out database with 1 new entries
Data Base Updated

Certificate created at: /【ホームディレクトリ】/easy-rsa/pki/issued/server.crt

~/easy-rsa$ ls -l pki/issued/*.crt
-rw------- 1 xxx xxx 4609  x月 xx xx:xx pki/issued/server.crt

DHパラメーターの作成

以下のコマンドを実行して、OpenVPNサーバー用のDH(Diffie Hellman)パラメーターファイルを作成します。

./easyrsa gen-dh
/easy-rsa$ ./easyrsa gen-dh
Using SSL: openssl OpenSSL 3.0.2 15 Mar 2022 (Library: OpenSSL 3.0.2 15 Mar 2022)
Generating DH parameters, 2048 bit long safe prime
........................+.........................................................................................................................................................+.........................................................................................................++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*++*

DH parameters of size 2048 created at /【ホームディレクトリ】/easy-rsa/pki/dh.pem

~/easy-rsa$ ls -l pki/*.pem
-rw------- 1 xxx xxx 424  x月 xx xx:xx pki/dh.pem

TLS認証用秘密鍵の作成

以下のコマンドを実行して、TLS認証用秘密鍵を作成します。

openvpn --genkey secret ta.key

以前は以下のように–secretを指定していましたが、2023年5月現在のUbuntu Server 22.04.2 LTSでは警告メッセージが表示されるようになりました。

~/easy-rsa$ openvpn --genkey --secret ta.key
2023-05-14 15:46:44 WARNING: Using --genkey --secret filename is DEPRECATED.  Use --genkey secret filename instead.

/etc/openvpn/server/にファイルコピー

ここまで作成したファイルを/etc/openvpn/server/にコピーします。

sudo cp pki/ca.crt pki/private/ca.key pki/issued/server.crt pki/private/server.key pki/dh.pem ta.key /etc/openvpn/server/

クライアントごとに証明書と秘密鍵の作成

OpenVPNサーバーに接続するクライアント用の証明書を作っていきます。この作業はクライアントごとに実施します。クライアントの名前は例として【myclient1】を使っています。

./easyrsa gen-req myclient1 nopass    # Common NameはデフォルトのままEnterキーを押す
./easyrsa sign-req client myclient1   # 確認メッセージが表示されたら「yes」を入力する

OpenVPNサーバーの環境設定

サンプルのserver.confをコピーして、OpenVPNサーバーの環境設定を行います。

sudo bash    # root権限でbashを起動する
cd /etc/openvpn/server/
cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf .
nano server.conf

以下はserver.confの一部抜粋です。「push “route 【ネットワークアドレス】【サブネットマスク】”」はLANのネットワークアドレス(192.168.xxx.0/24)のドット表記です。他の設定項目はデフォルトのままにしています。

port   1194    # ポート番号
proto  udp     # プロトコル
dev    tun     # ルーティング方式を使用

ca     ca.crt     # CA証明書のファイル名
cert   server.crt # サーバー証明書のファイル名
key    server.key # サーバー秘密鍵のファイル名
dh     dh.pem     # DHパラメーターのファイル名

server 10.8.0.0 255.255.255.0                   # VPNで使用するプライベートIPとサブネットマスク
ifconfig-pool-persist /var/log/openvpn/ipp.txt  # IPアドレスのテーブルファイル
push "route 192.168.xxx.0 255.255.255.0"        # 外部からLANへのトラフィックをVPNサーバー経由とする 
push "redirect-gateway def1 bypass-dhcp"        #トラフィックの全てをOpenVPN経由とする
push "dhcp-option DNS 8.8.8.8"                  # GoogleDNSを使用
client-to-client                                # クライアント間の接続を許可
keepalive 10 120                                # 生存確認を実施
tls-auth ta.key 0                               # TLS認証有効化(0はサーバ側, 1はクライアント側)
data-ciphers AES-256-GCM:AES-128-GCM:AES-128-CBC  # 互換性確保のため、複数のcipherを指定する

server.confの編集が終わったらroot権限で起動したbashを終了します。

exit

OpenVPNサーバーの起動

openvpn-serverサービスの起動

systemctlコマンドを使ってOpenVPNサーバーを起動します。openvpnサービスを使わずにopenvpn-serverサービスを使います。

# openvpnサービスは使わない
sudo systemctl stop openvpn
sudo systemctl disable openvpn

# openvpn-serverサービスを使う
sudo systemctl enable openvpn-server@server
sudo systemctl start openvpn-server@server

systemctl statusコマンドでopenvpn-serverサービスの状態を確認します。「Active:」が「active (running)」になっていれば動作しています。

~$ sudo systemctl status openvpn-server@server
● openvpn-server@server.service - OpenVPN service for server
     Loaded: loaded (/lib/systemd/system/openvpn-server@.service; enabled; vendor preset: enabled)
     Active: active (running) since ・・・
       Docs: man:openvpn(8)
             https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
             https://community.openvpn.net/openvpn/wiki/HOWTO
   Main PID: ・・・ (openvpn)
     Status: "Initialization Sequence Completed"
      Tasks: 1 (limit: 18358)
     Memory: 1.8M
        CPU: 31ms
     CGroup: /system.slice/system-openvpn\x2dserver.slice/openvpn-server@server.service
             └─31826 /usr/sbin/openvpn --status /run/openvpn-server/status-server.log --status-version 2 --suppress-timestamps --config server.conf

また、ssコマンドを使ってUDPのポートが受信待ち(listeningの状態)になっていることを確認します。server.confに指定した1194はopenvpnのデフォルトポート番号です。

~$ ss -ul|grep openvpn
UNCONN 0      0            0.0.0.0:openvpn          0.0.0.0:*

ufwによるファイアウォールとルーティングの設定

ネットを検索すると、iptablesコマンドを使ってOpenVPNとLANのルーティングを設定するやり方をよく見かけますが、ファイアウォールを有効にしている場合はiptablesによるルーティング設定がうまく動作しませんでした。

そこで、ufwの設定ファイルを変更してOpenVPNとLANのルーティングを設定します。

ファイアウォールの設定

ufwコマンドを使ってOpenVPNサーバーのUDPポートへの接続を許可します。

sudo ufw allow openvpn/udp

FORWARDのポリシーの許可

/etc/default/ufwを編集します。

sudo nano /etc/default/ufw

DEFAULT_FORWARD_POLICYを”ACCEPT”にします。

DEFAULT_OUTPUT_POLICY="ACCEPT"

ufwのルールの追加

/etc/ufw/before.rulesを編集します。

sudo nano /etc/ufw/before.rules

OpenVPNクライアントからインターネットへアクセスできるようにnatの設定を追加します。*nat〜COMMITを*filterより前に挿入します。「enp2s0f0」の部分はLAN側のネットワークインターフェイス名に変更します。

#
# rules.before
#
# Rules that should be run before the ufw command line added rules. Custom
# rules should be added to one of these chains:
#   ufw-before-input
#   ufw-before-output
#   ufw-before-forward
#

# natの設定は*filterの前に追加する
*nat
:POSTROUTING ACCEPT [0:0]

# OpenVPNクライアントをインターネットにルーティングできるようにする
-A POSTROUTING -s 10.8.0.0/24 -o enp2s0f0 -j MASQUERADE

COMMIT

# Don't delete these required lines, otherwise there will be errors
*filter
(以下略)

さらに、OpenVPNクライアントからOpenVPNサーバーへアクセスできるようにfilterの設定を追加します。

# Don't delete these required lines, otherwise there will be errors
*filter
:ufw-before-input - [0:0]
:ufw-before-output - [0:0]
:ufw-before-forward - [0:0]
:ufw-not-local - [0:0]
# End required lines

# OpenVPNクライアントからOpenVPNサーバーへの接続を許可する
-A ufw-before-input -i tun+ -j ACCEPT

# allow all on loopback
(以下略)

/etc/ufw/before.rulesを保存したら、ufwの変更した設定を再読み込みします。

sudo ufw reload

ルーターの設定

静的NAPT設定の変更

自宅の外からOpenVPNサーバーに接続できるように、ルーターの静的NAPT設定を変更します。WAN 側に公開するポート番号はOpenVPNクライアントの接続先ポート番号になります。また、NAPTの宛先はOpenVPNサーバーのLAN側IPアドレスとUDPポート番号1194になります。

また、詳細は割愛しますが、ダイナミックDNSを使ってルーターのWAN側ホストを探索できるようにしておけば、WAN側IPアドレスが変わってもOpenVPNクライアント側は接続先ホストの設定を変更する必要が無くなるので便利です。

ovpnファイルの作成

OpenVPNクライアントには以下のようなソフト・アプリがあります。いずれもovpnファイルを読み込んでOpenVPNサーバーへの接続設定を追加することができます。

WindowsOpenVPN GUI for Windows
MacTunnelblick
iPhoneなどOpenVPN Connect

ovpnファイルはクライアント用の設定ファイルのサンプルを使って、PKIのセットアップ時に作成したCA証明書( pki/ca.crt)、クライアントごとに作成した証明書(pki/issued/myclient1.crt)と秘密鍵(pki/private/myclient1.key)、TLS認証用秘密鍵(ta.key)の中身をコピーして作ります。

テキストファイルを2つ開くと作業が楽ですので、WindowsやMacのターミナルを2つ起動するか、またはtmuxのような複数画面を開けるツールを使います。

1つ目のターミナルで以下のようにサンプルのclient.confをコピーして、myclient1.ovpnという名前のファイルを作成し、テキストエディタで開きます。

cp /usr/share/doc/openvpn/examples/sample-config-files/client.conf  ./myclient1.ovpn
nano ./myclient1.ovpn

./myclient1.ovpnの設定を確認しながら「ca」「cert」「key」行を探して、セミコロンでコメントアウトします。なお、「remote」行にはルーターのIPアドレスかダイナミックDNSのドメイン名と公開ポート番号を指定します。

client
dev tun
proto udp

remote 【ルーターのWAN側ホスト】 【ルーターのWAN側に公開するポート番号】

;ca ca.crt
;cert client.crt
;key client.key

「ca」「cert」「key」行の代わりに「<ca>〜</ca>」「<cert>〜</cert>」「<key>〜</key>」を追加して、それぞれの内側にCA証明書・クライアントの証明書および秘密鍵をコピーします。2つ目のターミナルでこれらのファイルをテキストエディタで開くとコピーしやすいです。

<ca>
ここには pki/ca.crt の中身をコピーする
</ca>
<cert>
ここには pki/issued/myclient1.crt の
-----BEGIN CERTIFICATE-----から
-----END CERTIFICATE-----までをコピーする
</cert>
<key>
ここには pki/private/myclient1.key の中身をコピーする
</key>

同様に「tls-auth」行もコメントアウトして「<tls-auth>〜</tls-auth>」を追加します。さらに「key-direction」行も追加します。

;tls-auth ta.key 1
<tls-auth>
ta.keyの中身をコピーする
</tls-auth>
key-direction 1

OpenVPNサーバー側には複数のcipherを指定したので、クライアント側も同様にします。

;cipher AES-256-CBC
data-ciphers AES-256-GCM:AES-128-GCM:AES-128-CBC

作成したovpnファイルはWindowsやMac、iPhoneなどに転送して、各ソフト・アプリに登録します。

WindowsやMacにはSamba経由でも転送できますが、scpコマンドを使って転送するのが無難でしょう。

iPhoneの場合はMacとケーブル接続して、Finder経由でファイル共有するのが安全かと思います。

シェアする

  • このエントリーをはてなブックマークに追加

フォローする