子文件夹中的 lighttpd + Webmin

Edw*_*ler 1 lighttpd

我正在使用 Webmin 进行家庭服务器管理。

我不想在默认端口 ( https://myhost: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.
Run Code Online (Sandbox Code Playgroud)

所以我更深入地研究了这个问题。我没有运行 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
Run Code Online (Sandbox Code Playgroud)

而在使用 Apache 时,我得到:

myhost@myhost:~$ nc -l 10000
ÌÈOPù¶°$óI¢ÚH,-ånú­? ÆÀ2´ûZÀÀ
98ÀÀ5
À    ÀÀ
ÀÀ      32EDÀÀ/AÀÀÀ
ÀÿD

42
#PuTTYPuTTYPuTTY^C
Run Code Online (Sandbox Code Playgroud)

如您所见,这可能是一次 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
Run Code Online (Sandbox Code Playgroud)

我在 lighttpd.conf 中为 lighttpd 添加了以下内容(产生上述错误):

$HTTP["url"] =~ "^/webmin" {
   proxy.server  = ( "/webmin/" =>
     ( (
        "strip-request-uri" => "/webmin",
        "host" => "127.0.0.1",
        "port" => 10000,
        "fix-redirects" => 1
     ) ) )
}
Run Code Online (Sandbox Code Playgroud)

我正在为 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>
Run Code Online (Sandbox Code Playgroud)

Edw*_*ler 5

没关系,现在开始工作了。


哦等等,你以为就这些?不,Server Fault 和搜索引擎用户,这里是有关如何在子文件夹中运行 Webmin 的情况下设置 lighttpd 的指南。享受!

先决条件

本指南的目标是与 Webmin 一起设置 lighttpd 安装,以便可以通过 * http://myhost/webmin访问 Webmin 界面。

编写本指南时,当前的 Webmin 版本为 1.580,使用的 lighttpd 版本为 1.4.28。我假设您已经安装了两者。名称“myhost”始终表示运行 lighttpd 的机器的主机名。

脚步

1.Webmin配置

就像 Apache 官方指南中提到的那样,您必须将以下行添加到 /etc/webmin/config:

webprefix=/webmin
webprefixnoredir=1
referer=myhost
Run Code Online (Sandbox Code Playgroud)

2. 在 Webmin 中禁用 SSL

是的,你没听错,正如 Shane Madden 在上面的评论中提到的,这并不是不安全的,因为通信看起来像这样:

client <----SSL----> myhost <--Loopback--> myhost:10000
Run Code Online (Sandbox Code Playgroud)

Webmin 将通过回送设备与在 myhost 上运行的 lighttpd 实例进行通信,该设备位于机器内部,通常只能使用超级用户权限来观察。客户端和 lighttpd 之间的通信仍将使用 SSL。

那么如何在 Webmin 中禁用 SSL?只需在 /etc/webmin/miniserv.conf 中编辑以下行:

ssl=0
Run Code Online (Sandbox Code Playgroud)

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,
    ) ) )
}
Run Code Online (Sandbox Code Playgroud)

如您所见,我们检查 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
Run Code Online (Sandbox Code Playgroud)

这会从请求 URL 中去除“/webmin”前缀。

5. 修改代码以修复重定向

这已经几乎可以了,但是,Webmin的重定向代码中仍然存在一个错误,这里也提到。在 /usr/share/webmin/miniserv.pl 中,更改行

&write_data("Location: $prot://$host$portstr$in{'page'}\r\n");
Run Code Online (Sandbox Code Playgroud)

&write_data("Location: $prot://$host$config{'subfolder_prefix'}$in{'page'}\r\n");
Run Code Online (Sandbox Code Playgroud)

在 /etc/webmin/miniserv.conf 中,添加以下行:

subfolder_prefix=/webmin
Run Code Online (Sandbox Code Playgroud)

这修复了 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
Run Code Online (Sandbox Code Playgroud)

但是,此命令可能因您的本地配置而异。