Hello everyone,
I’m currently working on a Swift project using the Network framework to create a multicast-based communication system. Specifically, I’m implementing both a multicast receiver and a sender that join the same multicast group for communication. However, I’ve run into some challenges with the connection management, replying to multicast messages, and handling state updates for both connections and connection groups.
Below is a breakdown of my setup and the specific issues I’ve encountered.
I have two main parts in the implementation: the multicast receiver and the multicast sender. The goal is for the receiver to join the multicast group, receive messages from the sender, and send a reply back to the sender using a direct connection.
Multicast Receiver Code:
import Network
import Foundation
func setupMulticastGroup() -> NWConnectionGroup? {
let multicastEndpoint1 = NWEndpoint.hostPort(host: NWEndpoint.Host("224.0.0.1"), port: NWEndpoint.Port(rawValue: 45000)!)
let multicastParameters = NWParameters.udp
multicastParameters.multipathServiceType = .aggregate
do {
let multicastGroup = try NWMulticastGroup(for: [multicastEndpoint1], from: nil, disableUnicast: false)
let multicastConnections = NWConnectionGroup(with: multicastGroup, using: multicastParameters)
multicastConnections.stateUpdateHandler = InternalConnectionStateUpdateHandler
multicastConnections.setReceiveHandler(maximumMessageSize: 16384, rejectOversizedMessages: false, handler: receiveHandler)
multicastConnections.newConnectionHandler = newConnectionHandler
multicastConnections.start(queue: .global())
return multicastConnections
} catch {
return nil
}
}
func receiveHandler(message: NWConnectionGroup.Message, content: Data?, isComplete: Bool) {
print("Received message from \(String(describing: message.remoteEndpoint))")
if let content = content, let messageString = String(data: content, encoding: .utf8) {
print("Received Message: \(messageString)")
}
let remoteEndpoint = message.remoteEndpoint
message.reply(content: "Multicast group on 144 machine ACK from recv handler".data(using: .utf8))
if let connection = multicastConnections?.extract(connectionTo: remoteEndpoint) {
connection.stateUpdateHandler = InternalConnectionRecvStateUpdateHandler
connection.start(queue: .global())
connection.send(content: "Multicast group on 144 machine ACK from recv handler".data(using: .utf8), completion: NWConnection.SendCompletion.contentProcessed({ error in
print("Error code: \(error?.errorCode ?? 0)")
print("Ack sent to \(connection.endpoint)")
}))
}
}
func newConnectionHandler(connection: NWConnection) {
connection.start(queue: .global())
connection.send(content: "Multicast group on 144 machine ACK".data(using: .utf8), completion: NWConnection.SendCompletion.contentProcessed({ error in
print("Error code: \(error?.errorCode ?? 0)")
print("Ack sent to \(connection.endpoint)")
}))
}
func InternalConnectionRecvStateUpdateHandler(_ pState: NWConnection.State) {
switch pState {
case .setup:
NSLog("The connection has been initialized but not started")
case .preparing:
NSLog("The connection is preparing")
case .waiting(let error):
NSLog("The connection is waiting for a network path change. Error: \(error)")
case .ready:
NSLog("The connection is established and ready to send and receive data.")
case .failed(let error):
NSLog("The connection has disconnected or encountered an error. Error: \(error)")
case .cancelled:
NSLog("The connection has been canceled.")
default:
NSLog("Unknown NWConnection.State.")
}
}
func InternalConnectionStateUpdateHandler(_ pState: NWConnectionGroup.State) {
switch pState {
case .setup:
NSLog("The connection has been initialized but not started")
case .waiting(let error):
NSLog("The connection is waiting for a network path change. Error: \(error)")
case .ready:
NSLog("The connection is established and ready to send and receive data.")
case .failed(let error):
NSLog("The connection has disconnected or encountered an error. Error: \(error)")
case .cancelled:
NSLog("The connection has been canceled.")
default:
NSLog("Unknown NWConnection.State.")
}
}
let multicastConnections = setupMulticastGroup()
RunLoop.main.run()
Multicast Sender Code:
import Foundation
import Network
func setupConnection() -> NWConnection {
let params = NWParameters.udp
params.allowLocalEndpointReuse = true
return NWConnection(to: NWEndpoint.hostPort(host: NWEndpoint.Host("224.0.0.1"), port: NWEndpoint.Port(rawValue: 45000)!), using: params)
}
func sendData(using connection: NWConnection, data: Data) {
connection.send(content: data, completion: .contentProcessed { nwError in
if let error = nwError {
print("Failed to send message with error: \(error)")
} else {
print("Message sent successfully")
}
})
}
func setupReceiveHandler(for connection: NWConnection) {
connection.receive(minimumIncompleteLength: 1, maximumLength: 65000) { content, contentContext, isComplete, error in
print("Received data:")
print(content as Any)
print(contentContext as Any)
print(error as Any)
setupReceiveHandler(for: connection)
}
}
let connectionSender = setupConnection()
connectionSender.stateUpdateHandler = internalConnectionStateUpdateHandler
connectionSender.start(queue: .global())
let sendingData = "Hello, this is a multicast message from the process on mac machine 144".data(using: .utf8)!
sendData(using: connectionSender, data: sendingData)
setupReceiveHandler(for: connectionSender)
RunLoop.main.run()
Issues Encountered:
Error Code 0 Even When Connection Refused:
On the receiver side, I encountered this log:
nw_socket_get_input_frames [C1.1.1:1] recvmsg(fd 8, 9216 bytes) [61: Connection refused]
Error code: 0
Ack sent to 10.20.16.144:62707
Questions:
how do I reply to the message if above usage pattern is wrong?
how do I get a NWConnection from the received message to create a separate connection for communication with the sender.
Any insights or suggestions on resolving these issues or improving my multicast communication setup would be greatly appreciated.
Thanks :)
Networking
RSS for tagExplore the networking protocols and technologies used by the device to connect to Wi-Fi networks, Bluetooth devices, and cellular data services.
Post
Replies
Boosts
Views
Activity
Hi Everyone,
Is there a framework or pattern to allow peer to peer communication between multiple iOS application?
The use case would be as follow:
An organizer creates a session with multiple users.
The users receive an invitation (initially via email or sms), they install the app, upon accepting the invitation, they join a session.
The session then allow peer to peer communication between users, not necessarily in the form of text messages, but more on information and synchronization between states of models between the members.
Is there a framework for such a communication, or are we forced to go through a server to relay messages?
I found the Multipeer communication Framework but it is for the discovery of devices, not for communication between applications.
Thanks a lot.
I am working on developing a Mac app (WireGuard Apple VPN) that will be distributed outside the App Store.
I have added the network extension which is included in the system extension with packet tunneling capability.
I have created a build following these steps here: https://developer.apple.com/forums/thread/737894
as per your suggestions in my accepted post: https://developer.apple.com/forums/thread/761251
It works fine in this case when the machine has SIP disabled and systemextensionsctl developer enabled.
As soon as I have made changes on the machine to disable systemextensionsctl developer and enable SIP, it loads the system extension and also asks for network extension permission. But it does not connect to the VPN.
I have copied the app to the "/Applications" directory before opening it.
This issue is specific to macOS 15.1. It works fine for macOS 14.* and 13.*. Speaking of macOS 15.0, it didn't work in both cases with SIP enabled or disabled. So, it seems that it must be a bug in macOS 15.0 and it seems that this bug was partially fixed in macOS 15.1. Is that right?
I am currently planning to distribute the app to testers for final testing before rolling it out to a wider audience.
Am I missing something? Thanks in advance.
In the past, I used to ping my iPhone‘s local IP address via UDP. If local network permissions were not enabled, it would return an error. If they were enabled, it would return success, which I used to determine whether my app had local network permissions enabled. Now, with iOS 18, it seems to not work anymore. Regardless of whether local network permissions are enabled, pinging the iPhone‘s local IP address always returns success. Is there any other good method to check this permission status?
Case-ID: 9934335
When I try to use socket to connect to an ipv6 address created by PacketTunnelProvider in my iOS device, an error occurs. Here is the code to create socket server and client:
#include <stdio.h>
#include <string.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <unistd.h>
int dx_create_ipv6_server(const char *ipv6_address, int port) {
int server_fd;
struct sockaddr_in6 server_addr;
server_fd = socket(AF_INET6, SOCK_STREAM, 0);
if (server_fd == -1) {
perror("socket() failed");
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(port);
if (inet_pton(AF_INET6, ipv6_address, &server_addr.sin6_addr) <= 0) {
perror("inet_pton() failed");
close(server_fd);
return -1;
}
if (bind(server_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("bind() failed");
close(server_fd);
return -1;
}
if (listen(server_fd, 5) == -1) {
perror("listen() failed");
close(server_fd);
return -1;
}
printf("Server is listening on [%s]:%d\n", ipv6_address, port);
return server_fd;
}
int dx_accept_client_connection(int server_fd) {
int client_fd;
struct sockaddr_in6 client_addr;
socklen_t client_addr_len = sizeof(client_addr);
client_fd = accept(server_fd, (struct sockaddr *)&client_addr, &client_addr_len);
if (client_fd == -1) {
perror("accept() failed");
return -1;
}
char client_ip[INET6_ADDRSTRLEN];
inet_ntop(AF_INET6, &client_addr.sin6_addr, client_ip, sizeof(client_ip));
printf("Client connected: [%s]\n", client_ip);
return client_fd;
}
int dx_connect_to_ipv6_server(const char *ipv6_address, int port) {
int client_fd;
struct sockaddr_in6 server_addr;
client_fd = socket(AF_INET6, SOCK_STREAM, 0);
if (client_fd == -1) {
perror("socket() failed");
return -1;
}
memset(&server_addr, 0, sizeof(server_addr));
server_addr.sin6_family = AF_INET6;
server_addr.sin6_port = htons(port);
if (inet_pton(AF_INET6, ipv6_address, &server_addr.sin6_addr) <= 0) {
perror("inet_pton() failed");
close(client_fd);
return -1;
}
if (connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr)) == -1) {
perror("connect() failed");
close(client_fd);
return -1;
}
printf("Connected to server [%s]:%d\n", ipv6_address, port);
close(client_fd);
return 0;
}
@implementation SocketTest
+ (void)startSever:(NSString *)addr port:(int)port {
[[NSOperationQueue new] addOperationWithBlock:^{
int server_fd = dx_create_ipv6_server(addr.UTF8String, port);
if (server_fd == -1) {
return;
}
int client_fd = dx_accept_client_connection(server_fd);
if (client_fd == -1) {
close(server_fd);
return;
}
close(client_fd);
close(server_fd);
}];
}
+ (void)clientConnect:(NSString *)addr port:(int)port{
[[NSOperationQueue new] addOperationWithBlock:^{
dx_connect_to_ipv6_server(addr.UTF8String, port);
}];
}
@end
PacketTunnelProvider code:
override func startTunnel(options: [String : NSObject]?, completionHandler: @escaping (Error?) -> Void) {
let settings = NEPacketTunnelNetworkSettings(tunnelRemoteAddress: "fd84:306d:fc4e::1")
let ipv6 = NEIPv6Settings(addresses: ["fd84:306d:fc4e::1"], networkPrefixLengths: 64)
settings.ipv6Settings = ipv6
setTunnelNetworkSettings(settings) { error in
if error == nil {
self.readPackets()
}
completionHandler(error)
}
}
private func readPackets() {
// do nothing
packetFlow.readPackets { [self] packets, protocols in
self.packetFlow.writePackets(packets, withProtocols: protocols)
self.readPackets()
}
}
At main target, in viewcontroller's viewDidAppear, after starting the VPN, executed following code:
[SocketTest startSever:@"fd84:306d:fc4e::1" port:12345];
sleep(3);
[SocketTest clientConnect:@"fd84:306d:fc4e::1" port:12345];
The startSever is executed correctly, but when executing:
connect(client_fd, (struct sockaddr *)&server_addr, sizeof(server_addr))
in clientConnect, the code is blocked until it times out and returns -1.
Even if I use GCDAsyncSocket or BlueSocket, I get the same error.
The strange thing is that if I use the ipv4 address in PacketTunnelProvider, and change the above code to the ipv4 version and connect to ipv4 address, or use GCDAsyncSocket to perform the corresponding operation, it can be executed correctly.
I tried to search Google for problems with ios-related ipv6 addresses, but I still couldn't find a solution. Is this a bug in the ios system or is there something wrong with my code? I hope to get your help!
Hello,
I have a company laptop thats connected to the internet without a VPN. I need to be able to resolve my company's sub domains using a specific dns server, and have all other domains resolved by the system wide name server.
In windows, this is trivial to do. In an admin powershell I run
"Add-DnsClientNrptRule -Namespace ".foo.mycompany.com" -Nameserver "127.0.0.1"
and resolution requests for *.foo.mycompany.com is sent to a name server running on the localhost. All other dns resolution requests are handled by the system configured resolver.
MacOS does have the /etc/resolver/ solution for this, but my understanding from these forums is that this is not the recommended approach. Note - I have tried it and it works.
AFAIU, the recommended approach is to create a system Network extension using NEDNSProxyProvider, override handleNewFlow() and do what's necessary.
The issue with this solution is that it requires
handling all the dns flow
parsing of DNS datagrams to extract the host
forwarding the datagrams to the appropriate dns server
Handle responses.
Deal with flow control
Handle edge cases.
I was hoping for something much simpler than us needing to implement datagram parsing.
Could you please shed light on our options and how we could proceed ?
Hello!
I'd like to ask about the best way of getting a list of DNS servers from the system (iOS & macOS).
Why?
I am using NEPacketTunnelProvider to implement a VPN app. When a device joins a network with a Captive Portal and the VPN is on, the VPN should redirect DNS queries to the DNS servers that were received from the network's DHCP server. So that my VPN is able to correctly reroute the traffic which is not blocked by the network's gateway and the Captive Portal landing page is served.
When I don't do anything, the traffic goes to the tunnel and the tunnel's encrypted traffic is then dropped by the gateway serving the Captive Portal.
When I temporarily turn off the VPN, opt out of all the traffic or pass the traffic to the system resolver, the traffic gets affected by other network settings (like DNSSettings) which leads to the same situation - the user not being able to authenticate with the Captive Portal.
So far, I have tried multiple ways, including res_9_getservers but unsuccessfully. As a part of my investigation, I have found out that the /etc/resolv.conf file is not populated with DNS servers until the Captive Portal is acknowledged by the user which makes getaddrinfo unusable to achieve my goal. But I am not sure if that's a bug or intended behavior.
Thank you for your help!
Hi,
I developed a system extension that uses the content filter providers of the network extension. When I am using a VPN, I turn on the network extension and the VPN is disconnected. Can this problem be avoided? How to prevent VPN disconnection
Hi, I would like to know if it is safe to call the uploadTask from URLSession from the main thread ?
We've a user who is reporting repeated crashes at startup, here is the stack we see:
Exception Type: EXC_CRASH (SIGKILL)
Exception Codes: 0x0000000000000000, 0x0000000000000000
Termination Reason: FRONTBOARD 2343432205
<RBSTerminateContext| domain:10 code:0x8BADF00D explanation:scene-update watchdog transgression: app<com.appspot.myApp(E7590BB1-722C-491D-9199-F867DE4B880A)>:2212 exhausted real (wall clock) time allowance of 10.00 seconds
ProcessVisibility: Background
ProcessState: Running
WatchdogEvent: scene-update
WatchdogVisibility: Background
WatchdogCPUStatistics: (
"Elapsed total CPU time (seconds): 21.260 (user 10.230, system 11.030), 35% CPU",
"Elapsed application CPU time (seconds): 0.006, 0% CPU"
) reportType:CrashLog maxTerminationResistance:Interactive>
Triggered by Thread: 0
Thread 0 name: Dispatch queue: com.apple.main-thread
Thread 0 Crashed:
0 libsystem_kernel.dylib 0x1def7a688 mach_msg2_trap + 8
1 libsystem_kernel.dylib 0x1def7dd98 mach_msg2_internal + 80
2 libsystem_kernel.dylib 0x1def7dcb0 mach_msg_overwrite + 424
3 libsystem_kernel.dylib 0x1def7dafc mach_msg + 24
4 libdispatch.dylib 0x1968d8f14 _dispatch_mach_send_and_wait_for_reply + 544
5 libdispatch.dylib 0x1968d92b4 dispatch_mach_send_with_result_and_wait_for_reply + 60
6 libxpc.dylib 0x21714a930 xpc_connection_send_message_with_reply_sync + 256
7 Foundation 0x18d80a3ac __NSXPCCONNECTION_IS_WAITING_FOR_A_SYNCHRONOUS_REPLY__ + 16
8 Foundation 0x18d806b14 -[NSXPCConnection _sendInvocation:orArguments:count:methodSignature:selector:withProxy:] + 2160
9 CoreFoundation 0x18eb868dc ___forwarding___ + 1004
10 CoreFoundation 0x18eb86430 _CF_forwarding_prep_0 + 96
11 CFNetwork 0x1900c71e0 -[__NSURLBackgroundSession setupBackgroundSession] + 800
12 CFNetwork 0x1900b3e80 -[__NSURLBackgroundSession initWithConfiguration:delegate:delegateQueue:delegateDispatchQueue:] + 552
13 CFNetwork 0x1900b4784 +[NSURLSession _sessionWithConfiguration:delegate:delegateQueue:delegateDispatchQueue:] + 1496
14 MyApp 0x1054210b4 CombineBgXferRepository.session.getter (in MyApp) (CombineBgXferRepository.swift:62) + 7966900
15 MyApp 0x105422fa4 CombineBgXferRepository.startUploadTask(fileURL:request:) (in MyApp) (CombineBgXferRepository.swift:310) + 7974820
If it is ok to call this uploadTask from the main thread, does this crash indicate a problem with the operating system? Are there scenarios where the background upload service does not respond to requests?
In my iOS app I am currently using Bonjour (via Network.framework) to have two local devices find each other and then establish a single bidirectional QUIC connection between them.
I am now trying to transition from a single QUIC connection to a QUIC multiplex group (NWMultiplexGroup) with multiple QUIC streams sharing a single tunnel.
However I am hitting an error when trying to establish the NWConnectionGroup tunnel to the endpoint discovered via Bonjour.
I am using the same "_aircam._udp" Bonjour service name I used before (for the single connection) and am getting the following error:
nw_group_descriptor_allows_endpoint Endpoint iPhone15Pro._aircam._udp.local. is of invalid type for multiplex group
Does NWConnectionGroup not support connecting to Bonjour endpoints? Or do I need a different service name string? Or is there something else I could be doing wrong?
If connecting to Bonjour endpoints isn't supported, I assume I'll have to work around this by first resolving the discovered endpoint using Quinn's code from this thread?
And I guess I would then have to have two NWListeners, one just for Bonjour discovery and one listening on a port of my choice for the multiplex tunnel connection?
I'm working on a network extension that provides a VPN tunnel. The logic behind the tunnel provider requires me to connect the backend to pull recent configuration and then configure the routing. It works in general but fails with some circumstances. I have 100% reproducible fails if I run OpenVPN tunnel in parallel. When it happens it looks like the network extension cannot connect the backend (any internet resource actually). Requests fail by timeout.
To troubleshoot this situations I've added NWPathMonitor at my NEPacketTunnelProvider subclass:
pathMonitor?.pathUpdateHandler = { path in
logger.info("Path update: \(path)")
logger.info(" : \(path.availableInterfaces)")
}
On successful scenarios I observed logs:
14:53:19:829 Starting VPN tunnel...
14:53:19:895 Path update: satisfied (Path is satisfied), interface: en0[802.11], scoped, ipv4, ipv6, dns, uses wifi
14:53:19:899 : [en0]
14:53:22:237 Path update: satisfied (Path is satisfied), interface: en0[802.11], scoped, ipv4, ipv6, dns, uses wifi
14:53:22:253 : [en0, utun12]
14:53:22:325 VPN tunnel is started.
But if I start another tunnel first using OpenVPN (it's our corporate VPN) I observe failures with such log messages:
14:54:26:113 Starting VPN tunnel...
14:54:26:140 Path update: satisfied (Path is satisfied), interface: en0[802.11], scoped, ipv4, ipv6, dns, uses wifi
14:54:26:141 : [en0]
14:55:28:259 Failed to start VPN tunnel.
utun12 that was used by the extension in case of success is now occupied by the OpenVPN tunnel. The system creates utun13 for me but it feels like its misconfigured:
> ifconfig
(omitted most of the output)
utun12: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
inet 172.28.11.236 --> 172.28.10.1 netmask 0xfffffe00
nd6 options=201<PERFORMNUD,DAD>
utun13: flags=8051<UP,POINTOPOINT,RUNNING,MULTICAST> mtu 1500
options=6460<TSO4,TSO6,CHANNEL_IO,PARTIAL_CSUM,ZEROINVERT_CSUM>
Is it a system bug and what else can I do to diagnose the root cause of these failures?
I have a need to do a coverage test for the networkextension function code implemented by the system extension, but I don't know how to implement this method.
For example, how do you use gtest or how do you use xctest to achieve these capabilities?
If you know, please let me know. Thanks
Hello Apple Developer Community,
I am currently working on a macOS project where my primary goal is to intercept IP packets, modify them (specifically the TCP payload), and then forward them. My intended use case involves selectively intercepting outgoing packets based on their destination IP, altering their content, and sending them on their way to the original destination.
What I’ve Tried:
NEAppProxyProvider:
• I explored using App Proxy Provider to handle new TCP and UDP flows.
• While it allowed me to read the data, handling direct packet modification and forwarding without creating a new connection or proxy setup proved challenging, especially for maintaining TCP state and handling TLS traffic.
System Extension with NEFilterPacketProvider:
• I considered NEFilterPacketProvider for intercepting and modifying network packets.
• However, the documentation implies that packet filtering only supports allow/block actions, not modification and reinjection of packets back into the system.
I am planning to try NEPacketTunnelProvider: But the documentation states that this is not the right use case. Packets are expected to go into the tunnel. Since I don't have any requirement to create and maintain a tunnel, this doesn't look like an option for me.
Transparent proxy setups like NETransparentProxyProvider do not appear to offer direct packet modification capabilities without involving a user-space proxy approach.
Implementing packet-level interception outside of the Network Extension framework (e.g., Network Kernel Extension) seems unsupported in newer macOS versions (Sequoia and later).
My Questions:
Is there a recommended approach or combination of Network Extension capabilities that would allow intercepting and modifying IP packets directly?
Can NEFilterPacketProvider or any other extension be utilized in a way to modify and reinject packets back into the system?
Are there any examples or sample projects that achieve similar functionality, possibly using a blend of Network Extension and lower-level networking frameworks?
I appreciate any insights or pointers to documentation or examples that could help achieve this.
Thanks and Regards.
Prasanna.
Starting on macOS Sequoia, flows originated in Firefox have an empty sourceAppAuditToken. Other apps contain a valid token.
Background: in order to fetch process info for a certain NEFilterFlow, my content filter extension uses sourceAppAuditToken, audit_token_to_pid() and proc_* (as recommended in #126820). When that fails, we use SecCodeCopyGuestWithAttributes, recommended in some other thread as a better alternative. Both approaches break when the sourceAppAuditToken is empty since they need the pid.
Debugging:
My logging shows audit token is empty for Firefox
Typical logs from com.apple.networkextension also indicate it fails to fetch the same info I'm looking for:
com.apple.networkextension debug 11:22:07.024588-0300 Fetching appInfo from cache for pid: 948 uuid: 5C40B765-C6C9-3641-A822-2BC44D264361 bundle id: (null)
com.apple.networkextension debug 11:22:07.024657-0300 Calling delegate lookup handler with pid: 948, uuid: 5C40B765-C6C9-3641-A822-2BC44D264361, bundleID: (null)
com.apple.networkextension debug 11:22:07.025856-0300 Could not look up appInfo for pid: 948 bundle id: (null) uuid: 5C40B765-C6C9-3641-A822-2BC44D264361
com.apple.networkextension error 11:22:07.025897-0300 Could not find app info, return the original flow without filling in app info
Handling new flow:
identifier = D89B5B5D-793C-4940-D992-4E90F2AD1900
procPID = 953
eprocPID = 948
direction = outbound
inBytes = 0
outBytes = 0
signature = {length = 32, bytes = 0x4afeafde b484aa0c c5cb8698 0567343d ... 7cdee33e 135666dd }
socketID = 19adf2904e92d9
localEndpoint = 0.0.0.0:0
remoteEndpoint = 17.33.202.170:443
protocol = 6
family = 2
type = 1
procUUID = 0C68E603-967E-3643-B225-378BD2A655F7
eprocUUID = 5C40B765-C6C9-3641-A822-2BC44D264361
Perhaps there's a bug when generating the audit token or could it be something with the Firefox signature?
I double-checked Firefox and it seems fine:
$ codesign --verify --verbose /Applications/Firefox.app
/Applications/Firefox.app: valid on disk
/Applications/Firefox.app: satisfies its Designated Requirement
Not sure if relevant, but codesign with -dv showed different flags in CodeDirectory when compared to chrome:
codesign -dv /Applications/Firefox.app
...
CodeDirectory v=20500 size=863 flags=0x10000(runtime) hashes=18+5
...
Versus chrome
CodeDirectory v=20500 size=1821 flags=0x12a00(kill,restrict,library-validation,runtime) hashes=46+7 location=embedded
ISSUE
Upgrading a macOS Ventura host to Sequoia results in the attached three issues visible in either of the two screen shot:
Whether or not "Block all incoming connections" is enabled, a small subset of connections are hard-wired to "Allow incoming connections";
It is not possible to remove the hard-wired "Allow incoming connections" (e.g., selecting the row, the "-" button at bottom left is not available"; and
After the upgrade to Sequoia, SidecarRelay was set to "Block incoming connections".
QUESTIONs
a) What terminal level commands should be used to remove the hard-wired "Allow incoming connections"?
b) What other integrity checks should I run on the firewall configuration to see if other aspects of its operations are now botched?
FB15074003 tracks the issues noted above.
Hello ,
I have obtained three strings from the server: ca (the root certificate), cert (the client certificate), and privateKey (the private key) for authentication between the iOS client and server. I have successfully used ca for server authentication.
However, I am having trouble generating an NSURLCredential from the cert and privateKey strings for client authentication. Can anyone guide me on how to convert these strings into an NSURLCredential? Any example code would be greatly appreciated!
Thank you for your help!
Hello there!
We have an app that connects to an external device via Wi-Fi to send and query content from it. This external device generates a hidden AP that the phone connects against. However, sometimes the app fails to connect to the external device with the system alert "Unable to join the network...".
We have been debugging for a couple but couldn't find any clear reason of why this thing is happening. What could be the reason behind this alert appearing?
For the connection, we are using the NEHotspotConfigurationManager to connect to the AP of this external device.
The configuration for the connection is the following:
NEHotspotConfiguration(
ssid: ssid,
passphrase: password,
isWEP: false
)
configuration.hidden = true
There are some logs that we extracted that show two connections.
One happened at 20:37, which was a successful connection.
wifi_logs_success 2.log
Another connection was made at 20:38, which failed.
wifi_logs_failure.log
Inspecting the logs, one difference that I see between them is the __WiFiDeviceManagerDispatchUserForcedAssociationCallback: result %lld, which in the successful case is 0 and in the failed case is 1.
Can anyone help with this? We're very lost on why this configuration could be an issue at all.
I see that the iOS API includes the following
NEHotspotConfigurationManager
NEHotspotEAPSettings
NEHotspotHS20Settings
and
NEHotspotTTLSInnerAuthenticationMSCHAPv2
But..
I need to access the cloud server from the app to obtain the Passpoint configuration, and then set it to the user's phone.
Authentication requires EAP2 & MSCHAPv2, and of course, leaf certificates need to be loaded to the user.
I cannot find a simple code example to do this...
HELP! THKS..
Hello!
I'm developing NETransparentProxyProvider which started to work unexpectedly on macOS 15.
Seems that iCloud Private Relay is not auto-disabled anymore in favor of another filtering software, when Firewall is enabled in macOS 15. Disabling firewall immediately restores old behavior.
To reproduce this issue, you need to enable both iCloud Private Relay and Firewall.
Then, Safari will always try to use iCloud Private Relay, even if Transparent Proxy has "destinationAddress:nil" rule. Every connection from Safari will be to "mask.icloud.com" over HTTP/3. Connections inside are not visible as separate flows.
Since I have excludedRule for "icloud.com" (to not to alter Apple services), Safari traffic is just stopped to be processed.
Is new behavior is expected or some type of regression?
IMPORTANT The approach used by this code no longer works. See TN3179 Understanding local network privacy for a replacement.
Currently there is no way to explicitly trigger the local network privacy alert (r. 69157424). However, you can bring it up implicitly by sending dummy traffic to a local network address. The code below shows one way to do this. It finds all IPv4 and IPv6 addresses associated with broadcast-capable network interfaces and sends a UDP datagram to each one. This should trigger the local network privacy alert, assuming the alert hasn’t already been displayed for your app.
Oh, and if Objective-C is more your style, use this code instead.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@apple.com"
import Foundation
/// Does a best effort attempt to trigger the local network privacy alert.
///
/// It works by sending a UDP datagram to the discard service (port 9) of every
/// IP address associated with a broadcast-capable interface. This should
/// trigger the local network privacy alert, assuming the alert hasn’t already
/// been displayed for this app.
///
/// This code takes a ‘best effort’. It handles errors by ignoring them. As
/// such, there’s guarantee that it’ll actually trigger the alert.
///
/// - note: iOS devices don’t actually run the discard service. I’m using it
/// here because I need a port to send the UDP datagram to and port 9 is
/// always going to be safe (either the discard service is running, in which
/// case it will discard the datagram, or it’s not, in which case the TCP/IP
/// stack will discard it).
///
/// There should be a proper API for this (r. 69157424).
///
/// For more background on this, see [Triggering the Local Network Privacy Alert](https://developer.apple.com/forums/thread/663768).
func triggerLocalNetworkPrivacyAlert() {
let sock4 = socket(AF_INET, SOCK_DGRAM, 0)
guard sock4 >= 0 else { return }
defer { close(sock4) }
let sock6 = socket(AF_INET6, SOCK_DGRAM, 0)
guard sock6 >= 0 else { return }
defer { close(sock6) }
let addresses = addressesOfDiscardServiceOnBroadcastCapableInterfaces()
var message = [UInt8]("!".utf8)
for address in addresses {
address.withUnsafeBytes { buf in
let sa = buf.baseAddress!.assumingMemoryBound(to: sockaddr.self)
let saLen = socklen_t(buf.count)
let sock = sa.pointee.sa_family == AF_INET ? sock4 : sock6
_ = sendto(sock, &message, message.count, MSG_DONTWAIT, sa, saLen)
}
}
}
/// Returns the addresses of the discard service (port 9) on every
/// broadcast-capable interface.
///
/// Each array entry is contains either a `sockaddr_in` or `sockaddr_in6`.
private func addressesOfDiscardServiceOnBroadcastCapableInterfaces() -> [Data] {
var addrList: UnsafeMutablePointer<ifaddrs>? = nil
let err = getifaddrs(&addrList)
guard err == 0, let start = addrList else { return [] }
defer { freeifaddrs(start) }
return sequence(first: start, next: { $0.pointee.ifa_next })
.compactMap { i -> Data? in
guard
(i.pointee.ifa_flags & UInt32(bitPattern: IFF_BROADCAST)) != 0,
let sa = i.pointee.ifa_addr
else { return nil }
var result = Data(UnsafeRawBufferPointer(start: sa, count: Int(sa.pointee.sa_len)))
switch CInt(sa.pointee.sa_family) {
case AF_INET:
result.withUnsafeMutableBytes { buf in
let sin = buf.baseAddress!.assumingMemoryBound(to: sockaddr_in.self)
sin.pointee.sin_port = UInt16(9).bigEndian
}
case AF_INET6:
result.withUnsafeMutableBytes { buf in
let sin6 = buf.baseAddress!.assumingMemoryBound(to: sockaddr_in6.self)
sin6.pointee.sin6_port = UInt16(9).bigEndian
}
default:
return nil
}
return result
}
}