Initial Commit
This commit is contained in:
210
GlassDNS/DNSProxyProvider.swift
Normal file
210
GlassDNS/DNSProxyProvider.swift
Normal file
@@ -0,0 +1,210 @@
|
||||
import NetworkExtension
|
||||
import DNS
|
||||
|
||||
fileprivate var db: SQLiteDatabase?
|
||||
|
||||
class DNSProxyProvider: NEDNSProxyProvider {
|
||||
|
||||
override func startProxy(options:[String: Any]? = nil, completionHandler: @escaping (Error?) -> Void) {
|
||||
// Add code here to start the DNS proxy.
|
||||
simpleTunnelLog("startProxy")
|
||||
do {
|
||||
db = try SQLiteDatabase.open(path: DB_PATH)
|
||||
try db!.createTable(table: DNSQuery.self)
|
||||
} catch {
|
||||
simpleTunnelLog("Error: \(error)")
|
||||
completionHandler(error)
|
||||
return
|
||||
}
|
||||
completionHandler(nil)
|
||||
}
|
||||
|
||||
override func stopProxy(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
|
||||
// Add code here to stop the DNS proxy.
|
||||
simpleTunnelLog("stopProxy")
|
||||
db = nil
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func sleep(completionHandler: @escaping () -> Void) {
|
||||
// Add code here to get ready to sleep.
|
||||
simpleTunnelLog("sleep")
|
||||
completionHandler()
|
||||
}
|
||||
|
||||
override func wake() {
|
||||
// Add code here to wake up.
|
||||
simpleTunnelLog("wake")
|
||||
}
|
||||
|
||||
override func handleNewUDPFlow(_ flow: NEAppProxyUDPFlow, initialRemoteEndpoint remoteEndpoint: NWEndpoint) -> Bool {
|
||||
simpleTunnelLog("handleUDPFlow \(flow.metaData.sourceAppSigningIdentifier)")
|
||||
simpleTunnelLog("handleUDPFlow \((remoteEndpoint as! NWHostEndpoint).hostname)")
|
||||
|
||||
let con = createUDPSession(to: remoteEndpoint, from: (flow.localEndpoint as! NWHostEndpoint))
|
||||
let newConnection = ClientDNSProxy(newUDPFlow: flow)
|
||||
newConnection.open(con)
|
||||
return true
|
||||
}
|
||||
|
||||
|
||||
/*override func handleNewFlow(_ flow: NEAppProxyFlow) -> Bool {
|
||||
// Add code here to handle the incoming flow.
|
||||
NSLog("PSI: handleFlow %@", flow.metaData.sourceAppSigningIdentifier)
|
||||
|
||||
var newConnection: ClientAppProxyConnection?
|
||||
|
||||
guard let clientTunnel = tunnel else { return false }
|
||||
|
||||
|
||||
if let tcpFlow = flow as? NEAppProxyTCPFlow {
|
||||
let remoteHost = (tcpFlow.remoteEndpoint as! NWHostEndpoint).hostname
|
||||
let remotePort = (tcpFlow.remoteEndpoint as! NWHostEndpoint).port
|
||||
NSLog("PSI: TCP HOST : \(remoteHost)")
|
||||
NSLog("PSI: TCP PORT : \(remotePort)")
|
||||
newConnection = ClientAppProxyTCPConnection(tunnel: clientTunnel, newTCPFlow: tcpFlow)
|
||||
} else if let udpFlow = flow as? NEAppProxyUDPFlow {
|
||||
let localHost = (udpFlow.localEndpoint as! NWHostEndpoint).hostname
|
||||
let localPort = (udpFlow.localEndpoint as! NWHostEndpoint).port
|
||||
NSLog("PSI: UDP HOST : \(localHost)")
|
||||
NSLog("PSI: UDP PORT : \(localPort)")
|
||||
newConnection = ClientAppProxyUDPConnection(tunnel: clientTunnel, newUDPFlow: udpFlow)
|
||||
}
|
||||
|
||||
guard newConnection != nil else { return false }
|
||||
|
||||
newConnection!.open()
|
||||
|
||||
return true
|
||||
// return super.handleNewFlow(flow)
|
||||
}*/
|
||||
}
|
||||
|
||||
class ClientDNSProxy : NSObject {
|
||||
public let identifier: Int
|
||||
let appProxyFlow: NEAppProxyFlow
|
||||
var datagramsOutstanding = 0
|
||||
var conn: NWUDPSession?
|
||||
|
||||
/// The NEAppProxyUDPFlow object corresponding to this connection.
|
||||
var UDPFlow: NEAppProxyUDPFlow {
|
||||
return (appProxyFlow as! NEAppProxyUDPFlow)
|
||||
}
|
||||
|
||||
init(newUDPFlow: NEAppProxyUDPFlow) {
|
||||
appProxyFlow = newUDPFlow
|
||||
identifier = newUDPFlow.hash
|
||||
super.init()
|
||||
}
|
||||
|
||||
/// Send an "Open" message to the SimpleTunnel server, to begin the process of establishing a flow of data in the SimpleTunnel protocol.
|
||||
func open(_ connection: NWUDPSession) {
|
||||
// open([
|
||||
// TunnelMessageKey.TunnelType.rawValue: TunnelLayer.app.rawValue as AnyObject,
|
||||
// TunnelMessageKey.AppProxyFlowType.rawValue: AppProxyFlowKind.udp.rawValue as AnyObject
|
||||
// ])
|
||||
connection.setReadHandler({ datas, error in
|
||||
guard let datagrams = datas, error == nil else {
|
||||
simpleTunnelLog("Failed to read UDP connection: \(String(describing: error))")
|
||||
return
|
||||
}
|
||||
|
||||
self.UDPFlow.writeDatagrams(datagrams, sentBy: [connection.endpoint]) { error in
|
||||
if let error = error {
|
||||
simpleTunnelLog("Failed to write datagrams to the UDP Flow: \(error)")
|
||||
// self.tunnel?.sendCloseType(.read, forConnection: self.identifier)
|
||||
self.UDPFlow.closeWriteWithError(nil)
|
||||
}
|
||||
}
|
||||
}, maxDatagrams: 32)
|
||||
self.conn = connection
|
||||
UDPFlow.open(withLocalEndpoint: (UDPFlow.localEndpoint as! NWHostEndpoint)) { (e: Error?) in
|
||||
self.handleSendResult(nil)
|
||||
}
|
||||
}
|
||||
|
||||
/// Handle the result of sending a "Data" message to the SimpleTunnel server.
|
||||
func handleSendResult(_ error: NSError?) {
|
||||
|
||||
if let sendError = error {
|
||||
simpleTunnelLog("Failed to send message to Tunnel Server. error = \(sendError)")
|
||||
// handleErrorCondition(.hostUnreachable)
|
||||
return
|
||||
}
|
||||
|
||||
if datagramsOutstanding > 0 {
|
||||
datagramsOutstanding -= 1
|
||||
}
|
||||
|
||||
// Only read more datagrams from the source application if all outstanding datagrams have been sent on the network.
|
||||
guard datagramsOutstanding == 0 else { return }
|
||||
|
||||
// Read a new set of datagrams from the source application.
|
||||
UDPFlow.readDatagrams { datagrams, remoteEndPoints, readError in
|
||||
|
||||
guard let readDatagrams = datagrams,
|
||||
let readEndpoints = remoteEndPoints
|
||||
, readError == nil else
|
||||
{
|
||||
simpleTunnelLog("Failed to read data from the UDP flow. error = \(String(describing: readError))")
|
||||
// self.handleErrorCondition(.peerReset)
|
||||
return
|
||||
}
|
||||
|
||||
guard !readDatagrams.isEmpty && readEndpoints.count == readDatagrams.count else {
|
||||
simpleTunnelLog("\(self.identifier): Received EOF on the UDP flow. Closing the flow...")
|
||||
// self.tunnel?.sendCloseType(.write, forConnection: self.identifier)
|
||||
self.UDPFlow.closeReadWithError(nil)
|
||||
return
|
||||
}
|
||||
|
||||
self.datagramsOutstanding = readDatagrams.count
|
||||
|
||||
for (index, datagram) in readDatagrams.enumerated() {
|
||||
guard let endpoint = readEndpoints[index] as? NWHostEndpoint else { continue }
|
||||
|
||||
let response = try! Message.init(deserialize: datagram)
|
||||
for q in response.questions {
|
||||
simpleTunnelLog("got name \(q.name)")
|
||||
try? db?.insertDNSQuery(appId: self.UDPFlow.metaData.sourceAppSigningIdentifier as NSString,
|
||||
dnsQuery: q.name as NSString)
|
||||
}
|
||||
|
||||
simpleTunnelLog("(\(self.identifier)): Sending a \(datagram.count)-byte datagram to \(endpoint.hostname):\(endpoint.port)")
|
||||
// Send a data message to the SimpleTunnel server.
|
||||
// self.sendDataMessage(datagram, extraProperties:[
|
||||
// TunnelMessageKey.Host.rawValue: endpoint.hostname as AnyObject,
|
||||
// TunnelMessageKey.Port.rawValue: Int(endpoint.port)! as AnyObject
|
||||
// ])
|
||||
self.conn?.writeDatagram(datagram, completionHandler: { conError in
|
||||
simpleTunnelLog("write con err: \(String(describing: conError))")
|
||||
})
|
||||
}
|
||||
|
||||
// self.UDPFlow.writeDatagrams(readDatagrams, sentBy: readEndpoints) { writeError in
|
||||
// simpleTunnelLog("write error \(String(describing: writeError))")
|
||||
// }
|
||||
}
|
||||
}
|
||||
|
||||
/// Send a datagram received from the SimpleTunnel server to the destination application.
|
||||
func sendDataWithEndPoint(_ data: Data, host: String, port: Int) {
|
||||
let datagrams = [ data ]
|
||||
let endpoints = [ NWHostEndpoint(hostname: host, port: String(port)) ]
|
||||
|
||||
// Send the datagram to the destination application.
|
||||
UDPFlow.writeDatagrams(datagrams, sentBy: endpoints) { error in
|
||||
if let error = error {
|
||||
simpleTunnelLog("Failed to write datagrams to the UDP Flow: \(error)")
|
||||
// self.tunnel?.sendCloseType(.read, forConnection: self.identifier)
|
||||
self.UDPFlow.closeWriteWithError(nil)
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
public func simpleTunnelLog(_ message: String) {
|
||||
// NSLog("PSI: \(message)")
|
||||
}
|
||||
|
||||
18
GlassDNS/GlassDNS.entitlements
Normal file
18
GlassDNS/GlassDNS.entitlements
Normal file
@@ -0,0 +1,18 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>com.apple.developer.networking.networkextension</key>
|
||||
<array>
|
||||
<string>dns-proxy</string>
|
||||
</array>
|
||||
<key>com.apple.developer.networking.vpn.api</key>
|
||||
<array>
|
||||
<string>allow-vpn</string>
|
||||
</array>
|
||||
<key>com.apple.security.application-groups</key>
|
||||
<array>
|
||||
<string>group.de.uni-bamberg.psi.AppCheck</string>
|
||||
</array>
|
||||
</dict>
|
||||
</plist>
|
||||
31
GlassDNS/Info.plist
Normal file
31
GlassDNS/Info.plist
Normal file
@@ -0,0 +1,31 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
|
||||
<plist version="1.0">
|
||||
<dict>
|
||||
<key>CFBundleDevelopmentRegion</key>
|
||||
<string>$(DEVELOPMENT_LANGUAGE)</string>
|
||||
<key>CFBundleDisplayName</key>
|
||||
<string>GlassDNS</string>
|
||||
<key>CFBundleExecutable</key>
|
||||
<string>$(EXECUTABLE_NAME)</string>
|
||||
<key>CFBundleIdentifier</key>
|
||||
<string>$(PRODUCT_BUNDLE_IDENTIFIER)</string>
|
||||
<key>CFBundleInfoDictionaryVersion</key>
|
||||
<string>6.0</string>
|
||||
<key>CFBundleName</key>
|
||||
<string>$(PRODUCT_NAME)</string>
|
||||
<key>CFBundlePackageType</key>
|
||||
<string>$(PRODUCT_BUNDLE_PACKAGE_TYPE)</string>
|
||||
<key>CFBundleShortVersionString</key>
|
||||
<string>$(MARKETING_VERSION)</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>7</string>
|
||||
<key>NSExtension</key>
|
||||
<dict>
|
||||
<key>NSExtensionPointIdentifier</key>
|
||||
<string>com.apple.networkextension.dns-proxy</string>
|
||||
<key>NSExtensionPrincipalClass</key>
|
||||
<string>$(PRODUCT_MODULE_NAME).DNSProxyProvider</string>
|
||||
</dict>
|
||||
</dict>
|
||||
</plist>
|
||||
Reference in New Issue
Block a user