在服务器证书中使用 ip 地址作为通用名称在 Android 中不起作用?
Using ip address for common name in server certificate does not work in Android?
我一直在调查这个问题并发现了一些有趣的东西。
如果我使用服务器密钥库将服务器证书存储为 真实域 以建立与服务器的连接,它工作正常,但是如果我使用 ip 地址 而不是通用名称,它不起作用,但仅在 android 设备自制应用程序中(不是 android 设备中的桌面浏览器或浏览器应用程序)。注意我使用 openssl 创建了这两个 certificate/keystore。
事实证明这个异常是主机名未验证
但奇怪的是在桌面浏览器或 android 设备上都很好
经过调查我发现实际上我们可以构建我们自己的主机名验证器,它可以为主机名添加例外,但是android的默认验证器如何工作?一定是一些代码跳过 ip 地址 作为通用名称和 return false.
我查看了okhttp的源码,发现这行代码抛出了异常
但我找不到自定义主机名验证程序的代码。
任何人都可以给我一些提示吗?
谢谢~
更新::
我在 android studio 中调试后,在 运行 时间里它实际上是 OkHostnameVerifier
它检查主机名是否为 ip 地址,如果是,将检查证书中的所有主题备用名称,如果找到匹配项 return true 反之亦然。
private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) {
for (String altName : getSubjectAltNames(certificate, ALT_IPA_NAME)) {
if (ipAddress.equalsIgnoreCase(altName)) {
return true;
}
}
return false;
}
If I use a server keystore which stores server certificate with commomn name is real domain for establishing a connection with server it works fine, however if I use ip address instead for the common name it does not work,
它应该是这样工作的。 IP 地址必须作为 IP 类型的主题备用名称给出。不幸的是,不同的浏览器以不同的方式处理这个问题,而且通常与标准相反。有些接受通用名称的 IP,有些则不接受。有些人希望地址作为主题替代部分中的 DNS 条目而不是 IP 条目。因此,为了安全起见,您应该同时使用 IP 和 DNS 类型的主题备用名称。
we can build our own host name verifier which can add exception to host name
不要这样做。如果您忽略主机名,则验证将减少为仅检查信任链,这意味着任何由受信任的 CA 签署的证书都可用于对任何其他主机进行透明的中间人攻击。即使您只对 IP 地址禁用名称检查,一旦用户通过 IP 访问站点,仍然可以使用任何有效证书。
我一直在调查这个问题并发现了一些有趣的东西。
如果我使用服务器密钥库将服务器证书存储为 真实域 以建立与服务器的连接,它工作正常,但是如果我使用 ip 地址 而不是通用名称,它不起作用,但仅在 android 设备自制应用程序中(不是 android 设备中的桌面浏览器或浏览器应用程序)。注意我使用 openssl 创建了这两个 certificate/keystore。
事实证明这个异常是主机名未验证
但奇怪的是在桌面浏览器或 android 设备上都很好
经过调查我发现实际上我们可以构建我们自己的主机名验证器,它可以为主机名添加例外,但是android的默认验证器如何工作?一定是一些代码跳过 ip 地址 作为通用名称和 return false.
我查看了okhttp的源码,发现这行代码抛出了异常
但我找不到自定义主机名验证程序的代码。
任何人都可以给我一些提示吗?
谢谢~
更新:: 我在 android studio 中调试后,在 运行 时间里它实际上是 OkHostnameVerifier
它检查主机名是否为 ip 地址,如果是,将检查证书中的所有主题备用名称,如果找到匹配项 return true 反之亦然。
private boolean verifyIpAddress(String ipAddress, X509Certificate certificate) {
for (String altName : getSubjectAltNames(certificate, ALT_IPA_NAME)) {
if (ipAddress.equalsIgnoreCase(altName)) {
return true;
}
}
return false;
}
If I use a server keystore which stores server certificate with commomn name is real domain for establishing a connection with server it works fine, however if I use ip address instead for the common name it does not work,
它应该是这样工作的。 IP 地址必须作为 IP 类型的主题备用名称给出。不幸的是,不同的浏览器以不同的方式处理这个问题,而且通常与标准相反。有些接受通用名称的 IP,有些则不接受。有些人希望地址作为主题替代部分中的 DNS 条目而不是 IP 条目。因此,为了安全起见,您应该同时使用 IP 和 DNS 类型的主题备用名称。
we can build our own host name verifier which can add exception to host name
不要这样做。如果您忽略主机名,则验证将减少为仅检查信任链,这意味着任何由受信任的 CA 签署的证书都可用于对任何其他主机进行透明的中间人攻击。即使您只对 IP 地址禁用名称检查,一旦用户通过 IP 访问站点,仍然可以使用任何有效证书。