Cloudflare Zero Trust の WARP を有効化しつつ Apple Container を使う(pf 応用編)

外出先から自宅のネットワークへ接続する際、以前は SoftEther VPN を使用していましたが、ここ数年は「Cloudflare Zero Trust」を使用しています。

Cloudflare Zero Trust は SoftEther VPN と比べて下記のメリットがあります。

  • macOS, iPhone, Android の公式のクライアントがある
  • 海外から利用した際に全通信を日本の自宅を通す必要がない
  • 将来的に自宅の回線で PPPoE が利用できなくなった場合にも対応可能

逆に Linux 同士であったり、特定の回線をあえて通したいなどであれば SoftEther VPN のほうが良かったりします。

50人までは無償で利用できますので個人や小規模なチームであれば十分利用可能です。

ただ、Cloudflare Zero Trust を有効化すると、通信周りで特殊な挙動をするソフトウェアが一部正常に動かなくなり、Apple Container はその一例です。

調査していく中で、以前このブログでも紹介した macOS の pf (packet filter)を用いることでコンテナの通信が可能になったのでブログを更新します。

前提

下記のバージョンで確認しています。

  • MacBook Air M1, 2020
  • macOS Tahoe 26.5.2
  • Apple Container 1.1.0
  • Cloudflare WARP 2026.6.822.0

今後のバージョンアップによってこの設定が不要になったり、設定項目が変更になる可能性があります。

本記事は Cloudflare Zero Trust の設定や WARP の導入が完了した前提で記載しています。

CF_DNS_PROXY_FAILURE エラー

まず「CF_DNS_PROXY_FAILURE」エラーが表示される場合は、一旦 Apple Container を停止して、WARP → Apple Container の順で起動させてみてください。

デフォルト設定の問題点

WARP、Apple Container ともにステータスは正常であるものの、正常に通信できません。

具体的には、下記のコマンドでエラーが出力されないことがゴールです。

curl https://1.1.1.1 --insecure
# そもそも 1.1.1.1 への疎通ができない

curl http://example.com
# (6) Could not resolve host: example.com

curl https://1.1.1.1
# (60) SSL certificate OpenSSL verify result: self-signed certificate in certificate chain (19)

pf (packet filter)の基本コマンド

/etc/pf.conf のファイル編集後、下記コマンドを実施することになります。

# 編集
sudo vim /etc/pf.conf

# 確認
pfctl -nf /etc/pf.conf

# 反映
sudo pfctl -f /etc/pf.conf

# ルール確認
sudo pfctl -v -sr

通信が行えるようにする

デフォルトの状態では外部通信は可能であるものの pf コマンドで操作していると外部への通信ができなくなるようです。

下記の Issue のコメントに沿って、pf に下記の設定を行います。

具体的には、WARP で使用している utun のみ設定すればよいのですが、状況によって番号が変わるので、全てにおいて設定する方針のようです。

https://github.com/apple/container/issues/989#issuecomment-3797661091

nat on utun0 inet from 192.168.64.0/24 to any -> (utun0:0)
nat on utun1 inet from 192.168.64.0/24 to any -> (utun1:0)
nat on utun2 inet from 192.168.64.0/24 to any -> (utun2:0)
nat on utun3 inet from 192.168.64.0/24 to any -> (utun3:0)
nat on utun4 inet from 192.168.64.0/24 to any -> (utun4:0)
nat on utun5 inet from 192.168.64.0/24 to any -> (utun5:0)
nat on utun6 inet from 192.168.64.0/24 to any -> (utun6:0)
nat on utun7 inet from 192.168.64.0/24 to any -> (utun7:0)
nat on utun8 inet from 192.168.64.0/24 to any -> (utun8:0)
nat on utun9 inet from 192.168.64.0/24 to any -> (utun9:0)
nat on utun10 inet from 192.168.64.0/24 to any -> (utun10:0)

名前解決ができるようにする

先程の設定は完了し、外部への通信ができるようになるのですが、名前解決ができません。

具体的には、WARP を使用するとホストの DNS サーバーが「127.0.2.2」に変更されるのですが、コンテナで自動設定されるゲートウェイ「192.168.64.1」から「127.0.2.2」の通信ができず名前解決に失敗します。

そのため下記の設定を行います。

rdr pass on bridge100 inet proto udp from 192.168.64.0/24 to self port 53 -> 127.0.2.2 port 53

なお、この設定を有効化した状態で WARP をオフにすると今度は「127.0.2.2」が利用できなくなり名前解決に失敗します。

その場合、container system stop → start で bridge100 を再作成するとこの pf ルールが消滅し正常に利用できるようになります。

使用する際はまた下記コマンドで有効化する必要があります。

sudo pfctl -f /etc/pf.conf

おまけ:HTTPS 通信を正常に行えるようにする

上記にて名前解決と通信は通るようになりますが、Zero Trust を使用すると、Cloudflare 独自のルート証明書に変更されるため、証明書の追加を行わないとコンテナ側も認証エラー(自己署名証明書エラー)になります。

これを防ぐには、各コンテナの OS やアプリケーションに Cloudflare のルート証明書を追加する必要があります。

例えば Fedora の Docker イメージをベースにする場合、下記のように Dockerfile に証明書のインポートを行う必要があります。

FROM quay.io/fedora/fedora:44

COPY certificate.pem /etc/pki/ca-trust/source/anchors/certificate.crt
RUN update-ca-trust extract

最後に

最近バージョン 1.0 が公開された Apple Container において、Cloudflare WARP を有効化した状態で正常に利用できることを確認しました。

コメント行を除く pf.conf の全体像は下記となります。

scrub-anchor "com.apple/*"
nat-anchor "com.apple/*"

nat on utun0 inet from 192.168.64.0/24 to any -> (utun0:0)
nat on utun1 inet from 192.168.64.0/24 to any -> (utun1:0)
nat on utun2 inet from 192.168.64.0/24 to any -> (utun2:0)
nat on utun3 inet from 192.168.64.0/24 to any -> (utun3:0)
nat on utun4 inet from 192.168.64.0/24 to any -> (utun4:0)
nat on utun5 inet from 192.168.64.0/24 to any -> (utun5:0)
nat on utun6 inet from 192.168.64.0/24 to any -> (utun6:0)
nat on utun7 inet from 192.168.64.0/24 to any -> (utun7:0)
nat on utun8 inet from 192.168.64.0/24 to any -> (utun8:0)
nat on utun9 inet from 192.168.64.0/24 to any -> (utun9:0)
nat on utun10 inet from 192.168.64.0/24 to any -> (utun10:0)

rdr-anchor "com.apple/*"

rdr pass on bridge100 inet proto udp from 192.168.64.0/24 to self port 53 -> 127.0.2.2 port 53

dummynet-anchor "com.apple/*"
anchor "com.apple/*"
load anchor "com.apple" from "/etc/pf.anchors/com.apple"

ここで紹介した手順は Apple Container Machine でも同様に利用可能です。

WARP との相性問題で対応しておらず、Apple Container の導入をためらっていた方も是非利用してみてください。

コメントを残す

メールアドレスが公開されることはありません。 が付いている欄は必須項目です

*

日本語が含まれない投稿は無視されますのでご注意ください。(スパム対策)