krz/domain-dig

an ios app for DNS & SSL analysis

clone: git clone https://gitbay.org/krz/domain-dig.git

v1.7.1: 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}