我们运营一项社交/本地服务,该服务受益于对用户 IP 进行地理定位。问题是,使用 IPv6,地理定位比使用 IPv4 更不准确。
在装有 nginx 的 Ubuntu 主机上,有没有办法优先使用 IPv6 上的传入连接?配置如下:
server {
listen 80 default_server;
listen [::]:80 ipv6only=off default_server;
}
答案1
IPv6/IPv4 优先权由连接发起者(即 Web 浏览器)决定。地址选择规则定义在RFC 6724。虽然这些可以被覆盖,但只有通过用户重新配置他们的操作系统才能实现。
唯一能做的力量让某人使用 IPv4 的最好办法就是根本不提供 IPv6。显然,即使在中期内,这也不是一个切实可行的解决方案……
那么,让我们回到最初的问题:IPv6 的地理定位“比 IPv4 更加不稳定”。
在某种程度上,这在很大程度上取决于你从哪里获取地理位置数据。例如,Maxmind 只给出我的 IPv6 地址为“美国”,没有给出任何城市,一组有趣的坐标,而谷歌至少正确地识别了大都市地区,但距离仍有约 50 英里。Maxmind 和谷歌都允许报告更正,至少对于 Maxmind任何人都可以做到这一点对于任何 IP 地址。
我认为这种情况不会持续太久。随着 IPv6 的使用不断扩大,此类地理定位服务的用户将要求 IPv6 地址具有更高的准确性,他们最终必须满足这一要求,至少对于付费用户来说是这样,否则这些客户就会转向其他地方。
与此同时,你应该确保你的应用程序有其他方法来定位用户。如果他们登录了,你可以读取他们现有的帐户以获取有关他们所在位置的线索。你可以要求用户明确选择一个国家。等等...
您可以做的另一件事是为您的网站提供一个仅支持 IPv4 的子域和一个仅支持 IPv6 的子域,您的页面会尝试加载这两个子域。然后,您可以在客户端将它们关联起来并报告给服务器。并非巧合的是,Maxmind 已经在自己的网站上这样做了。
答案2
此类偏好可以使用 SRV 记录来表达。遗憾的是,HTTP 不支持这些偏好。因此,您只能让客户端独自在 IPv4 和 IPv6 之间做出选择。
许多客户端使用 SYN + SYN-ACK 的往返时间来决定使用哪一个。因此,通过减慢 IPv6 上 SYN-ACK 数据包的发送速度,您可以让大多数客户端更喜欢 IPv4。但故意减慢网站速度是一种糟糕的做法。
相反,我会退一步来看看问题所在。您需要更好的地理位置数据。每次访问者访问您的网站时,您都会立即知道他们的一个 IP 地址。该地址是 IPv4 还是 IPv6 取决于他们的浏览器更喜欢使用哪个地址与您的服务器进行通信。
在您的页面中,您可以使用 AJAX 请求来了解另一个 IP 地址。对于使用 IPv4 的客户端,请将 AJAX 请求发送到仅支持 IPv6 的域;对于使用 IPv6 的客户端,请将 AJAX 请求发送到仅支持 IPv4 的域。
一旦 AJAX 请求到达服务器,您就会知道用户的 IPv4 和 IPv6 地址。了解这种对应关系将使您能够比只知道其中一个地址更好地进行地理定位。
您经常会看到 AJAX 请求从未到达服务器的情况。对于这些用户,您必须进行地理定位,因为您最好只基于一个 IP 地址进行定位。但只要对该 AJAX 请求的回复未在客户端用于任何用途,用户甚至不会注意到这些失败的 AJAX 请求。因此,AJAX 请求不会导致任何明显的减速或不稳定行为。