事始め

site2site routingができるようになり、vpn_clientのネットワーク内のサーバとvpn_server間で通信ができるようになったわけだが。 今回、新たにもう一つvpn_clientをつなぎ、新しいローカルネットワークをこのVPNネットワークに参加させようとしたわけだ。 しかしこれがうまくいかない。

環境の整理

ネットワークA : 100.64.0.0/22 ネットワークB : 192.168.1.0/24

で、以下のような設定をvpn_serverに書き込むわけです。

port   1194
proto  udp
dev    tun

ca          ca.crt
cert        server.crt
key         server.key
dh          dh.pem
crl-verify  crl.pem

ifconfig-pool-persist ipp.txt

server 10.8.0.0 255.255.255.0

# client側から通信させたい、server側のLanセグメントを指定
push "redirect-gateway def1 bypass-dhcp"
push "route 10.8.0.0 255.255.255.0"
push "dhcp-option DNS 8.8.8.8"

# server側から通信させたい、client側のlanセグメントを指定
client-config-dir /etc/openvpn/ccd
route 100.64.0.0 255.255.252.0
route 192.168.3.0 255.255.255.0

#fragment 1400
#mssfix
tun-mtu 1400


client-to-client
keepalive 10 120
comp-lzo

user  nobody
group nogroup

persist-key
persist-tun

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

verb 3
duplicate-cn

これをやればA -> vpn_server B -> vpn_serverにつながると思っていた。

しかしうまくいかない。

問題

問題は二つある。

  1. Bのネットワークのvpn_clientがvpn_serverに接続するときに、vpn_serverがなぜかAのネットワークのクライアントだと思ってしまい、 Aのネットワークのpublic ipをBのpublic ipに紐づけて routing tableに保存してしまう件。これ、大問題です。
moved in a future release. Please migrate to --topology subnet as soon as possible.
2025-02-22 15:21:51 Note: --cipher is not set. OpenVPN versions before 2.5 defaulted to BF-CBC as fallback when cipher negotiation failed in this case. If you need this fallback please add '--data-ciphers-fallback BF-CBC' to your configuration and/or add BF-CBC to --data-ciphers.
2025-02-22 15:21:51 Note: '--allow-compression' is not set to 'no', disabling data channel offload.
2025-02-22 15:21:51 Consider using the '--compress migrate' option.
2025-02-22 15:21:51 OpenVPN 2.6.9 x86_64-pc-linux-gnu [SSL (OpenSSL)] [LZO] [LZ4] [EPOLL] [PKCS11] [MH/PKTINFO] [AEAD] [DCO]
2025-02-22 15:21:51 library versions: OpenSSL 3.0.13 30 Jan 2024, LZO 2.10
2025-02-22 15:21:51 DCO version: N/A
2025-02-22 15:21:51 WARNING: using --duplicate-cn and --client-config-dir together is probably not what you want
2025-02-22 15:21:51 WARNING: --ifconfig-pool-persist will not work with --duplicate-cn
2025-02-22 15:21:51 net_route_v4_best_gw query: dst 0.0.0.0
2025-02-22 15:21:51 net_route_v4_best_gw result: via 162.43.53.1 dev ens3
2025-02-22 15:21:51 Diffie-Hellman initialized with 2048 bit key
2025-02-22 15:21:51 CRL: loaded 1 CRLs from file crl.pem
2025-02-22 15:21:51 net_route_v4_best_gw query: dst 0.0.0.0
2025-02-22 15:21:51 net_route_v4_best_gw result: via 162.43.53.1 dev ens3
2025-02-22 15:21:51 ROUTE_GATEWAY 162.43.53.1/255.255.255.0 IFACE=ens3 HWADDR=fa:16:3e:f1:af:bf    
2025-02-22 15:21:51 TUN/TAP device tun0 opened
2025-02-22 15:21:51 net_iface_mtu_set: mtu 1400 for tun0
2025-02-22 15:21:51 net_iface_up: set tun0 up
2025-02-22 15:21:51 net_addr_ptp_v4_add: 10.8.0.1 peer 10.8.0.2 dev tun0
2025-02-22 15:21:51 net_route_v4_add: 100.64.0.0/22 via 10.8.0.2 dev [NULL] table 0 metric -1      
2025-02-22 15:21:51 net_route_v4_add: 192.168.1.0/24 via 10.8.0.2 dev [NULL] table 0 metric -1     
2025-02-22 15:21:51 net_route_v4_add: 10.8.0.0/24 via 10.8.0.2 dev [NULL] table 0 metric -1        
2025-02-22 15:21:51 Could not determine IPv4/IPv6 protocol. Using AF_INET
2025-02-22 15:21:51 Socket Buffers: R=[212992->212992] S=[212992->212992]
2025-02-22 15:21:51 UDPv4 link local (bound): [AF_INET][undef]:1194
2025-02-22 15:21:51 UDPv4 link remote: [AF_UNSPEC]
2025-02-22 15:21:51 UID set to nobody
2025-02-22 15:21:51 GID set to nogroup
2025-02-22 15:21:51 Capabilities retained: CAP_NET_ADMIN
2025-02-22 15:21:51 MULTI: multi_init called, r=256 v=256
2025-02-22 15:21:51 IFCONFIG POOL IPv4: base=10.8.0.4 size=62
2025-02-22 15:21:51 IFCONFIG POOL LIST
2025-02-22 15:21:51 Initialization Sequence Completed
2025-02-22 15:22:01 114.177.104.2:55528 VERIFY OK: depth=1, CN=blog.ingenboy.com
2025-02-22 15:22:01 114.177.104.2:55528 VERIFY OK: depth=0, CN=nanae
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_VER=2.4.7
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_PLAT=linux
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_PROTO=2
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_NCP=2
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_LZ4=1
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_LZ4v2=1
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_LZO=1
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_COMP_STUB=1
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_COMP_STUBv2=1
2025-02-22 15:22:01 114.177.104.2:55528 peer info: IV_TCPNL=1
2025-02-22 15:22:01 114.177.104.2:55528 TLS: move_session: dest=TM_ACTIVE src=TM_INITIAL reinit_src=1
2025-02-22 15:22:01 114.177.104.2:55528 TLS: tls_multi_process: initial untrusted session promoted to trusted
2025-02-22 15:22:01 114.177.104.2:55528 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 2048 bits RSA, signature: RSA-SHA256, peer temporary key: 253 bits X25519  
2025-02-22 15:22:01 114.177.104.2:55528 [nanae] Peer Connection Initiated with [AF_INET]114.177.104.2:55528
2025-02-22 15:22:01 nanae/114.177.104.2:55528 MULTI_sva: pool returned IPv4=10.8.0.6, IPv6=(Not enabled)
2025-02-22 15:22:01 nanae/114.177.104.2:55528 OPTIONS IMPORT: reading client specific options from: /etc/openvpn/ccd/nanae
2025-02-22 15:22:01 nanae/114.177.104.2:55528 MULTI: Learn: 10.8.0.6 -> nanae/114.177.104.2:55528  
2025-02-22 15:22:01 nanae/114.177.104.2:55528 MULTI: primary virtual IP for nanae/114.177.104.2:55528: 10.8.0.6
2025-02-22 15:22:01 nanae/114.177.104.2:55528 MULTI: internal route 100.64.0.0/22 -> nanae/114.177.104.2:55528
2025-02-22 15:22:01 nanae/114.177.104.2:55528 MULTI: Learn: 100.64.0.0/22 -> nanae/114.177.104.2:55528
2025-02-22 15:22:03 nanae/114.177.104.2:55528 Data Channel: cipher 'AES-256-GCM', peer-id: 0, compression: 'lzo'
2025-02-22 15:22:03 nanae/114.177.104.2:55528 Timers: ping 10, ping-restart 240
2025-02-22 15:22:03 nanae/114.177.104.2:55528 PUSH: Received control message: 'PUSH_REQUEST'       
2025-02-22 15:22:03 nanae/114.177.104.2:55528 SENT CONTROL [nanae]: 'PUSH_REPLY,redirect-gateway def1 bypass-dhcp,route 10.8.0.0 255.255.255.0,dhcp-option DNS 8.8.8.8,route 10.8.0.0 255.255.255.0,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.6 10.8.0.5,peer-id 0,cipher AES-256-GCM' (status=1)
2025-02-22 15:22:16 MULTI: Learn: 100.64.1.61 -> nanae/114.177.104.2:55528
2025-02-22 15:24:29 MULTI: Learn: 100.64.1.61 -> nanae/114.177.104.2:55528
2025-02-22 15:39:05 MULTI: Learn: 100.64.1.61 -> nanae/114.177.104.2:55528
2025-02-22 15:40:36 219.104.129.32:6267 VERIFY OK: depth=1, CN=blog.ingenboy.com
2025-02-22 15:40:36 219.104.129.32:6267 VERIFY OK: depth=0, CN=nanae
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_VER=2.5.11
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_PLAT=linux
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_PROTO=6
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_NCP=2
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_CIPHERS=AES-256-GCM:AES-128-GCM
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_LZ4=1
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_LZ4v2=1
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_LZO=1
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_COMP_STUB=1
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_COMP_STUBv2=1
2025-02-22 15:40:36 219.104.129.32:6267 peer info: IV_TCPNL=1
2025-02-22 15:40:36 219.104.129.32:6267 TLS: move_session: dest=TM_ACTIVE src=TM_INITIAL reinit_src=1
2025-02-22 15:40:36 219.104.129.32:6267 TLS: tls_multi_process: initial untrusted session promoted to trusted
2025-02-22 15:40:36 219.104.129.32:6267 Control Channel: TLSv1.3, cipher TLSv1.3 TLS_AES_256_GCM_SHA384, peer certificate: 2048 bits RSA, signature: RSA-SHA256, peer temporary key: 253 bits X25519  
2025-02-22 15:40:36 219.104.129.32:6267 [nanae] Peer Connection Initiated with [AF_INET]219.104.129.32:6267
2025-02-22 15:40:36 nanae/219.104.129.32:6267 MULTI_sva: pool returned IPv4=10.8.0.10, IPv6=(Not enabled)
2025-02-22 15:40:36 nanae/219.104.129.32:6267 OPTIONS IMPORT: reading client specific options from: /etc/openvpn/ccd/nanae
2025-02-22 15:40:36 nanae/219.104.129.32:6267 MULTI: Learn: 10.8.0.10 -> nanae/219.104.129.32:6267 
2025-02-22 15:40:36 nanae/219.104.129.32:6267 MULTI: primary virtual IP for nanae/219.104.129.32:6267: 10.8.0.10
2025-02-22 15:40:36 nanae/219.104.129.32:6267 MULTI: internal route 100.64.0.0/22 -> nanae/219.104.129.32:6267
2025-02-22 15:40:36 nanae/219.104.129.32:6267 MULTI: Learn: 100.64.0.0/22 -> nanae/219.104.129.32:6267
2025-02-22 15:40:36 nanae/219.104.129.32:6267 SENT CONTROL [nanae]: 'PUSH_REPLY,redirect-gateway def1 bypass-dhcp,route 10.8.0.0 255.255.255.0,dhcp-option DNS 8.8.8.8,route 10.8.0.0 255.255.255.0,topology net30,ping 10,ping-restart 120,ifconfig 10.8.0.10 10.8.0.9,peer-id 1,cipher AES-256-GCM' (status=1)
2025-02-22 15:40:37 nanae/219.104.129.32:6267 Data Channel: cipher 'AES-256-GCM', peer-id: 0, compression: 'lzo'
2025-02-22 15:40:37 nanae/219.104.129.32:6267 Timers: ping 10, ping-restart 240
2025-02-22 15:40:51 MULTI: Learn: 100.64.1.61 -> nanae/219.104.129.32:6267
2025-02-22 15:43:51 MULTI: Learn: 100.64.1.48 -> nanae/219.104.129.32:6267
2025-02-22 15:50:04 MULTI: Learn: 100.64.1.48 -> nanae/219.104.129.32:6267

こんな感じですね。なぜかBのクライアントがAであるnanaeだと思ってしまう。 さて、openvpnクライアントはどうやってクライアントとを見分けているのでしょうか?

はい、これの回答ですがね、クライアント証明書のCNを見ています。 これ、確認方法はこれです。

openssl x509 -in ~/easy-rsa/easyrsa3/pki/issued/nanae.crt -no
out -subject

subject=CN = nanae

しかし、jhonnyの方を見るとちゃんとCNは

root@x162-43-53-234:/etc/openvpn/ccd# openssl x509 -in ~/easy-rsa/easyrsa3/pki/issued/jhonny-at-wh.crt -noout -subject
subject=CN = jhonny-at-wh

結論から言うと、openvpn serverの以下の設定が問題だったようです。

duplicate-cn

そういえばそうだ、一つの証明書でみんなが使えるようにするためにこれをつけたけど、これをつけると

ただし、複数の異なるクライアントが なぜか同じ CN に見えてしまう現象 が発生することがあります。

らしい。恐ろしい。ということで、これを直す。

いや、これでも治りませんでした。jhonnyように発行したと思っていた証明書ではなく、alphaの証明書をjhonnyにもっていってしまっていた。 これが原因でいろいろとうまくいかなかった。

あと、VPNサーバから192.168.1.7へのsshができなかった理由だが、上記に加え、/etc/openvpn/ccd/{CN}の中にrouting設定を書かないとだめだったらしい。 これを書いたら問題なくroutingされた。 なので、site2site routingを追加する方法をまとめると以下のようになる。

site2site rougingの追加方法。

  1. 新しくVPNネットワークに所属するクライアント用にクライアント証明書を発行する
  2. /etc/openvpn/ccd いかに、発行したクライアント証明書のCNと同じ名前でファイルを作る。 例えば、
./easyrsa build-client-full jhonny-at-wh

でjhonny-at-whでcnを発行した時は、「jhonny-at-wh」でファイルを作る 3. ccdファイルの中身は以下のようにする

iroute 192.168.1.0 255.255.255.0

何を書いているかというと、 「server側から通信させたい、client側のlanセグメントを指定」ですね。 jhonny-at-whファイルの中にこのような設定を書くと、openvpnサーバが自動的に 「jhonny-at-whのクライアントには、192.168.1.0/24あてのパケットを流してもいいのだ」と理解をしてくれます。 はい、OKです。完璧です!!お疲れ様です。

おまけ

openvpnサーバやクライアントの再起動のさせ方 まず、unitファイルを見てみよう

server

いやめんどいからいったん保留で。 ただ、clientの再起動のさせ方は

sudo systemctl restart openvpn-client@hogehoge

です。お願いします。

おまけ

openvpn-client@myvpn の @ とは?

この @ 記号は、systemd の「テンプレートユニット (template unit)」を使ったサービス起動の仕組み を意味します。

通常の systemd サービス (.service ファイル) は、例えば nginx.service のように 固定された1つの設定ファイル を使って起動します。

しかし、openvpn-client@.service のように @ を含むユニットファイルは テンプレートユニット となり、「@ の後に付いた部分」を変数として扱い、異なる設定ファイルを使って複数のインスタンスを起動できる という特徴があります。

@ の後の部分が設定ファイル名になる openvpn-client@myvpn.service → myvpn という名前の設定を使う openvpn-client@openvpn.service → openvpn という名前の設定を使う この myvpn や openvpn は /etc/openvpn/client/ にある設定ファイルと対応 しています。

対応する OpenVPN の設定ファイル(例):

/etc/openvpn/client/myvpn.conf
/etc/openvpn/client/openvpn.conf

ってことなんだけど、自分は以下のように固定化してしまっているわけです。

ray@jhonny:~$ cat /lib/systemd/system/openvpn-client@.service
[Unit]
Description=OpenVPN tunnel for %I
After=network-online.target
Wants=network-online.target
Documentation=man:openvpn(8)
Documentation=https://community.openvpn.net/openvpn/wiki/Openvpn24ManPage
Documentation=https://community.openvpn.net/openvpn/wiki/HOWTO

[Service]
Type=notify
PrivateTmp=true
WorkingDirectory=/etc/openvpn/client
ExecStart=/usr/sbin/openvpn --suppress-timestamps --nobind --config hugo_server.conf
CapabilityBoundingSet=CAP_IPC_LOCK CAP_NET_ADMIN CAP_NET_RAW CAP_SETGID CAP_SETUID CAP_SYS_CHROOT CAP_DAC_OVERRIDE    
LimitNPROC=10
DeviceAllow=/dev/null rw
DeviceAllow=/dev/net/tun rw
ProtectSystem=true
ProtectHome=true
KillMode=process

[Install]
WantedBy=multi-user.target

だから、毎回同じhugo_server.confで実行されるわけですね。知らなかったです。勉強になりました。