我正在使用 Webmin 来管理我的家庭服务器。
而不是在默认端口上运行它(https://我的主机:10000),我想将其托管在子文件夹中(https://myhost/webmin/)。使用 Apache 时,此操作运行正常(Apache 配置文件附在下面)。但是,我通常使用 lighttpd,我想用 lighttpd 做同样的事情(在子文件夹中运行 Webmin)。但是,它无法正常工作。每当我访问https://myhost/webmin/,我收到消息:
Error - Bad Request
This web server is running in SSL mode. Try the URL https://localhost:10000/ instead.
因此,我深入研究了这个问题。我没有运行 Webmin,而是使用 netcat 来监听端口 10000。使用 lighttpd 时,我得到:
myhost@myhost:~$ nc -l 10000
GET /webmin/ HTTP/1.0
Host: myhost
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64; rv:10.0.2) Gecko/20100101 Firefox/10.0.2
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8
Accept-Language: en-us,en;q=0.5
Accept-Encoding: gzip, deflate
DNT: 1
Cookie: testing=1
Cache-Control: max-age=0
X-Forwarded-For: 192.168.159.1
X-Host: myhost
X-Forwarded-Proto: https
而当使用 Apache 时,我得到:
myhost@myhost:~$ nc -l 10000
ÌÈOPù¶°$óI¢ÚH,-ånú? ÆÀ2´ûZÀÀ
98ÀÀ5
À ÀÀ
ÀÀ 32EDÀÀ/AÀÀÀ
ÀÿD
42
#PuTTYPuTTYPuTTY^C
如您所见,这可能是 SSL 握手。此时中断 netcat 还会显示 Apache 错误消息“原因:与远程服务器进行 SSL 握手时出错”,因此我很确定这里确实发生了 SSL 握手。
也就是说Webmin是正确的,它收到的请求不是HTTPS,而是HTTP请求。
所以问题是,为什么 Apache 正确地使用 HTTPS 进行代理,而 lighttpd 使用带有一些 X-Forwarded-Proto 的 HTTP 进行代理?如何使用 lighttpd 实现类似的 SSL 代理?
为了记录,我对配置文件进行了所有更改。我在 /etc/webmin/config 中添加了以下几行:
webprefix=/webmin
webprefixnoredir=1
referer=myhost
我在 lighttpd.conf 中为 lighttpd 添加了以下内容(产生了上述错误):
$HTTP["url"] =~ "^/webmin" {
proxy.server = ( "/webmin/" =>
( (
"strip-request-uri" => "/webmin",
"host" => "127.0.0.1",
"port" => 10000,
"fix-redirects" => 1
) ) )
}
我正在使用以下 Apache 配置文件(它可以正常工作):
LoadModule proxy_module modules/mod_proxy.so
LoadModule proxy_ftp_module modules/mod_proxy_ftp.so
LoadModule proxy_http_module modules/mod_proxy_http.so
LoadModule proxy_connect_module modules/mod_proxy_connect.so
ProxyPass /webmin/ https://myhost:10000/
ProxyPassReverse /webmin/ https://myhost:10000/
SSLProxyEngine On
<Proxy *>
allow from all
SSLRequireSSL
</Proxy>
<IfModule mod_ssl.c>
<VirtualHost _default_:443>
SSLEngine on
SSLCertificateFile /etc/ssl/certs/ssl-cert-snakeoil.pem
SSLCertificateKeyFile /etc/ssl/private/ssl-cert-snakeoil.key
</VirtualHost>
</IfModule>
答案1
没关系,现在可以工作了。
哦,等等,你以为就这些了吗?不,各位 Server Fault 和搜索引擎用户,这里有一个指南,介绍如何在子文件夹中运行 Webmin 来设置 lighttpd。尽情享受吧!
先决条件
本指南的目标是设置 lighttpd 与 Webmin 的安装,以便可以通过 * 访问 Webmin 界面http://myhost/webmin。
撰写本指南时,当前的 Webmin 版本为 1.580,而使用的 lighttpd 版本为 1.4.28。我假设您已经安装了这两个版本。名称“myhost”始终表示运行 lighttpd 的计算机的主机名。
脚步
1.Webmin 配置
正如 Apache 官方指南中提到的,您必须在 /etc/webmin/config 中添加以下行:
webprefix=/webmin
webprefixnoredir=1
referer=myhost
2. 在 Webmin 中禁用 SSL
是的,你没听错,正如 Shane Madden 在上面的评论中提到的那样,这并不危险,因为交流方式如下:
client <----SSL----> myhost <--Loopback--> myhost:10000
Webmin 将通过机器内部的环回设备与在 myhost 上运行的 lighttpd 实例进行通信,通常只有超级用户权限才能查看。客户端和 lighttpd 之间的通信仍将使用 SSL。
那么如何在 Webmin 中禁用 SSL?只需在 /etc/webmin/miniserv.conf 中编辑以下行:
ssl=0
3.Lighttpd配置
将以下行添加到您的 /etc/lighttpd/lighttpd.conf:
$HTTP["url"] =~ "^/webmin" {
magnet.attract-physical-path-to = ( "/var/www/webmin/conf/webmin-rewrite.lua" )
proxy.server = ( "" =>
( (
"host" => "127.0.0.1",
"port" => 10000,
) ) )
}
如您所见,我们检查 URL 是否以“/webmin”开头,并重定向到监听 127.0.0.1:10000 的 Webmin 实例。但是,Webmin 不希望其请求 URL 中包含额外的路径“.../webmin”,因此我们必须从 URL 中删除该路径。但是,由于我们处于 $HTTP["url"] 条件中,因此我们不能使用 mod_rewrite 提供的任何 URL 重写技术。(否则我们只需说“strip-request-uri”=>“/webmin”,但这不起作用。这是 lighttpd 1.4 的一个已知且不会修复的问题。另请参阅 mod_rewrite 文档。)但是,我们可以使用 mod_magnet 在 LUA 脚本中重写 URL。
4. mod_magnet 的 LUA 脚本
创建 /var/www/webmin/conf/webmin-rewrite.lua,内容如下:
subfolder = "/webmin"
n = string.len(subfolder)
if string.sub(lighty.env["request.uri"], 1, n) == subfolder then
lighty.env["request.uri"] = string.sub(lighty.env["request.uri"], n+1)
end
这将从请求 URL 中删除“/webmin”前缀。
5. 修改代码以修复重定向
这几乎已经起作用了,但是,Webmin 的重定向代码中仍然存在一个错误,也提到了这里在 /usr/share/webmin/miniserv.pl 中,将以下行
&write_data("Location: $prot://$host$portstr$in{'page'}\r\n");
到
&write_data("Location: $prot://$host$config{'subfolder_prefix'}$in{'page'}\r\n");
并在 /etc/webmin/miniserv.conf 中添加以下行:
subfolder_prefix=/webmin
这修复了 Webmin 登录重定向,您就完成了!
进一步说明
从 lighttpd 1.5 版开始,您可能可以用 mod_proxy_core 替换 LUA 脚本,因为它能够重写请求 URL。不过,我没有尝试过。
此外,由于不再需要从外部访问端口 10000,我建议阻止它:
iptables -A INPUT -i eth0 -p tcp --dport 10000 -j REJECT --reject-with tcp-reset
但是,此命令可能因您的本地配置而异。