Skip to content

Commit 2905bbb

Browse files
dmitryskorbovenkoДмитрий Скорбовенко
andauthored
Fix: Mitmproxy run in local mode stops working on Mac OS in an hour #7675 (#260)
Co-authored-by: Дмитрий Скорбовенко <[email protected]>
1 parent 7e96ac7 commit 2905bbb

File tree

3 files changed

+25
-10
lines changed

3 files changed

+25
-10
lines changed

CHANGELOG.md

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,7 @@
11
## Unreleased: mitmproxy_rs next
22

3+
- Fix a bug where macOS local capture mode wouldn't clean up connections and stop working after a while.
4+
The changes may break half-closed TCP streams.
35
- tun mode: allow using a pre-configured persistent tun interface, to avoid requiring CAP_NET_ADMIN.
46

57
## 29 April 2025: mitmproxy_rs 0.12.3

mitmproxy-macos/redirector/network-extension/FlowExtensions.swift

Lines changed: 20 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -17,17 +17,17 @@ extension NEAppProxyTCPFlow {
1717
self.outboundCopier(conn)
1818
} else {
1919
// log.debug("outbound copier: error copying: \(String(describing: error), privacy: .public)")
20+
self.closeConnection(conn, error)
2021
}
2122
}))
2223
} else {
2324
log.debug(
2425
"outbound copier end: \(String(describing: data), privacy: .public) \(String(describing: error), privacy: .public)"
2526
)
2627
conn.send(content: nil, isComplete: true, completion: .contentProcessed({ error in
27-
conn.cancel()
2828
// log.debug("outbound copier: sent end.")
29+
self.closeConnection(conn, error)
2930
}))
30-
self.closeWriteWithError(error)
3131
}
3232
}
3333
}
@@ -40,12 +40,14 @@ extension NEAppProxyTCPFlow {
4040
self.write(data) { error in
4141
if error == nil {
4242
self.inboundCopier(conn)
43+
} else {
44+
self.closeConnection(conn, error)
4345
}
4446
}
4547
case (_, true, _):
46-
self.closeReadWithError(error)
48+
self.closeConnection(conn, error)
4749
default:
48-
self.closeReadWithError(error)
50+
self.closeConnection(conn, error)
4951
log.info(
5052
"inbound copier error=\(String(describing: error), privacy: .public) isComplete=\(String(describing: isComplete), privacy: .public)"
5153
)
@@ -61,8 +63,9 @@ extension NEAppProxyUDPFlow {
6163
func readDatagrams() async throws -> ([Data], [NetworkExtension.NWEndpoint]) {
6264
return try await withCheckedThrowingContinuation { continuation in
6365
readDatagrams { datagrams, endpoints, error in
64-
if let error = error {
66+
if let error {
6567
continuation.resume(throwing: error)
68+
return
6669
}
6770
guard let datagrams = datagrams, let endpoints = endpoints else {
6871
fatalError("No error, but also no datagrams")
@@ -94,10 +97,10 @@ extension NEAppProxyUDPFlow {
9497
try await conn.send(ipc: message)
9598
}
9699
}
100+
self.closeConnection(conn, nil)
97101
} catch {
98102
log.error("Error in outbound UDP copier: \(String(describing: error), privacy: .public)")
99-
self.closeWriteWithError(error)
100-
conn.cancel()
103+
self.closeConnection(conn, error)
101104
}
102105
}
103106
}
@@ -108,18 +111,25 @@ extension NEAppProxyUDPFlow {
108111
while true {
109112
// log.debug("UDP inbound: receiving...")
110113
guard let packet = try await conn.receive(ipc: MitmproxyIpc_UdpPacket.self) else {
111-
self.closeReadWithError(nil)
112114
break
113115
}
114116
// log.debug("UDP inbound: received packet.: \(String(describing: packet), privacy: .public)")
115117
let endpoint = NWHostEndpoint(address: packet.remoteAddress)
116118
try await self.writeDatagrams([packet.data], sentBy: [endpoint])
117119
}
120+
self.closeConnection(conn, nil)
118121
} catch {
119122
log.error("Error in inbound UDP copier: \(String(describing: error), privacy: .public)")
120-
self.closeReadWithError(error)
121-
conn.cancel()
123+
self.closeConnection(conn, error)
122124
}
123125
}
124126
}
125127
}
128+
129+
extension NEAppProxyFlow {
130+
func closeConnection(_ conn: NWConnection, _ error: Error?) {
131+
conn.cancel()
132+
self.closeReadWithError(error)
133+
self.closeWriteWithError(error)
134+
}
135+
}

mitmproxy-macos/redirector/network-extension/TransparentProxyProvider.swift

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -32,9 +32,11 @@ class TransparentProxyProvider: NETransparentProxyProvider {
3232
switch state {
3333
case .failed(.posix(.ENETDOWN)):
3434
log.debug("control channel closed, stopping proxy.")
35+
control.forceCancel()
3536
self.cancelProxyWithError(.none)
3637
case .failed(let err):
3738
log.error("control channel failed: \(err, privacy: .public)")
39+
control.forceCancel()
3840
self.cancelProxyWithError(err)
3941
default:
4042
break
@@ -48,6 +50,7 @@ class TransparentProxyProvider: NETransparentProxyProvider {
4850
}
4951
} catch {
5052
log.error("Error on control channel: \(String(describing: error), privacy: .public)")
53+
control.forceCancel()
5154
self.cancelProxyWithError(error)
5255
}
5356
}

0 commit comments

Comments
 (0)