今天的內容又是關於反向代理、效能與安全性的提升。不過,關於安全性的部分設定,往往需要透過限制某些功能或增加檢查來達成。因此,在進行正式佈署前,務必測試這些變更是否對系統原本的設計造成影響。
為了開發方便,odoo 會直接在每個模組中提供所有靜態檔案,開發者在本地環境中可以快速存取這些資源,無需額外設定;然而,當系統進入生產環境時,因為這些檔案會與其他對 odoo 的動態請求競爭伺服器資源,導致效能下降。因此,為了改善系統的效能,應該將靜態檔案交由 NGINX 這種專門的靜態 HTTP 伺服器處理。
在網頁安全領域,XSS(跨站腳本攻擊,Cross-Site Scripting) 是一種常見的攻擊方式。攻擊者利用網站的漏洞,將惡意的腳本程式注入到網頁中。當其他使用者瀏覽受感染的頁面時,這些惡意腳本就會在他們的瀏覽器中執行。這可能導致:
CSP(內容安全政策,Content Security Policy) 是一種用來防止 XSS 攻擊的瀏覽器安全機制。它透過讓網站管理員制定一組規則,告訴瀏覽器應該允許或阻止哪些類型的資源載入和執行。
當我們瀏覽一個網頁時,瀏覽器會從伺服器請求並載入各種資源,例如:
這些資源可能來自於同一個網站(同源),也可能來自於其他網站(跨源)。在沒有適當限制的情況下,惡意資源可能會被載入並執行,帶來安全風險。
透過設定 CSP,網站可以指定哪些來源的資源是被信任的,瀏覽器只會載入和執行這些被允許的資源。例如:
為了讓 nginx 能夠存取這些靜態檔案,我們需要在 docker-compose.yml
的反向代理容器中掛載相應的檔案:
# 掛載 odoo 靜態檔案來處理(如 JS、CSS 等靜態資源)
- ./odoo-dev/source/addons:/opt/odoo-dev/addons:ro
- ./odoo-dev/source/odoo:/opt/odoo-dev/core:ro
這樣,我們就能夠在 /opt/odoo-dev
路徑下訪問到 odoo 的靜態資源。
odoo 的靜態檔案位於每個模組的 static/
資料夾中,因此可以透過攔截所有 /MODULE/static/FILE
的請求,並根據不同的 addons
路徑查找相應的模組與檔案,來服務這些靜態檔案。
另外我們同時進行建議的 CSP 設定,為伺服器傳遞的所有圖片設置 Content-Security-Policy: default-src 'none'
標頭:雖然使用者無法修改或注入模組的 static/
資料夾內容,且已存在的圖片也是最終版本(不會自行抓取新的資源),但這仍然是一種良好的安全實踐。
首先,在 nginx.conf
中添加以下 map
區塊:
# 根據傳遞的內容類型設置 Content-Security-Policy 標頭,只對圖片資源應用安全策略
map $sent_http_content_type $content_type_csp {
default "";
~image/ "default-src 'none'";
}
接下來,在 nginx_odoo.conf
的 odoo-dev server {}
區塊中加入:
# 定義一個命名位置,用於將未被其他規則處理的請求代理到 odoo 伺服器
location @odoo { # 內容跟 default 的 location / 一樣
set $upstream odoo-dev:8069;
proxy_pass http://$upstream;
include /etc/nginx/conf.d/proxy_odoo_http.include;
}
# 匹配所有指向模組靜態資源的請求,直接由 NGINX 服務
location ~ ^/[^/]+/static/.+$ {
# 指定靜態檔案的根目錄,我們設定為 /opt/odoo-dev
root /opt/odoo-dev;
# 按照順序嘗試在指定路徑中尋找請求的檔案
# 如果都找不到,則將請求轉發到 @odoo
try_files /core/odoo/addons$uri /core/addons$uri /addons$uri @odoo;
# 設置客戶端快取過期時間為 24 小時
expires 24h;
# 添加 Content-Security-Policy 標頭,應用我們在 map 中定義的策略
add_header Content-Security-Policy $content_type_csp;
}
設定好後,我測試了在同樣的操作下登入 odoo,並觀察 odoo container 的 log 差異。原本在未設定反向代理處理靜態檔案時,有大約 60 個請求;設定完成後,請求數量減少到了約 20 個。像下方這些關於 static
資源的請求,都已經由 reverse-proxy 直接處理掉了。
2024-10-10 15:50:06 2024-10-10 07:50:06,342 90 INFO ? werkzeug: 172.19.0.1 - - [10/Oct/2024 07:50:06] "GET /website_hr_recruitment/static/description/icon.png HTTP/1.0" 200 - 0 0.000 0.001
2024-10-10 15:50:06 2024-10-10 07:50:06,344 95 INFO ? werkzeug: 172.19.0.1 - - [10/Oct/2024 07:50:06] "GET /base/static/img/icons/sale_amazon.png HTTP/1.0" 200 - 0 0.000 0.001
2024-10-10 15:50:06 2024-10-10 07:50:06,355 92 INFO ? werkzeug: 172.19.0.1 - - [10/Oct/2024 07:50:06] "GET /base/static/img/icons/sale_ebay.png HTTP/1.0" 200 - 0 0.000 0.002
2024-10-10 15:50:06 2024-10-10 07:50:06,359 92 INFO ? werkzeug: 172.19.0.1 - - [10/Oct/2024 07:50:06] "GET /hr_contract/static/description/icon.png HTTP/1.0" 200 - 0 0.000 0.002
透過今天設定,我們可以直接使用 reverse-proxy 來處理 odoo 的靜態檔案,提升整體系統的效能。還有設定適當的安全標頭也能增強系統的安全性,明天會繼續處理類似的問題。