节点不会使用自签名证书连接到服务器

Node wont make connection to server with self signed certificate

一点背景: 我有一个 Tesla Powerwall,它有自己的内置 Web 服务器,可以在本地网络上访问。它只允许 SSL 连接并使用自签名证书。我设置了端口转发,允许我远程连接到 Web 服务器。有一段时间,我已经在本地 Pi 和远程 AWS 实例上运行 node.js 应用程序,这些应用程序向 Powerwall Web 服务器发出请求以检索信息位。

从昨天开始,特斯拉更新了我的 Powerwall,现在一切都停止了。我只能假设他们已经改变了一些关于网络服务器如何处理它的自签名 SSL 证书的东西。

首先,我在本地网络上的 Pi 运行 无法向本地服务器发出成功的 node.js 请求。我设法通过在我的 /etc/hosts 文件中添加一个条目来实现这一点,如下所示:

192.168.1.42 powerwall

现在我的 node.js 应用可以使用 https://powerwall

再次成功连接

当使用 SafariChrome 进行远程连接时,如果我使用我的 IP 地址(在信任自签名证书之后),我可以连接但使用我的 DDNS 时无法连接指向家的地址。 (我已确认 DDNS 正在运行)。它给了我错误:

Safari can’t open the page “https://home.xxxxxx.com:4444” because Safari can’t establish a secure connection to the server “ home.xxxxxx.com”.

无论我使用 IP 地址还是 DDNS 地址,我的 AWS node.js 应用程序都无法连接,给我错误:

Client network socket disconnected before secure TLS connection was established

这就是我尝试连接的方式:

request({
    url: 'https://xx.xx.xx.xx:xxxx/api/system_status/soe',
    method: 'GET',
    rejectUnauthorized: false,
    requestCert: true,
    agent: false,
    headers: headers
}

我试过添加:

secureProtocol: 'TLSv1_method'

并尝试使用方法 TLSv1_method TLSv1_1_method TLSv1_2_method 以防需要特定方法,但没有成功。

以上听起来像是服务器上的 SSL 设置被搞砸了吗? 我能做什么:

a) 使用 DDNS 地址通过浏览器远程访问网站

b) 强制 node.js 对 SSL 证书根本不感兴趣,只是连接

----- 编辑

Certificate:
    Data:
        Version: 3 (0x2)
        Serial Number:
            46:.....
    Signature Algorithm: ecdsa-with-SHA256
        Issuer: C=US, ST=California, L=Palo Alto, O=Tesla, OU=Tesla Energy Products, CN=335cbec3e3d8baee7742f095bd4f8f17
        Validity
            Not Before: Mar 29 22:17:28 2019 GMT
            Not After : Mar 22 22:17:28 2044 GMT
        Subject: C=US, ST=California, L=Palo Alto, O=Tesla, OU=Tesla Energy Products, CN=335cbec3e3d8baee7742f095bd4f8f17
        Subject Public Key Info:
            Public Key Algorithm: id-ecPublicKey
                Public-Key: (256 bit)
                pub: 
                    04:ca...
                ASN1 OID: prime256v1
                NIST CURVE: P-256
        X509v3 extensions:
            X509v3 Key Usage: critical
                Digital Signature, Key Encipherment
            X509v3 Extended Key Usage: 
                TLS Web Server Authentication
            X509v3 Basic Constraints: critical
                CA:FALSE
            X509v3 Subject Alternative Name: 
                DNS:teg, DNS:powerwall, DNS:powerpack, IP Address:192.168.90.1, IP Address:192.168.90.2, IP Address:192.168.91.1

试试这个调试:

openssl s_client \
-connect 192.168.1.42:4444 \
-CAfile /path/to/self-signed-cert \
-verify_hostname powerwall \
-debug

可以在 openssl s_client -help

中找到更多选项

您的家庭网络上是否有任何服务器 运行ning(apache、nginx 等)?您可能正在尝试连接到 https://my.ddns.com 并将其直接传递给 powerwall,它具有 powerwall.

的证书

连接到 returns 不包含该主机名的证书的主机将导致 TLS 错误。您可能想要 运行 一个转发代理,其中您的服务器托管 my.ddns.com,设置 TLS 连接,然后将流量(没有 TLS)转发到 192.168.1.44

使用 HTTPS,域需要与证书中签名的相匹配;通常是 public 域。 它不应该是 IP,当然也不会是你指向它的 DDNS 主机名(如果我理解正确的话)。

有 3 种可能的方法;

  1. 将来自 powerwall 的证书添加为“已知”根 CA(如已建议的那样),
  2. 告诉node.js跳过检查证书的有效性,或者
  3. 尝试使用 HTTP

HTTPS 连接过程的正确操作还取决于您使用在证书 中注册的域名访问 powerwall(这可能需要您的 DNS 服务器以适当的响应进行查找时的 IP ~> 类似于 CTF 的 DNS 欺骗概念验证)。

此外,关于您在评论中的想法,虽然某些浏览器可能允许您覆盖过期或自签名证书(或通过 IP 连接时),但它非常 粗略连接域并获得指定完全不同域的证书(这就是浏览器甚至可能不向您提供该选项的原因)。

HTH

Post-分辨率更新:

  • 如何获取 DNS 名称以匹配证书上的内容:
    • 在客户端系统的 /etc/hosts 或等效项中添加一个条目
    • 使用主机名(不是 IP)连接

通过 public 互联网连接时:

  • 如何让 public-internet 连接到本地主机:
    • 获取与您的 DDNS 域或 /etc/hosts 条目匹配的 public-facing HTTPS cert (e.g.)
    • 托管 HTTP 代理
      • 将来自 Internet 的请求(希望 filtering/validation)中继到 powerwall
      • (您将有 2 个 HTTPS 连接:一个来自 AWS -> 代理,一个来自代理 -> powerwall)
    • 托管一个自定义 API,它将 return 正好是 AWS 服务
    • 所需的 [最少] 信息
  • 如何信任自签名证书? (这不是阻止因素)