|
// retoor <retoor@molodetz.nl>
|
|
|
|
import Foundation
|
|
|
|
enum GuardUrl {
|
|
static let privateRanges: [(UInt32, UInt32)] = [
|
|
(0x0A000000, 0x0AFFFFFF), // 10.0.0.0/8
|
|
(0x7F000000, 0x7FFFFFFF), // 127.0.0.0/8
|
|
(0xA9FE0000, 0xA9FEFFFF), // 169.254.0.0/16
|
|
(0xAC100000, 0xAC1FFFFF), // 172.16.0.0/12
|
|
(0xC0A80000, 0xC0A8FFFF), // 192.168.0.0/16
|
|
(0x64400000, 0x647FFFFF), // 100.64.0.0/10
|
|
(0xCB007100, 0xCB0071FF), // 203.0.113.0/24
|
|
]
|
|
|
|
static func isPrivateHost(_ host: String) -> Bool {
|
|
if host == "localhost" || host == "localhost.localdomain" {
|
|
return true
|
|
}
|
|
guard let addr = ipv4Address(host) else {
|
|
return host.hasSuffix(".local") || host.hasSuffix(".internal")
|
|
}
|
|
for (start, end) in privateRanges {
|
|
if addr >= start && addr <= end {
|
|
return true
|
|
}
|
|
}
|
|
return false
|
|
}
|
|
|
|
static func isPrivateURL(_ urlString: String) -> Bool {
|
|
guard let url = URL(string: urlString), let host = url.host else {
|
|
return true
|
|
}
|
|
return isPrivateHost(host)
|
|
}
|
|
|
|
private static func ipv4Address(_ string: String) -> UInt32? {
|
|
var sin = sockaddr_in()
|
|
guard string.withCString({ cstring in
|
|
inet_pton(AF_INET, cstring, &sin.sin_addr) == 1
|
|
}) else { return nil }
|
|
let addr = sin.sin_addr.s_addr.bigEndian
|
|
return addr
|
|
}
|
|
}
|