子文件夾中的 lighttpd + Webmin
我正在使用 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.
所以我對這個問題進行了更深入的研究。我沒有執行 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 使用 HTTP 和一些 X-Forwarded-Proto 進行代理?如何使用 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>
沒關係,現在開始工作了。
哦等等,你以為就這些了?不,其他伺服器故障和搜尋引擎使用者,這裡是關於如何設置 lighttpd 的指南,Webmin 在子文件夾中執行。享受!
先決條件
本指南的目標是與 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
- 在 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”前綴。
- 修復重定向的程式碼更改
這已經幾乎可以工作了,但是,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 版開始,您可能可以將 LUA 腳本替換為 mod_proxy_core,因為它能夠重寫請求 URL。但是,我沒有嘗試過。
此外,由於不再需要從外部訪問埠 10000,我建議將其阻止:
iptables -A INPUT -i eth0 -p tcp --dport 10000 -j REJECT --reject-with tcp-reset
但是,此命令可能會因您的本地配置而異。