WSL環境から(Symantec Endpoint Protectionが邪魔して) apt update できない場合の対処法

f:id:Naotsugu:20211021235443j:plain


事象

WSL2 の Ubuntu から外部へのネットワークが繋がらず、apt update で以下のエラーとなる。

Err:1 http://security.ubuntu.com/ubuntu focal-security InRelease
  Cannot initiate the connection to security.ubuntu.com:80 (...). - connect (101: Network is unreachable) 
  Cannot initiate the connection to security.ubuntu.com:80 (...). - connect (101: Network is unreachable)
  Could not connect to security.ubuntu.com:80 (...), connection timed out Could not connect to security.ubuntu.com:80 (...), connection timed out

connection timed out により、Network is unreachable となっている。

WSL2のネットワーク関連で良く問題になるDNS関連は、ping が通るので別問題。

$ ping -c 2 security.ubuntu.com
PING security.ubuntu.com (...) bytes of data.
64 bytes from kazooie.canonical.com (...): icmp_seq=1 ttl=44 time=255 ms
64 bytes from kazooie.canonical.com (...): icmp_seq=2 ttl=44 time=188 ms

--- security.ubuntu.com ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 1001ms
rtt min/avg/max/mdev = 187.596/221.281/254.967/33.685 ms


アンチウィルスソフトで通信がはじかれている模様。

端末には Symantec Endpoint Protection が入っており、ファイアウォールを無効にすれば解決するはず。

f:id:Naotsugu:20211018200629p:plain

だが、管理サーバで制御されており端末側での設定変更が許可されていない。

f:id:Naotsugu:20211018200711p:plain


対応方法

ホスト端末自体からは通信可能なため、ホストの Windows にフォワード Proxy を立てて、この Proxy を経由すれば対処可能。

Nginx でも良いが、HTTPS通信用の ngx_http_proxy_connect_module は静的モジュールとしてNginx のコンパイルが必要になり少し面倒。Squid はメンテナンス状況が良くわからないのでパス。

Apache でフォワードプロキシ立てることにする。


Apache の導入

最近は、本家からはバイナリリリースは提供されなくなった模様。

f:id:Naotsugu:20211018200842p:plain

今回は、下部のリンクにある「Apache Lounge」から httpd-2.4.51-win64-VS16.zip を取得。

適当なディレクトリに解凍。

> bin\httpd -v
Server version: Apache/2.4.51 (Win64)
Apache Lounge VS16 Server built:   Oct  7 2021 16:27:02


Apache の設定

conf\httpd.conf を編集。

SRVROOT にインストールしたディレクトリを指定し、Listen に適当なポートを指定。

Define SRVROOT "c:/<path>/apache24"
ServerRoot "${SRVROOT}"

Listen 8080

Proxy のモジュールを読み込み設定を追加(末尾に追加すれば良い)。

LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so

<IfModule proxy_module>
  ProxyRequests On
  ProxyVia On
  AllowCONNECT 443
  <Proxy *>
    Require all granted
  </Proxy>
</IfModule>

なお、Apache/2.4 からはアクセス制御の指定が変更になっている。

Require all granted は、Apache/2.2 系では以下と同じ。

<Proxy *>
  Order allow,deny
  Allow from all
</Proxy>

httpd.conf の定義を以下でテスト。

> bin\httpd -t

問題なければ以下で起動(今回はサービスではなくコンソールから起動するのみ)。

> bin\httpd

なお、終了は Ctrl+C。


apt update && apt upgrade

WSL から Windows に立てた Proxy へアクセスするので、IPを調べる。

> ipconfig
...
イーサネット アダプター vEthernet (WSL):

   接続固有の DNS サフィックス . . . . .:
   リンクローカル IPv6 アドレス. . . . .: xxx
   IPv4 アドレス . . . . . . . . . . . .: 172.22.80.1
   サブネット マスク . . . . . . . . . .: 255.255.240.0
   デフォルト ゲートウェイ . . . . . . .:

vEthernet (WSL) の IPがそれ。このIPアドレスはOS起動の度に変わる。 WSLでは /etc/resolv.conf に以下のように定義されたものと同じものとなる。

# This file was automatically generated by WSL. To stop automatic generation of this file, add the following entry to /etc/wsl.conf:
# [network]
# generateResolvConf = false
nameserver 172.22.80.1

よって、WSL側の環境変数で以下のように proxy を指定できる。

$ export http_proxy=http://$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):8080
$ export https_proxy=${http_proxy}

これにより apt updateapt upgrade が可能となる。

$ sudo -E apt update
$ sudo -E apt upgrade -y

-E で sudo 時に元の環境変数を引き継ぎ実行できる。


-E はあまりよろしくないので、visudo で /etc/sudoers を編集した方が良い(visudo は sudoers 編集用のエディタで構文誤りなどがチェックできる)。

$ sudo visudo

以下を追加する。

Defaults  env_keep += "http_proxy"
Defaults  env_keep += "https_proxy"
Defaults  env_keep += "HTTP_PROXY"
Defaults  env_keep += "HTTPS_PROXY"

編集終了後は Ctrl + X -> Y -> Enter で抜ける。

これにより、sudo で proxy の環境変数が引き継がれるようになり、-E での実行は不要となる。


proxy 環境変数の定義

システムワイドな環境変数は、/etc/environment に定義することが多い。 しかし、Win10 20H2 時点の WSL ではこのファイルに定義した内容が bash から見えない模様(Win11 でも同様)(https://github.com/microsoft/WSL/issues/1405)。 かつ、/etc/environment は bash ではなく PAM の機能であり、name=value でしか定義できない。

よって、.profile.bashrc などで定義することになる。

if [ -z "$http_proxy" ]; then
  export http_proxy=http://$(cat /etc/resolv.conf | grep nameserver | awk '{print $2}'):8080
  export https_proxy=${http_proxy}
  export HTTP_PROXY=${http_proxy}
  export HTTP_PROXY=${https_proxy}
fi

多くの場合、上記4つを定義することで proxy が有効になる。