我们的 EC2 实例上的 DNS 出现了一个非常奇怪的问题。我们在某些实例上运行的应用程序是基于 Java 的服务,它为 Android 应用程序提供后端。作为其功能的一部分,它通过 Google API 向手机发送推送通知。为此,它必须向android.apis.google.com不幸的是,在我们的 EC2 实例上运行此程序时,我们收到证书错误,因为主机名与证书名称不匹配:
hostname in certificate didn't match: <android.apis.google.com> != <.gstatic.com> OR <gstatic.com> OR <.gstatic.com>
我们已经将问题追溯到 DNS 结果的差异。当我们查询 DNS 时android.apis.google.com从我们的办公室(一切正常的地方),我们得到了以下回复:
android.apis.google.com. 300 IN CNAME clients.l.google.com.
clients.l.google.com. 160 IN A 74.125.226.230
clients.l.google.com. 160 IN A 74.125.226.231
clients.l.google.com. 160 IN A 74.125.226.232
clients.l.google.com. 160 IN A 74.125.226.233
clients.l.google.com. 160 IN A 74.125.226.238
clients.l.google.com. 160 IN A 74.125.226.224
clients.l.google.com. 160 IN A 74.125.226.225
clients.l.google.com. 160 IN A 74.125.226.226
clients.l.google.com. 160 IN A 74.125.226.227
clients.l.google.com. 160 IN A 74.125.226.228
clients.l.google.com. 160 IN A 74.125.226.229
当我们从 EC2 服务器执行相同的查询时,我们会得到一组不同的 DNS 结果:
android.apis.google.com. 300 IN CNAME clients.l.google.com.
clients.l.google.com. 300 IN A 72.14.204.138
clients.l.google.com. 300 IN A 72.14.204.100
clients.l.google.com. 300 IN A 72.14.204.101
clients.l.google.com. 300 IN A 72.14.204.102
clients.l.google.com. 300 IN A 72.14.204.113
你知道为什么 EC2 上的 DNS 结果会有如此大的差异吗?更重要的是,我们如何解决这个问题?
我们确实尝试使用自定义主机名验证器。据我们的开发人员说,这允许连接继续,但问题是它连接到了错误的服务器,因此请求仍然失败。
答案1
Google 有大量的 IP,他们会为您提供地理位置最接近您所在位置的 IP。
当我dig
针对 Google 自己的公共 DNS 时8.8.8.8
,我得到了与您从 EC2 获得的相同列表:
[] csternal@~: dig @8.8.8.8 android.apis.google.com
; <<>> DiG 9.6-ESV-R4-P3 <<>> @8.8.8.8 android.apis.google.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 38592
;; flags: qr rd ra; QUERY: 1, ANSWER: 6, AUTHORITY: 0, ADDITIONAL: 0
;; QUESTION SECTION:
;android.apis.google.com. IN A
;; ANSWER SECTION:
android.apis.google.com. 300 IN CNAME clients.l.google.com.
clients.l.google.com. 300 IN A 72.14.204.102
clients.l.google.com. 300 IN A 72.14.204.113
clients.l.google.com. 300 IN A 72.14.204.100
clients.l.google.com. 300 IN A 72.14.204.101
clients.l.google.com. 300 IN A 72.14.204.138
;; Query time: 83 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Thu Mar 15 11:38:13 2012
;; MSG SIZE rcvd: 145
您遇到的问题似乎是这样的: https://stackoverflow.com/questions/6296547/c2dm-ioexception-when-sending-message
解决您收到的错误消息的最常见解决方案是定义自定义主机名验证。您面临的主要问题是 Google 的 Android URL 返回的域名是.google.com。不幸的是,这会导致一些问题,因为 Android SDK 位于 android.apis.google.com。默认情况下,JVM 不会验证此组合(.sdk.google.com 即可接受)。
以下是如何创建自己的主机名验证器的示例:
URL url = new URL("https://android.apis.google.com/c2dm/send"); HostnameVerifier hVerifier = new HostnameVerifier() { public boolean verify(String hostname, SSLSession session) { return true; } }; HttpsURLConnection conn = (HttpsURLConnection) url.openConnection(); conn.setHostnameVerifier(hVerifier);
答案2
奇怪。一切又开始正常运转了——就像魔术一样。
答案3
这可能是来自 Amazon EC2 DNS 平台的问题(刷新问题)或来自“虚拟平台”或 Amazon 平台的缓存结果问题。