socket return -1 (EPERM, Operation not permitted) on macOS

I am build a VPN app for macOS by useing Packet Tunnel Provider. I try to use UDP socket to send data to server in the Extension, but the socket "sendto" return -1 with errno set to EPERM(Operation not permitted). However I try the same code in iOS, it is working fine. Below is the sample code.


#include <sys/socket.h>

#include <netinet/in.h>

#include <arpa/inet.h>

#include <netdb.h>


int sock = socket(AF_INET, SOCK_DGRAM, 0);

assert(sock >= 0);

int success = fcntl(sock, F_SETFL, O_NONBLOCK);

assert(success == 0);

struct sockaddr_in addr = {

.sin_len = sizeof(struct sockaddr),

.sin_family = AF_INET,

.sin_port = htons(1235)

};

success = bind(sock, (const struct sockaddr *) &addr, sizeof(addr));

assert(success == 0);

struct sockaddr_in addrsock = {

.sin_len = sizeof(struct sockaddr),

.sin_family = AF_INET,

.sin_port = htons(1235),

.sin_addr.s_addr = inet_addr("119.xx.***.102")

};

char *my_messsage = "this is a test message";

ssize_t bytesSent = sendto(

sock,

my_messsage,

strlen(my_messsage),

0,

(const struct sockaddr *) &addrsock,

sizeof(addr)

);



Thanks!

Replies

If you use an NWUDPSession, does that work?

Not that NWUDPSession is required in this context, I’m just curious if it behaves differently.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi Eskimo,

I tried code below by using NWUDPSession, there is also error(NWUDPSessionStateFailed) on macOS. But no error if run same code on iOS.


//create the UDP sesstion with server addr and port, and observe state change

NWHostEndpoint* endpoint = [NWHostEndpoint endpointWithHostname:@"119.xx.***.102" port: @"1235"];

_udpSession = [self createUDPSessionToEndpoint: endpoint fromEndpoint: nil];

[_udpSession addObserver:self forKeyPath:@"state" options:NSKeyValueObservingOptionInitial context:&_udpSession];


- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void *)context{

if ([keyPath isEqualToString:@"state"]) {

NSLog(@"state: %ld", self.udpSession.state);

switch (self.udpSession.state) {

case NWUDPSessionStateFailed:

//hit here

break;

default:

break;

}

}

}

However I want to use BSD socket to build VPN app so that make it platform independent.

However I want to use BSD socket to build VPN app so that make it platform independent.

Right. I suggested NWUDPSession purely for testing purposes.

Anyway, this sounds like a bug to me and I encourage you to file it as such. Please post your bug number, just for the record.

If you’d like someone (and by “someone” I mean “me” :-) to see if there’s a way around this, you should open a DTS tech support incident.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thanks!

Can you please help me have a look at this ticket?

I have filed one ticket for this, bug number is 30580487.

Hi Eskimo,


Do you have any update for this bug? Any suggestion to work around this?

Do you have any update for this bug?

I had a look at your bug (r. 30580487) and there’s nothing of note to share. If you want me to look at this in more detail, you’ll need to open a DTS tech support incident. There’s a limit to how much time I can spend investigating issues in the context of DevForums, and most Network Extension provider questions are beyond that limit )-:

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Hi eskimo

I had encountered problem same as xwu's problem. I did many tests:

1. Create NWUDPSession for local UDP server. example:

NWHostEndpoint* endpoint = [NWHostEndpoint endpointWithHostname:@"192.168.0.2" port: @"1235"];
_udpSession = [self createUDPSessionToEndpoint: endpoint fromEndpoint: nil];

I got NWUDPSessionStateFailed error.

2. Create BSD UDP socket, I got "Operation not permitted"

3. Same codes run on iOS all OK. But on macOS 10.12.4, always failed.


Any suggestion to work around this? Thanks.

This turned out to be a problem with the App Sandbox. As documented in the App Sandbox Design Guid and Entitlement Key Reference, an app (or app extension) must use the following sandbox entitlements to access the network on macOS:

  • com.apple.security.network.client
    for outgoing TCP connections
  • com.apple.security.network.server
    for incoming TCP connections

Network Extension providers are app extensions and must follow the same rules.

Now, it turns out that for UDP the stronger, server entitlement is required, because the system can’t tell that you’re using UDP solely for outgoing ‘connections’. So, set both of these entitlements in your provider and you should be all set.

Share and Enjoy

Quinn “The Eskimo!”
Apple Developer Relations, Developer Technical Support, Core OS/Hardware

let myEmail = "eskimo" + "1" + "@apple.com"

Thank you so much. My app is OK now.