🔗 代理认证
🔗 详细信息
目前 HTTP 世界中有六种主要的认证方式
- 基本 (Basic) - 自始至终都存在
- NTLM - 微软首次尝试在 LAN 环境中实现单点登录
- 摘要 (Digest) - W3C 尝试提供安全的认证系统
- 协商 (Negotiate,又称 SPNEGO) - 微软第二次尝试实现单点登录。
- OAuth - IETF 尝试实现单点登录
- OAuth 2.0 (又称 Bearer) - IETF 第二次尝试实现单点登录
Squid-2.6 及更高版本支持基本 (Basic)、NTLM (SMB LM, v1 和 v2)、摘要 (Digest) 以及协商 (Negotiate) (Kerberos 和/或 NTLM)。
🔗 Squid 中的代理认证是如何工作的?
如果 squid 配置为使用 *proxy_auth* ACL(参见下一个问题),用户将被认证。
浏览器在 HTTP *Authorization:* 请求头中发送用户的认证凭据。
如果 Squid 收到一个请求,并且 http_access 规则列表遇到了 *proxy_auth* ACL 或带有 *%LOGIN* 参数的 *external* ACL(external_acl_type),Squid 会查找 *Authorization:* 头。如果头存在,Squid 会对其进行解码并提取用户凭据。
如果头丢失,Squid 会返回一个状态为 407(需要代理认证)的 HTTP 回复。用户代理(浏览器)收到 407 回复后,会尝试定位用户的凭据。有时这需要后台查找,有时会弹出一个提示框让用户输入用户名和密码。用户名和密码会被编码,并在后续请求代理时发送在 *Authorization* 头中。
*注意*:“用户名和密码使用“base64”进行编码(参见 RFC 2616 的第 11.1 节)。然而,base64 仅是一种二进制到文本的编码,它不会加密其编码的信息。这意味着用户名和密码在浏览器和代理之间实际上是“明文”传输的。因此,您可能不应该使用与您的账户登录相同的用户名和密码。
认证实际上是在 Squid 主进程之外执行的。当 Squid 启动时,它会生成多个认证子进程。这些进程在标准输入 (stdin) 中读取用户凭据,并在标准输出 (stdout) 中回复“OK”或“ERR”。这种技术允许您使用多种不同的认证协议(在此上下文中称为“方案”)。当服务器(本例中是 Squid)提供多种认证方案时,用户代理 (User-Agent) 会选择一种并使用它进行认证。根据 RFC,它应该选择它能处理的最安全的方案;实际上,Microsoft Internet Explorer 通常会选择它能处理的第一个方案,而 Mozilla 浏览器在此方面与 Microsoft 系统兼容(虽然是 bug 兼容)。
除了众所周知的基本认证外,Squid 还支持 NTLM、协商 (Negotiate) 和摘要 (Digest) 认证方案,它们提供了更安全的认证方法,因为密码不会以明文形式在网络上传输。每种方案都有自己的一组辅助程序和 auth_param 设置。请注意,不同认证方案的辅助程序使用不同的协议与 squid 通信,因此它们不能混合使用。
有关如何设置 NTLM 认证的信息,请参阅 NTLM 配置示例。
Squid 源代码捆绑了几个用于认证的后端(“*辅助程序*”)。这些包括:
- DB:使用 SQL 数据库。
- getpwam:使用旧式的 Unix 密码文件。
- LDAP:使用轻量级目录访问协议。
- MSNT:使用 Windows NT 认证域。
- MSNT-multi-domain:允许登录到多个 Windows NT 域中的一个。
- NCSA:使用 NCSA 风格的用户名和密码文件。
- NIS (或 YP):使用 NIS 数据库
- PAM:使用 Unix 可插拔认证模块方案。
- POP3:使用电子邮件服务器验证凭据。对于代理和电子邮件的单点登录很有用。
- RADIUS:使用 RADIUS 服务器进行登录验证。
- SASL:使用 SASL 库。
- SMB:使用 SMB 服务器,如 Windows NT 或 Samba。
- SSPI:Windows 原生认证器
每个辅助程序的文档都可以在 https://squid.org.cn/Doc/man/ 找到。由于其简单性,基本认证拥有最多的辅助程序,但其他方案也有几个可用的辅助程序。
要认证用户,您需要编译并安装一个提供的认证辅助程序,或者 其他,或者提供您自己的。
您可以使用 squid.conf 中的 auth_param 指令告诉 Squid 使用哪个认证辅助程序。指定程序的名称,以及必要的命令行选项。例如:
auth_param basic program /usr/local/squid/bin/ncsa_auth /usr/local/squid/etc/passwd
(上面链接的手册页中可以找到您选择的具体辅助程序的完整配置详细信息)。
🔗 如何在访问控制中使用认证?
确保您的认证程序已安装并正常工作。您可以手动测试它。
在您的 squid 配置中添加一些 *proxy_auth* ACL 条目。例如:
acl foo proxy_auth REQUIRED
http_access allow foo
http_access deny all
REQUIRED 条目意味着任何已认证用户都将匹配名为 *foo* 的 ACL。
请注意,如果用户尚未正确登录,*allow* 不会触发 407 认证拒绝来获取新的认证详细信息。一些浏览器默认会发送 *anonymous* 认证详细信息。
一种更好的方法是确保浏览器认证得到验证:
acl foo proxy_auth REQUIRED
http_access deny !foo
http_access allow localnet
http_access deny all
Squid 允许您通过指定单个用户名来提供细粒度的控制。例如:
acl foo proxy_auth REQUIRED
acl bar proxy_auth lisa sarah frank joe
acl daytime time 08:00-17:00
http_access allow foo daytime
http_access allow bar
http_access deny all
在此示例中,名为 lisa、sarah、joe 和 frank 的用户可以随时使用代理。其他用户仅在白天允许使用。
ConfigExamples 区域包含一些详细示例:
- ConfigExamples/Authenticate/Bypass
- ConfigExamples/Authenticate/Groups
- ConfigExamples/Authenticate/Kerberos
- ConfigExamples/Authenticate/Ldap
- ConfigExamples/Authenticate/LoggingOnly
- ConfigExamples/Authenticate/MultipleSources
- ConfigExamples/Authenticate/Mysql
- ConfigExamples/Authenticate/Ncsa
- ConfigExamples/Authenticate/Ntlm
- ConfigExamples/Authenticate/NtlmCentOS5
- ConfigExamples/Authenticate/NtlmWithGroups
- ConfigExamples/Authenticate/Radius
- ConfigExamples/Authenticate/WindowsActiveDirectory
🔗 如何要求已认证用户进行认证?
如果用户已在代理上认证,您将无法“注销”并重新认证。用户通常需要关闭并重新打开浏览器窗口才能在代理上重新登录。一个简单的配置可能看起来像这样:
acl my_auth proxy_auth REQUIRED
http_access deny !my_auth
http_access allow my_auth
http_access deny all
在某些情况下,有一种技巧可以强制用户使用不同的帐户进行认证。如果您在 `http_access` deny 语句的 **最后** 使用与认证相关的 ACL 进行访问拒绝,就会发生这种情况。示例配置:
acl my_auth proxy_auth REQUIRED
acl google_users proxy_auth user1 user2 user3
acl google dstdomain .google.com
http_access deny google !google_users
http_access allow my_auth
http_access deny all
在这种情况下,如果用户请求 `www.google.com`,则第一条 `http_access` 行会匹配并触发重新认证,除非用户是列出的用户之一。
记住:`http_access` 行的 **最后一个 ACL** 决定是否执行认证。如果 ACL 处理认证,则会触发新的挑战。如果您不希望这样做,则需要切换 ACL 的顺序,以便您得到 `http_access deny !google_users google`,或者使用下面概述的循环预防方法。
但是,如果您不小心,也可能会遇到持续的认证挑战循环。
🔗 如何阻止登录弹出窗口?
弹出要求输入用户名和密码的登录对话框是您的网页浏览器的功能。只有当网页浏览器在被要求登录时没有可用的有效凭据交给 Squid 时,才会发生这种情况。
Squid 仅在未发送凭据且需要凭据时才会要求提供凭据。
acl mustLogin proxy_auth REQUIRED
这可能会导致登录弹出窗口。然而,现代浏览器内置了密码管理器或可以访问操作系统凭据,它们可以找到首次尝试。这通常被称为单点登录。值得注意的是,尽管流行的广告声称,单点登录可以与任何 HTTP 认证机制一起使用,因为它是一种客户端浏览器功能,而不是 HTTP 或代理功能。
如果浏览器无法找到任何初始详细信息,您将收到登录弹出窗口。无论我们在 Squid 中做什么。
为了防止登录失败后对错误的登录详细信息进行重新挑战,您只需阻止登录 ACL 成为认证行的最后一行。
例如,这种正常配置会导致登录重新挑战,直到提供有效的详细信息为止:
http_access deny mustLogin
这种 **全额黑客** 将呈现一个简单的访问拒绝页面,而不会挑战不同的凭据:
http_access deny mustLogin all
🔗 如何阻止认证循环?
上述登录循环的另一个更微妙的版本发生在循环由组检查而不是用户名检查触发时。
假设您使用 LDAP 组查找,并希望根据 LDAP 组拒绝访问(例如,只有特定 LDAP 组成员才能访问某些网站)。在这种情况下,您可能会触发重新认证,尽管您不打算这样做。此配置可能不适合您:
acl ldapgroup-allowed external LDAP_group PROXY_ALLOWED
http_access deny !ldapgroup-allowed
http_access allow all
如果用户不是 PROXY_ALLOWED 组的成员,`http_access` deny 行会反复强制用户重新认证。这可能不是您想要的。您更希望拒绝非成员的访问。
您需要重写此 `http_access` 行,以便一个与认证无关的 ACL 匹配。这是正确的示例:
acl ldapgroup-allowed external LDAP_group PROXY_ALLOWED
http_access deny !ldapgroup-allowed all
http_access allow all
这样,`http_access` 行仍然匹配。但现在 `all` ACL 是该行的最后一个。由于 `all` 是一个静态 ACL(始终匹配)且与认证无关,您会发现访问被简单地拒绝了。
另请参见:https://squid.org.cn/mail-archive/squid-users/200511/0339.html
🔗 Squid 是否缓存认证查找?
这取决于认证方案;Squid 在可能的情况下会进行一些缓存。
注意:缓存凭据与用户需要多久重新认证一次无关。是浏览器维护会话,重新认证是用户和浏览器之间的事务,而不是浏览器和 Squid 之间的。浏览器代表用户在每次发送到 Squid 的请求时进行认证。Squid 参数仅控制 Squid 将多久询问一次已定义的辅助程序密码是否仍然有效。
-
成功的基本认证结果默认缓存一小时。这意味着(在最坏的情况下),在用户从认证数据库中删除后,最多可能有一个小时的时间可以继续使用您的缓存。您可以使用 `auth_param basic credentials_ttl` 配置选项控制过期时间。
-
成功的 NTLM 和协商认证结果与客户端 TCP 连接状态绑定,并且每个新请求都会根据存储的凭据令牌进行验证。因此,凭据仅在 TCP 连接持续时间内被“缓存”,每个新的 TCP 连接都需要完全不同的认证。
🔗 密码是以明文还是加密方式存储的?
在基本方案中,密码以明文形式交换。在其他方案中,只交换密码的加密哈希。
Squid 在其基本认证内存缓存中存储明文密码。
Squid 在与外部基本认证进程通信时写入明文用户名和密码。请注意,这种进程间通信通过绑定到本地回环接口的 TCP 连接或私有 UNIX 管道进行。因此,其他计算机上的进程或没有 root 权限的本地用户无法“窃听”认证流量。
每个认证程序必须选择自己的密码和用户名持久存储方案。
对于摘要方案,Squid 从未见过实际密码,但后端辅助程序需要明文密码或与之对应的特定于摘要的哈希。
在 NTLM 或协商方案中,Squid 也从不看到实际密码。通常,这与 Windows 领域或 Kerberos 领域相关联,而这些认证服务如何存储密码超出了本文档的范围,但通常不是明文存储。
在边带认证中,使用 `external_acl_type` 指令。有一个 `password=` 值,可能从辅助程序传输到 Squid。此值是完全 **可选** 的,实际上可能与真实密码无关,因此我们无法确定实际涉及的风险。接收到后,Squid 通常将其视为明文基本认证密码,并可能将其以明文形式传递给对等代理或服务。
🔗 我可以同时使用不同的认证机制吗?
是的,但有限制。
常用用户代理至少支持一种,最多支持四种不同的认证协议(也称为 *方案*)。
这些方案在其他地方有详细解释(请参阅 Features/NegotiateAuthentication 和 SquidFaq/TroubleShooting)。您可以随时启用多个方案,只需为希望提供给浏览器的每种不同方案配置相关的 `auth_param` 部分即可。
RFC 2617 第 4.6 章指出:*用户代理必须选择使用它能理解的最强认证方案*。当然,“最强”的定义可能有所不同。
| 由于常见用户代理(尤其是某些 Microsoft Internet Explorer 和 Firefox 版本)存在 **bug**,因此 `auth-schemes` 配置的 **顺序** 是相关的。MSIE 的早期版本会选择它能理解的 *第一个* 认证方案(按提供顺序)。 |
换句话说,您 **应该** 为 `auth_params` 指令使用此顺序:
-
negotiate
-
ntlm
-
digest
-
basic
不包含您计划不提供的方案。
一旦管理员决定向客户端提供多种认证方案,Squid **无法** 强制客户端选择其中一种而不是另一种。
🔗 我可以使用多个用户数据库吗?
总的来说,答案是否定的,至少不能从 Squid 内部实现。
Unix 的 PAM 认证方法非常灵活,可以以“或/或/两者”的方式从多个认证源进行认证。
您可以配置两个不同的认证方案,使用不同的用户数据库。但是,由于无法控制浏览器选择使用哪个,这是一个不可靠的选项,如果您能正常工作就太好了,如果不行,我们无能为力。
Web 服务器的基本认证方案提供了另一种方法,您可以编写一个代理脚本,将请求中继到不同的认证器并应用“OR”逻辑。对于所有其他认证方案,这都无法实现;这不是 Squid 的限制,而是认证协议本身的特性:允许多个用户数据库会为协议的重放攻击打开大门。
🔗 参考资料
- Winbind:使用域账户
- 域成员资格
- winbindd man 页
- wbinfo man 页
- nmbd man 页
- smbd man 页
- smb.conf man 页
- smbclient man 页
- ntlm_auth man 页
🔗 拦截和透明模式下的认证
简单来说,在拦截或透明模式下运行的代理无法使用代理认证方案来认证用户。有关原因的详细信息,请参阅 SquidFaq/InterceptionProxy。
🔗 我可以编写自己的认证器吗?
Squid 提供了大量灵活的辅助程序,可以集成到大量流行的认证后端,包括定制的企业数据库。查看捆绑的辅助程序手册和在线搜索引擎,您很可能会发现已经有人完成了繁重的工作。
然而,您可能仍然发现有必要为尚未被梦想到的系统编写自己的辅助程序。Squid 与其认证辅助程序通信所使用的协议非常简单,并且 wiki 中有几个示例。
🔗 其他资源
类别:功能
导航:站点搜索,站点页面,类别,🔼 向上