Skip to content

Commit

Permalink
pipes prototype
Browse files Browse the repository at this point in the history
  • Loading branch information
mhils committed Aug 21, 2023
1 parent 867b7e2 commit 2a05fc7
Show file tree
Hide file tree
Showing 3 changed files with 77 additions and 40 deletions.
12 changes: 10 additions & 2 deletions macos-redirector/ipc/utils.swift
Original file line number Diff line number Diff line change
Expand Up @@ -9,7 +9,7 @@ enum IpcError: Error {

func readIpcMessage<T: SwiftProtobuf.Message>(ofType: T.Type, fh: FileHandle) throws -> T? {
// read u32
guard let len_buf = try FileHandle.standardInput.read(upToCount: 4) else { throw IpcError.emptyRead }
guard let len_buf = try fh.read(upToCount: 4) else { throw IpcError.emptyRead }
guard len_buf.count == 4 else { throw IpcError.incompleteRead }
let len = len_buf[...].reduce(Int(0)) { $0 << 8 + Int($1) };
// 4x \n (testing)
Expand All @@ -18,7 +18,15 @@ func readIpcMessage<T: SwiftProtobuf.Message>(ofType: T.Type, fh: FileHandle) th
}
guard len < 1024 * 1024 else { throw IpcError.tooLarge(len) }
// read protobuf data
guard let data = try FileHandle.standardInput.read(upToCount: len) else { throw IpcError.incompleteRead }
guard let data = try fh.read(upToCount: len) else { throw IpcError.incompleteRead }
// decode protobuf
return try T(contiguousBytes: data)
}


func writeIpcMessage(message: SwiftProtobuf.Message, fh: FileHandle) throws {
let data = try message.serializedData()
let len = withUnsafeBytes(of: UInt32(data.count).bigEndian, Array.init)
try fh.write(contentsOf: len)
try fh.write(contentsOf: data)
}
6 changes: 2 additions & 4 deletions macos-redirector/macos-redirector/app.swift
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ struct App {
while let spec = try readIpcMessage(ofType: Mitmproxy_Ipc_InterceptSpec.self, fh: FileHandle.standardInput) {

log.debug("received intercept spec: \(spec.spec)")

guard !spec.spec.starts(with: "!") else {
log.error("inverse specs are not implemented yet.")
continue
Expand Down Expand Up @@ -97,9 +96,8 @@ func startVPN() async throws -> NETunnelProviderManager {

let providerProtocol = NETunnelProviderProtocol()
providerProtocol.providerBundleIdentifier = networkExtensionIdentifier
// TODO: Use either of these to signal pipes.
//providerProtocol.providerConfiguration = ["server": "127.0.0.1", "port": 1234]
providerProtocol.serverAddress = "mitmproxy"
providerProtocol.serverAddress = "/tmp/mitmproxy-123"

// XXX: it's unclear if these are actually necessary for per-app VPNs
providerProtocol.enforceRoutes = true
providerProtocol.includeAllNetworks = true
Expand Down
99 changes: 65 additions & 34 deletions macos-redirector/network-extension/PacketTunnelProvider.swift
Original file line number Diff line number Diff line change
@@ -1,52 +1,83 @@
import NetworkExtension

class PacketTunnelProvider: NEPacketTunnelProvider {

var t: Task<Void, Error>?

override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
log.debug("startTunnel options=\(String(describing:options), privacy: .public)")
log.debug("startTunnel")

let tunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "10.0.0.42")
let ipv4Settings = NEIPv4Settings(addresses: ["10.0.0.1"], subnetMasks: ["255.255.255.0"])
ipv4Settings.includedRoutes = [
NEIPv4Route.default()
]
tunnelNetworkSettings.ipv4Settings = ipv4Settings
tunnelNetworkSettings.dnsSettings = NEDNSSettings(servers: ["10.0.0.53"])

let addr = self.protocolConfiguration.serverAddress!

self.t = Task {

log.debug("setting network settings")

let tunnelNetworkSettings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "10.0.0.42")

let ipv4Settings = NEIPv4Settings(addresses: ["10.0.0.1"], subnetMasks: ["255.255.255.0"])
ipv4Settings.includedRoutes = [
NEIPv4Route.default()
]
tunnelNetworkSettings.ipv4Settings = ipv4Settings

tunnelNetworkSettings.dnsSettings = NEDNSSettings(servers: ["10.0.0.53"])

do {
try await self.setTunnelNetworkSettings(tunnelNetworkSettings)
} catch let error {
completionHandler(error)
throw error
let proxy_file: FileHandle, redir_file: FileHandle
do {
proxy_file = try FileHandle(forReadingFrom: URL(fileURLWithPath: "\(addr).proxy"));
redir_file = try FileHandle(forWritingTo: URL(fileURLWithPath: "\(addr).redir"))
} catch {
return completionHandler(error)
}

self.setTunnelNetworkSettings(tunnelNetworkSettings) { err in
completionHandler(err)
log.debug("tunnel settings set (err=\(err))")
if err == nil {
self.redirectPackets(redir_file)
self.reinjectPackets(proxy_file)
}

completionHandler(nil)

while !Task.isCancelled {
log.debug("reading packet objects...")
let packets = await self.packetFlow.readPacketObjects();
for packet in packets {
log.debug("received packet: \(packet, privacy: .public)")
}

log.debug("startTunnel done")
}

func redirectPackets(_ wfile: FileHandle) {
log.debug("redirecting packets to \(wfile, privacy: .public)...")
self.packetFlow.readPacketObjects { packets in
for packet in packets {

var message = Mitmproxy_Ipc_FromRedirector()
message.packet.data = packet.data
message.packet.pid = 0 // TODO
message.packet.processName = packet.metadata!.sourceAppSigningIdentifier

do {
try writeIpcMessage(message: message, fh: wfile)
} catch {
log.error("redirectPackets errored: \(error)")
exit(1)
}
self.redirectPackets(wfile)
}
log.debug("packet task cancelled")
}
log.debug("startTunnel done")
}

func reinjectPackets(_ rfile: FileHandle) {
log.debug("reading \(rfile, privacy: .public)...")
do {
while let packet = try readIpcMessage(ofType: Mitmproxy_Ipc_Packet.self, fh: rfile) {

log.debug("reinjecting packet...")
self.packetFlow.writePackets([packet.data], withProtocols: [AF_INET as NSNumber])

}
} catch {
log.error("redirectPackets errored: \(error)")
exit(1)
}

log.debug("exiting...")
exit(0)
}

override func stopTunnel(with reason: NEProviderStopReason, completionHandler: @escaping () -> Void) {
log.debug("stopTunnel \(String(describing:reason))")
self.t?.cancel()
completionHandler()
log.debug("stopTunnel done")
exit(0) // XXX: is that a reasonable approach to tear things down?
}

override func handleAppMessage(_ messageData: Data, completionHandler: ((Data?) -> Void)?) {
Expand Down

0 comments on commit 2a05fc7

Please sign in to comment.