在服务器证书中使用IP地址作为通用名称在Android中不起作用?

Qin*_*ing 5 ssl https android openssl okhttp

我一直在调查这个问题,发现了一些有趣的东西.如果我使用服务器密钥库存储服务器证书与commomn名称作为真实域建立与服务器的连接,它工作正常,但如果我使用IP地址而不是通用名称它不起作用,但只是在Android设备自制应用程序(不是Android设备中的桌面浏览器或浏览器应用程序).​​noted我使用openssl创建这两个证书/密钥库. 在此输入图像描述

事实证明这个例外是主机名未经验证

在此输入图像描述

但奇怪的是在浏览器中桌面或Android设备都很好

在此输入图像描述

经过调查,我发现实际上我们可以构建自己的主机名验证器,它可以为主机名添加异常,但android的默认验证器是如何工作的?它必须是一些跳过ip地址作为通用名称并返回false的代码.

我检查了okhttp的源代码,发现这行代码正在抛出异常

在此输入图像描述

但我找不到自定义主机名验证码的代码.

有人可以给我一些关于此的提示吗?

谢谢〜

更新::我在android studio中调试后,在运行时它实际上是OkHostnameVerifier

它检查主机名是否为IP地址,如果是,则检查证书中的所有主题备用名称,如果找到匹配则返回true,反之亦然.

private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) {
    for (String altName : getSubjectAltNames(certificate, ALT_IPA_NAME)) {
      if (ipAddress.equalsIgnoreCase(altName)) {
        return true;
      }
    }
    return false;
  }
Run Code Online (Sandbox Code Playgroud)

Ste*_*ich 5

如果我使用服务器密钥库存储服务器证书与commomn名称是真实域建立与服务器的连接它工作正常,但是如果我使用IP地址而不是通用名称它不起作用,

它应该如何运作.IP地址必须作为IP类型的主题替代名称给出.不幸的是,不同的浏览器以不同的方式处理这种情况并且经常违反标准.有些人接受普通名称的IP,有些则不接受.有些人希望地址作为主题备选部分中的DNS条目而不是IP条目.为了安全起见,您应该使用IP和DNS两种类型的主题替代名称.

我们可以构建自己的主机名验证程序,它可以为主机名添加例外

不要这样做.如果忽略主机名,则验证将简化为仅检查信任链,这意味着由可信CA签名的任何证书都可用于针对任何其他主机的透明中间人攻击.即使您仅对IP地址禁用名称检查,一旦用户通过IP访问站点,仍可以使用任何有效证书.