Merge pull request #196 from passepartoutvpn/secure-dns
DNS over HTTPS/TLS
This commit is contained in:
commit
9567be7563
|
@ -18,6 +18,7 @@ custom_categories:
|
||||||
children:
|
children:
|
||||||
- BidirectionalState
|
- BidirectionalState
|
||||||
- ConfigurationError
|
- ConfigurationError
|
||||||
|
- DNSProtocol
|
||||||
- DNSResolver
|
- DNSResolver
|
||||||
- DNSRecord
|
- DNSRecord
|
||||||
- EndpointProtocol
|
- EndpointProtocol
|
||||||
|
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
||||||
### Added
|
### Added
|
||||||
|
|
||||||
- Handle `--data-ciphers` and `data-ciphers-fallback` from OpenVPN 2.5
|
- Handle `--data-ciphers` and `data-ciphers-fallback` from OpenVPN 2.5
|
||||||
|
- Support DNS over HTTPS (DoH) and TLS (DoT).
|
||||||
|
|
||||||
## 3.2.0 (2021-01-07)
|
## 3.2.0 (2021-01-07)
|
||||||
|
|
||||||
|
|
|
@ -186,6 +186,8 @@
|
||||||
0E749F622178911D00BB2701 /* pia-2048.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0E749F612178911C00BB2701 /* pia-2048.pem */; };
|
0E749F622178911D00BB2701 /* pia-2048.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0E749F612178911C00BB2701 /* pia-2048.pem */; };
|
||||||
0E7F3F6A246ABA0F006BE77F /* IPHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F3F69246ABA0F006BE77F /* IPHeader.swift */; };
|
0E7F3F6A246ABA0F006BE77F /* IPHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F3F69246ABA0F006BE77F /* IPHeader.swift */; };
|
||||||
0E7F3F6B246ABA0F006BE77F /* IPHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F3F69246ABA0F006BE77F /* IPHeader.swift */; };
|
0E7F3F6B246ABA0F006BE77F /* IPHeader.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E7F3F69246ABA0F006BE77F /* IPHeader.swift */; };
|
||||||
|
0E94E8EA25BACEBD0040BC30 /* DNSProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E94E8E925BACEBD0040BC30 /* DNSProtocol.swift */; };
|
||||||
|
0E94E8EB25BACEBD0040BC30 /* DNSProtocol.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0E94E8E925BACEBD0040BC30 /* DNSProtocol.swift */; };
|
||||||
0EA82A282190B220007960EB /* TunnelKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E3251C51F95770D00C108D9 /* TunnelKit.framework */; };
|
0EA82A282190B220007960EB /* TunnelKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 0E3251C51F95770D00C108D9 /* TunnelKit.framework */; };
|
||||||
0EA82A3E2190B2BC007960EB /* pia-2048.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0E749F612178911C00BB2701 /* pia-2048.pem */; };
|
0EA82A3E2190B2BC007960EB /* pia-2048.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0E749F612178911C00BB2701 /* pia-2048.pem */; };
|
||||||
0EAC57372494277A00D0FCE0 /* OpenVPNProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAC57312494277A00D0FCE0 /* OpenVPNProvider.swift */; };
|
0EAC57372494277A00D0FCE0 /* OpenVPNProvider.swift in Sources */ = {isa = PBXBuildFile; fileRef = 0EAC57312494277A00D0FCE0 /* OpenVPNProvider.swift */; };
|
||||||
|
@ -567,6 +569,7 @@
|
||||||
0E749F612178911C00BB2701 /* pia-2048.pem */ = {isa = PBXFileReference; lastKnownFileType = text; path = "pia-2048.pem"; sourceTree = "<group>"; };
|
0E749F612178911C00BB2701 /* pia-2048.pem */ = {isa = PBXFileReference; lastKnownFileType = text; path = "pia-2048.pem"; sourceTree = "<group>"; };
|
||||||
0E7F3F69246ABA0F006BE77F /* IPHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPHeader.swift; sourceTree = "<group>"; };
|
0E7F3F69246ABA0F006BE77F /* IPHeader.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = IPHeader.swift; sourceTree = "<group>"; };
|
||||||
0E85A25B202CCA3D0059E9F9 /* Host.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Host.entitlements; sourceTree = "<group>"; };
|
0E85A25B202CCA3D0059E9F9 /* Host.entitlements */ = {isa = PBXFileReference; lastKnownFileType = text.plist.entitlements; path = Host.entitlements; sourceTree = "<group>"; };
|
||||||
|
0E94E8E925BACEBD0040BC30 /* DNSProtocol.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = DNSProtocol.swift; sourceTree = "<group>"; };
|
||||||
0EA82A232190B220007960EB /* TunnelKitTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "TunnelKitTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
0EA82A232190B220007960EB /* TunnelKitTests-macOS.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = "TunnelKitTests-macOS.xctest"; sourceTree = BUILT_PRODUCTS_DIR; };
|
||||||
0EAC57312494277A00D0FCE0 /* OpenVPNProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNProvider.swift; sourceTree = "<group>"; };
|
0EAC57312494277A00D0FCE0 /* OpenVPNProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OpenVPNProvider.swift; sourceTree = "<group>"; };
|
||||||
0EAC57322494277A00D0FCE0 /* MockVPNProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockVPNProvider.swift; sourceTree = "<group>"; };
|
0EAC57322494277A00D0FCE0 /* MockVPNProvider.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = MockVPNProvider.swift; sourceTree = "<group>"; };
|
||||||
|
@ -1074,6 +1077,7 @@
|
||||||
0EFEB4432006D3C800F81029 /* Data+Manipulation.swift */,
|
0EFEB4432006D3C800F81029 /* Data+Manipulation.swift */,
|
||||||
0E411B992271F90700E0852C /* DNS.h */,
|
0E411B992271F90700E0852C /* DNS.h */,
|
||||||
0E411B9A2271F90700E0852C /* DNS.m */,
|
0E411B9A2271F90700E0852C /* DNS.m */,
|
||||||
|
0E94E8E925BACEBD0040BC30 /* DNSProtocol.swift */,
|
||||||
0EE2F9E522918DA100F56F49 /* DNSResolver.swift */,
|
0EE2F9E522918DA100F56F49 /* DNSResolver.swift */,
|
||||||
0E011F7C2196D97200BA59EE /* EndpointProtocol.swift */,
|
0E011F7C2196D97200BA59EE /* EndpointProtocol.swift */,
|
||||||
0EFEB4362006D3C800F81029 /* Errors.h */,
|
0EFEB4362006D3C800F81029 /* Errors.h */,
|
||||||
|
@ -2036,6 +2040,7 @@
|
||||||
0E23B44122982AF800304C30 /* OpenVPNSession+PIA.swift in Sources */,
|
0E23B44122982AF800304C30 /* OpenVPNSession+PIA.swift in Sources */,
|
||||||
0E23B42D22982AF800304C30 /* ControlChannelSerializer.swift in Sources */,
|
0E23B42D22982AF800304C30 /* ControlChannelSerializer.swift in Sources */,
|
||||||
0EE2F9F622918DA100F56F49 /* NEUDPSocket.swift in Sources */,
|
0EE2F9F622918DA100F56F49 /* NEUDPSocket.swift in Sources */,
|
||||||
|
0E94E8EA25BACEBD0040BC30 /* DNSProtocol.swift in Sources */,
|
||||||
0EE2F96E2291636B00F56F49 /* IPv4Settings.swift in Sources */,
|
0EE2F96E2291636B00F56F49 /* IPv4Settings.swift in Sources */,
|
||||||
0EFEB4662006D3C800F81029 /* ZeroingData.swift in Sources */,
|
0EFEB4662006D3C800F81029 /* ZeroingData.swift in Sources */,
|
||||||
0EE2FA0622918DA100F56F49 /* Utils.swift in Sources */,
|
0EE2FA0622918DA100F56F49 /* Utils.swift in Sources */,
|
||||||
|
@ -2125,6 +2130,7 @@
|
||||||
0E23B44222982AF800304C30 /* OpenVPNSession+PIA.swift in Sources */,
|
0E23B44222982AF800304C30 /* OpenVPNSession+PIA.swift in Sources */,
|
||||||
0E23B42E22982AF800304C30 /* ControlChannelSerializer.swift in Sources */,
|
0E23B42E22982AF800304C30 /* ControlChannelSerializer.swift in Sources */,
|
||||||
0EE2F9F722918DA100F56F49 /* NEUDPSocket.swift in Sources */,
|
0EE2F9F722918DA100F56F49 /* NEUDPSocket.swift in Sources */,
|
||||||
|
0E94E8EB25BACEBD0040BC30 /* DNSProtocol.swift in Sources */,
|
||||||
0EE2F96F2291636B00F56F49 /* IPv4Settings.swift in Sources */,
|
0EE2F96F2291636B00F56F49 /* IPv4Settings.swift in Sources */,
|
||||||
0EFEB49C2006D7F300F81029 /* Data+Manipulation.swift in Sources */,
|
0EFEB49C2006D7F300F81029 /* Data+Manipulation.swift in Sources */,
|
||||||
0EE2FA0722918DA100F56F49 /* Utils.swift in Sources */,
|
0EE2FA0722918DA100F56F49 /* Utils.swift in Sources */,
|
||||||
|
|
|
@ -0,0 +1,42 @@
|
||||||
|
//
|
||||||
|
// DNSProtocol.swift
|
||||||
|
// TunnelKit
|
||||||
|
//
|
||||||
|
// Created by Davide De Rosa on 1/22/21.
|
||||||
|
// Copyright (c) 2021 Davide De Rosa. All rights reserved.
|
||||||
|
//
|
||||||
|
// https://github.com/passepartoutvpn
|
||||||
|
//
|
||||||
|
// This file is part of TunnelKit.
|
||||||
|
//
|
||||||
|
// TunnelKit is free software: you can redistribute it and/or modify
|
||||||
|
// it under the terms of the GNU General Public License as published by
|
||||||
|
// the Free Software Foundation, either version 3 of the License, or
|
||||||
|
// (at your option) any later version.
|
||||||
|
//
|
||||||
|
// TunnelKit is distributed in the hope that it will be useful,
|
||||||
|
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||||
|
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||||
|
// GNU General Public License for more details.
|
||||||
|
//
|
||||||
|
// You should have received a copy of the GNU General Public License
|
||||||
|
// along with TunnelKit. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
//
|
||||||
|
|
||||||
|
import Foundation
|
||||||
|
|
||||||
|
/// The protocol used in DNS servers.
|
||||||
|
public enum DNSProtocol: String, Codable {
|
||||||
|
|
||||||
|
/// The value to fall back to when unset.
|
||||||
|
public static let fallback: DNSProtocol = .plain
|
||||||
|
|
||||||
|
/// Standard plaintext DNS (port 53).
|
||||||
|
case plain
|
||||||
|
|
||||||
|
/// DNS over HTTPS.
|
||||||
|
case https
|
||||||
|
|
||||||
|
/// DNS over TLS (port 853).
|
||||||
|
case tls
|
||||||
|
}
|
|
@ -692,10 +692,35 @@ extension OpenVPNTunnelProvider: OpenVPNSessionDelegate {
|
||||||
dnsServers = fallbackDNSServers
|
dnsServers = fallbackDNSServers
|
||||||
}
|
}
|
||||||
|
|
||||||
let dnsSettings = NEDNSSettings(servers: dnsServers)
|
var dnsSettings = NEDNSSettings(servers: dnsServers)
|
||||||
|
if #available(iOS 14, macOS 11, *) {
|
||||||
|
switch cfg.sessionConfiguration.dnsProtocol {
|
||||||
|
case .https:
|
||||||
|
guard let serverURL = cfg.sessionConfiguration.dnsHTTPSURL else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
let specific = NEDNSOverHTTPSSettings(servers: dnsServers)
|
||||||
|
specific.serverURL = serverURL
|
||||||
|
dnsSettings = specific
|
||||||
|
|
||||||
|
case .tls:
|
||||||
|
guard let serverName = cfg.sessionConfiguration.dnsTLSServerName else {
|
||||||
|
break
|
||||||
|
}
|
||||||
|
let specific = NEDNSOverTLSSettings(servers: dnsServers)
|
||||||
|
specific.serverName = serverName
|
||||||
|
dnsSettings = specific
|
||||||
|
|
||||||
|
default:
|
||||||
|
break
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// "hack" for split DNS (i.e. use VPN only for DNS)
|
||||||
if !isGateway {
|
if !isGateway {
|
||||||
dnsSettings.matchDomains = [""]
|
dnsSettings.matchDomains = [""]
|
||||||
}
|
}
|
||||||
|
|
||||||
if let searchDomains = cfg.sessionConfiguration.searchDomains ?? options.searchDomains {
|
if let searchDomains = cfg.sessionConfiguration.searchDomains ?? options.searchDomains {
|
||||||
log.info("DNS: Using search domains \(searchDomains.maskedDescription)")
|
log.info("DNS: Using search domains \(searchDomains.maskedDescription)")
|
||||||
dnsSettings.domainName = searchDomains.first
|
dnsSettings.domainName = searchDomains.first
|
||||||
|
|
|
@ -258,9 +258,18 @@ extension OpenVPN {
|
||||||
/// The settings for IPv6. `OpenVPNSession` only evaluates this server-side.
|
/// The settings for IPv6. `OpenVPNSession` only evaluates this server-side.
|
||||||
public var ipv6: IPv6Settings?
|
public var ipv6: IPv6Settings?
|
||||||
|
|
||||||
/// The DNS servers.
|
/// The DNS protocol, defaults to `.plain` (iOS 14+ / macOS 11+).
|
||||||
|
public var dnsProtocol: DNSProtocol?
|
||||||
|
|
||||||
|
/// The DNS servers if `dnsProtocol = .plain` or nil.
|
||||||
public var dnsServers: [String]?
|
public var dnsServers: [String]?
|
||||||
|
|
||||||
|
/// The server URL if `dnsProtocol = .https`.
|
||||||
|
public var dnsHTTPSURL: URL?
|
||||||
|
|
||||||
|
/// The server name if `dnsProtocol = .tls`.
|
||||||
|
public var dnsTLSServerName: String?
|
||||||
|
|
||||||
/// The search domain.
|
/// The search domain.
|
||||||
@available(*, deprecated, message: "Use searchDomains instead")
|
@available(*, deprecated, message: "Use searchDomains instead")
|
||||||
public var searchDomain: String? {
|
public var searchDomain: String? {
|
||||||
|
@ -327,7 +336,10 @@ extension OpenVPN {
|
||||||
peerId: peerId,
|
peerId: peerId,
|
||||||
ipv4: ipv4,
|
ipv4: ipv4,
|
||||||
ipv6: ipv6,
|
ipv6: ipv6,
|
||||||
|
dnsProtocol: dnsProtocol,
|
||||||
dnsServers: dnsServers,
|
dnsServers: dnsServers,
|
||||||
|
dnsHTTPSURL: dnsHTTPSURL,
|
||||||
|
dnsTLSServerName: dnsTLSServerName,
|
||||||
searchDomains: searchDomains,
|
searchDomains: searchDomains,
|
||||||
httpProxy: httpProxy,
|
httpProxy: httpProxy,
|
||||||
httpsProxy: httpsProxy,
|
httpsProxy: httpsProxy,
|
||||||
|
@ -438,9 +450,18 @@ extension OpenVPN {
|
||||||
/// - Seealso: `ConfigurationBuilder.ipv6`
|
/// - Seealso: `ConfigurationBuilder.ipv6`
|
||||||
public let ipv6: IPv6Settings?
|
public let ipv6: IPv6Settings?
|
||||||
|
|
||||||
|
/// - Seealso: `ConfigurationBuilder.dnsProtocol`
|
||||||
|
public let dnsProtocol: DNSProtocol?
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.dnsServers`
|
/// - Seealso: `ConfigurationBuilder.dnsServers`
|
||||||
public let dnsServers: [String]?
|
public let dnsServers: [String]?
|
||||||
|
|
||||||
|
/// - Seealso: `ConfigurationBuilder.dnsHTTPSURL`
|
||||||
|
public let dnsHTTPSURL: URL?
|
||||||
|
|
||||||
|
/// - Seealso: `ConfigurationBuilder.dnsTLSServerName`
|
||||||
|
public let dnsTLSServerName: String?
|
||||||
|
|
||||||
/// - Seealso: `ConfigurationBuilder.searchDomains`
|
/// - Seealso: `ConfigurationBuilder.searchDomains`
|
||||||
public let searchDomains: [String]?
|
public let searchDomains: [String]?
|
||||||
|
|
||||||
|
@ -514,7 +535,10 @@ extension OpenVPN.Configuration {
|
||||||
builder.peerId = peerId
|
builder.peerId = peerId
|
||||||
builder.ipv4 = ipv4
|
builder.ipv4 = ipv4
|
||||||
builder.ipv6 = ipv6
|
builder.ipv6 = ipv6
|
||||||
|
builder.dnsProtocol = dnsProtocol
|
||||||
builder.dnsServers = dnsServers
|
builder.dnsServers = dnsServers
|
||||||
|
builder.dnsHTTPSURL = dnsHTTPSURL
|
||||||
|
builder.dnsTLSServerName = dnsTLSServerName
|
||||||
builder.searchDomains = searchDomains
|
builder.searchDomains = searchDomains
|
||||||
builder.httpProxy = httpProxy
|
builder.httpProxy = httpProxy
|
||||||
builder.httpsProxy = httpsProxy
|
builder.httpsProxy = httpsProxy
|
||||||
|
@ -589,10 +613,27 @@ extension OpenVPN.Configuration {
|
||||||
} else {
|
} else {
|
||||||
log.info("\tGateway: not configured")
|
log.info("\tGateway: not configured")
|
||||||
}
|
}
|
||||||
if let dnsServers = dnsServers, !dnsServers.isEmpty {
|
switch dnsProtocol {
|
||||||
log.info("\tDNS: \(dnsServers.maskedDescription)")
|
case .https:
|
||||||
} else {
|
if let dnsHTTPSURL = dnsHTTPSURL {
|
||||||
log.info("\tDNS: not configured")
|
log.info("\tDNS over HTTPS: \(dnsHTTPSURL.maskedDescription)")
|
||||||
|
} else {
|
||||||
|
log.info("\tDNS: not configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
case .tls:
|
||||||
|
if let dnsTLSServerName = dnsTLSServerName {
|
||||||
|
log.info("\tDNS over TLS: \(dnsTLSServerName.maskedDescription)")
|
||||||
|
} else {
|
||||||
|
log.info("\tDNS: not configured")
|
||||||
|
}
|
||||||
|
|
||||||
|
default:
|
||||||
|
if let dnsServers = dnsServers, !dnsServers.isEmpty {
|
||||||
|
log.info("\tDNS: \(dnsServers.maskedDescription)")
|
||||||
|
} else {
|
||||||
|
log.info("\tDNS: not configured")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if let searchDomains = searchDomains, !searchDomains.isEmpty {
|
if let searchDomains = searchDomains, !searchDomains.isEmpty {
|
||||||
log.info("\tSearch domains: \(searchDomains.maskedDescription)")
|
log.info("\tSearch domains: \(searchDomains.maskedDescription)")
|
||||||
|
|
Loading…
Reference in New Issue