如何使用自签名证书为TLS创建iOS NWConnection?

时间:2019-01-31 01:35:50

标签: ios ssl ios12

我正在为我的MQTT客户端使用Apple的新NWConnection类。为了进行测试,我需要能够建立与具有自签名证书的本地测试代理的TLS连接。

到目前为止,我只是使用以下方法建立连接:

self.connection = NWConnection(host: NWEndpoint.Host("172.16.202.172"), port: NWEndpoint.Port(integerLiteral: 8899), using: .tls)

但是,当我连接时,控制台上会出现以下现象:

2019-01-30 17:05:51.010580-0800 myAp[2591:608137] [] nw_socket_handle_socket_event [C4.1:1] Socket SO_ERROR [54: Connection reset by peer]
2019-01-30 17:05:57.939157-0800 myApp[2591:608135] [BoringSSL] boringssl_context_alert_callback_handler(3724) [C5:1][0x103e087d0] Alert level: fatal, description: certificate unknown
2019-01-30 17:05:57.939382-0800 myApp[2591:608135] [BoringSSL] boringssl_context_error_print(3676) boringssl ctx 0x282226af0: 4360838776:error:1000007d:SSL routines:OPENSSL_internal:CERTIFICATE_VERIFY_FAILED:/BuildRoot/Library/Caches/com.apple.xbs/Sources/boringssl/boringssl-109.230.1/ssl/handshake.cc:360:
2019-01-30 17:05:57.939510-0800 myApp[2591:608135] [BoringSSL] boringssl_context_get_error_code(3560) [C5:1][0x103e087d0] SSL_AD_CERTIFICATE_UNKNOWN

过去,当我使用URLSession.shared.dataTask从nginx https服务器下载文件时,我将以下内容添加到了info.plist

<dict>
    <key>App Transport Security Settings</key>
    <dict>
        <key>NSExceptionDomains</key>
        <dict>
            <key>172.16.202.172</key>
            <dict>
                <key>NSIncludesSubdomains</key>
                <true/>
                <key>NSTemporaryExceptionsAllowsInsecureHTTPSLoads</key>
                <true/>
            </dict>
        </dict>
    </dict>
</dict>

但是在这种情况下,这似乎并没有解决问题。当我单击Apple的文档链接以使诸如NWParameter之类的东西代替股票.tls时,以为我可以调整xls设置,因此Apple文档中没有任何信息。

那么使用自签名证书为TLS通信创建NWConnection的正确方法是什么?

1 个答案:

答案 0 :(得分:0)

我不知道这是否是完整的/最好的答案,但我发现在苹果开发者论坛,这个方法:

func createTLSParameters(allowInsecure: Bool, queue: DispatchQueue) -> NWParameters {
    let options = NWProtocolTLS.Options()
    sec_protocol_options_set_verify_block(options.securityProtocolOptions, { (sec_protocol_metadata, sec_trust, sec_protocol_verify_complete) in
        let trust = sec_trust_copy_ref(sec_trust).takeRetainedValue()
        var error: CFError?
        if SecTrustEvaluateWithError(trust, &error) {
            sec_protocol_verify_complete(true)
        } else {
            if allowInsecure == true {
                sec_protocol_verify_complete(true)
            } else {
                sec_protocol_verify_complete(false)
            }
        }
    }, queue)
    return NWParameters(tls: options)
}

self.workQueue = DispatchQueue(label: "mqtt")
self.connection = NWConnection(
    host: NWEndpoint.Host("172.16.202.172"),
    port: NWEndpoint.Port(integerLiteral: 8899),
    using: createTLSParameters(allowInsecure: true, queue: self.workQueue))

使用这种技术,我根本不需要更改info.plist。

在上述论坛上有一些迹象表明,最好以某种方式将自签名证书放到iOS盒子中。