0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

Ubuntu 24.04 Server で OpenVPN のブリッジ接続サーバを導入しネームサーバ・DHCPサーバと同時運用する 2 : サーバの設定

Last updated at Posted at 2025-04-04

前の記事はこちら → 1 : Easy-RSA による証明書等の準備

2 : サーバの設定

以上で、必要な証明書や鍵などのファイルの準備が整いました。

いよいよ、サーバの設定ファイルなど、サーバ本体を構築していきます。

サーバのホストで作業します。

2-1 OpenVPNサーバの設定ファイルを作成

サーバの基本的な 設定ファイル server.conf/etc/openvpn/server.conf)を作ります。

実際には、 /etc/openvpn/server/ に ファイル server.conf を作って保持し、それへのシンボリックリンクを /etc/openvpn/ に置きました。

root<serverhost/etc/openvpn> % cd server
root<serverhost/etc/openvpn/server> % cp /usr/share/doc/openvpn/examples/sample-config-files/server.conf .
root<serverhost/etc/openvpn/server> % vim server.conf

下敷きにしたサンプルファイルの中には詳しい説明(コメント)が含まれているので、読めば参考にもなります。
ここでは、最終的な設定内容だけを示しておきます。

/etc/openvpn/server/server.conf
port 1194

proto udp

dev tap0

ca /etc/openvpn/ca.crt
cert /etc/openvpn/serverhost.crt
key /etc/openvpn/serverhost.key  # This file should be kept secret

dh /etc/openvpn/dh.pem

topology subnet

server-bridge

client-to-client

keepalive 10 120

tls-auth /etc/openvpn/ta.key 0 # This file is secret

user nobody
group nogroup

persist-key
persist-tun

status /var/log/openvpn/openvpn-status.log

log-append /var/log/openvpn/openvpn.log

verb 3

explicit-exit-notify 1

management localhost 7505

crl-verify /etc/openvpn/crl.pem

ファイルを保存したらシンボリックリンクを作ります。

root<serverhost/etc/openvpn/server> % cd ..
root<serverhost/etc/openvpn> % ln -s server/server.conf
server.conf の内容に関するメモ

参考 : man openvpn
参考 : Deprecated Options in OpenVPN

設定内容 メモ
port 1194proto udp ポートは UDP 1194 を使うようにしました。
dev tap0 OpenVPN の tap接続 は、 OS からはネットワークインタフェースとして扱われ、インタフェース名が tapXX は数字)となるようです。ここでは、 tap0 と指定しました。
topology subnet いまでは subnet にするのが当たり前らしいですが、 バージョン 2.0.9 以前の古い Windows クライアントと通信するには net30 にしなければならず、そのために用意されているオプションのようです。デフォルトが net30 のため、このオプションは入れておいたほうがいいようです。デフォルトの変更が検討されているとのことで、急にデフォルト挙動が変わったとき焦らないためにも、入れておくほうがよいとのこと。
server-bridge server-bridge の後に何も書かないこのオプションは、 mode server tls-server push "route-gateway dhcp" の3つを指定するのと同等とのこと。要するに、接続してきたクライアントがローカルネットワーク内の DHCPサーバ を使うようになるということです。なお、 server-bridge の後に色々つける形のオプションは、これと異なり OpenVPNサーバ が DHCP に相当する役割もする設定になります。
user nobodygroup nogroup 起動時の必要な設定が終わったらサーバの権限を降格させてセキュリティを向上させます。指定する ユーザ名 nobody と グループ名 nogroup が実際に存在しないと駄目だそうなので、システムに合わせて変える必要があります。
persist-keypersist-tun 上のオプションを使って権限を降格させるとサーバのリロード時に権限が足りずたとえば秘密鍵ファイルを読めないなどでエラーになるらしいのですが、それを防ぐ動作をさせるオプションです。 persist-key のほうは、「指定しなくてもつねに有効になるので不要」との情報を見つけたのですが、試しに消してみたところ接続できなくなりました。どうやら「今後そうする方向で検討中」ということのようです。
cipher AES-256-CBC いまのバージョンの OpenVPN では、サーバとクライアントが相談して利用可能な中から最適なサイファを決めるようになっているそうで、オプションでの指定は必要ないようです。 バージョン 2.3 以前のクライアントと通信する場合は互換性のために入れてもよいとの情報がありますが、しないと思うので省きました。
comp lzo ネット上の情報ではこれを入れるべきという説明が多いのですが、最新の情報では「圧縮は推奨しないしユーザが使うのを避けるべき機能の1つである」だそうです。なので入れませんでした。
management localhost 7505 稼働中のサーバをネットワークからアクセスしてコントロールできる 管理インタフェース を有効にします。 7505 は使うポートです。このポートに telnet でアクセスすることで利用できます。

2-2 証明書や鍵のファイルを適切な場所に置く

1 : Easy-RSA による証明書等の準備 で用意した証明書や鍵のファイルのうち OpenVPN のサーバに必要なものを、コピーしてきて適切な場所(/etc/openvpn)に置きます。

OpenVPN のサーバが必要とするファイルは以下です。

必要なもの ファイル名
サーバの証明書 serverhost.crt
サーバの秘密鍵 serverhost.key
CAの証明書 ca.crt
証明書失効リスト crl.pem
DHパラメータ dh.pem
TLS認証鍵 ta.key

2-2-1 CA証明書

CAの証明書 はサーバ・クライアントともに持つ必要があります。
サーバの分として、 ca.crt/etc/openvpn/ にコピーします。

root<serverhost/etc/openvpn> % cp /etc/openvpn/easy-rsa/pki/ca.crt .

CAの秘密鍵 は CA として証明書を発行するためのもので、 VPNサーバ や VPNクライアント には必要ないものです。
CA から絶対に漏洩してはならないものなので、ディレクトリのパーミッションに注意してそのまま保管します。

2-2-2 サーバ証明書・サーバ秘密鍵

(1) 適切な場所にコピーする

サーバの証明書サーバの秘密鍵 はサーバが持つ必要があります。
serverhost.crtserverhost.key/etc/openvpn/ にコピーします。
実際には、2つのファイルを /etc/openvpn/server/ にコピーして保持し、それらへのシンボリックリンクを /etc/openvpn/ に置きました。

root<serverhost/etc/openvpn> % cp /etc/openvpn/easy-rsa/pki/issued/serverhost.crt ./server/
root<serverhost/etc/openvpn> % cp /etc/openvpn/easy-rsa/pki/private/serverhost.key ./server/
root<serverhost/etc/openvpn> % ln -s server/serverhost.crt
root<serverhost/etc/openvpn> % ln -s server/serverhost.key

(2) 秘密鍵からパスフレーズを取り除く

サーバの秘密鍵 にはパスフレーズがついています。
試してみたところ、このままでは、パスフレーズを入力しない限りこれらを利用できないため、 VPN接続 ができないように思えました(実はあまりちゃんと確かめてませんが…)。
そこで、 サーバの秘密鍵 からパスフレーズを取り除きます。

openssl コマンドで行います。具体的には、 openssl rsa -in 元の秘密鍵ファイル -out パスフレーズの取り除かれた秘密鍵を格納するファイル名 とします。
Enter pass phrase for serverhost.key.BACKUP: でそのパスフレーズを入力します。

root<serverhost/etc/openvpn> % cd server/
root<serverhost/etc/openvpn/server> % mv serverhost.key serverhost.key.BACKUP
root<serverhost/etc/openvpn/server> % openssl rsa -in serverhost.key.BACKUP -out serverhost.key
Enter pass phrase for serverhost.key.BACKUP:
writing RSA key

なお、 サーバの秘密鍵 は決して漏れたり盗まれたりしてはならないものなわけですが、そこからパスフレーズを取り除いてしまうのはセキュリティ上の危険性をだいぶ上げてしまうことと言えます。ですから、このファイルが盗まれたら(パスフレーズがあれば秘密鍵は漏洩しない可能性があったところ、パスフレーズを取り除いてしまったので)一巻の終わり、と考え、ファイルとディレクトリのパーミッションに細心の注意を払っておく必要があります。

このファイルの オーナー は root:root にし、 パーミッション は 600 にしました。

2-2-3 DHパラメータ

DHパラメータ はサーバが使います。
dh.pem/etc/openvpn/ にコピーします。
実際には、ファイルを /etc/openvpn/server/ にコピーして保持し、それへのシンボリックリンクを /etc/openvpn/ に置きました。

root<serverhost/etc/openvpn> % cp /etc/openvpn/easy-rsa/pki/dh.pem ./server/
root<serverhost/etc/openvpn> % ln -s server/dh.pem

2-2-4 CRL

CRL はサーバが持ちます。
crl.pem/etc/openvpn/ にコピーします。
実際には、ファイルを /etc/openvpn/server/ にコピーして保持し、それへのシンボリックリンクを /etc/openvpn/ に置きました。

root<serverhost/etc/openvpn> % cp /etc/openvpn/easy-rsa/pki/crl.pem ./server/
root<serverhost/etc/openvpn> % ln -s server/crl.pem

CRL は、今後、何らかの証明書が失効するたびに直ちに作り直され、サーバに渡されなければなりません。
つまり、 OpenVPNサーバ が持つ CRL は、つねに 手動で 置き換えて最新のものに保たれ続けなければならないということです。

2-2-5 TLS認証鍵

TLS認証鍵 はサーバ・クライアントともに持つ必要があります。
ta.key ですが、サーバのホストでは、すでに適切な場所(/etc/openvpn)に置いてあります。

TLS認証鍵 は漏洩してはならないものですから、パーミッションに注意します。
オーナー は root:root にし、 パーミッション は 600 にしました。

2-3 ブリッジインタフェースを操作するスクリプトを用意

仮想インタフェースである tap0 と 物理インタフェース(eno1 とします) の間で自由にパケットを行き来させることにより、外部から接続しているクライアントにとって内部と全く同等な環境を実現することができます。
この、2つのインタフェースを繋ぐ機能は、 ブリッジインタフェース という仮想インタフェースの形で提供されます。

ブリッジインタフェース という仕組みを提供するのは、 OpenVPN ではなく、 OS です。
それを操作するためのツールが bridge-utils というパッケージで与えられているわけです。

ブリッジインタフェース を作ったり削除したりするツールは brctl です。
それを使い OpenVPN の tap接続 に必要な ブリッジインタフェース を起動/停止するシェルスクリプトを作ります。起動するほうを bridge-start、停止するほうを bridge-stop とします。
これらは、 /etc/openvpn/ に置くことにします。

下敷きにするサンプルファイルをコピーしてくる
root<serverhost/etc/openvpn> % cp /usr/share/doc/openvpn/examples/sample-scripts/bridge-start .
root<serverhost/etc/openvpn> % cp /usr/share/doc/openvpn/examples/sample-scripts/bridge-stop .
起動用のスクリプト
root<serverhost/etc/openvpn> % vim bridge-start

書き換える箇所を diff で示します。
左が元の(サンプル)ファイル、右が書き換え後。

17,18c17,18
< eth="eth0"
< eth_ip="192.168.8.4"
---
> eth="eno1"
> eth_ip="192.168.0.2"
20c20,21
< eth_broadcast="192.168.8.255"
---
> eth_broadcast="192.168.0.255"
> gw="192.168.0.1"
32a34,35
> sleep 1
> 
36a40,41
> sleep 1
> 
39a45,47
> 
> route add default gw $gw
> 

ファイル全体はこうです。

/etc/openvpn/bridge-start
#!/bin/sh

#################################
# Set up Ethernet bridge on Linux
# Requires: bridge-utils
#################################

# Define Bridge Interface
br="br0"

# Define list of TAP interfaces to be bridged,
# for example tap="tap0 tap1 tap2".
tap="tap0"

# Define physical ethernet interface to be bridged
# with TAP interface(s) above.
eth="eno1"
eth_ip="192.168.0.2"
eth_netmask="255.255.255.0"
eth_broadcast="192.168.0.255"
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

sleep 1

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

sleep 1

ifconfig $eth 0.0.0.0 promisc up

ifconfig $br $eth_ip netmask $eth_netmask broadcast $eth_broadcast

route add default gw $gw

停止用のスクリプト

bridge-stop はサンプルファイルのまま、どこも書き換えずに使うことができました。

ファイル全体はこうです。

/etc/openvpn/bridge-stop
#!/bin/sh

####################################
# Tear Down Ethernet bridge on Linux
####################################

# Define Bridge Interface
br="br0"

# Define list of TAP interfaces to be bridged together
tap="tap0"

ifconfig $br down
brctl delbr $br

for t in $tap; do
    openvpn --rmtun --dev $t
done
実行権限をつける

これら2つのスクリプトに実行パーミッションを与えます。

root<serverhost/etc/openvpn> % chmod a+x bridge-start bridge-stop

2-4 systemd のサービスの設定

システム起動時に OpenVPN のサーバを起動しブリッジインタフェースを起動するように systemd に指示するため、ユニットファイルを用意し、サービスの設定をします。

OpenVPNサーバ を起動するユニットファイルは openvpn.service など用意されているようなのですが、ブリッジインタフェースを起動/停止するユニットファイルはないようなので、作ります。

2-4-1 ブリッジインタフェースを起動/停止するユニットファイルを作る

openvpn-bridge.service/usr/lib/systemd/system/openvpn-bridge.service)として作りました。

root<serverhost/etc/openvpn> % cd /usr/lib/systemd/system/
root<serverhost/usr/lib/systemd/system> % ls o*
open-iscsi.service     openvpn-client@.service  openvpn.service
open-vm-tools.service  openvpn-server@.service  openvpn@.service
root<serverhost/usr/lib/systemd/system> % vim openvpn-bridge.service

openvpn-bridge.service は、 bridge-startbridge-stop を呼び出してブリッジインタフェースを起動したり停止したりする内容です。
ファイル全体は次のとおり。

/usr/lib/systemd/system/openvpn-bridge.service
[Unit]
Description=Openvpn bridge service
Requires=openvpn@server.service
After=openvpn@server.service

[Service]
Type=oneshot
RemainAfterExit=yes
ExecStart=/etc/openvpn/bridge-start
ExecReload=/bin/true
ExecStop=/etc/openvpn/bridge-stop

[Install]
WantedBy=multi-user.target

2-4-2 systemd で必要なサービスを有効化する

あとは、 systemd で適切なサービスを有効化しておけば、システム起動時に OpenVPN のサーバが自動的に起動します。

有効化するのは、いま作ったブリッジインタフェースを起動する openvpn-bridge と、 server.conf の設定に従うサーバを起動する openvpn@server です。

最初から有効化されている openvpn は必要ないので、無効化してしまいます。

サービス openvpn の無効化
root<serverhost/usr/lib/systemd/system> % cd
root<serverhost~> % systemctl disable openvpn
Synchronizing state of openvpn.service with SysV service script with /usr/lib/systemd/systemd-sysv-install.
Executing: /usr/lib/systemd/systemd-sysv-install disable openvpn
Removed "/etc/systemd/system/multi-user.target.wants/openvpn.service".
サービス openvpn-bridge の有効化
root<serverhost~> % systemctl enable openvpn-bridge
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn-bridge.service → /usr/lib/systemd/system/openvpn-bridge.service.
サービス openvpn@server の有効化
root<serverhost~> % systemctl enable openvpn@server
Created symlink /etc/systemd/system/multi-user.target.wants/openvpn@server.service → /usr/lib/systemd/system/openvpn@.service.

なお、 openvpn@serveropenvpn@.service というユニットファイルが実体です。 @ の後ろの serverサーバの設定ファイルの名前 で、今回は server.conf なので server をつけているのです。

2-5 ファイアウォールの設定

ゲートウェイ(ブロードバンドルータ)の設定を変え、ホスト 192.168.0.2 の udp 1194 ポート を WAN に開放します。

2-6 ブリッジインタフェースに関わるリゾルバの設定

いろいろ試してみて気づいたのですが、サーバのホストでブリッジインタフェースを起動すると、なぜかサーバのホストから DNS にアクセスできなくなることがわかりました。 DNSサーバ は同じホストで稼働しています。他のホストからは問題なく DNS を使えているので、ブリッジインタフェースの起動によってサーバのホストのリゾルバの設定がおかしくなってしまうのだと考えられます。

さらにいろいろ試した結果、リゾルバ設定が ネットワークインターフェース eno1 に関連づけられているためだとわかりました。
リゾルバ設定は NetworkManager によって管理されているので、 NetworkManager の設定を編集して、 ブリッジインタフェース br0 に関連づけたリゾルバ設定を加えます。
恥ずかしながら NetworkManager もあまりよく理解していないので、ちょっと苦戦しました。

/etc/netplan/50-cloud-init.yaml を編集します。

root<serverhost~> % cd /etc/netplan/
root<serverhost/etc/netplan> % vim 50-cloud-init.yaml

network: の下の ethernets: の下に br0: エントリを追加します。
最終的にファイル全体はこうなりました。

/etc/netplan/50-cloud-init.yaml
# This file is generated from information provided by the datasource.  Changes
# to it will not persist across an instance reboot.  To disable cloud-init's
# network configuration capabilities, write a file
# /etc/cloud/cloud.cfg.d/99-disable-network-config.cfg with the following:
# network: {config: disabled}
network:
    ethernets:
        eno1:
            addresses:
            - 192.168.0.2/24
            nameservers:
                addresses:
                - 192.168.0.2
                search:
                - my.domain
            routes:
            -   to: default
                via: 192.168.0.1
        br0:
            nameservers:
                addresses:
                - 192.168.0.2
                search:
                - my.domain
    version: 2

書き換えを反映させるために次のコマンドを実行します。

root<serverhost/etc/netplan> % netplan apply

これで、 DNS の問題は解決しました。

2-7 DHCPサーバが正しく機能するようにする

受け売りになりますが、 VPNサーバ を DHCPサーバ と同じホスト上で動かした場合、 DHCPサーバ の起動より先にブリッジインタフェースが作られていないと、 DHCPサーバ がブリッジインタフェースを listen しないことがあるそうです。
参考 : OpenVPNのtapブリッジングでDHCPを使う場合のTips

そうなると、 VPNクライアント が接続してきたとき、 VPN として接続できたとしてもIPアドレスなどが割り振られず、結局、機能しないことになってしまいます。
実際に、試してみると、そのとおりだと思えるようなことが起こりました。

この問題を解決するために、システムを起動するときの isc-dhcp-server の起動が openvpn-bridge の起動よりも後になるようにします。

systemd の ユニットファイル isc-dhcp-server.service を書き換えます。

root<serverhost/etc/netplan> % cd /usr/lib/systemd/system/
root<serverhost/usr/lib/systemd/system> % vim isc-dhcp-server.service

[Unit] セクションに次の1行を加えます。

After=openvpn-bridge.service

ファイル全体はこうなります。

/usr/lib/systemd/system/isc-dhcp-server.service
[Unit]
Description=ISC DHCP IPv4 server
Documentation=man:dhcpd(8)
Wants=network-online.target
After=network-online.target
After=time-sync.target
After=openvpn-bridge.service
ConditionPathExists=/etc/default/isc-dhcp-server
ConditionPathExists=|/etc/ltsp/dhcpd.conf
ConditionPathExists=|/etc/dhcp/dhcpd.conf

[Service]
EnvironmentFile=/etc/default/isc-dhcp-server
RuntimeDirectory=dhcp-server
# The leases files need to be root:dhcpd even when dropping privileges
ExecStart=/bin/sh -ec '\
    CONFIG_FILE=/etc/dhcp/dhcpd.conf; \
    if [ -f /etc/ltsp/dhcpd.conf ]; then CONFIG_FILE=/etc/ltsp/dhcpd.conf; fi; \
    [ -e /var/lib/dhcp/dhcpd.leases ] || touch /var/lib/dhcp/dhcpd.leases; \
    chown root:dhcpd /var/lib/dhcp /var/lib/dhcp/dhcpd.leases; \
    chmod 775 /var/lib/dhcp ; chmod 664 /var/lib/dhcp/dhcpd.leases; \
    exec dhcpd -user dhcpd -group dhcpd -f -4 -pf /run/dhcp-server/dhcpd.pid -cf $CONFIG_FILE $INTERFACESv4'

[Install]
WantedBy=multi-user.target

isc-dhcp-server6.service も同様にしておきます。

root<serverhost/usr/lib/systemd/system> % vim isc-dhcp-server6.service

これで、 DHCP の問題は解決しました。


次の記事はこちら → 3 : クライアントの設定

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?