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:
|
||||
- BidirectionalState
|
||||
- ConfigurationError
|
||||
- DNSProtocol
|
||||
- DNSResolver
|
||||
- DNSRecord
|
||||
- EndpointProtocol
|
||||
|
|
|
@ -10,6 +10,7 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
|
|||
### Added
|
||||
|
||||
- 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)
|
||||
|
||||
|
|
|
@ -186,6 +186,8 @@
|
|||
0E749F622178911D00BB2701 /* pia-2048.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0E749F612178911C00BB2701 /* pia-2048.pem */; };
|
||||
0E7F3F6A246ABA0F006BE77F /* 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 */; };
|
||||
0EA82A3E2190B2BC007960EB /* pia-2048.pem in Resources */ = {isa = PBXBuildFile; fileRef = 0E749F612178911C00BB2701 /* pia-2048.pem */; };
|
||||
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>"; };
|
||||
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>"; };
|
||||
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; };
|
||||
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>"; };
|
||||
|
@ -1074,6 +1077,7 @@
|
|||
0EFEB4432006D3C800F81029 /* Data+Manipulation.swift */,
|
||||
0E411B992271F90700E0852C /* DNS.h */,
|
||||
0E411B9A2271F90700E0852C /* DNS.m */,
|
||||
0E94E8E925BACEBD0040BC30 /* DNSProtocol.swift */,
|
||||
0EE2F9E522918DA100F56F49 /* DNSResolver.swift */,
|
||||
0E011F7C2196D97200BA59EE /* EndpointProtocol.swift */,
|
||||
0EFEB4362006D3C800F81029 /* Errors.h */,
|
||||
|
@ -2036,6 +2040,7 @@
|
|||
0E23B44122982AF800304C30 /* OpenVPNSession+PIA.swift in Sources */,
|
||||
0E23B42D22982AF800304C30 /* ControlChannelSerializer.swift in Sources */,
|
||||
0EE2F9F622918DA100F56F49 /* NEUDPSocket.swift in Sources */,
|
||||
0E94E8EA25BACEBD0040BC30 /* DNSProtocol.swift in Sources */,
|
||||
0EE2F96E2291636B00F56F49 /* IPv4Settings.swift in Sources */,
|
||||
0EFEB4662006D3C800F81029 /* ZeroingData.swift in Sources */,
|
||||
0EE2FA0622918DA100F56F49 /* Utils.swift in Sources */,
|
||||
|
@ -2125,6 +2130,7 @@
|
|||
0E23B44222982AF800304C30 /* OpenVPNSession+PIA.swift in Sources */,
|
||||
0E23B42E22982AF800304C30 /* ControlChannelSerializer.swift in Sources */,
|
||||
0EE2F9F722918DA100F56F49 /* NEUDPSocket.swift in Sources */,
|
||||
0E94E8EB25BACEBD0040BC30 /* DNSProtocol.swift in Sources */,
|
||||
0EE2F96F2291636B00F56F49 /* IPv4Settings.swift in Sources */,
|
||||
0EFEB49C2006D7F300F81029 /* Data+Manipulation.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
|
||||
}
|
||||
|
||||
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 {
|
||||
dnsSettings.matchDomains = [""]
|
||||
}
|
||||
|
||||
if let searchDomains = cfg.sessionConfiguration.searchDomains ?? options.searchDomains {
|
||||
log.info("DNS: Using search domains \(searchDomains.maskedDescription)")
|
||||
dnsSettings.domainName = searchDomains.first
|
||||
|
|
|
@ -258,9 +258,18 @@ extension OpenVPN {
|
|||
/// The settings for IPv6. `OpenVPNSession` only evaluates this server-side.
|
||||
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]?
|
||||
|
||||
/// The server URL if `dnsProtocol = .https`.
|
||||
public var dnsHTTPSURL: URL?
|
||||
|
||||
/// The server name if `dnsProtocol = .tls`.
|
||||
public var dnsTLSServerName: String?
|
||||
|
||||
/// The search domain.
|
||||
@available(*, deprecated, message: "Use searchDomains instead")
|
||||
public var searchDomain: String? {
|
||||
|
@ -327,7 +336,10 @@ extension OpenVPN {
|
|||
peerId: peerId,
|
||||
ipv4: ipv4,
|
||||
ipv6: ipv6,
|
||||
dnsProtocol: dnsProtocol,
|
||||
dnsServers: dnsServers,
|
||||
dnsHTTPSURL: dnsHTTPSURL,
|
||||
dnsTLSServerName: dnsTLSServerName,
|
||||
searchDomains: searchDomains,
|
||||
httpProxy: httpProxy,
|
||||
httpsProxy: httpsProxy,
|
||||
|
@ -438,9 +450,18 @@ extension OpenVPN {
|
|||
/// - Seealso: `ConfigurationBuilder.ipv6`
|
||||
public let ipv6: IPv6Settings?
|
||||
|
||||
/// - Seealso: `ConfigurationBuilder.dnsProtocol`
|
||||
public let dnsProtocol: DNSProtocol?
|
||||
|
||||
/// - Seealso: `ConfigurationBuilder.dnsServers`
|
||||
public let dnsServers: [String]?
|
||||
|
||||
/// - Seealso: `ConfigurationBuilder.dnsHTTPSURL`
|
||||
public let dnsHTTPSURL: URL?
|
||||
|
||||
/// - Seealso: `ConfigurationBuilder.dnsTLSServerName`
|
||||
public let dnsTLSServerName: String?
|
||||
|
||||
/// - Seealso: `ConfigurationBuilder.searchDomains`
|
||||
public let searchDomains: [String]?
|
||||
|
||||
|
@ -514,7 +535,10 @@ extension OpenVPN.Configuration {
|
|||
builder.peerId = peerId
|
||||
builder.ipv4 = ipv4
|
||||
builder.ipv6 = ipv6
|
||||
builder.dnsProtocol = dnsProtocol
|
||||
builder.dnsServers = dnsServers
|
||||
builder.dnsHTTPSURL = dnsHTTPSURL
|
||||
builder.dnsTLSServerName = dnsTLSServerName
|
||||
builder.searchDomains = searchDomains
|
||||
builder.httpProxy = httpProxy
|
||||
builder.httpsProxy = httpsProxy
|
||||
|
@ -589,10 +613,27 @@ extension OpenVPN.Configuration {
|
|||
} else {
|
||||
log.info("\tGateway: not configured")
|
||||
}
|
||||
if let dnsServers = dnsServers, !dnsServers.isEmpty {
|
||||
log.info("\tDNS: \(dnsServers.maskedDescription)")
|
||||
} else {
|
||||
log.info("\tDNS: not configured")
|
||||
switch dnsProtocol {
|
||||
case .https:
|
||||
if let dnsHTTPSURL = dnsHTTPSURL {
|
||||
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 {
|
||||
log.info("\tSearch domains: \(searchDomains.maskedDescription)")
|
||||
|
|
Loading…
Reference in New Issue