1. はじめに
こんにちは。HealthCare Innovation Group (HIG)の清水雄一郎です。
本記事は、春の入門祭り2026の1日目の記事です。
新年度・新チーム配属のこの季節、「開発環境のセットアップで丸一日溶かした」という経験をされている方も多いのではないでしょうか。特にエンタープライズ企業の「プロキシ・VPN配下」での開発環境構築は、ドキュメント通りに進めても謎のエラーに阻まれがちです。
プロキシに関しては、過去の記事123もぜひご確認ください。
少し前(2026/01頃)に私が遭遇した事象は、WSL2環境で「自宅に帰るとapt updateできない」というものです。
当時を振り返ると、次のような状況でした。
- オフィスに出社してネットワークに繋ぐと、
apt updateが成功する - 自宅(無線/有線LAN&VPN接続中)だと、
apt updateが失敗する - ただし、iPhoneのテザリング+VPN の場合、
apt updateが成功する
結論から言うと、今回のケースではDNSの順序を変えることで解決しました。
その頃のSlackスレッドやGeminiとのチャット履歴を遡りつつ、体験記兼トラブルシューティングログとして残します。
2. 調査編: 泥沼のトラブルシューティング
2.0. 前提
本記事は、次の環境下で確認したものです。
※Windows側のバージョンは、事象発生時から少し変わっているかもしれません。
環境情報
# Windows |
2.1. エラーログ
まずは事象を整理するため、発生していたエラーログを確認します。
$ sudo apt update |
10.x.x.x:8080は、社内プロキシサーバーです。
「タイムアウト」と「接続が相手からリセットされました」が混在しており、この時点では原因が全く特定できていません。
試しに同じ社内プロキシを経由している wget / curl コマンドを試しましたが、成功することを確認できました。
$ wget google.com |
※いま振り返ると、http://archive.ubuntu.com/ubuntu宛にwget / curl コマンドを試した方が良かったかもしれません。
ここで一人では抱え込めないと判断し、Slackでチームメンバーに助けを求め、Geminiにも相談しながら仮説検証を始めました。
他の人に相談することは、私の環境だけの問題かどうか切り分けるという一つの検証と言えると思います。
2.2. 仮説① プロキシ設定が間違っている?
最初に疑ったのは、やはりプロキシ周りです。aptはwget/curlとは別経路の設定を見るため、apt自体のプロキシ設定を確認します。
cat /etc/apt/apt.conf |
設定済みでした。環境変数もaptと同じ設定値が入っています。
env | grep -i proxy |
aptのプロキシ設定は、問題なさそうです。
またこの時、環境変数を引き継ぐため、sudo -E apt updateを実行してみましたが、最初と同様のエラーになりました。
2.3. 仮説②~⑤ プロキシ設定以外はどう?
プロキシ設定以外に考えられる原因をGeminiやメンバーに聞いて片っ端から試しました。結論から言うと、いずれも空振りでした。
仮説② 社内プロキシの証明書が未インストール?
証明書周りはプロキシの次にトラブルが多い印象なので、試しに手動で入れ替えて確認します。
→ 変化なし
# 非推奨。次のコードブロックの手順を推奨。 |
原因特定のために/etc/ssl/certs/配下の証明書を直接操作しましたが、本来はupdate-ca-certificatesを使う方が正しいです。
推奨される方法は、次の通りです。
sudo cp path/to/ca.crt /usr/local/share/ca-certificates/corp-proxy.crt |
仮説③ WSLのHyper-Vファイアウォールが遮断している?
「デフォルトでオンになっているHyper-V FirewallをOFFにするとaptが通ることがある」という情報を教えてもらい、「WSL Settings」のGUIから無効化してみました。
→ 変化なし
仮説④ MTUの設定が経路と合っていない?
Geminiにエラーログを渡して相談すると、MTU(Maximum Transmission Unit)4の影響を疑うよう提案を受けました。VPN環境下では実効MTUが小さくなり、デフォルト1500バイトのままだと通信に失敗するケースがあるとのこと。
→ こちらも変化なし
sudo ip link set dev eth0 mtu 1300 |
後から振り返ると、MTU調整は「大きいパケットだけ落ちる」症状に有効な対策で、数十KBのリクエストで失敗する今回の症状とは整合しません。生成AIの提案を鵜呑みにして試した回り道でした。
仮説⑤ archive.ubuntu.comが遠いから?
リポジトリを日本のミラーサーバーに変更してみます。
→ ログは割愛しますが、タイムアウトエラーになってしまいます。
sudo sed -i.bak -E 's!http://(archive|security)\.ubuntu\.com!http://jp.archive.ubuntu.com!g' /etc/apt/sources.list |
2.4. 仮説⑥ 接続するネットワークの問題?
出社する日が多く、自宅でのみ発生する問題の解消を後回しにしていたのですが、オフィスにいる時に時間ができたので再度向き合ってみることにしました。
VPN接続時に発生するため、オフィスにいながらBYODであるiPhoneのテザリングに切り替えて、VPN接続してみます。
なんと、apt updateが正常終了することに気が付きます。整理すると次の状況です。
- オフィス無線LAN → OK
- 自宅(無線/有線)LAN+VPN → NG
- iPhoneテザリング+VPN → OK 🤔
ひとまず成功したことに喜びつつ、ずっとテザリングで業務するわけにはいきません。
VPNがすべてダメというわけではないと分かったので、他の手立てを考えてみました。
3. 原因編: 名前解決を疑う
wgetは通ってaptは通らない、かつ、同じVPNを使っていても回線(自宅LAN/テザリング)によって成否が変わることが分かりました。
つまり原因は「どの回線でも共通に使われる設定」ではなく、「回線ごとに切り替わる何か」 にあると考えました。
回線ごとに切り替わるものの一つに、ホストであるWindowsが参照するDNSがあります。
WSL2は、デフォルトでWindows側のDNSを継承するため、回線が変わればWSLが使うDNSも変わります。
ここから、名前解決(DNS)の速度を疑うことにしました。
※名前解決とは、ドメイン名(例: archive.ubuntu.com)をIPアドレスに変換する処理のことです。
apt updateは、内部で複数のリポジトリに問い合わせているため、1問い合わせあたりの名前解決が遅いとそれが積み重なり、接続タイムアウトに抵触しやすいのではないかと考えました(最初に試したwget / curl は単発リクエストなので、1回の遅延くらいは待てる、という仮説)。
実際に、名前解決の時間を計測してみます。getent hostsは、指定したホストの情報を取得するコマンドです。
time getent hosts proxy.example.com |
それがたった1件の社内ホスト情報取得に15秒かかっていました。
ちなみに、その時の/etc/resolv.confの中身はこうでした。
cat /etc/resolv.conf |
172.x.x.xは、WSL2がデフォルトで参照するWindowsホスト側の仮想ルーターです。
Windows側の設定を引き継いで名前解決してくれる便利な仕組みですが、私の環境かつVPN接続状態ではボトルネックになっていると考えました。
4. 解決編: /etc/resolv.confへの記載順序を変える
原因が掴めれば対処は単純です。WSLのデフォルト仮想DNS(172.x.x.x)より先に、社内DNSに直接問い合わせるよう、/etc/resolv.confのnameserver順序を並び替えます。
Linuxのリゾルバは、/etc/resolv.confのnameserverを上から順に試すようです。56先頭から応答が返ればそこで終了、タイムアウトすれば次へフォールバックする仕組みです。1問い合わせあたりデフォルト5秒 × 複数回リトライすることで7、先頭が遅いと十数秒単位で待たされていたと推測します。
つまり、社内DNSを先頭に置くだけで、ほぼ全ての問い合わせが1行目で即解決するようになるはずです。
sudo vim /etc/resolv.conf |
# /etc/resolv.conf |
効果を計測します。
time getent hosts proxy.example.com |
15.225秒 → 0.033秒。約460倍の改善です。
この状態でapt updateを叩くと、自宅(無線/有線)LAN+VPN環境で、一発で成功することを確認できました🎉
ここで忘れてはいけないのですが、/etc/resolv.confは、WSLを再起動するとデフォルトで自動再生成され、上の変更が上書きされて消えてしまいます。
「せっかく直したのに翌朝また詰まった」を防ぐため、/etc/wsl.confで自動生成を無効化しておきます。
sudo vim /etc/wsl.conf |
# /etc/wsl.conf |
5. おわりに
今回の泥沼を振り返ると、最も反省すべき点は、「十分な評価をしないまま、ありがちな原因を手当たり次第試し続けた時間」 の長さでした。
生成AIにエラーログを投げると、どんなに長くても中身を読んで自分が思いつかない次の一手を考えてくれます。
特に、環境構築周りは色々な層に原因が潜んでいるため、これまで自分よりも生成AIの方が得意な分野だと思っていました。
もちろん多くの場合その通りだと思いますが、今回のケースのようにうまくいかない時もあります。
改めて、開発環境構築において「何ができて何ができなかったか」を整理することはもちろん、「何が『どこまで』できているか」を「計測する」 ことが重要だと実感しました。
これから開発環境を構築する皆さんは、詰まった際に生成AIに「何をやるといいか」と同時に、「何を計測すると原因が測れるか」を聞いてみると解決の近道になるかもしれません。
そしてぜひ、詰まった経緯と解決策を記事にしてネットに公開してください!
今度は、生成AIが学習して解決がもっと早まるかもしれません……!
参考
- 1.TCP Proxyを作って面倒なProxy設定を一掃する ~Rust製moproxyとnftablesによる透過プロキシ設定~ ↩
- 2.ローカルプロキシで認証プロキシの煩わしさを解消! ↩
- 3.ProxyとDockerと新人社員と時々わたし ↩
- 4.https://wa3.i-3-i.info/word13207.html ↩
- 5.https://linuxjm.sourceforge.io/html/LDP_man-pages/man5/resolv.conf.5.html ↩
- 6.https://kazmax.zpp.jp/cmd/r/resolv.conf.5.html ↩
- 7.https://manpages.ubuntu.com/manpages/noble/ja/man5/resolv.conf.5.html ↩