OpenVPNの構築(ルーティングモード)

1.はじめに

モバイル環境も良くなると、外出先から自宅内のネットワークに接続したくなることがある。
昔は会社だと会社に設置したアナログモデムへ電話して社内ネットワークに接続するなんて方法もあったが、VPN接続をすることで安全に外からローカルネットワークの接続が可能となった。
そんな中でIPsecやL2TPなどいろいろあるが、今回はその中でも良いと思われる扱いやすいOpenVPNを導入してみた。

2.ルーティングモードとブリッジモード

OpenVPNにはルーティングモードとブリッジモードがあります。
すべての作業ができるのはブリッジモードですが、まずは確実に動作させられるだろうルーティングモードで構築します。
ブリッジモードもこの後で成功しましたので別のページに作成しておきます。
全体的な構成はこんな感じ

携帯電話キャリアのインターネット接続は比較的ローカルIPが多い。
会社によってIPアドレスは違うが、自宅と同じIPにならないよう注意が必要。
この場合、キャリアからもらうIPアドレスは192.168.43.**として自宅内を192.168.0.0/24
OpenVPNで使うアドレスを192.168.1.0/24とする。
外出先のクライアントPCからは192.168.1.2→192.168.1.1→192.168.0.1→自宅内へと言うルートになる。

3.インストール

いつものようにportからインストールします。
cd /usr/ports/security/openvpn
make install clean

次に設定ファイルがデフォルトで置かれないのでコピーします。
mkdir /usr/local/etc/openvpn
cp /usr/local/share/examples/openvpn/sample-config-files/server.conf /usr/local/etc/openvpn/openvpn.conf
これでインストールは終了

4.鍵・証明書関係の作成

鍵と証明書を作成しますが、まずはデフォルトですと有効期限が短いと感じる人もいるので、最初に有効期限を設定します。
●pki環境の作成
# cd /usr/local/share/easy-rsa
# easyrsa init-pki
WARNING!!!
You are about to remove the EASYRSA_PKI at:
* /usr/local/share/easy-rsa/pki
and initialize a fresh PKI here.
Type the word 'yes' to continue, or any other input to abort.
Confirm removal:yes
* Notice:
Aborting without confirmation.
#

●有効期限の設定
/usr/local/share/easy-rsa/pki/vars
set_var EASYRSA_CA_EXPIRE 3650 #CAの期限、デフォルトは10年
set_var EASYRSA_CERT_EXPIRE 825 #証明書の期限、デフォルトは2年3カ月くらい
set_var EASYRSA_CRL_DAYS 180 #失効期限
set_var EASYRSA_CERT_RENEW 30 #期限の何日前から証明書を更新できるか
好きな長さに変更します。

●CAの鍵と証明書の作成
# easyrsa build-ca
* Notice:
Using Easy-RSA configuration from: /usr/local/share/easy-rsa/pki/vars
* Notice:
Using SSL: openssl OpenSSL 1.1.1k-freebsd 24 Aug 2021
Enter New CA Key Passphrase:パスワード
Re-Enter New CA Key Passphrase:パスワード
........................+++++
............+++++
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]:hogehoge.mydns.jp

* Notice:

CA creation complete and you may now import and sign cert requests.
Your new CA certificate file for publishing is at:
/usr/local/share/easy-rsa/pki/ca.crt

#
pki/private/ca.key と pki/ca.crt ができる。

●サーバの鍵と証明書の作成
# easyrsa build-server-full server nopass
* Notice:
Using Easy-RSA configuration from: /usr/local/share/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 1.1.1k-freebsd 24 Aug 2021

Generating a RSA private key
........................+++++
..+++++
writing new private key to '/usr/local/share/easy-rsa/pki/ebbb2044/temp.c8d9d5c7'
-----
* Notice:

Keypair and certificate request completed. Your files are:
req: /usr/local/share/easy-rsa/pki/reqs/server.req
key: /usr/local/share/easy-rsa/pki/private/server.key

Using configuration from /usr/local/share/easy-rsa/pki/ebbb2044/temp.f0696a26
Enter pass phrase for /usr/local/share/easy-rsa/pki/private/ca.key:パスワード
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 Mar 16 11:02:09 2026 GMT (825 days)

Write out database with 1 new entries
Data Base Updated

* Notice:
Certificate created at: /usr/local/share/easy-rsa/pki/issued/server.crt

#
pki/private/server.key と、pki/reqs/server.req、pki/issued/server.crt ができる。

●dhの作成
# easyrsa gen-dh
* Notice:
Using Easy-RSA configuration from: /usr/local/share/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 1.1.1k-freebsd 24 Aug 2021

Generating DH parameters, 2048 bit long safe prime, generator 2
This is going to take a long time
...............................
* Notice:

DH parameters of size 2048 created at /usr/local/share/easy-rsa/pki/dh.pem

#
pki/dh.pemができる。

●失効リストの作成
# easyrsa gen-crl
miyakoshi:# easyrsa gen-crl
* Notice:
Using Easy-RSA configuration from: /usr/local/share/easy-rsa/pki/vars

* Notice:
Using SSL: openssl OpenSSL 1.1.1k-freebsd 24 Aug 2021

Using configuration from /usr/local/share/easy-rsa/pki/1b1b795c/temp.846d448f
Enter pass phrase for /usr/local/share/easy-rsa/pki/private/ca.key:パスワード

* Notice:

An updated CRL has been created.
CRL file: /usr/local/share/easy-rsa/pki/crl.pem

#
pki/crl.pem ができる

●クライアント用の鍵と証明書の作成
# easyrsa build-client-full client
Note: using Easy-RSA configuration from: /usr/local/share/easy-rsa/vars
Using SSL: openssl OpenSSL 1.1.1k-freebsd 25 Mar 2021
Generating a RSA private key
............................................................................................................+++++
.......+++++
writing new private key to '/usr/local/share/easy-rsa/pki/easy-rsa-26415.jk7wgS/tmp.q5DnbQ'
Enter PEM pass phrase:パスワード
Verifying - Enter PEM pass phrase:パスワード
-----
Using configuration from /usr/local/share/easy-rsa/pki/easy-rsa-26415.jk7wgS/tmp.nIitwB
Enter pass phrase for /usr/local/share/easy-rsa/pki/private/ca.key:パスワード
Check that the request matches the signature
Signature ok
The Subject's Distinguished Name is as follows
commonName :ASN.1 12:'false'
Certificate is to be certified until Nov 24 10:16:50 2023 GMT (825 days)
Write out database with 1 new entries
Data Base Updated
pki/issued/client.crt, pki/private/false.key, pki/reqs/client.req ができる
接続するクライアントを同時に複数接続できるようにするには、このクライアント用の名前を変えて複数作成します。

証明書関係をコピー
# cp /usr/local/share/easy-rsa/pki/ca.crt /usr/local/share/easy-rsa/pki/issued/server.crt /usr/local/share/easy-rsa/pki/private/server.key /usr/local/share/easy-rsa/pki/dh.pem /usr/local/share/easy-rsa/pki/crl.pem /usr/local/etc/openvpn/
# cp /usr/local/share/easy-rsa/pki/private/client.key /usr/local/share/easy-rsa/pki/issued/client.crt /usr/local/etc/openvpn/client/

●tlsキー生成
# openvpn --genkey secret /usr/local/etc/openvpn/ta.key
以上でファイル作成は終了。

5.サーバーの設定・起動

/usr/local/etc/openvpn/openvpn.conf を編集
# ポート設定
port 1194
# tcpよりudpのほうが早い
proto udp
# ブリッジの場合はtap、ルーティングはtun、tun0は既にWAN側で使用しているので1
dev tun1
# Root CAの証明書
ca ca.crt
# サーバのフルチェーン証明書
cert server.crt
# サーバの秘密鍵
key server.key
# dh2048の設定
dh dh.pem
# キーの設定
tls-auth ta.key 0 # This file is secret
# 古いクライアントのサポート不要なので、ワーニングも出る
topology subnet
# VPNの内側IP設定
server 192.168.1.0 255.255.255.0 #VPN用IPアドレス
push "route 192.168.0.0 255.255.255.0" #これでローカル向けのルーティングを教える
#push "dhcp-option DNS 192.168.0.1" #本来はDNSサーバーを設定するはずだが、これを書くと名前解決できなかったのでコメントアウトした
# クライアント同士の接続を許可
client-to-client
#必須
push "redirect-gateway def1 bypass-dhcp" #これを入れるとすべてがVPN経由になる
#ユーザー設定
user nobody
group nobody
keepalive 30 120
# 暗号化方法(ここはちょっと怪しい)
cipher AES-256-GCM
# 圧縮
comp-lzo
persist-key
persist-tun
verb 3
script-security 2
explicit-exit-notify 1
# ログ
status /var/log/openvpn-status.log
log /var/log/openvpn.log
log-append /var/log/openvpn.log

/etc/rc.conf へ追記
openvpn_enable="YES"
openvpn_configfile="/usr/local/etc/openvpn/openvpn.conf"
手動スタート
# /usr/local/etc/rc.d/openvpn start

ifconfigを確認する
$ ifconfig
igb0: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=4e527bb<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,JUMBO_MTU,VLAN_HWCSUM,TSO4,TSO6,LRO,WOL_MAGIC,VLAN_HWFILTER,VLAN_HWTSO,RXCSUM_IPV6,TXCSUM_IPV6,NOMAP>
        ether XX:XX:XX:XX:XX:XX
        media: Ethernet autoselect (100baseTX <full-duplex>)
        status: active
em0: flags=8863<UP,BROADCAST,RUNNING,SIMPLEX,MULTICAST> metric 0 mtu 1500
        options=481049b<RXCSUM,TXCSUM,VLAN_MTU,VLAN_HWTAGGING,VLAN_HWCSUM,LRO,VLAN_HWFILTER,NOMAP>
        ether XX:XX:XX:XX:XX:XX
        inet 192.168.0.1 netmask 0xffffff00 broadcast 192.168.0.255
        media: Ethernet autoselect (1000baseT <full-duplex>)
        status: active
lo0: flags=8049<UP,LOOPBACK,RUNNING,MULTICAST> metric 0 mtu 16384
        options=680003<RXCSUM,TXCSUM,LINKSTATE,RXCSUM_IPV6,TXCSUM_IPV6>
        inet 127.0.0.1 netmask 0xff000000
        groups: lo
tun0: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1454
        options=80000<LINKSTATE>
        inet 219.121.16.42 --> 202.224.43.122 netmask 0xffffff00
        groups: tun
        Opened by PID 887
tun1: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> metric 0 mtu 1500
        options=80000<LINKSTATE>
        inet 192.168.1.1 --> 192.168.1.2 netmask 0xffffff00
        groups: tun
        Opened by PID 44063
$
igb0はWAN側の物理インターフェースでIPは割り当てられていない。
em0はローカル側の物理インターフェースで192.168.0.1となっている。
tun0はPPPoE接続のトンネルデバイスで、ここにグローバルIPが割り当てられている。219.121.16.42は現在アクセスしているこのサーバーになる。
tun1が今回OpenVPNで作成されたトンネルデバイスでtun1に192.168.1.1になっていて、その先はVPN接続するクライアントPCの192.168.1.2となる。

ここで注意したいのがVPN接続してくるマシンのIPがローカルと言っても少し違うので、使用する関係の設定で許可を加えておく必要がある。
例えばsambaなどは
hosts allow = 192.168.0.0/255.255.255.0
となっているので
hosts allow = 192.168.0.0/255.255.254.0
などと修正しておく必要がある。
結構ここでアクセスできず悩むことが多い。
他には
Webmin、proftpd、SSH、unbound、sendmail、squidなど必要に応じて確認しておくと良いだろう。

次にipfとipnatの設定を行う。
192.168.1.X→192.168.0.XはOpenVPNがルーティングしてくれるが、クライアントPCから外に出るルートがブロックと、そもそものipfが設定されていないので設定する。
/etc/ipf.rules 追記
###########################################
# incomming packets (group 500)
###########################################
pass in on tun1 all head 500
block in from 127.0.0.0/8 to any group 500

##########################################
# outgoing packets (group 600)
##########################################
pass out on tun1 all head 600
block out from 127.0.0.0/8 to any group 600
block out from any to 127.0.0.0/8 group 600
/etc/ipnat.rules
元は
map tun0 192.168.0.0/24 -> 0/32 proxy port ftp ftp/tcp
map tun0 192.168.0.0/24 -> 0/32 portmap tcp/udp auto
map tun0 192.168.0.0/24 -> 0/32
だったのを
map tun0 192.168.0.0/23 -> 0/32 proxy port ftp ftp/tcp
map tun0 192.168.0.0/23 -> 0/32 portmap tcp/udp auto
map tun0 192.168.0.0/23 -> 0/32
へ変更する。
これで192.168.1.Xからも自宅内と自宅からのWANへのアクセスができるようになる。

6.クライアントPCの設定・接続

クライアントPCはWindowsでの場合、サイトへ行きまずはダウンロード。
https://www.openvpn.jp/
右にWindowsのインストーラがあるので、必要なものをダウンロードしインストールする。

サーバー側でコピーするファイルを集約する。
# mkdir /usr/local/etc/openvpn/client
# cd /usr/local/etc/openvpn/client
# cp /usr/local/share/examples/openvpn/sample-config-files/client.conf wizard-limit.ovpn
# cp ../ca.crt ../ta.key /usr/local/share/easy-rsa/pki/issued/false.crt /usr/local/share/easy-rsa/pki/private/false.key /usr/local/etc/openvpn/client
これで /usr/local/etc/openvpn/client にまとまる。
wizard-limit.ovpnは内容を編集。
client
dev tun数字
proto udp
pull
float
remote 接続先サーバーアドレス 1194
resolv-retry infinite
nobind
persist-key
persist-tun
ca ca.crt
cert client.crt
key client.key
;remote-cert-tls server
tls-auth ta.key 1
cipher AES-256-GCM
comp-lzo
verb 3
;mute 20
redirect-gateway def1l
そして /usr/local/etc/openvpn/client にまとまったファイルを、クライアントPCの
C:\ユーザー\ユーザー名\openvpn\config
の中へ安全な方法でコピーする。
起動後、接続方法は右下のopenvpnアイコンを右クリックして接続を選べば
問題ない場合接続できます。

うまく接続できた場合は、Windowsのコマンドプロンプトを出してipfonfig /allで確認する。
不明なアダプター OpenVPN TAP-Windows6:

   接続固有の DNS サフィックス . . . . .: 
   説明. . . . . . . . . . . . . . . . .: TAP-Windows Adapter V9
   物理アドレス. . . . . . . . . . . . .: XX-XX-XX-XX-XX-XX
   DHCP 有効 . . . . . . . . . . . . . .: はい
   自動構成有効. . . . . . . . . . . . .: はい
   IPv4 アドレス . . . . . . . . . . . .: 192.168.1.2(優先) 
   サブネット マスク . . . . . . . . . .: 255.255.255.0
   リース取得. . . . . . . . . . . . . .: 2021年9月12日 19:07:21
   リースの有効期限. . . . . . . . . . .: 2022年9月12日 19:07:21
   デフォルト ゲートウェイ . . . . . . .: 
   DHCP サーバー . . . . . . . . . . . .: 192.168.1.254
   DNS サーバー. . . . . . . . . . . . .: 192.168.0.1
   NetBIOS over TCP/IP . . . . . . . . .: 有効
とこんな感じでIPアドレスが割り当てられるはずである。

次にファイル共有などいろいろやりたいので、このOpenVPNアクセスはWindowsとしてパブリックネットワークではなくプライベートネットワークとして認識させたい。
ところがデフォルトではパブリックネットワークで、2つが同時に接続されているので、片方だけプライベートネットワークへ変更できなかったので、マニュアルでネットワークを変更する。
@スタートメニュー→WindowsPowerShell→WindowsPowerShellを右クリック→管理者として実行する

もしくはスタートメニュー右クリックで出てくる場合もあります。
コマンドラインを開いたら
PS> Get-NetConnectionProfile
Name : XXXXXXXXXXXXXXXX
InterfaceAlias : Wi-Fi
InterfaceIndex : 21
NetworkCategory : Public
IPv4Connectivity : Internet
IPv6Connectivity : NoTraffic

Name : OpenVPN TAP-Windows6
InterfaceAlias : OpenVPN TAP-Windows6
InterfaceIndex : 9
NetworkCategory : Public
IPv4Connectivity : Internet
IPv6Connectivity : NoTraffic
となっていますので、このOpenVPNの9番を変更します。
PS> Set-NetConnectionProfile -InterfaceIndex 9 -NetworkCategory Public
変更されているか確認
PS> Get-NetConnectionProfile
Name : XXXXXXXXXXXXXXXX
InterfaceAlias : Wi-Fi
InterfaceIndex : 21
NetworkCategory : Public
IPv4Connectivity : Internet
IPv6Connectivity : NoTraffic

Name : OpenVPN TAP-Windows6
InterfaceAlias : OpenVPN TAP-Windows6
InterfaceIndex : 9
NetworkCategory : Private
IPv4Connectivity : Internet
IPv6Connectivity : NoTraffic
これでOpenVPNはプライベートネットワークに変わりました。
ネットワークと共有センターで最終確認

7.ローカル接続しているWindowsマシンの設定

このままですと192.168.0.0/24に接続されているWindowsマシンは192.168.1.0/24からの接続はローカルとは認識されないのでブロックされてしまいます。
pingも返事しませんし、ファイル共有もできません。
デフォルトではリモート接続は許可されいてたので、リモート接続のみ出来ました。
pingはチェック用としてファイル共有関係の許可を追加します。
設定の「更新とセキュリティ」をクリック。

左のWindowsセキュリティを選び、右のダイアウォールとネットワーク程保護をクリック。

左のファイアーウォールとネットワーク保護を選び、右下の詳細設定をクリック

するとWindows Defender ファイアウォールが開きます。
まずは右の「プロファイルでフィルター」からプライベートだけにすると数が減って探しやすいです。
その中でファイルとプリンタ共有に関する部分をすべて修正します。

ダブルクリックで設定が開きますので、スコープタグを選びます。

するとリモートアドレスがご覧のようにローカルサブネットとなっているので、192.168.0.0/24からしか受信許可していないことが分かります。
ここに追加で192.168.1.0/24を追加することで、ローカル内のPCへVPN経由でも応答するようになります。
しかし、pingやファイル共有はできますがネットワークコンピューター一覧には出てきません。
アクセスする場合は
\\192.168.1.1
と言うようにIPアドレスを直接指定することでアクセスできます。
できるだけローカル内も固定IPの方が扱いやすいでしょう。

FreeBSDからIPアドレスとマシン名の関係を調べる場合は
$ nmblookup -S WORKGROUP
で調べられます。

Windwosマシンからの場合は
C:\> nbtstat -a マシン名
でまず確認させるとキャッシュに入ります。
キャッシュに入ったところで
C:\> nbtstat -c
でマシン名とIPアドレスが出てきます。