綾小路龍之介の素人思考

[OpenVPN] RESOLVE: Cannot resolve host addressを解決するには静的ルーティングを追加

ダイナミックアドレスで運用中の openvpn サーバを再起動すると、クライアントとのリンクが切れる問題があった。これを解決するには、クライアント側で DNS サーバへの静的ルーティングを追加しておく。これにより、名前解決パケットは VPN を経由しなくなる。秘密が漏れるのと引き換えにクライアントはサーバとの接続を維持できるようになる。

クライアント側でルーティングテーブルとネットワークインターフェイスの情報を表示

# route  -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.12.1    0.0.0.0         UG    0      0        0 eth0
192.168.12.0    0.0.0.0         255.255.255.248 U     0      0        0 eth0
# ip route
default via 192.168.12.1 dev eth0
192.168.12.0/29 dev eth0  proto kernel  scope link  src 192.168.12.6
# ifconfig
eth0      Link encap:Ethernet  HWaddr 00:40:26:cb:df:03
          inet addr:192.168.12.6  Bcast:192.168.12.7  Mask:255.255.255.248
          inet6 addr: fe80::240:26ff:fecb:df03/64 Scope:Link
          UP BROADCAST RUNNING MULTICAST  MTU:1500  Metric:1
          RX packets:44138 errors:4 dropped:0 overruns:0 frame:4
          TX packets:41098 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:1000
          RX bytes:51186688 (48.8 MiB)  TX bytes:4085461 (3.8 MiB)

lo        Link encap:Local Loopback
          inet addr:127.0.0.1  Mask:255.0.0.0
          inet6 addr: ::1/128 Scope:Host
          UP LOOPBACK RUNNING  MTU:16436  Metric:1
          RX packets:0 errors:0 dropped:0 overruns:0 frame:0
          TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
          collisions:0 txqueuelen:0
          RX bytes:0 (0.0 B)  TX bytes:0 (0.0 B)

# ip addr
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 16436 qdisc noqueue state UNKNOWN
    link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
    inet 127.0.0.1/8 scope host lo
    inet6 ::1/128 scope host
       valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
    link/ether 00:40:26:cb:df:03 brd ff:ff:ff:ff:ff:ff
    inet 192.168.12.6/29 brd 192.168.12.7 scope global eth0
    inet6 fe80::240:26ff:fecb:df03/64 scope link
       valid_lft forever preferred_lft forever

openvpn server に接続して、その状態でクライアントのルーティングテーブルを確認。

# /etc/init.d/openvpn start
# route  -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.20.13   128.0.0.0       UG    0      0        0 tun0
0.0.0.0         192.168.12.1    0.0.0.0         UG    0      0        0 eth0
XXX.XXX.XXX.XXX 192.168.12.1    255.255.255.255 UGH   0      0        0 eth0
128.0.0.0       192.168.20.13   128.0.0.0       UG    0      0        0 tun0
192.168.12.0    0.0.0.0         255.255.255.248 U     0      0        0 eth0
192.168.20.0    192.168.20.13   255.255.255.0   UG    0      0        0 tun0
192.168.20.1    192.168.20.13   255.255.255.255 UGH   0      0        0 tun0
192.168.20.13   0.0.0.0         255.255.255.255 UH    0      0        0 tun0
# ip route
0.0.0.0/1 via 192.168.20.13 dev tun0
default via 192.168.12.1 dev eth0
XXX.XXX.XXX.XXX via 192.168.12.1 dev eth0
128.0.0.0/1 via 192.168.20.13 dev tun0
192.168.12.0/29 dev eth0  proto kernel  scope link  src 192.168.12.6
192.168.20.0/24 via 192.168.20.13 dev tun0
192.168.20.1 via 192.168.20.13 dev tun0
192.168.20.13 dev tun0  proto kernel  scope link  src 192.168.20.14

この状態で server 側で openvpn server をリスタート。

# /etc/init.d/openvpn restart
Stopping virtual private network daemon: server.
Starting virtual private network daemon: server.

クライアント側の syslog をみると以下のようなログが流れて再接続に失敗。名前解決に失敗しているようなので、resolv.confを確認。

# tail -f /var/log/syslog
MMM DD 22:46:24 HHHHHH ovpn-client[2182]: RESOLVE: Cannot resolve host address: XXXXXXXXXXXXXX: [TRY_AGAIN] A temporary error occurred on an authoritative name server.
MMM DD 22:47:49 HHHHHH ovpn-client[2182]: RESOLVE: Cannot resolve host address: XXXXXXXXXXXXXX: [TRY_AGAIN] A temporary error occurred on an authoritative name server.
MMM DD 22:49:14 HHHHHH ovpn-client[2182]: RESOLVE: Cannot resolve host address: XXXXXXXXXXXXXX: [TRY_AGAIN] A temporary error occurred on an authoritative name server.
MMM DD 22:50:40 HHHHHH ovpn-client[2182]: RESOLVE: Cannot resolve host address: XXXXXXXXXXXXXX: [TRY_AGAIN] A temporary error occurred on an authoritative name server.
MMM DD 22:52:05 HHHHHH ovpn-client[2182]: RESOLVE: Cannot resolve host address: XXXXXXXXXXXXXX: [TRY_AGAIN] A temporary error occurred on an authoritative name server.
MMM DD 22:53:30 HHHHHH ovpn-client[2182]: RESOLVE: Cannot resolve host address: XXXXXXXXXXXXXX: [TRY_AGAIN] A temporary error occurred on an authoritative name server.
...
# cat /etc/resolv.conf
# Dynamic resolv.conf(5) file for glibc resolver(3) generated by resolvconf(8)
#     DO NOT EDIT THIS FILE BY HAND -- YOUR CHANGES WILL BE OVERWRITTEN
nameserver NNN.NNN.NNN.NNN
nameserver MMM.MMM.MMM.MMM

適当なマシン(ここではサーバ側)でクライアント側のresolv.confにあったDNSサーバを使って名前解決を試みると成功。

# dig @NNN.NNN.NNN.NNN XXXXXXXXXXXXXX

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @NNN.NNN.NNN.NNN XXXXXXXXXXXXXX
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 30439
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;XXXXXXXXXXXXXX.                        IN      A

;; ANSWER SECTION:
XXXXXXXXXXXXXX.         60      IN      A       XXX.XXX.XXX.XXX

;; Query time: 97 msec
;; SERVER: NNN.NNN.NNN.NNN#53(NNN.NNN.NNN.NNN)
;; WHEN: ************************
;; MSG SIZE  rcvd: 48

# dig @MMM.MMM.MMM.MMM XXXXXXXXXXXXXX

; <<>> DiG 9.8.4-rpz2+rl005.12-P1 <<>> @MMM.MMM.MMM.MMM XXXXXXXXXXXXXX
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 13228
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0

;; QUESTION SECTION:
;XXXXXXXXXXXXXX.                        IN      A

;; ANSWER SECTION:
XXXXXXXXXXXXXX.         60      IN      A       XXX.XXX.XXX.XXX

;; Query time: 98 msec
;; SERVER: MMM.MMM.MMM.MMM#53(MMM.MMM.MMM.MMM)
;; WHEN: ************************
;; MSG SIZE  rcvd: 48

クライアント側でルーティングテーブルを再確認。openvpnサーバに接続成功後のものと全く同じということが分かる。この状態で NNN.NNN.NNN.NNN または MMM.MMM.MMM.MMM 行きのパケットはどの Iface で外に行くかを調べるには ip route getを使う。ルーティングテーブル的には tun0 でパケットを外に出そうとするが、tun0 は未接続なので失敗する。これが原因で "RESOLVE: Cannot resolve host address" が止まらないわけだ。

# route  -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.20.13   128.0.0.0       UG    0      0        0 tun0
0.0.0.0         192.168.12.1    0.0.0.0         UG    0      0        0 eth0
XXX.XXX.XXX.XXX 192.168.12.1    255.255.255.255 UGH   0      0        0 eth0
128.0.0.0       192.168.20.13   128.0.0.0       UG    0      0        0 tun0
192.168.12.0    0.0.0.0         255.255.255.248 U     0      0        0 eth0
192.168.20.0    192.168.20.13   255.255.255.0   UG    0      0        0 tun0
192.168.20.1    192.168.20.13   255.255.255.255 UGH   0      0        0 tun0
192.168.20.13   0.0.0.0         255.255.255.255 UH    0      0        0 tun0
# ip route
0.0.0.0/1 via 192.168.20.13 dev tun0
default via 192.168.12.1 dev eth0
XXX.XXX.XXX.XXX via 192.168.12.1 dev eth0
128.0.0.0/1 via 192.168.20.13 dev tun0
192.168.12.0/29 dev eth0  proto kernel  scope link  src 192.168.12.6
192.168.20.0/24 via 192.168.20.13 dev tun0
192.168.20.1 via 192.168.20.13 dev tun0
192.168.20.13 dev tun0  proto kernel  scope link  src 192.168.20.14
# ip route get NNN.NNN.NNN.NNN
NNN.NNN.NNN.NNN via 192.168.20.13 dev tun0  src 192.168.20.14
    cache
# ip route get MMM.MMM.MMM.MMM
MMM.MMM.MMM.MMM via 192.168.20.13 dev tun0  src 192.168.20.14
    cache

これを解決するには、クライアント側で /etc/init.d/openvpn restart を行う方法が考えられる。しかし、サーバ側の openvpn 再起動や、IP アドレスの変化に伴って毎回クライアント側の再起動が必要になるため、クライアント側を操作する方法が限られているケースだとこの解決策は採用しづらい。そこで、DNS サーバへのアクセスだけは VPN を通らないような静的ルーティングをクライアント側に設定する。

# echo "route NNN.NNN.NNN.NNN 255.255.255.255 net_gateway 0" >> client.conf
# echo "route MMM.MMM.MMM.MMM 255.255.255.255 net_gateway 0" >> client.conf

設定が終わったらクライアント側で client を再起動し、ルーティングの確認。NNN.NNN.NNN.NNN および MMM.MMM.MMM.MMM へのパケットは eth0 を通って外に出るようになったことが分かる。

# /etc/init.d/openvpn restart
Stopping virtual private network daemon: client.
Starting virtual private network daemon: client.
# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         192.168.20.13   128.0.0.0       UG    0      0        0 tun0
0.0.0.0         192.168.12.1    0.0.0.0         UG    0      0        0 eth0
XXX.XXX.XXX.XXX 192.168.12.1    255.255.255.255 UGH   0      0        0 eth0
128.0.0.0       192.168.20.13   128.0.0.0       UG    0      0        0 tun0
192.168.12.0    0.0.0.0         255.255.255.248 U     0      0        0 eth0
192.168.20.0    192.168.20.13   255.255.255.0   UG    0      0        0 tun0
192.168.20.1    192.168.20.13   255.255.255.255 UGH   0      0        0 tun0
192.168.20.13   0.0.0.0         255.255.255.255 UH    0      0        0 tun0
NNN.NNN.NNN.NNN 192.168.12.1    255.255.255.255 UGH   0      0        0 eth0
MMM.MMM.MMM.MMM 192.168.12.1    255.255.255.255 UGH   0      0        0 eth0
# ip route show
0.0.0.0/1 via 192.168.20.13 dev tun0
default via 192.168.12.1 dev eth0
XXX.XXX.XXX.XXX via 192.168.12.1 dev eth0
128.0.0.0/1 via 192.168.20.13 dev tun0
192.168.12.0/29 dev eth0  proto kernel  scope link  src 192.168.12.6
192.168.20.0/24 via 192.168.20.13 dev tun0
192.168.20.1 via 192.168.20.13 dev tun0
192.168.20.13 dev tun0  proto kernel  scope link  src 192.168.20.14
NNN.NNN.NNN.NNN via 192.168.12.1 dev eth0
MMM.MMM.MMM.MMM via 192.168.12.1 dev eth0
# ip route get NNN.NNN.NNN.NNN
NNN.NNN.NNN.NNN via 192.168.12.1 dev eth0  src 192.168.12.6
    cache
# ip route get MMM.MMM.MMM.MMM
MMM.MMM.MMM.MMM via 192.168.12.1 dev eth0  src 192.168.12.6
    cache

この状態でサーバ側でマシンの再起動やopenvpnの再起動を行う。適当な時間後にクライアントが接続していることを確認する。

# /etc/init.d/openvpn restart
Stopping virtual private network daemon: server.
Starting virtual private network daemon: server.
# cat /etc/openvpn/openvpn-status.log
OpenVPN CLIENT LIST
Updated,************************
Common Name,Real Address,Bytes Received,Bytes Sent,Connected Since
*******,192.168.12.6:34799,9336,9722,************************
ROUTING TABLE
Virtual Address,Common Name,Real Address,Last Ref
192.168.20.14,*******,192.168.12.6:34799,************************
GLOBAL STATS
Max bcast/mcast queue length,0
END

上に挙げた NNN.NNN.NNN.NNN や MMM.MMM.MMM.MMM は組織の提供する DNS サーバのアドレスである。可能であれば DNS だって組織の監視から逃れたいわけで、正直に DNS 問い合わせを組織の監視下に置く必要はないし、組織がアドレスを変えると再設定が必要になる。このようなケースを避けるために public dns を使うことを考える。以下の設定を client.conf に追加することで、dns 問い合わせは public dns を使うようになり、そのトラフィックは静的ルーティングで VPN ではない経路をたどるようになる。

dhcp-option DNS 129.250.35.250
dhcp-option DNS 8.8.8.8
dhcp-option DNS 129.250.35.251
dhcp-option DNS 8.8.4.4
route 129.250.35.250 255.255.255.255 net_gateway 0
route 8.8.8.8 255.255.255.255 net_gateway 0
route 129.250.35.251 255.255.255.255 net_gateway 0
route 8.8.4.4 255.255.255.255 net_gateway 0
script-security 2
up /etc/openvpn/update-resolv-conf
down /etc/openvpn/update-resolv-conf

最終的なクライアント用設定ファイルと雛形との差分は以下。

# diff /usr/share/doc/openvpn/examples/sample-config-files/client.conf /etc/openvpn/client.conf
36,37c36,37
< ;proto tcp
< proto udp
---
> proto tcp
> ;proto udp
42c42
< remote my-server-1 1194
---
> ;remote my-server-1 1194
43a44
> remote XXXXXXXXXXXXXX 443
89,90c90,91
< cert client.crt
< key client.key
---
> cert client2.crt
> key client2.key
123a125,136
>
> dhcp-option DNS 129.250.35.250
> dhcp-option DNS 8.8.8.8
> dhcp-option DNS 129.250.35.251
> dhcp-option DNS 8.8.4.4
> route 129.250.35.250 255.255.255.255 net_gateway 0
> route 8.8.8.8 255.255.255.255 net_gateway 0
> route 129.250.35.251 255.255.255.255 net_gateway 0
> route 8.8.4.4 255.255.255.255 net_gateway 0
> script-security 2
> up /etc/openvpn/update-resolv-conf
> down /etc/openvpn/update-resolv-conf

DNS問い合わせ時に秘密が漏れることが問題。サーバをDDNSではなく固定アドレスで運用すればこのような問題は起きない。すべてのクライアントをこのような設定にするのではなく、手動で再起動がしづらいクライアントだけにこのような設定を行うべきである。

リファレンス

  1. Deprecated Linux networking commands and their replacements | Doug Vitale Tech Blog
  2. route ip deprecated - Google 検索

ソーシャルブックマーク

  1. はてなブックマーク
  2. Google Bookmarks
  3. del.icio.us

ChangeLog

  1. Posted: 2008-11-17T06:40:56+09:00
  2. Modified: 2008-11-17T06:40:56+09:00
  3. Generated: 2017-02-05T23:09:19+09:00