前言
研究室最近分配了個任務,要求在研究室伺服器上架設一個資訊共享系統,便於高年級生畢業後做資訊引繼,但有以下要求:
- 使用盡可能方便
- 由於是面向研究室內的系統,因此私密性需要保證
對於第一點,我思考了兩個方案,第一種是延用往年的解決方案:使用開源軟體GROWI直接重新構建一個輕量的情報分享系統,但當我翻閱文件準備安裝docker來構建專案時,才聽說教授提供的伺服器配置是
CPU:2 cores, Memory:1G
,初次啟動直接把伺服器給down掉了,對於一個還同時執行其他服務的小心server使用docker未免有些牽強,因此我放棄了這個方案(後來才發現GROWI官方有提供基於NodeJS的安裝指南); 第二種是使用Gitbook構建靜態的文件站點,當時第一反應想到Gitbook主要還是由於它的知名度,等我實際去原repo查閱部署方案時發現專案已經幾乎停止維護,Gitbook團隊貌似已經專注於Gitbook的商業化事業,想要有較好的使用體驗只能去官網註冊賬號使用雲服務,這與本次任務的私密性和定製化要求顯然是相違背的,因此我選擇去尋找Gitbook的替代產品。最終我找到了Docsify.
本文主要就實現前言中的要求2進一步展開說明。
實現的思路是利用前端伺服器(即中間伺服器)反向代理客戶端的應用請求,並將請求轉發到實際部署應用的後端應用伺服器,對於同一臺機器而言(假設應用實際部署在2367埠),在預設情況下前端相當於監聽該機器80埠的虛擬伺服器(本文使用Apache),後端相當於監聽2367埠的虛擬伺服器(本文使用Nginx).
對於Nginx和Apache的區別:
- Nginx高度模組化設計,編寫配置簡單,處理靜態檔案速度高於Apache,記憶體佔用較少,同時併發性較好(非同步非阻塞型),適合做前端伺服器
- Apache非常穩定,動態頁面處理能力高,模組非常豐富,rewrite效能強大
因此對於單獨選擇其中一種web伺服器來構建專案時,如果追求專案效能,可以使用Nginx;相對的如果追求穩定性以及更多配置選項,建議使用Apache。對於兩者結合使用來說,Nginx更適合作為前端來擔任負載均衡和反向代理,將Apache用作後端伺服器來處理動態請求。本文是在現有配置的基礎(Apache監聽80埠)並且不方便修改配置的情況下,用Apache作為前端反向代理,並不盲目推薦仿造該做法,應根據實際情況進行調整。
構建過程
具體構建過程如下圖所示:
左邊的綠框表示基於Apache構建的反向代理伺服器,右邊的粉框表示基於Nginx構建的應用伺服器。反向代理伺服器除了基礎的反向代理配置以外,還加了一層ip過濾,用來阻止校園網以外ip(因為對於我的需求來說,應用的受訪物件是學校研究室)的訪問;應用伺服器上除了配置應用以外還增加了一個登入認證的環節(使用者名稱密碼)來過濾研究室成員以外的訪問。Apache和Nginx間新增了個白名單,使得應用伺服器只能接受來自反向代理伺服器的請求(這樣外部即使探測到應用的地址也無法直接訪問)。
反向代理
Apache的配置如下:
# Include module configuration:
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
# Include list of ports to listen on
Include ports.conf
#NameVirtualHost *:443
<VirtualHost *:443>
ServerName abc.example.com
ServerAlias abc.example.com
ProxyRequests Off
<Proxy "*">
Require ip yyy.yyy.yyy.yyy/zz
</Proxy>
ProxyPass / http://xxx.xxx.xxx.xxx:2367/
ProxyPassReverse / http://xxx.xxx.xxx.xxx:2367
SSLCertificateFile "/path/to/your/sslcert/fullchain.pem"
SSLCertificateKeyFile "/path/to/your/sslcert/privkey.pem"
</VirtualHost>
其中要注意的是,Apache的反向代理功能是需要手動開啟的。首先需要向apache.conf
裡匯入mod_proxy
,mod_proxy_http.so
,mod_proxy_connect.so
這三個模組。如果你是FreeBSD,你只需要在httpd.conf
上把註釋取消掉,並重啟服務後就可以了;但如果你使用的是Ubuntu,與sites-available
和sites-enabled
的使用方法相同,mods-available
是所有模組的儲存目錄,但是服務載入的模組是儲存在mods-enabled
的。
這一點透過apache.conf
的以下幾行可以證實:
# Include module configuration:
IncludeOptional mods-enabled/*.load
IncludeOptional mods-enabled/*.conf
當apache服務執行時,只載入mods-enabled
裡面的模組,而部分模組在安裝時預設是不會載入的。(即該模組不會出現在mods-enabled
)
Apache給我們提供了a2enmod
指令幫助我們快速新增模組,相對的停用模組使用a2dismod
命令:
admin@ubuntu:~$ sudo a2enmod proxy proxy_http proxy_connect # 啟用模組
admin@ubuntu:~$ sudo a2dismod proxy proxy_http proxy_connect # 停用模組
啟用之後,指定的模組會以軟連結的形式被放進mods-enabled
中,重啟服務生效。
新增模組之後,需要在apache.conf
中新增如下行即可啟用反向代理功能。
ProxyRequests Off
新增如下行設定你的代理目標
ProxyPass / http://xxx.xxx.xxx.xxx:2367/
ProxyPassReverse / http://xxx.xxx.xxx.xxx:2367
新增ip白名單,你可以指定具體ip,也可以像我一樣限定一個網段。
<Proxy "*">
Require ip yyy.yyy.yyy.yyy/zz
</Proxy>
新增https證照,關於代理伺服器與應用伺服器是否需要https這一點可以參考反向代理伺服器代理HTTPS。
SSLCertificateFile "/path/to/your/sslcert/fullchain.pem"
SSLCertificateKeyFile "/path/to/your/sslcert/privkey.pem"
至此,反向代理伺服器的配置到此為止。
應用伺服器
Nginx的配置如下,筆者配置的是靜態頁面,php等動態應用請根據Nginx文件自行調整:
server {
listen 2367;
listen [::]:2367;
root /path/to/app;
# Add index.php to the list if you are using PHP
index index.html index.htm;
server_name _;
auth_basic "Please enter your username and password.";
auth_basic_user_file /path/to/your/htpasswd;
location / {
# First attempt to serve request as file, then
# as directory, then fall back to displaying a 404.
try_files $uri $uri/ =404;
alias /path/of/your/app/;
index index.html;
}
}
以下開始說明。在/etc/nginx/sites-availble/
下以預設模板建立一個全新的配置檔案,將其軟連結到/etc/nginx/sites-enabled/
:
sudo touch /etc/nginx/sites-available/mysite.conf
sudo ln -s /etc/nginx/sites-available/mysite.conf /etc/nginx/sites-enabled/mysite.conf.enable
使用絕對路徑,不然會報錯。
應用的部署配置,根據你的實際情況進行編寫。
登入驗證我們透過nginx配置以及htpasswd工具實現。htpasswd是一款Apache內建的使用者名稱密碼生成工具,使用方法如下:
$ htpasswd -c /usr/local/nginx/password username
# 假如我們想將驗證檔案儲存在/usr/local/nginx/下
# 檔名為password,登入使用者名稱為username
# 回車後輸入密碼
# -c 建立加密檔案
至此登入資訊建立完畢,將驗證資訊寫入網站配置檔案中:
auth_basic "Please enter your username and password.";
auth_basic_user_file /usr/local/nginx/password;
實現效果如圖所示:
該實現是一個最基本的驗證功能,它有一個缺陷在於你無法設定登入過期時間,也就是說某臺裝置一次登入成功後它將一直保持登入成功狀態,直到網站cache被使用者手動清除。
配置完成後,重啟nginx伺服器生效。
代理伺服器與應用伺服器之間新增白名單
這部分實現很簡單粗暴,直接在應用伺服器上(Nginx)過濾除代理伺服器以外的所有請求即可,新增如下配置。
# Whitelist
allow zzz.zzz.zzz.zzz; # 反向代理伺服器的地址
deny all;
allow關鍵字後跟的ip以外的請求會全部deny掉。
尾聲
至此,全部實現的介紹完畢。
參考:
https://caloskao.org/ubuntu-a...
https://www.cnblogs.com/kevin...
https://segmentfault.com/a/11...