The version tag of current system is: 11.5 Beta (20G5023d)
After some time testing, not able to browse anymore although appproxy device is still connected and can still ping through.
Post
Replies
Boosts
Views
Activity
Also, can you help indicate how to update in the tsi ticket? I would like to go on discussion fromTSI case 767665663, but don't know what is the link for it.
Thanks in advance.
You can let the system handle all UDP flows. You can attempt to target a small subset of UDP flows and if you
receive port 53 flows, you can proxy them. Proxying UDP flows is something that can be done without a crash.
That is what I am trying at the moment. But when letting all udp traffic through with filter setting like below, within around three hours, network is gone like below. Crash might not happen though.
ping apple.com
...
Request timeout for icmp_seq 14745
ping: sendto: No route to host
Request timeout for icmp_seq 14746
ping: sendto: No route to host
I have tried both udp session and NWConnection for remote connection, same result.
Any suggestion?
for seg in 1...254 {
if seg != 127 {
hosts = [("\(seg).0.0.0", "0")]
for host in hosts {
let ep = NWHostEndpoint(hostname: host.0, port: host.1)
let rule = NENetworkRule.init(remoteNetwork: ep, remotePrefix: 8, localNetwork: nil, localPrefix: 0, protocol: .UDP, direction: .outbound)
rules.append(rule)
}
}
}
Hi there,
Following this topic, we managed to make both appproxy and dnsproxy work together at the same time, but have some constraints. Wonder if you can provide some help.
Need uninstall extension each time before you run the application.
It is with below command to control the extension.
systemextensionsctl uninstall $DNSExtensionID $DNSExtensionName
If start dnsproxy first, then only one network service is prompted and added without the one for appproxy.
If start approxy first, both network service are added, but dnsproxy doesn’t work (as the extension access right problem).
AppDelegate.swift:applicationDidFinishLaunching() {
...
// Start App Proxy
ProxyManager.shared().loadProxyManager(connect: true) {
ProxyManager.shared().addObserver {}
ProxyManager.shared().start()
// Start the DNS Proxy
DNSManager.shared().start() {}
}
...
Any suggestion on this?
Stability thing, mainly from dns proxy.
After running for a while with both proxies, name resolution failed.
We will go on checking this point as well.
As confirmed that by only capturing all udp traffic can cause the network crash. Tried different approaches around udp, but all failed. That include exclude reserved ip segments for local network, exclude multicast segments, only include 1.0.0.0/8 to 127.0.0.0/8 for udp traffic.
So far, I do believe that if there is any way to exclude udp 53 traffic, should get resolved. But as you see, I am using none zero default route as suggested, but udp 53 packets still comes in. Furthermore, as you side noted that " you cannot filter localNetwork traffic with NEAppProxyProvider either", does it mean that we have no way to eliminate udp 53 traffic with NEAppProvider?
Thanks in advance for any suggestion.
Confirmed that only by doing all udp traffic capturing like below will cause network crash.
Would like to try NWConnection .udp rather than NWUDPSession currently in use.
Do you have any sample code for using NWconnection together with NEAppProxyUDPFlow?
for seg in 1...254 {
if seg != 127 {
hosts = [("\(seg).0.0.0", "0")]
for host in hosts {
let ep = NWHostEndpoint(hostname: host.0, port: host.1)
let rule = NENetworkRule.init(remoteNetwork: ep, remotePrefix: 8, localNetwork: nil, localPrefix: 0, protocol: .UDP, direction: .outbound)
rules.append(rule)
}
}
}
Thanks for the good point.
To rule out whether it is tcp or udp that caused the crash, I would like to have a try with NWConnection rather than NWUDPSession (I am currently in use).
The question is:
If I want to try NWConnection for udp flow handle (with .udp option), how to handle the multi datagrams with connection.send?
udpflow.readDatagrams(completionHandler: { [unowned self] (datagrams: [Data]?, endpoints: [NWEndpoint]?, readError) in
Attach the full mode crash log:
full mode crash - https://developer.apple.com/forums/content/attachment/1cb207e3-6fb0-4df4-9484-bcae07ae33b5
Some progress:
After updated the code like below, that web page show up.
Only thing remains is: the browser keeps loading this web page: waiting for ....
Seen from the traces, new flowId keeps generated.
connection.readMinimumLength(1, maximumLength: 65535, completionHandler: { [unowned self] (data, error) in
guard error == nil else {
FZLog(.error, "read from TCP connection error: \(error.debugDescription) \(connection.remoteAddress.debugDescription)")
// Close down only when read complete
if let error = error {
if error._code == ECANCELED {
FZLog(.verbose, "TCP connection cancelled: \(connection.debugDescription)")
tcpflow.closeWriteWithError(error)
tcpflow.closeReadWithError(error)
connection.cancel()
}
}
return
}
...
Following your suggestions, tested with below code capturing all port traffics:
Two things to mention: It is better than before: network keeps alive for a couple of hours before it dies.
Attached the log when it crashed.
2. still seen udp 53 traffic.
for seg in 1...254 {
if seg != 127 {
hosts = [("\(seg).0.0.0", "0")]
for host in hosts {
let ep = NWHostEndpoint(hostname: host.0, port: host.1)
var rule = NENetworkRule.init(remoteNetwork: ep, remotePrefix: 8, localNetwork: nil, localPrefix: 0, protocol: .TCP, direction: .outbound)
rules.append(rule)
hosts = [("\(seg).0.0.0", "0...52"),
("\(seg).0.0.0", "54...65535"),]
rule = NENetworkRule.init(remoteNetwork: ep, remotePrefix: 8, localNetwork: nil, localPrefix: 0, protocol: .UDP, direction: .outbound)
rules.append(rule)
}
}
}
let settings = NETransparentProxyNetworkSettings.init(tunnelRemoteAddress: "127.0.0.1")
settings.includedNetworkRules = rules
settings.excludedNetworkRules = nil
[full mode crash](https://developer.apple.com/forums/content/attachment/88570304-6dc8-4bcb-a54e-5df782fdebca){: .log-attachment}
Also, I tried below setup, but still see udp port 53 traffic captured.
Thanks in advance for any suggestion.
var hosts = [("", "")]
var rules: [NENetworkRule] = []
for seg in 1...254 {
if seg != 127 {
hosts = [("\(seg).0.0.0", "0...52"),
("\(seg).0.0.0", "54...65535"),]
rule = NENetworkRule.init(remoteNetwork: ep, remotePrefix: 8, localNetwork: nil, localPrefix: 0, protocol: .UDP, direction: .outbound)
rules.append(rule)
}
}
}
let settings = NETransparentProxyNetworkSettings.init(tunnelRemoteAddress: "127.0.0.1")
settings.includedNetworkRules = rules
settings.excludedNetworkRules = nil
Are you using Catalina or Big Sur for this Network Extension?
I am using BigSur 11.2.3
So if you do not want port 53 UDP traffic this leaves you with a few options; first you could try to filter only on a specific set of addresses or ranges that are not the default route (0.0.0.0). For example, here is one that I used for all 17.0.0.0 traffic on port 443:
settings.includedNetworkRules = [
NENetworkRule.init(remoteNetwork: NWHostEndpoint(hostname: "17.0.0.0", port: "443"),
remotePrefix: 8,
localNetwork: nil,
localPrefix: 0,
protocol: .any,
direction: .outbound)
]
Next, you could proxy this traffic and handle it just like your regular UDP flows.
Thanks for suggesting touching the default route. That might be the way to go.
Can you say something more about usage of remotePrefix?
What I understand is value 8 means taking care of the first eight bits of the ip address which is 17 in this example. Any other examples showing different cases?
1) What are you getting for the remoteEndpoint for the NEAppProxyTCPFlow in handleNewFlow?
🤪FZ$--hostName: dns-block-page-sm.familyzone.com remoteEp: 13.210.37.51:80 appId: com.google.Chrome.helper fzmacappproxy 09:43:24.523718+1000
2) After you open the remote side of the connection and open the local flow, where is this happening in your flow copying process?
We use NWTCPConnection instead, but the logic is the same.
private func readFromTcpConnection(tcpflow: NEAppProxyTCPFlow) - Void {
...
if !self.waitForTCPConnectionToBeReady(connection) {
flowClose(tcpFlow: tcpflow, error: nil, connStruct: connStruct)
return
}
connection.readMinimumLength(1, maximumLength: 65535, completionHandler: { [unowned self] (data, error) in
guard error == nil else {
FZLog(.error, "read from TCP connection error: \(error.debugDescription) \(connection.remoteAddress.debugDescription)")
tcpflow.closeWriteWithError(error)
tcpflow.closeReadWithError(error)
connection.cancel()
return
}
guard let readData = data else {
FZLog(.error, "read from TCP connection error: \(connection.remoteAddress.debugDescription)")
tcpflow.closeWriteWithError(error)
tcpflow.closeReadWithError(error)
connection.cancel()
}
tcpflow.write(readData) { [unowned self] error in
guard error == nil else {
FZLog(.error, "write to TCP flow error: \(error.debugDescription)")
tcpflow.closeWriteWithError(error)
tcpflow.closeReadWithError(error)
connection.cancel()
return
}
FZLog(.verbose, "write \(readData.count) bytes to TCP flow from \(connection.remoteAddress.debugDescription)")
self.readFromTcpConnection(tcpflow: tcpflow)
}
})
}
3) Does the same thing happen when you use a hostname?
No difference when I use the hostname:
http://dns-block-page-sm.familyzone.com/
Ok. Will raise a new one for it (handleNewFlow() sometimes not invoked). Seems need to pay then.
Some more traces with that filter rules:
🤪FZ$--hostName: www.apple.com remoteEp: 23.202.173.153:443 appId: com.google.Chrome.helper fzmacappproxy 18:22:57.007704+1000
🤪FZ$--hostName: supportmetrics.apple.com remoteEp: 17.137.160.100:443 appId: com.google.Chrome.helper fzmacappproxy 18:23:47.128264+1000
🤪FZ$--hostName: developer.apple.com remoteEp: 17.253.67.203:443 appId: com.google.Chrome.helper fzmacappproxy 18:23:47.485234+1000