krz/domain-dig
an ios app for DNS & SSL analysis
clone: git clone https://gitbay.org/krz/domain-dig.git
v1.5.0: DomainDig/ReverseDNSService.swift · raw
1import Foundation
2
3struct ReverseDNSService {
4 /// Look up the PTR record for an IPv4 address via Cloudflare DoH.
5 static func lookup(ip: String) async -> String? {
6 let octets = ip.split(separator: ".")
7 guard octets.count == 4 else { return nil }
8
9 let reversed = octets.reversed().joined(separator: ".")
10 let ptrDomain = "\(reversed).in-addr.arpa"
11
12 // PTR record type = 12
13 do {
14 let records = try await lookupPTR(domain: ptrDomain)
15 return records.first
16 } catch {
17 return nil
18 }
19 }
20
21 private static func lookupPTR(domain: String) async throws -> [String] {
22 var components = URLComponents(string: "https://cloudflare-dns.com/dns-query")!
23 components.queryItems = [
24 URLQueryItem(name: "name", value: domain),
25 URLQueryItem(name: "type", value: "12") // PTR
26 ]
27
28 var request = URLRequest(url: components.url!)
29 request.setValue("application/dns-json", forHTTPHeaderField: "Accept")
30
31 let (data, response) = try await URLSession.shared.data(for: request)
32
33 guard let httpResponse = response as? HTTPURLResponse,
34 httpResponse.statusCode == 200 else {
35 throw URLError(.badServerResponse)
36 }
37
38 let dnsResponse = try JSONDecoder().decode(CloudflareDNSResponse.self, from: data)
39
40 guard let answers = dnsResponse.Answer else {
41 return []
42 }
43
44 return answers
45 .filter { $0.type == 12 }
46 .map { $0.data.trimmingCharacters(in: CharacterSet(charactersIn: "\"")) }
47 }
48}