Local Network Access Permission

We provide software that our customers deploy on their employee work computers to secure sensitive data. We have a daemon which could connect to an on-premise web-server for certain functionality. In Mac OS 15 beta we see that there is a local network access permission dialog that comes up sometimes, and it requires a permission to be provided under the Privacy & Security section of the system preferences.

We have seen the local network access permission would pop up only when both Server and Client are residing in the same private network range (eg 172.16.x.x. in our case.)

When the same server is accessed from a Sequoia machine over a VPN from external network, the local network access permission does NOT pop up. But note in this case, the Sequoia machine has an IP in the 10.x.y.z range, whereas the server is at 172.16.x.y.

We have the following questions:

  • In our setup with Macs connecting to a web-server, what conditions can trigger the local network prompt?
  • In particular, do both the client and server need to be in the same private subnet range for the prompt to be shown?
  • Is it possible that a user at home, working on a Sequoia machine, connecting over VPN to an on-prem server, would trigger this prompt?
  • If so, we would submit this is not expected, as a VPN is not really a local network.
  • Is there an MDM way of automatically providing the permission, so that the prompt is suppressed?
  • In general, is there a programmatic way of providing this permission during installation ? if yes how can we do it.
  • How do we stop users from disabling the permission incase the user has admin rights?
Answered by DTS Engineer in 799081022
during address resolution we end up getting the LNP

If you follow the links through my QSockets code, you’ll see that it calls getaddrinfo under the covers. So that’s not the critical factor.

You’re passing in a hints value, but you’ve set that up in a very vanilla fashion so I don’t see how it’d be relevant.

At this point I’m out of ideas. Clearly this is related to the environment in which your code is running, and that’s hard for me to investigate here on the forums. My recommendation is that you file a bug about this. Make sure to include a sysdiagnose log taken shortly after you see the issue.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

I ran a test here in my office today and my daemon is able to access the Local Network. That gels with my understanding of how this is supposed to work.

The code for my daemon is pasted in below. It uses the QSocket stuff from Calling BSD Sockets from Swift. fluffy.local. is the name of a web server on my local network.

I’ve also included the daemon’s launchd property list.

On macOS 15.0b4, I installed this [1] as a launchd daemon:

```shell` % sudo cp DaemonLNP /Library/PrivilegedHelperTools/ % sudo cp com.example.apple-samplecode.DaemonLNP.plist /Library/LaunchDaemons % sudo launchctl load /Library/LaunchDaemons/com.example.apple-samplecode.DaemonLNP.plist


I then started it:

```shell
% sudo launchctl start com.example.apple-samplecode.DaemonLNP

In Console I see it access the web server without any grief.

type: default
time: 2024-07-31 17:03:42.734337 +0100
process: DaemonLNP
subsystem: com.example.apple-samplecode.DaemonLNP
category: daemon
message: will start, name: fluffy.local.

type: default
time: 2024-07-31 17:03:42.736644 +0100
process: DaemonLNP
subsystem: com.example.apple-samplecode.DaemonLNP
category: daemon
message: will connect, v4: 192.168.1.39:80

type: default
time: 2024-07-31 17:03:42.838046 +0100
process: DaemonLNP
subsystem: com.example.apple-samplecode.DaemonLNP
category: daemon
message: did received: data: 'HTTP/1.1 200 OK…'

type: default
time: 2024-07-31 17:03:42.838186 +0100
process: DaemonLNP
subsystem: com.example.apple-samplecode.DaemonLNP
category: daemon
message: did finish, EOF

I’m not sure why this is failing in your setup. My advice is that you try reproducing this with a small focused test project, like the one I’ve described here. That’ll tell us whether this is something specific to your environment, or something specific to the code of your main project.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"


import Foundation
import System
import os.log

// subsystem:com.example.apple-samplecode.DaemonLNP

let logger = Logger(subsystem: "com.example.apple-samplecode.DaemonLNP", category: "daemon")

func runThrowing(hostName: String) throws {
    let addresses = try QSockAddr.resolving(host: hostName, service: "80")
    guard let v4 = addresses.first(where: { $0.address.contains(".") }) else {
        fatalError()
    }
    let fd = try FileDescriptor.socket(AF_INET, SOCK_STREAM, 0)
    defer {
        try! fd.close()
    }
    logger.log("will connect, v4: \(v4.address, privacy: .public):\(v4.port)")
    try fd.connect(v4.address, v4.port)
    let request = """
        GET / HTTP/1.1\r
        Host: \(hostName)\r
        Connection: close\r
        \r\n
        """
    try fd.writeAll(request.utf8)
    while true {
        guard let d = try fd.read() else {
            break
        }
        if let s = String(data: d, encoding: .utf8) {
            logger.log("did received: data: '\(s, privacy: .public)'")
        } else {
            logger.log("did received: data: '\((d as NSData).debugDescription, privacy: .public)'")
        }
    }
}

func run() {
    do {
        let hostName = "fluffy.local."
        logger.log("will start, name: \(hostName, privacy: .public)")
        try runThrowing(hostName: hostName)
        logger.log("did finish, EOF")
    } catch {
        logger.log("did fail, error: \(error, privacy: .public)")
    }
}

run()

<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
	<key>Label</key>
	<string>com.example.apple-samplecode.DaemonLNP</string>
	<key>ProgramArguments</key>
	<array>
		<string>/Library/PrivilegedHelperTools/DaemonLNP</string>
	</array>
</dict>
</plist>

@DTS Engineer

We are using the int err = getaddrinfo(dest, port_str, &hints, &ai); call and during address resolution we end up getting the LNP

One more critical observation i have is

  1. LNP is not seen on machine which is upgraded from 14.x to 15.x
  2. LNP is only seen on machine where the 15.x is installed fresh i.e no prior OS on the volume on which 15.x is installed.
during address resolution we end up getting the LNP

If you follow the links through my QSockets code, you’ll see that it calls getaddrinfo under the covers. So that’s not the critical factor.

You’re passing in a hints value, but you’ve set that up in a very vanilla fashion so I don’t see how it’d be relevant.

At this point I’m out of ideas. Clearly this is related to the environment in which your code is running, and that’s hard for me to investigate here on the forums. My recommendation is that you file a bug about this. Make sure to include a sysdiagnose log taken shortly after you see the issue.

Please post your bug number, just for the record.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

@DTS Engineer Following is the feedback ticket which was created. https://feedbackassistant.apple.com/feedback/14602669

Ticket Number: FB14602669

@DTS Engineer ,

We see that in the latest beta release i.e Beta7 the daemon was able to connect to the server which is part of the same sub domain and the LNP pop was also not seen.

More history on this, On Beta 6 we have the geaddrinfo call was able to resolve the address, but was not able make any socket connection we have also seen the LNP Pop up being displayed . this got resolved in the beta7 release also we are not seeing the LNP pop up.

Can we know what all changed in beta6 and beta7 so that we can have a informed decision on what was root cause for the problem of LNP being triggered till Beta 6 and what changed from beta 6 to beta 7

Based on my reading of your bug report (FB14602669), the behaviour you’re seeing on b7 is correct; that is, the behaviour on b6 and earlier was a bug.

Share and Enjoy

Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"

Local Network Access Permission
 
 
Q