毎回どういうことなのか、どうやって繋いだかを忘れて調べながら設定する羽目になってるのでメモとして残す。
背景
今の職場では L2TP/IPSec な VPN を使っていて、勤怠とかの社内システムにはそれ経由じゃないとアクセスできない様になっている。
自分のマシンから繋ぐ際 1 の環境としては、例によって OS (ディストリビューション) は ArchLinux でネットワークの管理に NetworkManager 、 L2TP/IPSec 接続のために以下のパッケージを使っている。
- community/networkmanager-l2tp
- aur/libreswan
ただ、単純にこれらのパッケージを AUR から入れて NetworkManager で VPN の設定をしただけだと接続に失敗する。
journalctl で失敗時の NetworkManager.service
ipsec.service
辺りのログを見ても、
「あぁコレが原因か」というログを見つけられず「 IKEv1 の途中で何故かタイムアウトで失敗してるっぽい?」くらいしか分からなかったのだが、
色々調べたり試した結果から言うと VPN サーバとクライアントの両方で利用可能な鍵交換方式が存在せず、
結果として IPSec の最初のネゴシエーションが完了せず失敗、ということらしかった。
IPSec でのネゴシエーション失敗について
まず「 IPSec の最初のネゴシエーションに失敗する」という部分について、 IPSec 自体について調べたことと合わせて今回の状況をざっくりまとめる。
IPSec はその処理の中でいくつかのプロトコルを組み合わせて使っている。
- 通信データの改ざん防止のための認証ヘッダを付加する AH (Authentication Header)
- データのカプセル化を行う ESP (Encapsulating Security Payload)
- 鍵交換を行う IKE (Internet Key Exchange)
- 等
また、それぞれのプロトコルの中で使う具体的な暗号方式等のネゴシエーションは、 IPSec での通信の最初の方にある IKE プロトコルの中で行っている。 そしてネゴシエーションの結果を VPN サーバのアドレス等の情報と合わせて SA (Security Association) と呼ばれるパラメータセット 2 にまとめ、 これを使って通信を行うような流れになっている。
この IKE の中に、鍵交換に使う Diffie-Hellman グループのネゴシエーションと実際の鍵交換処理が含まれるのだが、 当然 VPN サーバとクライアントの両方で使用可能なグループが存在しないと通信できないことになる。
しかし今回の場合それが存在せず、ネゴシエーションが成功しないというのが接続失敗の原因らしかった。
実際に VPN サーバ側で利用可能なグループを確認すると以下のような感じになる。
❯ sudo ./ike-scan.sh <VPNサーバのアドレス> | grep SA=
SA=(Enc=3DES Hash=SHA1 Group=2:modp1024 Auth=PSK LifeType=Seconds LifeDuration=28800)
SA=(Enc=3DES Hash=SHA1 Group=2:modp1024 Auth=RSA_Sig LifeType=Seconds LifeDuration=28800)
確認方法について
Known Issues · nm-l2tp/NetworkManager-l2tp Wiki · GitHub
こちら参考に、というかそのままスクリプトを作って VPN サーバに対してスキャンを行っている。 問題ないとは思うがネットワーク越しに対向をスキャンする行為ではあるので、実行する際はそのことを認識しておいた方が良いかもしれない。
スクリプトの中で使っている ike-scan コマンドは AUR にもあるので、 yay -S ike-scan
とかでインストールできる。
#!/bin/sh
# Encryption algorithms: 3des=5, aes128=7/128, aes192=7/192, aes256=7/256
ENCLIST="5 7/128 7/192 7/256"
# Hash algorithms: md5=1, sha1=2, sha256=5, sha384=6, sha512=7
HASHLIST="1 2 5 6 7"
# Diffie-Hellman groups: 1, 2, 5, 14, 15, 19, 20, 21
GROUPLIST="1 2 5 14 15 19 20 21"
# Authentication method: Preshared Key=1, RSA signatures=3
AUTHLIST="1 3"
for ENC in $ENCLIST; do
for HASH in $HASHLIST; do
for GROUP in $GROUPLIST; do
for AUTH in $AUTHLIST; do
echo ike-scan --trans=$ENC,$HASH,$AUTH,$GROUP -M "$@"
ike-scan --trans=$ENC,$HASH,$AUTH,$GROUP -M "$@"
done
done
done
done
上記の通り VPN サーバ側は Diffie-Hellman グループとして DH2/modp1024 しか対応してないのだが、 この DH2/modp1024 はもはやセキュアじゃないって事でデフォルトではやサポートされなくなってきている。
- Diffie Hellman Groups - Cisco Community
- ike string error: IKE DH algorithm ‘modp1024’ is not supported · Issue #123 · nm-l2tp/NetworkManager-l2tp · GitHub
なので、この DH2/modp1024 使えない問題を回避する必要があり、以下で行っているのはその作業になる。
設定作業
ということで、 DH2/modp1024 を自分のマシン側で使えるようにする必要があるのだが、
実のところ networkmanager-l2tp
にしても libreswan
にしても実装としては残っているので大した作業は必要なく、
ビルド時に必要なパラメータを指定してビルドし直してやれば使えるようになる。
各パッケージの PKGBUILD を取ってきて現状を確認する。
- aur/libreswan (4.12-1)
- ビルド時に
USE_DH2=true
を指定する必要がある
- ビルド時に
❯ yay -G libreswan
:: (1/1) Downloaded PKGBUILD: libreswan
❯ cat libreswan/PKGBUILD
〜(省略)〜
# https://git.centos.org/rpms/libreswan/blob/c8s/f/SPECS/libreswan.spec
_bargs=(
FINALLIBEXECDIR='/usr/lib/ipsec'
#INC_MANDIR='/usr/share/man'
FINALMANDIR='/usr/share/man'
FINALSBINDIR='/usr/bin'
#INC_USRLOCAL='/usr' # required by 3.32 for /usr/share/doc
PREFIX='/usr'
USE_DNSSEC=false
USE_LABELED_IPSEC=false
USE_LIBCAP_NG=true
USE_DH2=true # insecure modp1024
USE_LEAK_DETECTIVE=false
USE_XAUTH=true
)
〜(省略)〜
build() {
set -u
cd "${_srcdir}"
# Disable new warning introduced with GCC 6 (-Wunused-const-variable=)
local _cf=(
#-Wno-error=sign-compare
#-Wno-error=unused-const-variable
#-Wno-error=implicit-fallthrough
#-Wno-error=maybe-uninitialized
#-Wno-error=pointer-compare
#-Wno-error=format-truncation
#-DNSS_PKCS11_2_0_COMPAT=1 # nss 3.52 https://github.com/libreswan/libreswan/issues/342
-Wno-error=unused-result
)
CFLAGS="${CFLAGS} ${_cf[*]}" \
nice make -s "${_bargs[@]}" programs
set +u
}
〜(省略)〜
- aur/networkmanager-l2tp (1.20.10-1)
- ビルド時に
--enable-libreswan-dh2
を指定する必要がある
- ビルド時に
❯ yay -G networkmanager-l2tp
:: (1/1) ABS から PKGBUILD をダウンロード: networkmanager-l2tp
❯ cat networkmanager-l2tp/PKGBUILD
〜(省略)〜
build() {
export NOCONFIGURE=1
cd $pkgname-$pkgver
./autogen.sh
./configure \
--libexecdir=/usr/lib/NetworkManager \
--localstatedir=/var \
--prefix=/usr \
--sysconfdir=/etc \
--with-pppd-plugin-dir=/usr/lib/pppd/$_pppver \
--with-gtk4
sed -i -e 's/ -shared / -Wl,-O1,--as-needed\0/g' libtool
make
}
〜(省略)〜
以上の通り、 libreswan
の方はこのままで良いが networkmanager-l2tp
の方はビルドし直す必要があることが分かるので、
PKGBUILD を修正してビルドし直す。
また、修正してインストールしたパッケージが AUR の方でバージョンアップがあった際に置き換えられないように、
modified
グループに追加して AUR ヘルパーでのアップデート時に無視するような設定もついでに足しておく。
- networkmanager-l2tp/PKGBUILD
@@ -22,6 +22,7 @@
'strongswan: IPSec support')
source=("$pkgname-$pkgver.tar.gz"::"$url/archive/$pkgver.tar.gz")
b2sums=('d2958b9aa803ffb498ed9481ef1726587f881570a247c0f9d06738a2188adf3130e3a91fa3facb67994bd6add196caeb6344a94ef04b4785c5389ed511343258')
+groups=('modified')
prepare() {
ln -sf NetworkManager-l2tp-$pkgver $pkgname-$pkgver
@@ -37,7 +38,8 @@
--prefix=/usr \
--sysconfdir=/etc \
--with-pppd-plugin-dir=/usr/lib/pppd/$_pppver \
- --with-gtk4
+ --with-gtk4 \
+ --enable-libreswan-dh2
sed -i -e 's/ -shared / -Wl,-O1,--as-needed\0/g' libtool
make
}
- /etc/pacman.conf
@@ -24,6 +24,7 @@
# Pacman won't upgrade packages listed in IgnorePkg and members of IgnoreGroup
#IgnorePkg =
#IgnoreGroup =
+IgnoreGroup = modified
#NoUpgrade =
#NoExtract =
で、ビルドしてインストールする。
❯ cd networkmanager-l2tp/
❯ makepkg -si
==> パッケージを作成: networkmanager-l2tp 1.20.10-1 (2024年02月11日 07時30分23秒)
〜(省略)〜
❯ yay -Qs networkmanager-l2tp
local/networkmanager-l2tp 1.20.10-1 (modified)
L2TP support for NetworkManager
あとは NetworkManager で VPN の設定をすれば接続が成功する。( IPSec の設定に注意する)
おわりに
調べた感じ今回の DH2/modp1024 は危殆化を理由に使われなくなってきているという理解をしているのだが、 Windows や Mac 使ってる人からは特にこういった話もなく普通に繋がっているらしい( DH2/modp1024 を標準でサポートしている?)ので、 実際のところどのくらい気にするものなんだろうかというのは若干気になる。
おそらくは関連する CVE とかいろんなソフトウェアの対応傾向とかを整理して各々で対応決めているんだろうとは思うが、 その辺りの調べ方というか判断のコツというか勘所というかがあんまりわかってなく、時間ばっかりかかりそうだったので自分は少しググったくらいで諦めてしまった。