【问题标题】:"CFNetwork SSLHandshake failed (-9807)" with local IP in "Exception Domains"“CFNetwork SSLHandshake failed (-9807)”,本地 IP 在“异常域”中
【发布时间】:2017-01-04 06:29:26
【问题描述】:

我正在尝试在 OS X 和 iOS(8.1 版本)上使用openssl 之间的 SSL TCP 连接。 Exception Domains192.168.0.104

Swift iOS 代码:

class SSLSocketLite {

    // The input stream.
    private var inStream: NSInputStream?
    // The output stream.
    private var outStream: NSOutputStream?
    // The host to connect to.
    private var host: String
    // The port to connect on.
    private var port: Int

    init(inHost:String, inPort:Int) {
        host = inHost
        port = inPort
        NSStream.getStreamsToHostWithName(host, port: port, inputStream: &inStream, outputStream: &outStream)
    }

    func Open() {
        inStream?.open()
        outStream?.open()

        inStream?.setProperty(NSStreamSocketSecurityLevelTLSv1, forKey: NSStreamSocketSecurityLevelKey)
        outStream?.setProperty(NSStreamSocketSecurityLevelTLSv1, forKey: NSStreamSocketSecurityLevelKey)

        inStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
        outStream?.scheduleInRunLoop(.mainRunLoop(), forMode: NSDefaultRunLoopMode)
    }

    func Read() -> String! {
        var buffer = Array<UInt8>(count:1024, repeatedValue: 0)
        if inStream!.hasBytesAvailable {
            inStream!.read(&buffer, maxLength: 1024)
            let responseString = NSString(bytes: buffer, length: buffer.count, encoding: NSUTF8StringEncoding) as! String
            return responseString
        }
        return nil
    }

    func Write(msg:String) {
        let data:NSData = msg.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false)!
        outStream!.write(UnsafePointer(data.bytes), maxLength: data.length)
    }

    func Close() {
        inStream?.close()
        outStream?.close()
    }
}


class ViewController: UIViewController  {

    override func viewDidLoad() {
        super.viewDidLoad()

        let sslsock = SSLSocketLite(inHost: "192.168.0.104", inPort: 1678)

        sslsock.Open()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()
        // Dispose of any resources that can be recreated.
    }
}

在 OS X 端,我使用以下方法创建了证书和密钥:

openssl req -x509 -newkey rsa:1024 -keyout key.key -out key.crt -days 365 -nodes

并使用以下方式启动 TCP SSL 服务器:

openssl s_server -key key.key -cert key.crt -accept 1678

在那之后,我在 iOS 端得到了CFNetwork SSLHandshake failed (-9807),在 OS X 端得到了bad gethostbyaddr。我该如何解决这个问题?

UPD:

1.touch openssl-ca.cnf

2.复制粘贴到openssl-ca.cnf中。改变了一行:

commonName_default = localhost

3.openssl req -x509 -config openssl-ca.cnf -newkey rsa:4096 -sha256 -nodes -out cacert.pem -outform PEM

4.touch openssl-server.cnf

5.复制粘贴到openssl-server.cnf中。两行更改:

commonName_default = localhost

DNS.1 = localhost

6.openssl req -config openssl-server.cnf -newkey rsa:2048 -sha256 -nodes -out servercert.csr -outform PEM

7.openssl-ca.cnf新增2+1部分:

[ CA_default ]
    ...
    base_dir    = .
    certificate = $base_dir/cacert.pem  # The CA certifcate
    private_key = $base_dir/cakey.pem   # The CA private key
    new_certs_dir   = $base_dir     # Location for new certs after signing
    database    = $base_dir/index.txt   # Database index file
    serial      = $base_dir/serial.txt  # The current serial number

    unique_subject  = no            # Set to 'no' to allow creation of
                    # several certificates with same subject.

...

####################################################################
[ signing_policy ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

8.touch index.txt

9.echo '01' &gt; serial.txt

10.openssl ca -config openssl-ca.cnf -policy signing_policy -extensions signing_req -out servercert.pem -infiles servercert.csr

11.openssl x509 -in servercert.pem -inform PEM -out servercert.der -outform DER

12.iOS项目中添加servercert.der

13.let sslsock = SSLSocketLite(inHost: "localhost", inPort: 1678)

14.异常域 -> +localhost

15.openssl s_server -key serverkey.pem -cert servercert.pem -accept 1678

openssl-ca.cnf的最终版本:

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ ca ]
default_ca  = CA_default        # The default ca section

[ CA_default ]

default_days    = 1000          # how long to certify for
default_crl_days= 30            # how long before next CRL
default_md  = sha256        # use public key default MD
preserve    = no            # keep passed DN ordering

x509_extensions = ca_extensions     # The extensions to add to the cert

email_in_dn = no            # Don't concat the email in the DN
copy_extensions = copy          # Required to copy SANs from CSR to cert

base_dir    = .
certificate = $base_dir/cacert.pem  # The CA certifcate
private_key = $base_dir/cakey.pem   # The CA private key
new_certs_dir   = $base_dir     # Location for new certs after signing
database    = $base_dir/index.txt   # Database index file
serial      = $base_dir/serial.txt  # The current serial number

unique_subject  = no            # Set to 'no' to allow creation of
                # several certificates with same subject.
####################################################################
[ req ]
default_bits        = 4096
default_keyfile     = cakey.pem
distinguished_name  = ca_distinguished_name
x509_extensions     = ca_extensions
string_mask         = utf8only

####################################################################
[ ca_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = Maryland

localityName            = Locality Name (eg, city)
localityName_default        = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test CA, Limited

organizationalUnitName  = Organizational Unit (eg, division)
organizationalUnitName_default  = Server Research Department

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = localhost

emailAddress            = Email Address
emailAddress_default        = test@example.com

####################################################################
[ ca_extensions ]

subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid:always, issuer
basicConstraints = critical, CA:true
keyUsage = keyCertSign, cRLSign

####################################################################
[ signing_policy ]
countryName     = optional
stateOrProvinceName = optional
localityName        = optional
organizationName    = optional
organizationalUnitName  = optional
commonName      = supplied
emailAddress        = optional

####################################################################
[ signing_req ]
subjectKeyIdentifier=hash
authorityKeyIdentifier=keyid,issuer

basicConstraints = CA:FALSE
keyUsage = digitalSignature, keyEncipherment

openssl-server.cnf 的最终版本:

HOME            = .
RANDFILE        = $ENV::HOME/.rnd

####################################################################
[ req ]
default_bits        = 2048
default_keyfile     = serverkey.pem
distinguished_name  = server_distinguished_name
req_extensions      = server_req_extensions
string_mask         = utf8only

####################################################################
[ server_distinguished_name ]
countryName         = Country Name (2 letter code)
countryName_default     = US

stateOrProvinceName     = State or Province Name (full name)
stateOrProvinceName_default = MD

localityName            = Locality Name (eg, city)
localityName_default        = Baltimore

organizationName            = Organization Name (eg, company)
organizationName_default    = Test CA, Limited

commonName          = Common Name (e.g. server FQDN or YOUR name)
commonName_default      = localhost

emailAddress            = Email Address
emailAddress_default        = test@example.com

####################################################################
[ server_req_extensions ]

subjectKeyIdentifier        = hash
basicConstraints        = CA:FALSE
keyUsage            = digitalSignature, keyEncipherment
subjectAltName          = @alternate_names
nsComment           = "OpenSSL Generated Certificate"

####################################################################
[ alternate_names ]

DNS.1       = localhost

iOS 输出:

SwiftPlayground[917:31077] CFNetwork SSLHandshake 失败 (-9807)

OpenSSL s_server 输出(什么都没发生):

Using default temp DH parameters  
Using default temp ECDH parameters 
ACCEPT

【问题讨论】:

  • openssl req -x509 ... - 创建证书时使用的主机名是什么? Objective C 代码中使用的host, port 是什么?另请参阅How do you sign Certificate Signing Request with your Certification AuthorityHow to create a self-signed certificate with openssl?,它提供了大量有关 X.509 服务器证书的背景信息,以及各种规则的来源。
  • @jww 谢谢。我按照How do you sign Certificate Signing Request with your Certification Authority 中所说的做了一切,之后我转换了证书:openssl x509 -in servercert.pem -inform PEM -out servercert.der -outform DER,在 iOS 应用程序中添加了 servercert.der 并启动了sudo openssl s_server -key serverkey.pem -cert servercert.pem -accept 1678。但是在 iOS 端得到了SSLHandshake failed (-9807),在 OS X 服务器端没有。我做错了什么?
  • 如果 X.509 和证书和主机名都正常,那么接下来转到这个:sudo openssl s_server ... - 您使用的是 Apple 的 OpenSSL 0.9.8 吗?如果是这样,您可能必须使用 OpenSSL 1.0.1 或更高版本。 OpenSSL 1.0.2 将是一个不错的选择。
  • 如果您使用的是 OpenSSL 1.0.1 或更高版本,请注意 Apple 的 SecureTransport/ECDHE-ECDSA 错误。它在许多 iOS 和 OS X 主机上未打补丁。另请参阅 OpenSSL wiki 上的 SSL_OP_SAFARI_ECDHE_ECDSA BUG
  • @jww openssl version 输出:OpenSSL 0.9.8zg 14 July 2015。我使用自制软件安装了 openssl,所以我需要安装其他供应商的版本吗?您确定我之前评论中的所有命令都有效吗?在服务器端使用pem 版本的servercert 和在客户端使用der 可以吗?

标签: ios ssl networking tcp openssl


【解决方案1】:

我写了一个包来帮助解决这个问题,不幸的是它是 Obj-C,但我确实有资源用于创建适用于新 iOS 13 TLS 限制的证书。以下是创建 CA、中间 CA 和服务器/用户证书的教程的链接。

https://jamielinux.com/docs/openssl-certificate-authority/introduction.html

如果您完全遵循它,您将获得有效的证书,但本教程没有考虑最新的更改之一。但是,如果您使用我的配置文件,我会进行必要的小改动,以便证书可以正常工作,如果您按照教程的过程进行操作 - 在这里您可以找到这些配置文件:

https://github.com/eamonwhiter73/IOSObjCWebSockets

您必须对配置文件进行一些小的更改 - 您的基本路径以及每个文件底部的 DNS 名称。

【讨论】:

    猜你喜欢
    • 2013-11-24
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-11
    • 2015-08-23
    • 1970-01-01
    相关资源
    最近更新 更多