iOS14 encrypted DNS(DNS over TLS(DoT), DNS over HTTPS(DoH)) Profile

# 概要と注意事項

- iOS14から追加された[DNSSettingsペイロード](https://developer.apple.com/documentation/devicemanagement/dnssettings)による暗号化DNS利用プロファイルの例
    - ネイティブにDoT、DoHが利用可能
    - macOS11からでも使えるっぽい
    - DoTとDoHのどっちがいいだとか、使う必要性とかは面倒な話はなし
- DNSフィルタリングと組み合わせれば簡単なフィルタリングがOS標準機能で実現できる
    - 例えばサンプルのDoHの方であれば、エロサイトを（完全ではないだろうが）ブロックできる
    - 解除できちゃうからやっぱりSupervisorでガチガチにするしかねぇ
- 見落としか、いつの間にか追記か、以下の注釈が公式に
    - When installed from an MDM, the setting only applies to managed wifi networks. When installed manually, this setting also applies to cellular.
        - 意訳）MDMから突っ込んだら管理WiFiにしか効かんで。モバイルに適用させたかったら手動で突っ込みぃや。
        - おそらく、Appleのプライバシー上、管理されていないネットワーク（モバイル、非管理WiFi）において、管理者によるDNSの強制変更は認めたくない模様
- ProhibitDisablementがtrueの場合は要Supervisor
    - falseの場合、「設定→一般→VPNとネットワーク」で変更が可能
- ちゃんと切り替わっているかは[CloudflareのDebug Information](https://1.1.1.1/help)でしか見ていない
- 値を書き換えれば[Google Public DNS](https://developers.google.com/speed/public-dns/docs/doh)、[IIS Public DNS](https://public.dns.iij.jp/)は使えたっぽい
    - こちらはちゃんと切り替わっているかの裏まではきちんと確認していない
- 上のリファレンスのうち最低限しか記述していないため、すべての通信のDNSが切り替わる
    - 特定のDNSサーバでしか名前解決できないようなものがあるともちろんコケる
        - 社内Wi-Fiとかキャリアサービスとか、VVMとMMS辺りが怪しげ
    - [OnDemandRules](https://developer.apple.com/documentation/devicemanagement/dnssettings/ondemandruleselement)を書けば「モバイルの時だけ」とか「このWi-Fi APに繋いだ時だけ」とかルールが作れるっぽい。後述。
        - もし常用するならCellular除外の「WiFiの時だけ」ルールでいいかもしれない
- 複数設定が入る
    - サンプルの二つはPayloadIdentifierが同一なので互いに上書きし合う（重複せずどちらか一方）
    - 値を書き換えて複数入れ、切り替えは可能
    - 設定は最後に入れたものに切り替わるっぽい
    - 一つのプロファイルに複数のDNS設定を記載することも可能
- これを入れたから通信速度が速くなるとかそんなことを期待してはいけない
- どうでもいい話、Android EnterpriseでもAPI 29（Android 10）から同様の機能あり
- プロファイルを入れる方法でなく、アプリから制御する方法もある
    - この場合、設定側にアプリアイコンを出せるようになるのでブランディングで有利かもしれない
    - アプリ側で切替が完結するので、更新やユーザビリティの面で有利かもしれない
    - 「参考とか」にコメントで頂いた参考アプリのソースを紹介
- Wi-Fi設定の警告「このネットワークは暗号化されたDNSのトラフィックをブロックしています」が消せるかもしれないけど未確認


## DNS over TLS

[Cloudflare 1.1.1.1 のTLS](https://developers.cloudflare.com/1.1.1.1/dns-over-tls)を利用する場合

```xml:DoT_Cloudflare.mobileconfig
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
	<dict>
		<key>PayloadContent</key>
		<array>
			<dict>
				<key>PayloadDescription</key>
				<string>DNS Settings</string>
				<key>PayloadDisplayName</key>
				<string>DNS設定（DoT）</string>
				<key>PayloadIdentifier</key>
				<string>com.apple.dnsSettings.managed.91C836B1-5749-4C12-B613-384008F96D92</string>
				<key>PayloadType</key>
				<string>com.apple.dnsSettings.managed</string>
				<key>PayloadUUID</key>
				<string>91C836B1-5749-4C12-B613-384008F96D92</string>
				<key>PayloadVersion</key>
				<integer>1</integer>
				<key>DNSSettings</key>
				<dict>
					<key>DNSProtocol</key>
					<string>TLS</string>
					<key>ServerAddresses</key>
					<array>
						<string>2606:4700:4700::1111</string>
						<string>2606:4700:4700::1001</string>
						<string>1.1.1.1</string>
						<string>1.0.0.1</string>
					</array>
					<key>ServerName</key>
					<string>cloudflare-dns.com</string>
				</dict>
				<key>ProhibitDisablement</key>
				<false/>
			</dict>
		</array>
		<key>PayloadDisplayName</key>
		<string>DNSSettings</string>
		<key>PayloadIdentifier</key>
		<string>com.apple.dnsSettings.managed</string>
		<key>PayloadRemovalDisallowed</key>
		<false/>
		<key>PayloadType</key>
		<string>Configuration</string>
		<key>PayloadUUID</key>
		<string>2C3575D8-8480-4AD0-B6A9-803D9FBEDB5E</string>
		<key>PayloadVersion</key>
		<integer>1</integer>
	</dict>
</plist>

```

## DNS over HTTPS

[Cloudflare 1.1.1.1 for Families(Block Malware And Adult Content) のHTTPS](https://developers.cloudflare.com/1.1.1.1/1.1.1.1-for-families/setup-instructions/dns-over-https/)を利用する場合

```xml:DoH_Cloudflare_Families3.mobileconfig
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>PayloadContent</key>
	<array>
		<dict>
			<key>PayloadDescription</key>
			<string>DNS Settings</string>
			<key>PayloadDisplayName</key>
			<string>DNS設定（DoH）</string>
			<key>PayloadIdentifier</key>
			<string>com.apple.dnsSettings.managed.91C836B1-5749-4C12-B613-384008F96D92</string>
			<key>PayloadType</key>
			<string>com.apple.dnsSettings.managed</string>
			<key>PayloadUUID</key>
			<string>91C836B1-5749-4C12-B613-384008F96D92</string>
			<key>PayloadVersion</key>
			<integer>1</integer>
			<key>DNSSettings</key>
			<dict>
				<key>DNSProtocol</key>
				<string>HTTPS</string>
				<key>ServerURL</key>
				<string>https://family.cloudflare-dns.com/dns-query</string>
			</dict>
			<key>ProhibitDisablement</key>
			<false/>
		</dict>
	</array>
	<key>PayloadDisplayName</key>
	<string>DNSSettings</string>
	<key>PayloadIdentifier</key>
	<string>com.apple.dnsSettings.managed</string>
	<key>PayloadRemovalDisallowed</key>
	<false/>
	<key>PayloadType</key>
	<string>Configuration</string>
	<key>PayloadUUID</key>
	<string>2C3575D8-8480-4AD0-B6A9-803D9FBEDB5E</string>
	<key>PayloadVersion</key>
	<integer>1</integer>
</dict>
</plist>
```

## キーと値

- PayloadDisplayName
    - DNS設定名、切替画面のリストとプロファイル内での表示
- DNSProtocol
    - DoTならばTLS、DoHならHTTPS
- DoT用設定値
    - ServerAddresses
        - DNSサーバのIPアドレスを記載する（ホスト名でも通るがリファレンス上は「IPv4 and IPv6 addresses.」）
    - ServerName
        - たぶんサーバ証明書のSANs
- DoH用設定値
    - ServerURL
        - クエリを投げる先のURL
- ProhibitDisablement
    - 手動変更を禁止するのであればtrue

- PayloadDisplayName
    - プロファイル名

組織名とか説明書きとかその他諸々は省略

## IPv6シングルスタックの時

[ドコモが2022年春から「IPv6シングルスタック」を導入へ　7月1日から開発者向けに試験環境を提供 - ITmedia Mobile](https://www.itmedia.co.jp/mobile/articles/2106/29/news133.html)
[作ろうスマートフォンコンテンツ : IPv6シングルスタック　接続試験詳細 | サービス・機能 | NTTドコモ](https://www.nttdocomo.co.jp/service/developer/smart_phone/etc/v6ft/index.html)

DNS64に対応したDoH、DoTならいけるかもしれない。

[Supporting IPv6-only networks](https://developers.cloudflare.com/1.1.1.1/support-nat64)
たぶん「dns64.cloudflare-dns.com」、「https://dns64.cloudflare-dns.com/dns-query」

[Google Public DNS64](https://developers.google.com/speed/public-dns/docs/dns64)
「dns64.dns.google」、「https://dns64.dns.google/dns-query」

ただ、モバイル網内での注意事項はたぶん残る
網内で完結するので無理に使わなくてもいいかも知れない

## 条件設定

- おさらい
    - 手動でプロファイルを入れた場合は、デフォルトで全ての接続（モバイル、Wi-Fi、Ethernet）に影響する。VPNは知らん。
    - MDMからプロファイルを入れた場合は、管理Wi-Fiに対してのみ影響する。条件指定してもたぶん効かぬ。
- 条件設定
    - プロファイル内でパラメータを記述することにより、DNS設定の適用・除外を操作することができる。
    - 書式とかは[Appleの公式ドキュメント](https://developer.apple.com/documentation/devicemanagement/dnssettings/ondemandruleselement)を参照
    - マッチ条件
        - DNSDomainMatch
            - 解決しようとしたドメインの一致判定
        - DNSServerAddressMatch
            - ネットワークで指定されたDNSサーバ設定との一致判定
        - InterfaceTypeMatch
            - インターフェースの判定
        - SSIDMatch
            - 接続しているWi-FiのSSIDとの一致判定
        - URLStringProbe
            - 指定したURLにリダイレクトなしで到達できるかの判定
    - アクション
        - ドメイン条件のときはEvaluateConnection、それ以外はConnectとDisconnect
- 気をつける点
    - この条件はプロファイル単位ではなく、DNS設定単位で設定するっぽい
        - なので、下のサンプルみたいに一つのプロファイルに複数のDNS設定を入れた場合でも、それぞれに条件を記載する必要がありそう。
    - 条件設定するときは、最後にデフォルト動作を入れておいた方が動作が安定するかもしれない

```xml:例1：モバイル通信の時だけDNSを指定したものを利用
<key>OnDemandRules</key>
<array>
    <dict>
        <key>Action</key>
        <string>Connect</string>
        <key>InterfaceTypeMatch</key>
        <array>
            <string>Cellular</string>
        </array>
    </dict>
    <dict>
        <key>Action</key>
        <string>Disconnect</string>
    </dict>
</array>
```

```xml:例2：モバイル通信の時はキャリアDNSを利用し、SecreDNSを利用しない
<key>OnDemandRules</key>
<array>
    <dict>
        <key>Action</key>
        <string>Disconnect</string>
        <key>InterfaceTypeMatch</key>
        <array>
            <string>Cellular</string>
        </array>
    </dict>
    <dict>
        <key>Action</key>
        <string>Connect</string>
    </dict>
</array>
```

```xml:例３：指定したSSIDのWi-Fiに接続している時と、example.comドメインに対してはSecureDNSを利用しない
<key>OnDemandRules</key>
<array>
    <dict>
        <key>Action</key>
        <string>Disconnect</string>
        <key>SSIDMatch</key>
        <array>
            <string>My Home's SSID</string>
        </array>
    </dict>
    <dict>
        <key>Action</key>
        <string>EvaluateConnection</string>
        <key>ActionParameters</key>
        <array>
            <dict>
                <key>DomainAction</key>
                <string>NeverConnect</string>
                <key>Domains</key>
                <array>
                    <string>example.com</string>
                </array>
            </dict>
        </array>
    </dict>
    <dict>
        <key>Action</key>
        <string>Connect</string>
    </dict>
</array>
```

## 参考元とか

- [DNSSettings | Apple Developer Documentation](https://developer.apple.com/documentation/devicemanagement/dnssettings)
    - 公式リファレンス
- [GitHub paulmillr/encrypted-dns](https://github.com/paulmillr/encrypted-dns)
    - プロファイルの入手が可能
    - いくつかサンプルがある様子
- [iOS 14でAdGuard DNSを使う方法 | AdGuard](https://adguard.com/ja/blog/encrypted-dns-ios-14.html)
    - プロファイルの入手が可能
    - このペイロードを利用するDNSサービスで、広告ブロックとかアダルト阻止とか強制セーフサーチあり
    - プロファイルに署名がされているため、中身を参考にするのであれば上の方を使うか署名解除が必要
- [iOS14の暗号化DNSサポートと広告ブロック | 280blocker](https://280blocker.net/blog/20200924/2368/)
    - 記事を参考頂きありがとうございます
- [Apple Configuration Profile | NextDNS](https://apple.nextdns.io/)
    - NextDNS用のプロファイル作成・ダウンロード
    - OnDemandRulesを用いたSSID、ドメインの除外設定のサンプルを入手可能
- [GitHub kkk669/DNSecure](https://github.com/kkk669/DNSecure)
    - アプリによるDNS設定のサンプルコード
    - [アプリをApp Storeにて公開されておられます](https://apps.apple.com/jp/app/id1533413232)（2020/10/02時点）
- [NTTドコモのIPv6シングルスタック化についての調査メモ](https://qiita.com/lighthawk/items/d3a762acf58932bc643f)

## お試し用

下記テキストをコピーして、SafariのURL欄に張り付けて開く
中身を確認したい場合はBase64部分を復号化するか、PCブラウザでやればプロファイル実体の取得が可能
MIMEを「text/xml」にでもすればブラウザ上で表示
まともに使えるかどうかを含めて無保証

```

data:application/x-apple-aspen-config;charset=UTF-8;base64,PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCFET0NUWVBFIHBsaXN0IFBVQkxJQyAiLS8vQXBwbGUvL0RURCBQTElTVCAxLjAvL0VOIiAiaHR0cDovL3d3dy5hcHBsZS5jb20vRFREcy9Qcm9wZXJ0eUxpc3QtMS4wLmR0ZCI+CjxwbGlzdCB2ZXJzaW9uPSIxLjAiPjxkaWN0PjxrZXk+UGF5bG9hZENvbnRlbnQ8L2tleT48YXJyYXk+PGRpY3Q+PGtleT5QYXlsb2FkRGVzY3JpcHRpb248L2tleT48c3RyaW5nPkROUyBTZXR0aW5nczwvc3RyaW5nPjxrZXk+UGF5bG9hZERpc3BsYXlOYW1lPC9rZXk+PHN0cmluZz5DbG91ZEZsYXJlIERvVDwvc3RyaW5nPjxrZXk+UGF5bG9hZElkZW50aWZpZXI8L2tleT48c3RyaW5nPmNvbS5hcHBsZS5kbnNTZXR0aW5ncy5tYW5hZ2VkLjkxQzgzNkIxLTU3NDktNEMxMi1CNjEzLTM4NDAwOEY5NkQ5MDwvc3RyaW5nPjxrZXk+UGF5bG9hZFR5cGU8L2tleT48c3RyaW5nPmNvbS5hcHBsZS5kbnNTZXR0aW5ncy5tYW5hZ2VkPC9zdHJpbmc+PGtleT5QYXlsb2FkVVVJRDwva2V5PjxzdHJpbmc+OTFDODM2QjEtNTc0OS00QzEyLUI2MTMtMzg0MDA4Rjk2RDkwPC9zdHJpbmc+PGtleT5QYXlsb2FkVmVyc2lvbjwva2V5PjxpbnRlZ2VyPjE8L2ludGVnZXI+PGtleT5ETlNTZXR0aW5nczwva2V5PjxkaWN0PjxrZXk+RE5TUHJvdG9jb2w8L2tleT48c3RyaW5nPlRMUzwvc3RyaW5nPjxrZXk+U2VydmVyQWRkcmVzc2VzPC9rZXk+PGFycmF5PjxzdHJpbmc+MjYwNjo0NzAwOjQ3MDA6OjExMTE8L3N0cmluZz48c3RyaW5nPjI2MDY6NDcwMDo0NzAwOjoxMDAxPC9zdHJpbmc+PHN0cmluZz4xLjEuMS4xPC9zdHJpbmc+PHN0cmluZz4xLjAuMC4xPC9zdHJpbmc+PC9hcnJheT48a2V5PlNlcnZlck5hbWU8L2tleT48c3RyaW5nPmNsb3VkZmxhcmUtZG5zLmNvbTwvc3RyaW5nPjwvZGljdD48a2V5PlByb2hpYml0RGlzYWJsZW1lbnQ8L2tleT48ZmFsc2UvPjwvZGljdD48ZGljdD48a2V5PlBheWxvYWREZXNjcmlwdGlvbjwva2V5PjxzdHJpbmc+RE5TIFNldHRpbmdzPC9zdHJpbmc+PGtleT5QYXlsb2FkRGlzcGxheU5hbWU8L2tleT48c3RyaW5nPjEuMS4xLjEgZm9yIEZhbWlsaWVzKEJsb2NrIE1hbHdhcmUgYW5kIEFkdWx0IENvbnRlbnQpPC9zdHJpbmc+PGtleT5QYXlsb2FkSWRlbnRpZmllcjwva2V5PjxzdHJpbmc+Y29tLmFwcGxlLmRuc1NldHRpbmdzLm1hbmFnZWQuOTFDODM2QjEtNTc0OS00QzEyLUI2MTMtMzg0MDA4Rjk2RDkxPC9zdHJpbmc+PGtleT5QYXlsb2FkVHlwZTwva2V5PjxzdHJpbmc+Y29tLmFwcGxlLmRuc1NldHRpbmdzLm1hbmFnZWQ8L3N0cmluZz48a2V5PlBheWxvYWRVVUlEPC9rZXk+PHN0cmluZz45MUM4MzZCMS01NzQ5LTRDMTItQjYxMy0zODQwMDhGOTZEOTE8L3N0cmluZz48a2V5PlBheWxvYWRWZXJzaW9uPC9rZXk+PGludGVnZXI+MTwvaW50ZWdlcj48a2V5PkROU1NldHRpbmdzPC9rZXk+PGRpY3Q+PGtleT5ETlNQcm90b2NvbDwva2V5PjxzdHJpbmc+SFRUUFM8L3N0cmluZz48a2V5PlNlcnZlclVSTDwva2V5PjxzdHJpbmc+aHR0cHM6Ly9mYW1pbHkuY2xvdWRmbGFyZS1kbnMuY29tL2Rucy1xdWVyeTwvc3RyaW5nPjwvZGljdD48a2V5PlByb2hpYml0RGlzYWJsZW1lbnQ8L2tleT48ZmFsc2UvPjwvZGljdD48ZGljdD48a2V5PlBheWxvYWREZXNjcmlwdGlvbjwva2V5PjxzdHJpbmc+RE5TIFNldHRpbmdzPC9zdHJpbmc+PGtleT5QYXlsb2FkRGlzcGxheU5hbWU8L2tleT48c3RyaW5nPklJSiBQdWJsaWMgRE5TKERvVCk8L3N0cmluZz48a2V5PlBheWxvYWRJZGVudGlmaWVyPC9rZXk+PHN0cmluZz5jb20uYXBwbGUuZG5zU2V0dGluZ3MubWFuYWdlZC45MUM4MzZCMS01NzQ5LTRDMTItQjYxMy0zODQwMDhGOTZEOTI8L3N0cmluZz48a2V5PlBheWxvYWRUeXBlPC9rZXk+PHN0cmluZz5jb20uYXBwbGUuZG5zU2V0dGluZ3MubWFuYWdlZDwvc3RyaW5nPjxrZXk+UGF5bG9hZFVVSUQ8L2tleT48c3RyaW5nPjkxQzgzNkIxLTU3NDktNEMxMi1CNjEzLTM4NDAwOEY5NkQ5Mjwvc3RyaW5nPjxrZXk+UGF5bG9hZFZlcnNpb248L2tleT48aW50ZWdlcj4xPC9pbnRlZ2VyPjxrZXk+RE5TU2V0dGluZ3M8L2tleT48ZGljdD48a2V5PkROU1Byb3RvY29sPC9rZXk+PHN0cmluZz5UTFM8L3N0cmluZz48a2V5PlNlcnZlckFkZHJlc3Nlczwva2V5PjxzdHJpbmc+cHVibGljLmRucy5paWouanA8L3N0cmluZz48a2V5PlNlcnZlck5hbWU8L2tleT48c3RyaW5nPnB1YmxpYy5kbnMuaWlqLmpwPC9zdHJpbmc+PC9kaWN0PjxrZXk+UHJvaGliaXREaXNhYmxlbWVudDwva2V5PjxmYWxzZS8+PC9kaWN0PjxkaWN0PjxrZXk+UGF5bG9hZERlc2NyaXB0aW9uPC9rZXk+PHN0cmluZz5ETlMgU2V0dGluZ3M8L3N0cmluZz48a2V5PlBheWxvYWREaXNwbGF5TmFtZTwva2V5PjxzdHJpbmc+QWRHdWFyZCBETlMgRmFtaWx5IHByb3RlY3Rpb248L3N0cmluZz48a2V5PlBheWxvYWRJZGVudGlmaWVyPC9rZXk+PHN0cmluZz5jb20uYXBwbGUuZG5zU2V0dGluZ3MubWFuYWdlZC45MUM4MzZCMS01NzQ5LTRDMTItQjYxMy0zODQwMDhGOTZEOTM8L3N0cmluZz48a2V5PlBheWxvYWRUeXBlPC9rZXk+PHN0cmluZz5jb20uYXBwbGUuZG5zU2V0dGluZ3MubWFuYWdlZDwvc3RyaW5nPjxrZXk+UGF5bG9hZFVVSUQ8L2tleT48c3RyaW5nPjkxQzgzNkIxLTU3NDktNEMxMi1CNjEzLTM4NDAwOEY5NkQ5Mzwvc3RyaW5nPjxrZXk+UGF5bG9hZFZlcnNpb248L2tleT48aW50ZWdlcj4xPC9pbnRlZ2VyPjxrZXk+RE5TU2V0dGluZ3M8L2tleT48ZGljdD48a2V5PkROU1Byb3RvY29sPC9rZXk+PHN0cmluZz5IVFRQUzwvc3RyaW5nPjxrZXk+U2VydmVyVVJMPC9rZXk+PHN0cmluZz5odHRwczovL2Rucy1mYW1pbHkuYWRndWFyZC5jb20vZG5zLXF1ZXJ5PC9zdHJpbmc+PC9kaWN0PjxrZXk+UHJvaGliaXREaXNhYmxlbWVudDwva2V5PjxmYWxzZS8+PC9kaWN0PjxkaWN0PjxrZXk+UGF5bG9hZERlc2NyaXB0aW9uPC9rZXk+PHN0cmluZz5ETlMgU2V0dGluZ3M8L3N0cmluZz48a2V5PlBheWxvYWREaXNwbGF5TmFtZTwva2V5PjxzdHJpbmc+R29vZ2xlIFB1YmxpYyBETlMoRG9UKTwvc3RyaW5nPjxrZXk+UGF5bG9hZElkZW50aWZpZXI8L2tleT48c3RyaW5nPmNvbS5hcHBsZS5kbnNTZXR0aW5ncy5tYW5hZ2VkLjkxQzgzNkIxLTU3NDktNEMxMi1CNjEzLTM4NDAwOEY5NkQ5NDwvc3RyaW5nPjxrZXk+UGF5bG9hZFR5cGU8L2tleT48c3RyaW5nPmNvbS5hcHBsZS5kbnNTZXR0aW5ncy5tYW5hZ2VkPC9zdHJpbmc+PGtleT5QYXlsb2FkVVVJRDwva2V5PjxzdHJpbmc+OTFDODM2QjEtNTc0OS00QzEyLUI2MTMtMzg0MDA4Rjk2RDk0PC9zdHJpbmc+PGtleT5QYXlsb2FkVmVyc2lvbjwva2V5PjxpbnRlZ2VyPjE8L2ludGVnZXI+PGtleT5ETlNTZXR0aW5nczwva2V5PjxkaWN0PjxrZXk+RE5TUHJvdG9jb2w8L2tleT48c3RyaW5nPlRMUzwvc3RyaW5nPjxrZXk+U2VydmVyQWRkcmVzc2VzPC9rZXk+PHN0cmluZz5kbnMuZ29vZ2xlPC9zdHJpbmc+PGtleT5TZXJ2ZXJOYW1lPC9rZXk+PHN0cmluZz5kbnMuZ29vZ2xlPC9zdHJpbmc+PC9kaWN0PjxrZXk+UHJvaGliaXREaXNhYmxlbWVudDwva2V5PjxmYWxzZS8+PC9kaWN0PjwvYXJyYXk+PGtleT5QYXlsb2FkRGlzcGxheU5hbWU8L2tleT48c3RyaW5nPkROU1NldHRpbmdzPC9zdHJpbmc+PGtleT5QYXlsb2FkSWRlbnRpZmllcjwva2V5PjxzdHJpbmc+Y29tLmFwcGxlLmRuc1NldHRpbmdzLm1hbmFnZWQ8L3N0cmluZz48a2V5PlBheWxvYWRSZW1vdmFsRGlzYWxsb3dlZDwva2V5PjxmYWxzZS8+PGtleT5QYXlsb2FkVHlwZTwva2V5PjxzdHJpbmc+Q29uZmlndXJhdGlvbjwvc3RyaW5nPjxrZXk+UGF5bG9hZFVVSUQ8L2tleT48c3RyaW5nPjJDMzU3NUQ4LTg0ODAtNEFEMC1CNkE5LTgwM0Q5RkJFREI1RTwvc3RyaW5nPjxrZXk+UGF5bG9hZFZlcnNpb248L2tleT48aW50ZWdlcj4xPC9pbnRlZ2VyPjwvZGljdD48L3BsaXN0Pgo=

```

※コピペするときは、枠の右上にコピペボタンが出てきます。モバイルだと切れるけど、指で全選択するよりかは楽かもしれない。
※このDataURIをWebClipにしておけば、通信不可の状態であってもWerClipからプロファイルインストールができるので稀に便利。

### プロファイルの概要

以下のDNS設定を含む
切り替えは「設定→一般→VPNとネットワーク」から

- Cloudflare DoT
    - 上記、DoTサンプルと同一内容
- Cloudflare Families(Block Malware And Adult Content)
    - 上記、DoHサンプルと同一内容
- IIJ Public DNS(DoT)
    - 上記DoTサンプルのうち、値をIIJ Public DNSに書き換えたもの
    - アドレスをIPでなく「public.dns.iij.jp」で指定しているため、プロファイルのリファレンスから逸脱の可能性
- AdGuard DNS Family protection
    - 上記DoHサンプルのうち、値を「参考元とか」にあるAdGuardの一つに書き換えたもの
- Google Public DNS(DoT)
    - 上記DoTサンプルのうち、値をGoogle Public DNSに書き換えたもの
    - アドレスをIPでなく「dns.google」で指定しているため、プロファイルのリファレンスから逸脱の可能性

<!--
# 余談：このネットワークは暗号化されたDNSのトラフィックをブロックしています

## わりとどうでもいいひとりごと

「このネットワークは暗号化されたDNSのトラフィックをブロックしています」
これ、ちょっと不親切な表現よなあ。

## とりあえず結論

暗号化DNSを自動的に使うようにしたい場合はSANにIPアドレスを含めれ。

## こんなことを考え始めた経緯

ちょっと諸事情でAdGuard Homeを立ててLet’s Encryptの証明書を設定したところ、AndroidはDoTで通信してくれたが、iOSは平文かつ例ののメッセージを吐くようになったといった事象にハマる

なお、別記事にあるプロファイルやアプリでDoT/DoHを明示的に指定する場合は問題なく利用できる。

## 推測と妄想

Androidの場合は、設定されたDNSのIPアドレスに対して[Opportunistic](https://developer.android.com/reference/android/app/admin/DevicePolicyManager#setGlobalPrivateDnsModeOpportunistic(android.content.ComponentName))なDoTを試みるのがデフォルトの動作。
要するに証明書検証を行わずにTLSさえ確立できればOKな方式なので、SANにIPアドレスが含まれていなかろうが、自己証明を使っていようが行くっぽい。

iOSは通常の証明書検証を行い、かつSVCBレコードを見ていないような気がする。
そして、DoTでなく[RFC8484](https://datatracker.ietf.org/doc/html/rfc8484)に準じたリクエストをIPアドレス宛に投げているような気がするので、SANにIPアドレスが含まれていなければならないのかもしれない。

挙動としては
Android：即DoT
iOS：ずっと平文

試しに853を塞いでiOSでリトライしてみたが、ブロックログも残らずiOSの挙動も変わらず。
wiresharkで覗けば早いのだが、もう眠い。

## SANにIPアドレスを持つ自己署名証明書でトライ

ZeroSSLならできるらしいがDNSチャレンジじゃダメということで、自己署名のものを作ってサーバーに設定。
iOSにもルート証明書を入れて信頼。
無事にiOSが平文の後にDoHでAdGuardを利用するようになった。

## だが深まる謎

Cloudflareは当初からSANにIPアドレスを入れていた。


```text
X509v3 Subject Alternative Name:
                DNS:cloudflare-dns.com, DNS:*.cloudflare-dns.com, DNS:one.one.one.one, IP Address:1.0.0.1, IP Address:1.1.1.1, IP Address:162.159.36.1, IP Address:162.159.46.1, IP Address:2606:4700:4700:0:0:0:0:1001, IP Address:2606:4700:4700:0:0:0:0:1111, IP Address:2606:4700:4700:0:0:0:0:64, IP Address:2606:4700:4700:0:0:0:0:6400
```


以前はGoogle Public DNSには含まれていなかったので、「8.8.8.8にしたら早くなる裏技」的な話が出回った結果、このエラーを目にする機会が多い認識だった。
今はGoogleもSANにIPを含めるようになったので見る機会が減ってきたのかもしれない。

```text
X509v3 Subject Alternative Name:
                DNS:dns.google, DNS:dns.google.com, DNS:*.dns.google.com, DNS:8888.google, DNS:dns64.dns.google, IP Address:8.8.8.8, IP Address:8.8.4.4, IP Address:2001:4860:4860:0:0:0:0:8888, IP Address:2001:4860:4860:0:0:0:0:8844, IP Address:2001:4860:4860:0:0:0:0:6464, IP Address:2001:4860:4860:0:0:0:0:64
```

## だが深まる謎

Cloudflare securityとfamiliesのアドレスはSANに入ってないなーと思い試しに設定したところ、プライバシーに関する警告は出ているもののDoHで通信しているっぽい。解せぬ。

-->