このトピックでは、Alibaba Cloud HTTPDNS の DNS over HTTPS (DoH) エンドポイント、リクエストとレスポンスのフォーマット、およびエラーセマンティクスについて説明します。
1. 前提条件
DoH サービスを設定した後、DoH API を直接呼び出して、名前解決された IP アドレスを取得できます。
2. DoH API の詳細
この API は RFC 8484 標準に準拠しており、GET と POST の両方のメソッドをサポートしています。GET リクエストは dns パラメーター (Base64URL) を使用して DNS メッセージを送信します。POST リクエストはバイナリリクエストボディで DNS メッセージを送信します。
2.1 GET メソッド
このメソッドを使用して、Base64URL エンコードされた DNS メッセージを URL クエリパラメーターとして渡すことができます。リクエストとレスポンスは次のとおりです。
リクエスト
メソッド:
GETパス:
/dns-query?dns=<base64url(dns_wire_message)>リクエストヘッダー:
Accept: application/dns-message
クエリパラメーター:
dns(必須): バイナリ DNS メッセージの Base64URL エンコードされた文字列。文字列には=パディングは含まれません。
レスポンス
200: 成功。本文は
application/dns-message(バイナリ DNS 確認応答) です。400: 不正なリクエスト。このエラーは、パラメーターが無効な場合に発生します。たとえば、DoH が有効になっていない場合や、
dnsパラメーターがないか無効な場合です。5xx: 内部サーバーエラー。
ドメイン名が名前解決リストにない場合、DoH は 200 ステータスコードを返しますが、名前解決の結果は返しません。
2.2 POST メソッド
このメソッドを使用して、リクエストボディでバイナリ DNS メッセージを直接送信できます。リクエストとレスポンスは次のとおりです。
リクエスト
メソッド: POST
パス:
/dns-queryリクエストヘッダー:
Content-Type: application/dns-messageAccept: application/dns-message
リクエストボディ:
バイナリ DNS メッセージ (ワイヤーフォーマット)。
レスポンス
200: 成功。本文は
application/dns-message(バイナリ DNS 確認応答) です。400: 不正なリクエスト。このエラーは、パラメーターが無効な場合に発生します。たとえば、DoH が有効になっていない場合や、メッセージが無効な場合です。
5xx: 内部サーバーエラー。
ドメイン名が名前解決リストにない場合、DoH は 200 ステータスコードを返しますが、名前解決の結果は返しません。
2.3 リクエストの例
次の Python の例は、DoH リクエストを送信して www.aliyun.com の名前解決の結果を取得する方法を示しています。この例では、ネットワークライブラリ dnspython と requests が必要です。
GET リクエストの例
サンプルコード
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import requests import base64 import dns.message def query_doh(domain, rrType): # DNS リクエストを作成 request = dns.message.make_query(domain, rrType) request_data = request.to_wire() # リクエストを Base64URL フォーマットでエンコード base64_query = base64.urlsafe_b64encode(request_data).decode().rstrip("=") # HTTPDNS の DoH エンドポイントを使用 url = f"https://1xxxx3.aliyunhttpdns.com/dns-query?dns={base64_query}" # GET リクエストを送信 headers = { "Accept": "application/dns-message" } response = requests.get(url, headers=headers) # エラーをチェック if response.status_code != 200: print(f"Error: {response.status_code}") return # レスポンスを解析 response_data = response.content dns_response = dns.message.from_wire(response_data) # IP アドレスを取得して出力 for answer in dns_response.answer: ttl = answer.ttl for item in answer.items: print(f"Answer: {item} TTL: {ttl}") if __name__ == "__main__": # クエリするドメイン名 domain = "www.aliyun.com" rrType = "A" query_doh(domain, rrType)期待される結果
Answer: www-jp-de-intl-adns.aliyun.com. TTL: 3600 Answer: www-jp-de-intl-adns.aliyun.com.gds.alibabadns.com. TTL: 3600 Answer: www.aliyun.com.w.cdngslb.com. TTL: 3600 Answer: 61.164.xxx.xxx TTL: 3600 Answer: 183.146.xxx.xxx TTL: 3600 Answer: 60.188.xxx.xxx TTL: 3600 Answer: 122.228.xxx.xxx TTL: 3600
POST リクエストの例
サンプルコード
#!/usr/bin/env python3 # -*- coding: utf-8 -*- import requests import dns.message def query_doh_post(domain, rrType): # DNS リクエストを作成 request = dns.message.make_query(domain, rrType) request_data = request.to_wire() # HTTPDNS の DoH エンドポイントを使用 url = "https://1xxxx3.aliyunhttpdns.com/dns-query" # POST リクエストを送信 headers = { "Accept": "application/dns-message", "Content-Type": "application/dns-message" } # DNS ワイヤーフォーマットデータを POST ボディとして直接送信 response = requests.post(url, headers=headers, data=request_data) # エラーをチェック if response.status_code != 200: print(f"Error: {response.status_code}") return # レスポンスを解析 response_data = response.content dns_response = dns.message.from_wire(response_data) # IP アドレスを取得して出力 for answer in dns_response.answer: ttl = answer.ttl for item in answer.items: print(f"Answer: {item} TTL: {ttl}") if __name__ == "__main__": # クエリするドメイン名 domain = "www.aliyun.com" rrType = "AAAA" query_doh_post(domain, rrType)期待される結果
Answer: www-jp-de-intl-adns.aliyun.com. TTL: 120 Answer: www-jp-de-intl-adns.aliyun.com.gds.alibabadns.com. TTL: 300 Answer: www.aliyun.com.w.cdngslb.com. TTL: 120 Answer: 240e:f7:7c00:xxxx:xxxx::xxxx TTL: 60 Answer: 240e:f7:7c00:xxxx:xxxx::xxxx TTL: 603. まとめ
このトピックでは、HTTPDNS が提供する DoH API について説明しました。API の詳細とサンプルコードを参照して、DoH エンドポイントにアクセスし、ドメイン名の名前解決を行うことができます。