如何在Nginx Proxy Manager上添加NTLM模組
先前介紹過 Nginx Proxy Manager 這個以 Nginx 為底的代理伺服器,之前我的 LAB 是用 host 上的 IIS 當 Proxy,最近才慢慢把 IIS 上的Proxy全部遷移到NPM上。
但是我的 LAB 裡面剛好有一台 MS 的 Exchange 伺服器,Proxy設定好沒問題,OWA 也進得去,但是如果用 Outlook 之類的 Client 會登不進去,會一直跳出登入視窗,就算你輸入正確的帳號密碼也還是會跳出。
甚至網路上各種設定 Proxy 標頭的方法都試過了,依舊還是不行…
我用 Microsoft Remote Connectivity Analyzer 下去檢查,結果回報的是 401 錯誤,後來 Google 了一下發現 Nginx 一般版本是不支援 NTLM Authentication功能的,也就是說我們輸入的帳號密碼過了 Nginx 送到後面 Exchange 根本看不懂,自然也就拒絕給你登入了。
如果要讓 Nginx 支援 NTLM 功能,就必須買商業版的授權,具這篇文章介紹一年要 2,500$usd/year,我只是個興趣架設的 LAB 環境可付不起這麼高昂的費用。
不過 Nginx 關了一扇門又開了一扇窗,畢竟 Nginx 就算被收購了,免費版還是開源的,並且支援外掛模組,網路上就有人發佈 Nginx NTLM的模組,只要將這個模組一起編譯進 Nginx 裡面就可以使用 NTLM功能了。
但是 Nginx Proxy Manager 是在 Docker 上面建立的,當初安裝的時候都幫我們編譯好了,要再另外編譯模組進去有點難度。
又剛好在Nginx Proxy Manager的 Github 上有一個 PR,希望可以把這個外掛的NTLM模組一起包進 Nginx Proxy Manager 裡面,而且裡面有教你如何讓 Nginx Proxy Manager 直接就地支援NTLM功能,媽呀根本直接看到救星!
我照著做後發現確實可以直接讓 Nginx Proxy Manager 支援NTLM,而且 Proxy設定好後 Exchange確實不會再跳出登入視窗了。
過程稍微有點複雜不過還算簡單,如果要讓 Nginx Proxy Manager 支援NTLM 就繼續往下看吧。
操作環境為 Ubuntu server 24.04,Nginx Proxy Manager版本為v2.12.1
將docker-nginx-full下載到本地
git clone https://github.com/NginxProxyManager/docker-nginx-full
修改build-openresty
nano docker-nginx-full/scripts/build-openresty
將原本裡面的內容全部清除,貼上下面文字
#!/bin/bash -e
BLUE='\E[1;34m'
CYAN='\E[1;36m'
YELLOW='\E[1;33m'
GREEN='\E[1;32m'
RESET='\E[0m'
echo -e "${BLUE}❯ ${CYAN}Building OpenResty ${YELLOW}${OPENRESTY_VERSION} with nginx_http_geoip2 and nginx-ntlm module...${RESET}"
cd /tmp
wget "https://openresty.org/download/openresty-${OPENRESTY_VERSION}.tar.gz"
tar -xzf openresty-${OPENRESTY_VERSION}.tar.gz
mv /tmp/openresty-${OPENRESTY_VERSION} /tmp/openresty
git clone https://github.com/leev/ngx_http_geoip2_module.git
mv /tmp/ngx_http_geoip2_module /tmp/openresty/ngx_http_geoip2_module
git clone https://github.com/gabihodoroaga/nginx-ntlm-module.git
mv /tmp/nginx-ntlm-module /tmp/openresty/nginx-ntlm-module
cd /tmp/openresty
./configure \
--prefix=/etc/nginx \
--sbin-path=/usr/sbin/nginx \
--modules-path=/usr/lib/nginx/modules \
--conf-path=/etc/nginx/nginx.conf \
--error-log-path=/var/log/nginx/error.log \
--http-log-path=/var/log/nginx/access.log \
--pid-path=/var/run/nginx.pid \
--lock-path=/var/run/nginx.lock \
--http-client-body-temp-path=/var/cache/nginx/client_temp \
--http-proxy-temp-path=/var/cache/nginx/proxy_temp \
--http-fastcgi-temp-path=/var/cache/nginx/fastcgi_temp \
--http-uwsgi-temp-path=/var/cache/nginx/uwsgi_temp \
--http-scgi-temp-path=/var/cache/nginx/scgi_temp \
--user=nginx \
--group=nginx \
--with-compat \
--with-threads \
--with-http_addition_module \
--with-http_auth_request_module \
--with-http_dav_module \
--with-http_flv_module \
--with-http_gunzip_module \
--with-http_gzip_static_module \
--with-http_mp4_module \
--with-http_random_index_module \
--with-http_realip_module \
--with-http_secure_link_module \
--with-http_slice_module \
--with-http_ssl_module \
--with-http_stub_status_module \
--with-http_sub_module \
--with-http_v2_module \
--with-mail \
--with-mail_ssl_module \
--with-stream \
--with-stream_realip_module \
--with-stream_ssl_module \
--with-stream_ssl_preread_module \
--add-dynamic-module=/tmp/openresty/ngx_http_geoip2_module \
--add-dynamic-module=/tmp/openresty/nginx-ntlm-module
make -j2
echo -e "${BLUE}❯ ${GREEN}OpenResty build completed${RESET}"
執行local-build.sh
切換到docker-nginx-full目錄
cd docker-nginx-full
執行local-build.sh
bash local-build.sh
之後就會開始在docker上編譯Nginx,過程需要一段時間,編譯完成後會跳出All done!
搜尋編譯好的ngx_http_upstream_ntlm_module.so
find / -type f -name ngx_http_upstream_ntlm_module.so
正常搜尋會跑出三個ngx_http_upstream_ntlm_module.so,隨便挑一個都可以
將編譯好的NTLM模組放進Nginx Proxy Manager裡面
先回到Nginx Proxy Manager的nginx資料夾
cd ~/nginx-proxy-manager/data/nginx
建立custom與modules資料夾
mkdir custom
mkdir modules
先切換到modules資料夾
cd modules
將剛編譯好的NTLM模組複製到modules資料夾
以/var/lib/docker/overlay2/vql6ayw8lerc8h78o4sht2om9/diff/usr/lib/nginx/modules/ngx_http_upstream_ntlm_module.so為例
cp /var/lib/docker/overlay2/vql6ayw8lerc8h78o4sht2om9/diff/usr/lib/nginx/modules/ngx_http_upstream_ntlm_module.so ngx_http_upstream_ntlm_module.so
確認一下有沒有把模組複製進來
ls
載入 NTLM 模組並新增 NTLM 感知上游目標
切換到custom資料夾
cd ../custom
新增 root_top.conf 以載入模組
nano root_top.conf
在 root_top.conf 裡面貼下以上內容並存檔退出
load_module /data/nginx/modules/ngx_http_upstream_ntlm_module.so;
新增 http.conf 以定義 NTLM 感知上游目標
nano http.conf
在root_top.conf裡面貼下以上內容並存檔退出
記得將server的IP位置改成你要使用NTLM的伺服器
upstream target {
server 192.168.1.1:443;
ntlm;
}
重啟Nginx Proxy Manager
docker restart nginx-proxy-manager_app_1
到這裡基本上就結束了,下來就換進到Nginx Proxy Manager的網頁上操作了。
打開Nginx Proxy Manager管理網頁,選擇你要使用NTLM的proxy,再把以下內容貼到選項卡中Advanced
。
location / {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass https://target;
}
之後點擊save存檔,基本上就大功告成了,NTLM 身份驗證應該正常運作。
現在你可以試試看是否可以正常登入了,如果都有照流程走登入應不會再跳出登入視窗,除非你帳號密碼打錯。
小提醒:這個方法不建議在正式環境中正式使用,如果有正式NTLM需求應該使用Nginx Plus版本。
這是NTLM模組作者自己說的,避免在正式使用中出現問題。
オマケ
如果你跟我一樣是用Nginx Proxy Manager代理MS Exchange的話,記得在 Custom locations
新增以下目錄
- /Autodiscover/Autodiscover.xml
- /owa
- /Microsoft-Server-ActiveSync
- /EWS
- /mapi
- /rpc
- /OAB
並且都要加上上面提到Advanced
裡面的內容,按旁邊的齒輪就可以開啟自訂窗格。
在location後方的斜線記得改成目錄名子,例如:/owa
#location後方的斜線記得改成目錄名子,例如:/owa
location /owa {
proxy_http_version 1.1;
proxy_set_header Connection "";
proxy_pass https://target;
}