Generate NetworkSettings with IPC

This generates and applies NetworkSettings object with unix socket IPC.

- domain socket, json-rpc based communication
- switches to anyhow for burrow crate
- adds support for starting daemons on macos
This commit is contained in:
Jett Chen 2023-10-01 11:49:00 +08:00 committed by Conrad Kramer
parent 6368ca7f74
commit c9f104e523
31 changed files with 909 additions and 117 deletions

View file

@ -1,39 +1,66 @@
import libburrow
import NetworkExtension
import OSLog
import os
class PacketTunnelProvider: NEPacketTunnelProvider {
let logger = Logger(subsystem: "com.hackclub.burrow", category: "General")
let logger = Logger(subsystem: "com.hackclub.burrow", category: "frontend")
var client: BurrowIpc?
var osInitialized = false
override func startTunnel(options: [String: NSObject]?, completionHandler: @escaping (Error?) -> Void) {
let fild = libburrow.retrieve()
if fild == -1 {
// Not sure if this is the right way to return an error
logger.error("Failed to retrieve file descriptor for burrow.")
let err = NSError(
domain: "com.hackclub.burrow",
code: 1_010,
userInfo: [NSLocalizedDescriptionKey: "Failed to find TunInterface"]
)
completionHandler(err)
logger.log("Starting tunnel")
if !osInitialized {
libburrow.initialize_oslog()
osInitialized = true
}
libburrow.start_srv()
client = BurrowIpc(logger: logger)
logger.info("Started server")
Task {
do {
let command = BurrowRequest(id: 0, command: "ServerConfig")
guard let data = try await client?.request(command, type: Response<BurrowResult<ServerConfigData>>.self)
else {
throw BurrowError.cantParseResult
}
let encoded = try JSONEncoder().encode(data.result)
self.logger.log("Received final data: \(String(decoding: encoded, as: UTF8.self))")
guard let serverconfig = data.result.Ok else {
throw BurrowError.resultIsError
}
guard let tunNs = self.generateTunSettings(from: serverconfig) else {
throw BurrowError.addrDoesntExist
}
try await self.setTunnelNetworkSettings(tunNs)
self.logger.info("Set remote tunnel address to \(tunNs.tunnelRemoteAddress)")
completionHandler(nil)
} catch {
self.logger.error("An error occurred: \(error)")
completionHandler(error)
}
}
logger.info("fd: \(fild)")
completionHandler(nil)
}
private func generateTunSettings(from: ServerConfigData) -> NETunnelNetworkSettings? {
let cfig = from.ServerConfig
guard let addr = cfig.address else {
return nil
}
// Using a makeshift remote tunnel address
var nst = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "1.1.1.1")
nst.ipv4Settings = NEIPv4Settings(addresses: [addr], subnetMasks: ["255.255.255.0"])
logger.log("Initialized ipv4 settings: \(nst.ipv4Settings)")
return nst
}
override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
completionHandler()
}
override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
if let handler = completionHandler {
handler(messageData)
}
}
override func sleep(completionHandler: @escaping () -> Void) {
completionHandler()
}
override func wake() {
}
}