[Apache][Nginx]構建僅對團隊內部公開使用的web應用

Kiotlin發表於2021-11-06

前言

研究室最近分配了個任務,要求在研究室伺服器上架設一個資訊共享系統,便於高年級生畢業後做資訊引繼,但有以下要求:

  1. 使用盡可能方便
  2. 由於是面向研究室內的系統,因此私密性需要保證

對於第一點,我思考了兩個方案,第一種是延用往年的解決方案:使用開源軟體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作為前端反向代理,並不盲目推薦仿造該做法,應根據實際情況進行調整。

構建過程

具體構建過程如下圖所示:
image.png
左邊的綠框表示基於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_proxymod_proxy_http.somod_proxy_connect.so這三個模組。如果你是FreeBSD,你只需要在httpd.conf上把註釋取消掉,並重啟服務後就可以了;但如果你使用的是Ubuntu,與sites-availablesites-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;

實現效果如圖所示:
image.png
該實現是一個最基本的驗證功能,它有一個缺陷在於你無法設定登入過期時間,也就是說某臺裝置一次登入成功後它將一直保持登入成功狀態,直到網站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...

相關文章