ETAG 是在 Web 浏览器和 Web 服务器之间在幕后发送的 HTTP 标头。此值旨在控制特定文件在客户端缓存的时间。
这项技术有一个有趣的副作用。即使 cookie 被删除,ETAG 也会保存在机器上。 一些人/软件利用这一事实使 ETAG 像 cookie 一样“行动”。
这意味着仅仅删除 cookie 是不够的。还必须删除整个网络缓存。每次我在我的测试机器上上网时,这是一个痛苦的过程。
问题
防止 ETAG 标头发生跟踪的最可靠方法是什么?
ETAG 是在 Web 浏览器和 Web 服务器之间在幕后发送的 HTTP 标头。此值旨在控制特定文件在客户端缓存的时间。
这项技术有一个有趣的副作用。即使 cookie 被删除,ETAG 也会保存在机器上。 一些人/软件利用这一事实使 ETAG 像 cookie 一样“行动”。
这意味着仅仅删除 cookie 是不够的。还必须删除整个网络缓存。每次我在我的测试机器上上网时,这是一个痛苦的过程。
问题
防止 ETAG 标头发生跟踪的最可靠方法是什么?
我不知道有什么好的解决方案。我可以提出三种可能的防御措施,尽管它们都有局限性:
隐私。 Privoxy可以阻止 ETag 标头。
特别是,您可以使用crunch-server-header
或server-header-filter
在您的 Privoxy 配置中阻止ETag:
来自服务器的标头。此外,您可以使用crunch-client-header
或client-header-filter
在您的 Privoxy 配置中阻止来自客户端If-None-Match:
的If-Modified-Since:
标头。但是,我不知道有任何现成的公式可供您获取和使用:您必须自己构建自己的 Privoxy 配置。
你的浏览器。如果您使用 Firefox,您可以将 Firefox 配置为在每次退出浏览器时清除缓存。这可能对性能不利。此外,通过这种方法,ETags 仍可用于在任何一个浏览器会话中跟踪您,因此它并不完美,但它应该在您退出浏览器时清除任何 ETag cookie。
请求策略。如果你使用 Firefox,你可以使用RequestPolicy扩展。一位作者指出RequestPolicy 可能有助于防御 ETag 跟踪. 通常,网站会通过包含来自第三方广告商或分析提供商的资源来跟踪您。RequestPolicy 允许您控制浏览器在访问网页时将请求哪些第三方资源,从而可以保护自己免受此类跟踪:如果您的浏览器从不加载第三方广告商的资源,那么第三方广告商没有机会跟踪您(使用 ETag 或任何其他机制)。这种防御不太理想,因为它需要您费力地组装您的策略,而且如果网站不依赖任何第三方资源,它们仍然可以直接跟踪您。
不幸的是,如果您通过透明代理访问网络,代理的存在可能会使您避免被跟踪的尝试变得复杂。
除了@DW提出的涉及较多的解决方案,可以考虑使用浏览器的隐私浏览模式,ala InPrivate (IE), PrivateBrowsing (FF), Incognito (Chrome)等。
这里主要是浏览器缓存是未使用(或至少未使用超过私人会话的长度)。因此,您的浏览器不会保存 Etag。
这种方法仍然存在一些缺点,例如在会话中进行跟踪,以及@DW 提到的代理。也就是说,使用起来非常简单。
如果您使用的是 Firefox,您可能会对我的 SecretAgent 附加组件的(可选)功能感兴趣...它会创建欺骗性的 ETag 标头以抑制跟踪。
不利的一面是,欺骗 ETag 显然会损害那些使用 ETag 来优化流量的网站的缓存(尽管这似乎对性能的影响很小)。
(免责声明:我是 SecretAgent 的作者)。
更新:以不同的方式和更清楚地写下答案
我有一个无需修改当前 HTTP 协议即可工作的解决方案。我很想看到这个的实现。
我们没有告诉服务器我们的 Etag ,而是向服务器询问它的 Etag,并将它与我们已经拥有的进行比较。
伪代码:
If (file_not_in_cache)
{
page=http_get_request();
page.display();
page.put_in_cache();
}
else
{
page=load_from_cache();
client_etag=page.extract_etag();
server_etag=http_HEAD_request().extract_etag();
//Instead of saying "my etag is xyz",
//the client says: what is YOUR etag, server?"
if (server_etag==client_etag)
{
page.display();
}
else
{
page.remove_from_cache();
page=http_get_request();
page.display();
page.put_in_cache();
}
}
解决方案 1 的 HTTP 对话示例:
客户:
HEAD /posts/46328
host: security.stackexchange.com
服务器:
HTTP/1.1 200 OK
Date: Mon, 23 May 2005 22:38:34 GMT
Server: Apache/1.3.3.7 (Unix) (Red-Hat/Linux)
Last-Modified: Wed, 08 Jan 2003 23:11:55 GMT
ETag: "ABCDE"
Content-Type: text/html
Content-Length: 131
案例1,客户端有一个相同的etag:
Connection closes, client loads page from cache.
案例 2,客户端的 etag 不匹配:
GET...... //and a normal http conversation begins.
编辑:值得注意的是,有一个小的开销,服务器必须发送两次 HTTP 标头:一次响应 HEAD,一次响应 GET。一个理论上的解决方法是修改 HTTP 协议并添加一种请求无标头内容的新方法。然后,如果 etag 不匹配,客户端将仅请求 HEAD,然后仅请求内容。
编辑 2:我遵循了 makerofthings7 的建议,并将其作为问题发布在 stackoverflow 上。