Zero Trustを使い始めたんだけど,こいつをモバイル端末で使う場合,WARP Clientを使うことになる.前回説明した通り,ブラウザ利用であれば特にWARPは不要なんだが,アプリ内でAPIを叩くような場合はこれが必須となる. で,WARPというのはVPNも使っているので,自動的にVPNが設定される.この状態でAdblockするにはどうしたらいいだろうか.
通常モバイル端末でAdblockしようとすると,
- VPNをいれる
- 広告をブロックしてくれるブラウザを使う
の2択になると思う.ブラウザしか使わないのであれば,2は良い選択肢である.アプリ内ブラウザ等まで対応しようと思うと,1しか選択肢がなくなる. しかし,このVPNはWARPのVPNと競合するので,どちらか一つしかいれることができない.
というわけで,理想的にはWARPのVNPを有効化している状態でもAdblockできたら良い.
大前提: Split TunnelsとGatewayは別物
Split Tunnels only impacts the flow of IP traffic. DNS requests are still resolved by Gateway and subject to DNS policies unless you add the domains to your Local Domain Fallback configuration.
Split Tunnelsはトラフィックを特定のTunnel経由にするというもの.対してGatewayはCloudflareのDNSであって,全く別のレイヤーの話をしている. WARP Clientを使うときは,常にDNSとしてCloudflareのDNSが使われている.ここの制御をするのがGatewayで,GatewayのpoliciesはDNSの挙動に関わる制御をしている.
対して,Split Tunnelsはドメインの解決後,トラフィックをどのルートで送るのかという話しかしていない.なので,ここにDNSは関係ない.
ということは,例えばSplit Tunnels側ではincludeルールで,example.com
のトラフィックのみをSplit Tunnelsに流しているとする.この場合でもWARP Clientを使えばGatewayを通るので,DNSのFirewall Policyは普通に使える.
このGatewayを回避できるのは,Local Domain Fallbackだけだ.ここに設定したドメインだけはCloudflareのDNSを通さずにドメイン解決することができる.だから,GatewayのPolicyを回避させたいようなドメインがある場合はここに設定すると良い.localhost
とかね.
Gatewayで特定のドメインをブロックする
基本的にはこの記事と同じことをしている.
Listを作るのは面倒くさかったので全部Terraformにしている.
locals { list_size = 1000 total_lists = ceil(length(var.ad_domains) / local.list_size) } resource "cloudflare_zero_trust_list" "ads" { count = local.total_lists account_id = var.account_id name = "advertisements_${count.index + 1}" description = "List of advertisement domains ${count.index + 1}" type = "DOMAIN" items = [ for domain in slice(var.ad_domains, count.index * local.list_size, min((count.index + 1) * local.list_size, length(var.ad_domains))) : { value = domain } ] }
Listsは上限が1000件なので,ドメインのリストを1000件ずつに分離してListを作っている.こうしておけば,ドメインリストが更新されたらterraform apply
するだけで良い.
resource "cloudflare_zero_trust_gateway_policy" "block_ad" { account_id = var.account_id name = "Block ad" description = "" device_posture = "" enabled = true action = "block" filters = ["dns"] identity = "" precedence = 2047 traffic = join( " or ", [for list in cloudflare_zero_trust_list.ads : format("any(dns.domains[*] in $%s)", list.id)] ) rule_settings = { block_page_enabled = false insecure_disable_dnssec_validation = false ip_categories = false ip_indicator_feeds = false ignore_cname_category_matches = false resolve_dns_through_cloudflare = false } }
あとはGateway Policyを作るだけ.
Split Tunnelsには特に触れない
すべてのトラフィックをcloudflared経由にする必要はないと思っていたので,Include IPs and domains
で運用している.家のサービスだけをここに追加しているので,他のトラフィックはZero Trustを流れなくなる.
これでWARP ClientのVPN接続した場合でもある程度の広告がブロックできるようになった.
ちなみにDNSを迂回するのは現実的じゃない
世の中にはpi-hole みたいなものもあって,「OS側の設定でDNSを全部pi-holeに回しちゃえばいいじゃん」と思ったときもありました. ここには大きな問題があって,そもそもWARP ClientはDNSも保護されていると謳っている.それはつまり,DNS自体もCloudflareが用意するDNS over HTTPSが強制的に使われていることを意味している.一応確認したけど,OSでのDNS設定をWARP Clientは上書きしてくるので,この方法は無力だった.
もちろんWARP Clientを使わない前提であれば良い選択肢だと思う.