NWConnection using TLS fails

Hi. I was able to connect to a public wss using tls like this:

let port = 443

let url = URL(string: "wss://echo.websocket.org")!

connection = NWConnection(host: NWEndpoint.Host.name(url.host!, nil), port: NWEndpoint.Port(rawValue: UInt16(port))!, using: .tls)


Now im trying to connect to a wss websocket in a private network and I'm getting some errors. This is my code:

let port = 8443

let url = URL(string: "wss://ip_address:8443/gs-guide-websocket/websocket")!

connection = NWConnection(host: NWEndpoint.Host.name(url.host!, nil), port: NWEndpoint.Port(rawValue: UInt16(port))!, using: .tls)

And these are the errors:


[BoringSSL] boringssl_context_alert_callback_handler(3747) [C1.1:1][0x7fe945708390] Alert level: fatal, description: certificate unknown


[BoringSSL] boringssl_context_error_print(3699) boringssl ctx 0x600001ec9500: 140639868076392:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl_Sim/boringssl-109.202.1/ssl/handshake.cc:372:


[BoringSSL] boringssl_context_get_error_code(3519) [C1.1:1][0x7fe945708390] SSL_AD_CERTIFICATE_UNKNOWN

Client failed with error: -9808: Optional(bad certificate format)

Do I need to add special options to connect here?


Also, I saw that the wss works because I'm able to connect with SocketRocket, but I want to connect with NWConnection

Thanks.

Accepted Reply

Now im trying to connect to a wss websocket in a private network and I'm getting some errors.

The Network framework, along with all of our other APIs that use TLS, applies RFC 2818 style server trust evaluation by default. Thus, your server has to have a certificate that was issued by a certificate authority that’s trusted by the system. Is that the case here?

Share and Enjoy

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

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

Replies

Now im trying to connect to a wss websocket in a private network and I'm getting some errors.

The Network framework, along with all of our other APIs that use TLS, applies RFC 2818 style server trust evaluation by default. Thus, your server has to have a certificate that was issued by a certificate authority that’s trusted by the system. Is that the case here?

Share and Enjoy

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

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

Hi, I'm facing a new related issue.
I followed the steps to install the certificate. I'm able to install it. When I'm installing it, device shows a warning saying that the certificate will not be trusted until I enable it in Certificate Trust Settings.
After installation, when I go to Settings > General > Profiles, certificate is there, it is verified and everything looks good.
Then, when I go to Settings > General > About > Certificate Trust Settings, certificate is not in the list of certificates that I can enable full trust. If I try to connect, I see the same issue, I guess because it is not a trusted certificate yet.
I made sure that this is a Root CA and not an intermediary. So, if the certificate cannot be trusted, is it because it is blocked by Apple? Is there any workaround for this?
Thanks.

I suspect you’re suffering from a problem that I helped debug for a different developer a while back. Settings has a bug where it only shows a root certificate if the certificate has the Common Name attribute (r. 35071483). Please make sure that’s the case.

If this doesn’t fix the problem then I’ll have to take a more in-depth look. The first step would be to examine your root certificate (you can simply post a hex dump of it here).

Share and Enjoy

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

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

Can we override that behavior because I'm using the local server for UI tests and we need the socket. I tried:

sec_protocol_options_set_verify_block(options.securityProtocolOptions, { [weak self] (_, secTrust, secVerifyComplete) in 
}

But doesn't work. Connecting to socket fails with error: -9836: bad protocol version

Error -9836 is errSSLPeerProtocolVersion, which isn’t like the other errors listed here. It sounds like your WebSocket server is used an old, and hence strongly discouraged, version of TLS. You can test for this using TLSTool sample code:

% TLSTool s_client -connect fluffy.local.:443 -noverify
…
* protocol: TLS 1.2
…
^C

It also supports a -min argument where you can tweak the minimum version supported.

Once you’ve worked out the minimum version, you can apply it to your NWConnection using sec_protocol_options_set_min_tls_protocol_version.

Share and Enjoy

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