DNS フィルタで pip が止まっても外さない。一時停止で確かめ、2つ許可

開発部門の人から Slack が来た。gcloud CLI のインストール中に Python のファイルが取ってこられなくなる、DNS フィルタのせいか、という内容だった。英語のエラー文が貼ってあった。

本人の読みは当たっていた。前日にその Mac を入れ替えて、DNS フィルタ(Soliton DNS Guard)を入れたのは自分たちだ。一時停止してやり直すと名前解決のエラーは消え、pip が使う2つのドメインを許可リストに入れて、DNS Guard は動かした状態に戻した。外してはいないし、止めたまま使ってもらってもいない。DNS Guard を戻した状態で、gcloud のインストールは最後まで通った。ある会社(約90名)での、入れた翌日の後始末の話だ。

この記事でわかること

  • ▶ Failed to resolve / [Errno 8] が言っていること、言っていないこと
  • ▶ 一時停止の一手で白黒をつける。当たった例と外れた例
  • ▶ 止めっぱなしにせず、必要なドメインだけ許可して戻すときに決める3つ
  • ▶ 開発者が同じエラーに当たったら、管理者に何を伝えればいいか

▼問い合わせ:DNS フィルタを入れた翌日、開発環境の作り直しが止まった

前日、その人の Mac を入れ替えた。別の MDM の管理下にあった Mac を初期化して、MDM を入れ替え、最後に DNS Guard を入れた。作業は1時間ちょっとで終わった。

翌朝、本人は開発環境を一から作り直していた。その途中、gcloud CLI(Google Cloud のコマンドラインツール)のインストールで止まった。貼られていたエラー文はこれだ(パスは短くしてある)。

WARNING: Retrying (Retry(total=4, …)) after connection broken by ‘NameResolutionError(“HTTPSConnection(host=’files.pythonhosted.org’, port=443): Failed to resolve ‘files.pythonhosted.org’ ([Errno 8] nodename nor servname provided, or not known)”)’: /packages/6b/b0/…/crcmod-1.7.tar.gz

Python のパッケージ管理ツールの pip が、crcmod というパッケージを取りに行って失敗し、再試行を繰り返している。

前日に DNS を触る製品を入れたばかりで、エラーは名前解決の失敗。容疑者はほぼ決まっていた。それでも、決め打ちで設定を触る前に、エラー文が何を言っているかを見ておく。

▼エラー文は「名前が引けなかった」とだけ言っている

英語のエラー文は、1か所だけ読めばいい。Failed to resolve と [Errno 8] nodename nor servname provided, or not known だ。どちらも「files.pythonhosted.org という名前を IP アドレスに変えられなかった」という意味になる。回線が遅い、証明書がおかしい、というエラーではない。

ただし、このエラーは「DNS フィルタのせい」とまでは言っていない。macOS の [Errno 8] は、名前が引けない原因なら何でも出る。Wi-Fi の DNS がおかしいときも、VPN の設定が残っているときも同じ表示になる。だからここで言えるのは「名前解決の段階で落ちている。前日に入れた DNS Guard の可能性が高い」までだ。

エラー文の読み分け(ネットワーク系の3種類)

  • ▶ Failed to resolve / NameResolutionError / [Errno 8](Mac):名前が引けない。DNS の段階で止まっている。DNS フィルタを入れた直後なら最初に疑う
  • ▶ Connection timed out / Connection refused:名前は引けて、その先の接続で止まっている
  • ▶ certificate verify failed:証明書の問題。通信の中身を検査する製品が入っていないかを見る

※DNS フィルタでも、止めたドメインに案内ページの IP アドレスを返す方式の製品だと、名前は引けてしまうので2・3行目の形で出ることがある。今回の DNS Guard は1行目の形で出た。

もう一つ、エラー文から読めることがある。pip は失敗した URL を /packages/.../crcmod-1.7.tar.gz まで知っていた。pip はまず pypi.org の一覧に問い合わせて、パッケージ本体の置き場の URL を受け取り、本体は files.pythonhosted.org から取る。つまり一覧の中身は手元にあって(キャッシュだった可能性もある)、本体の置き場の名前だけが引けなかった、と読める。ここは推定で、pypi.org が引けていたかは確かめていない。この話は、許可するドメインを決めるところでもう一度出てくる。

▼一時停止で白黒をつける。当たった今回と、外れた2週間あまり前

DNS のエラーで、前日に DNS を触る製品を入れたなら、最初の容疑者はそれだ。ただ、容疑者のまま許可リストを触ることはしない。製品を一時停止して、同じ操作をやり直す。この一手で、当たりか外れかがはっきり出る。

今回:止めたら先に進んだ

DNS Guard を一時停止して、同じインストールをやり直すと、名前解決のエラーは消えて先に進んだ。原因は DNS Guard で決まりだ。

DNS Guard は Mac の中で DNS の問い合わせを受け持ち、クラウド側で評価して、禁止しているドメインは名前解決をせずに止める仕組みだ。今回はそれが「名前が引けない」というエラーとして開発者の画面に出た。なぜ files.pythonhosted.org が止められたのか(脅威と判定されたのか、分類で止まったのか)は、確かめていない。だからこの記事では「誤検知だった」とは書かない。

2週間あまり前:止めても変わらなかった

同じ DNS Guard を入れている環境で、Windows App でリモート環境に繋がらない件があった。このときも DNS Guard を疑い、5分止めて試した。結果は変わらなかった。

だから DNS Guard は外れと判断して、リモート環境側の初期化に切り替えた。止めても変わらないなら、DNS フィルタの許可リストを触る理由はない。理由のない許可は、フィルタに穴を開けるだけになる。

一時停止は「当たり」も「外れ」もはっきり出る

止めて通れば、その製品が原因。止めても同じなら、その製品は原因ではない。どちらに転んでも次の一手が決まる。やってはいけないのは、一時停止で確かめる前に許可リストを触ることと、止めたまま使い続けることだ。

一時停止を利用者に任せるか

DNS Guard は、利用者に一時停止の権限を渡すかどうかを管理者が選べる(製品の説明では、緊急時のための機能という位置づけ)。渡していないなら、管理者が止めて試す。渡しているなら、試したあとに必ず再開したかまで確かめる。止めたまま忘れると、その Mac だけフィルタのない状態が続く。

▼止めっぱなしにしない。2つのドメインを許可して、DNS Guard は戻す

一時停止で通ると、「とりあえず外しておく」「止めたまま使ってもらう」に流れやすい。開発者の作業は止められないし、本人も早く進めたい。それでも外さないし、止めたままにもしない。外しても止めたままでも、その Mac だけフィルタのない状態が続く。必要なドメインだけを許可リストに入れて、DNS Guard は動かした状態に戻す。

エラー文に出たのは1つ、許可したのは2つ

今回、許可リストに入れたのは次の2つだ。

ドメイン pip が何に使うか 今回のエラー
pypi.org パッケージの一覧に問い合わせ、本体の置き場の URL を受け取る エラー文には出ていない(止まっていたかは未確認)
files.pythonhosted.org パッケージ本体(今回は crcmod-1.7.tar.gz)を取る 名前解決できずに止まった

エラー文に出たのは files.pythonhosted.org だけだ。前の節で書いたとおり、このとき pypi.org は引けていたのかもしれないし、一覧がキャッシュに残っていただけかもしれない。それでも pypi.org も入れた。止まっているのを管理コンソールで見たからではない。pip を通すなら2つで1組だと考えたからだ。pip は次のパッケージに進むたびに pypi.org の一覧へ問い合わせ、そこで受け取った URL で files.pythonhosted.org から本体を取る。一覧が引けなければ本体の URL がわからず、本体の置き場が引けなければファイルが取れない。pip を通すなら、この2つで1組になる。

許可したのは、管理コンソールの許可ドメイン(許可リスト)に、この2つのドメインを1件ずつ。カテゴリごと許可したり、フィルタの強さを下げたりはしていない。DNS Guard を動かした状態に戻してからインストールをやり直し、gcloud が最後まで入ったのを確かめた。

許可して戻すときに決める3つ

  • ▶ 何を許可するか:今回は、止まった files.pythonhosted.org と、pip が対で使う pypi.org の2つ。親ドメインやカテゴリでまとめては入れない。親ドメインで配下のサブドメインも通るかは、DNS Guard の公開資料では確かめられなかった
  • ▶ 誰が判断するか:許可リストに足すのは、フィルタに穴を開けることでもある。誰が足してよいか、足したら誰に知らせるかを、入れる時点で決めておく。DNS Guard は、利用者が自分で許可ドメインを足せるようにも設定できる。その権限を渡すかも、ここで一緒に決める
  • ▶ どこに残すか:許可したドメインと、なぜ許可したか

3つ目は、ヘルプデスクの切り分けの手順書に書き足した。DNS Guard の行に「インストール中に名前解決のエラーが出たら、まず DNS Guard を一時停止して再試行。通れば許可リストに追加」と入れ、「止まった実例」の表を作って、止まったドメインとエラー文、対応を1件目として残した。ここに残すのは、次の人の切り分けを速くするためだけではない。許可リストを見直すときに「このドメインは、いつ、何のために足したか」を答えられるようにするためだ。理由の残っていない許可は、あとで誰も消せなくなる。

開発者は、管理者に何を伝えればいいか

開発者の側から見れば、やることは1つだ。このエラーが出たら、止まったドメイン名(エラー文の host='...' の部分)と、何をインストールしていたか(pip、npm など)を管理者に伝えて、許可を頼めばいい。今回のように、エラー文に出ないドメインも一緒に要ることがある。ツール名がわかれば、管理者の側で対になるドメインまで見られる。DNS フィルタを自分で止めたまま作業を続けるより、そのほうが許可の記録が残り、次の人が同じところで止まらない。

開発環境の作り直しでは、npm や Homebrew、gcloud のコンポーネントも外から取ってくる。同じ症状が続くなら、開発部門向けにまとめて許可しておくかを相談する。ただしこれは見立てで、まだ止まった実例はなく、試してもいない。

▼まとめ

  • ▶ エラー文は1か所だけ読む。Failed to resolve / [Errno 8] は「名前が引けなかった」。DNS フィルタのせい、とまでは言っていない
  • ▶ 疑う順番は「直前に変えたもの」から。確かめるのは、一時停止して同じ操作をやり直す一手。外れることもある
  • ▶ 通ったら止めっぱなしにしない。必要なドメインだけ許可して、フィルタは動かしたまま。pip なら pypi.org と files.pythonhosted.org の2つ
  • ▶ 許可したドメインは理由と一緒に残す。あとで見直すときの根拠になる
📄 開発環境の作り直しでは「管理者権限をください」という依頼も重なりやすい。その依頼を分類した話はこちらの記事で書いています。
📄 ネットワークのエラーに見えて、原因は端末側の設定だった切り分けはこちらの記事で書いています。

📅 30分無料相談、受け付けています

「セキュリティ製品を入れたら、開発の作業が止まるようになった。外していいのか判断できない」——そういった段階からお気軽にどうぞ。切り分けの進め方から、許可リストの決め方・残し方まで一緒に考えます。

📅 30分無料相談を予約する →