塩焼きブログ

塩焼きに関しての研究内容を公開しています

Ubuntu 18.04 LTS / 18.10をVPNに接続する

Ubuntu 18.04 LTSの場合

ここでする説明はUbuntu 18.10ではうまく行かなかったが、システムへの変更が軽微で済みますが、ガッツリいじりたい場合はUbuntu 18.10の設定も見てみてください。

IPSec/IKEv2に接続したい場合

GUIの設定のネットワークからL2TPとPPTPはデフォルトで接続可能だが、IKEv2についてはデフォルトでは導入されていないのでstrongSwanを入れる。strongSwanはAndroidをIPSec/IKEv2に接続する時に入れるアプリで結構メジャーみたいです。

sudo update
sudo apt install strongswan network-manager-strongswan libcharon-extra-plugins

接続先VPN内のDNSサーバーを反映させる

VPNに接続すれば接続先のDNSサーバーも認識してくれると思うが、Ubuntuだとうまくいかなかった。DNSサーバー自体は疎通でき、dig @192.168.15.1 example.localとすれば名前解決ができるし、systemd-resolve --statusでは認識されていても駄目なのは、単にsystem-resolve --statusに反映されていないだけだった。

解決にはVPN接続後にsudo systemctl restart systemd-resolvedを実行すると良かった。

しかし、これでは再起動してもDNSサーバーが認識されないことがあるので、一番良かったのは/etc/systemd/resolved.confにDNSサーバーを直書きするのが良かった。

[Resolve]
DNS=1.1.1.1 192.168.15.1

1.1.1.1とは最近Cisco OpenDNSよりも速いと言われるパブリックDNSだとか。サンプルとして追加しておきました。この設定を保存したら、反映させるにはsudo systemctl restart systemd-resolvedを実行する。

これでPCを再起動してもVPNに再接続しても、sudo systemctl restart systemd-resolvedを実行すれば確実に繋がるようになります。もちろんブラウザからも正常に名前解決ができるようになる。

特定のSSL通信でタイムアウトする

VPNに接続するとSSL通信でタイムアウトする。curl -v 'https://example.com'とすると、ClientHelloの後のServerHelloが返らない。これはMTUのサイズがUbuntuではデフォルトで1500となっており、コネクションが途中で切れるのが問題らしいので下記のようにしてMTUのサイズを設定します。

ip link set enp0s8 mtu 1400

今回の発生ケースがSSL通信時のみだったので、PINGによる検証ができない。本来はPINGによる最適値の検証ができるそうだ。地道にop link setでMTUの値を弄ってもいいかもしれない。

Dockerでの疎通の問題について

他にDockerに関連した問題もありました。例えローカルで名前解決ができるようになっても、Dockerでは解決できない問題のようなことがおきたんですが、この時はPC全体を再起動して解決しました。おそらくDockerデーモンの再起動でも解決できるかもしれない。どこかに書いておかないと後々忘れるのでこちらに書いておきましたが、後々同じ問題が起きた時にしっかり調査して別記事で上げておきたいと思います。

Ubuntu 18.10の場合

Ubuntu18.10では上記のようにDNSサーバーを直書きしてもsystemd-resolve --statusの結果には反映されるが、実際の設定に影響がない。いつまでも謎の値を参照している。

そこでもう少し掘り下げてみたところnmcliで変更するのが最も適切だということがわかった。Ubuntu 18.04では試していないので上記の説明は残しておくとして、Ubuntu 18.10では下記のようにnmcliを使ってDNSサーバーを設定する。

まず自分の接続しているルーターのデバイス名を取得する。

$ nmcli device
DEVICE   TYPE      STATE     CONNECTION      
wlp2s0   wifi      接続済み  my-mobile-router
docker0  bridge    接続済み  docker0         
lo       loopback  管理無し  -- 

先に取得したデバイス名で本当に接続したいDNSを設定する。複数設定する場合はスペースで区切る。

nmcli con mod "my-mobile-router" ipv4.dns "1.1.1.1 192.168.0.15 192.168.0.16"

その後NetworkManagerを再起動し、systemd-resolvedを再起動することで反映される。

sudo systemctl restart NetworkManager
sudo systemctl restart systemd-resolved

この段階でsystemd-resolve --statusも正しく変更される。また、DHCPサーバーから返されたDNSサーバーがwlp2s0に適用されていると思うが、上記の設定を行うと消滅する。ipv4.ignore-auto-dns yesを実行するとDHCPサーバーから返されたDNSサーバーの自動設定を無効化できるが、それを行わずとも除去できるので実行の必要はないと思った。どこで悪さをするかわからない事があったので原因となる可能性の芽は摘むことにし、実行することにした。

ちなみに今回の場合でもMTUの変更は必要だが、最後に後付で行えば良い。

sudo ip link set wlp2s0 mtu 1400

この設定を行ったあとでresolv.confを覗いてみると先に設定したnameserverがずらずらと並ぶ。

cat /var/run/systemd/resolve/resolv.conf

再起動後も今行った設定はsystemd-resolve --statusで確認する限り維持されているように見えるが、実はされていない。ただし設定はNetworkManagerに残っているのか、下記のsystemd-resolvedを実行するだけで設定が反映(復元)される。

sudo systemctl restart systemd-resolved

またIPv6が有効な環境でも動作が不安定になるので無効にしておくのが吉。

nmcli con mod hoge ipv6.method ignore

nmcliはNetworkManagerのツールであり、このコマンドで設定した値はダイレクトにGUIのWi-Fi設定にも反映されている。GUIで設定すると重複して意味不明になるかと思うかもしれないが、ちゃんとGUIに反映されるので気持ちよくCLIで操作するのが良い。

以上で基本は問題ないが、systemd-resolvedが動作していると値が書き換わり接続が安定しないというケースもある。これについては停止するという方法も存在する。

sudo systemctl disable systemd-resolved.service
sudo systemctl stop systemd-resolved

/etc/NetworkManager/NetworkManager.confを開き、[main]項目の下に下記の設定を追加します。

dns=default

その後/etc/resolv.confのシンボリックリンクを削除する。

rm /etc/resolv.conf

最後にNetworkManagerを再起動する。

sudo service network-manager restart

まとめ

これらの複雑な設定はシェルにまとめて実行すると良い。環境に合わせてDNSの設定値も変更していくと思う。IPv6が不調ではない環境があるかもしれないし、1.1.1.1よりも8.8.8.8の方が高速な環境もあるかもしれないので、引数を取って処理してもいいかもしれません。

nmcli con mod hoge ipv4.ignore-auto-dns yes
nmcli con mod hoge ipv6.method ignore
nmcli con mod hoge ipv4.dns "1.1.1.1"
sudo systemctl restart NetworkManager
sudo systemctl restart systemd-resolved
sudo ip link set wlp2s0 mtu 1400

参考