搭建nghttp2.0作为apns服务的代理的相关问题总结

来源:互联网 发布:分水岭算法 过分割 编辑:程序博客网 时间:2024/06/07 06:16
搭建nghttpx作为apns服务的代理的过程中遇到的2个主要问题:

简介:
使用nghttp2作为连接apns的代理
该代理的特点是,frontend接收HTTP1.1协议,采用明文
backend接收HTTP2.0协议,与apns服务建立tls连接

tls连接的建立:
To establish a TLS session with APNs, an Entrust Secure CA root certificate must be installed on the provider’s server. If the server is running OS X, 
this root certificate is already in the keychain.On other systems, the certificate might not be available. You can download this certificate from the Entrust SSL Certificates 
website.

tls无法通过认证:
我装的是mini centos 6.3
压根没有安装受信用的CA证书,老是抛出errorcode = 20 : unable to get local issuer certificate错误的问题
这个问题让我十分惊慌,不知所措。apple apns官网推荐到https://www.entrust.com/get-support/ssl-certificate-support/root-certificate-downloads/下载
这个页面提供了多个证书,我不知道该下载哪个版本。于是随便下载了一个证书,该证书是以.cer结尾的,我尝试在linux上面用openssl将其转换成pem格式的。使用命令如下
openssl x509 -in entrust_2048_ca.cer -inform DER -out entrust_2048_ca.pem -outform PEM
运行这个命令,老是报错。我注意到受信用的根证书下载页面支持的平台没有包括linux,我一直怀疑是不是自己找错了页面。因为下载的这个证书支持windows平台,所以我在windows上面做了尝试安装。
没想到*.cer文件在windows上面可以双击安装。我就判断apple apns推荐的下载受信用的根证书的地址对linux没有用。
直接在google上面搜linux root certificate install,第一条就是如何为linux添加entrust root certificate
我运行命令
yum install ca-certificates
update-ca-trust force-enable
在/etc/pki/tls/cert.pem下,找到了受信用的根证书cert.pem
在nghttpx.conf配置文件中
添加cacert=/etc/pki/tls/cert.pem
再次运行
./nghttpx --conf=nghttpx.conf
终于ngttpx顺利通过tls认证!!!
该问题的官方解释:
This error occurs when you use a certificate signed by a third party (like VeriSign or Thawte) in the directory. In such cases, the directory server may not offer the complete
 certificate chain, prevents certificate verification.


tls连接莫名其妙的断开:
解决了tls无法通过认证的问题,我以为可以正常使用nghttpx了,很不幸,又遇到了tls连接无法建立的问题。这让我十分困惑,通过了授权认证,为什么还连接不上,让我不知所措。冷静下来,只能先
定位出这个错误信息,是由哪个函数打印的。这样才能了解这个错误出现的原因。
根据日志中打印的错误信息,在nghttp2.0/src中成功定位出打印错误日志的函数。接着向上查找到了所有调用这个打印错误日志的函数。结合错误日志的相邻日志信息,基本断定了打印错误日志的函数
被调用的地方。为了确保推断是正确的,我在怀疑点,增加了一条日志信息,并重新编译了源代码。通过运行最终确定了打印错误日志的函数被调用的地点。
我装的openssl的版本是1.0.1,只会运行一下代码片段中的SSL_get0_next_proto_negotiated函数,不过这个函数并没有成功调用。也就是next_proto==nullptr,直接打印出错信息。这样就让出错问题
变得清晰。以下代码中 #if OPENSSL_VERSION_NUMBER >= 0x10002000L表示检查openssl库的版本是否大于等于1.0.2。如果大于等于1.0.2版本,在next_proto为nullptr的情况下,会再次尝试初始化
next_proto。根据google,也查到了SSL_get0_next_proto_negotiated函数用于检查是否支持npn。我重新查看了https://github.com/nghttp2/nghttp2文档,该文档明确提示 ALPN support requires 
openssl >= 1.0.2。这个条件与代码一致。另外在网上也受到了google已经逐步废除npn而是采用alpn。这让我决定升级openssl,再做一次尝试。
  if (addr_->tls) {
    const unsigned char *next_proto = nullptr;
    unsigned int next_proto_len = 0;


    SSL_get0_next_proto_negotiated(conn_.tls.ssl, &next_proto, &next_proto_len);
    #if OPENSSL_VERSION_NUMBER >= 0x10002000L
    if (!next_proto) {
      SSL_get0_alpn_selected(conn_.tls.ssl, &next_proto, &next_proto_len);
    }
    #endif // OPENSSL_VERSION_NUMBER >= 0x10002000L
    SSLOG(WARN, this) << "TEST--[next_proto]" << __FILE__ <<"---" << __LINE__;
    if (!next_proto) {
      downstream_failure(addr_);
      return -1;
    }
openssl升级完成后,需要把相关的libevent,spdylay-1.3.2库,重新编译一下。因为这些库也是依赖openssl的。最后重新编译nghttp2





0 0