我们希望将开发服务器的访问权限限制为拥有有效 SSL 客户端证书的用户。我们在 Debian 6 上运行 Apache 2.2.16。
然而,对于某些部分(主要是 git-http,使用 gitolite 进行设置https://my.server/git/)我们需要一个例外,因为许多 git 客户端不支持 SSL 客户端证书。
我已成功要求服务器进行客户端证书身份验证,并为某些位置添加例外。然而,这似乎对 git 不起作用。
当前设置如下:
SSLCACertificateFile ssl-certs/client-ca-certs.crt
<Location />
SSLVerifyClient require
SSLVerifyDepth 2
</Location>
# this works
<Location /foo>
SSLVerifyClient none
</Location>
# this does not
<Location /git>
SSLVerifyClient none
</Location>
我也尝试了另一种解决方案,结果相同:
# require authentication everywhere except /git and /foo
<LocationMatch "^/(?!git|foo)">
SSLVerifyClient require
SSLVerifyDepth 2
</LocationMatch>
在这两种情况下,没有客户端证书的用户可以完美访问 my.server/foo/,但不能访问 my.server/git/(访问被拒绝,因为没有提供有效的客户端证书)。如果我完全禁用 SSL 客户端证书身份验证,my.server/git/ 就可以正常工作。
ScriptAlias 问题
Gitolite 是使用 ScriptAlias 指令设置的。我发现任何类似的 ScriptAlias 都会出现此问题:
# Gitolite
ScriptAlias /git/ /path/to/gitolite-shell/
ScriptAlias /gitmob/ /path/to/gitolite-shell/
# My test
ScriptAlias /test/ /path/to/test/script/
请注意,/path/to/test/script 是一个文件,而不是目录,/path/to/gitolite-shell/ 也是如此。
我的测试脚本只是打印出环境,非常简单:
#!/usr/bin/perl
print "Content-type:text/plain\n\n";
print "TEST\n";
@keys = sort(keys %ENV);
foreach (@keys) {
print "$_ => $ENV{$_}\n";
}
似乎如果我去https://my.server/test/someLocation,所有与 /test/someLocation 匹配的 Location 块中的 SSLVerifyClient 指令均被应用或者只是/someLocation。
如果我有以下配置:
<LocationMatch "^/f">
SSLVerifyClient require
SSLVerifyDepth 2
</LocationMatch>
然后,以下 URL 需要客户端证书:https://my.server/test/foo。但是,以下 URL 却没有:https://my.server/test/somethingElse/foo
请注意,这似乎仅适用于 SSL 配置。以下内容对https://my.server/test/foo:
<LocationMatch "^/f">
Order allow,deny
Deny from all
</LocationMatch>
然而,它确实阻止访问https://my.server/foo。
这对于我同时运行一些项目的情况来说是一个很大的问题https://my.server/project(需要 SSL 客户端证书授权)和该项目的 git 存储库位于https://my.server/git/project无法要求 SSL 客户端证书。由于 /git/project URL 也与 /projectLocation
块匹配,因此根据我目前的发现,这种配置似乎是不可能的。
问题:为什么会发生这种情况?我该如何解决我的问题?
最后,我希望要求除 /git 和 /someLocation 之外的整个服务器进行 SSL 客户端证书授权,并尽可能减少配置(这样我就不必在每次部署新内容或添加新的 git 存储库时修改配置)。
更新更多信息:请注意,在某些情况下,https://my.server/project实际上是反向代理,因此<Directory /path/to/project>
无法执行指令。如果我想使用 SSL 客户端证书保护该应用程序,则必须使用<Location /project>
(或更通用的<Location />
)块。
更新 2我刚刚在 apache 2.4.3 中测试了这个问题,结果是一样的。如果这是由于某个错误造成的,那么至少有两个版本都存在这个问题。
注意:我重写了我的问题(而不是仅仅在底部添加更多更新)以考虑到我的新发现并希望使这一点更加清楚。
答案1
根据目前Apache 文档这可能是一个问题:
在每个服务器上下文中,它适用于建立连接时标准 SSL 握手中使用的客户端身份验证过程。在每个目录上下文中,它会在读取 HTTP 请求之后但在发送 HTTP 响应之前强制使用重新配置的客户端验证级别进行 SSL 重新协商。
那么使用 <Directory> 上下文而不是 <Location> 怎么样?一个条目用于根级别,另一个用于 Script-Alias 路径:/path/to/gitolite-shell/
更新:
我找到了一些针对此案例的建议 ->Stackoverflow 上的问答