我設定了 Node.js 伺服器,並嘗試在 Apache 上將 HTTPS 與我的 Let's Encrypt 憑證結合使用。這是我設定的相關代碼:
var fs = require('fs'),
https = require('https'),
express = require('express'),
options = {
key: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/privkey.pem'),
cert: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/fullchain.pem'),
ca: fs.readFileSync('/etc/letsencrypt/live/www.mysite.com/chain.pem')
}, ...
當我嘗試啟動腳本時,出現以下錯誤:
Error: EACCES: permission denied, open '/etc/letsencrypt/live/www.mysite.com/privkey.pem'
這是因為只有 root 所有者擁有 SSL 的 Let's Encrypt 目錄和文件,目前我在 Apache 上的 30 多個常規網站都使用了 SSL。我正在嘗試為一個網站設定一個節點應用程式。我的節點 app.js 專案檔案歸 mysite1:mysite1 所有,我知道以非 root 使用者身分執行節點應用程式(如「mysite1」)應該會更安全。
讓我的 Let's Encrypt HTTPS 與 Node.js 應用程式(在 Apache 上)安全地工作的正確方法是什麼,而不必授予我的 /etc/letsencrypt 目錄 755 權限?
編輯-澄清:
Node.js 和 Apache 並行運行。在網站的 virtualHost .conf 檔案中,443 DocumentRoot 是 /home/mysite1/mysite1.com ,這就是安裝 Let's Encrypt SSL 的目的。
我的 Node.js 應用程式設定在 /home/mysite1/app 中。在網站上,我使用 socket.io 作為網站範圍的聊天室,它與以下內容連接/運作良好(如果應用程式以 root 使用者身分啟動),不需要 ProxyPass:
<script src="//www.mysite1.com:3000/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com:3000');</script>
當我以非 root 使用者身分執行應用程式時(出於安全目的),我看到的唯一錯誤是我的節點應用程式在嘗試存取/配置 SSL 檔案時出現權限錯誤。我具體應該做什麼,我不太清楚如何在 Apache“後面”運行這個,或者是否有更簡單的解決方案?
似乎必須有一個更簡單的解決方案,也許node.js以root身份運行來獲取SSL資料並讓伺服器運行,然後將其交給用戶,就像Apache一樣?
編輯2:
根據 Michael 和 ezra-s 的建議,我在 Google 上搜尋了一段時間,並更改了一些內容,但無法使其正常工作。在 Apache 中,我做了這樣的事情:
<VirtualHost *:443>
ServerAlias mysite1.com
DocumentRoot /home/mysite1/mysite1.com
DirectoryIndex index.html index.php
<Directory /home/mysite1/mysite1.com>
.. web config stuff
</Directory>
ProxyRequests Off
ProxyPreserveHost On
ProxyVia Full
<Proxy *>
Require all granted
</Proxy>
<Location /node>
ProxyPass http://127.0.0.1:3000
ProxyPassReverse http://127.0.0.1:3000
</Location>
SSLEngine on
Include /etc/letsencrypt/options-ssl-apache.conf
SSLCertificateFile /etc/letsencrypt/live/www.letshangout.com/fullchain.pem
SSLCertificateKeyFile /etc/letsencrypt/live/www.letshangout.com/privkey.pem
</VirtualHost>
在我的節點 app.js 專案檔案中,我刪除了 require('https') 和憑證選項,並將其替換為「http」套件,並嘗試初始化腳本。
在我網站的頁面上,我有嘗試加載 socket.io 並與節點應用程式連接的腳本:
<script src="https://www.mysite1.com/node/socket.io/socket.io.js"></script>
<script>var socket = io('https://www.mysite1.com/node/');</script>
當我載入頁面時,出現 500 錯誤且腳本未載入。我應該在 Apache 設定或腳本 URL 中更改哪些內容?我以前從未使用過節點代理,這是我的第一個節點應用程式。
解決方案:
我發現,這是涉及網路套接字和 javascript 的其他需要完成的事情的組合:
1) 用於處理 websocket 的 Apache 配置https://stackoverflow.com/a/41685748/2317571
2) 客戶端的 JavaScript Socket 連線配置https://stackoverflow.com/questions/22919276/how-to-connect-socket-io-through-a-reverse-proxy
3)(額外提示):感謝 Michael 和 ezra-s 的建議,讓 Node 應用程式位於 Apache 後面,我可以使用 ufw 防火牆並將 Node/socket.io 端口 3000 鎖定到 localhost - 少一個端口(以及安全性)洞)向世界開放。希望這些資訊可以幫助其他人。
答案1
1. 在連接埠上單獨執行 Node.js 應用程式。
2. 反向代理。
筆記:Node.js 應用程式和 Apache 之間的連接將使用 HTTP。然而,它只會發生在「本地主機」層級。因此,一切都會好起來的。
虛擬主機配置:
<VirtualHost *:443>
ServerName nodeapp.com
ServerAdmin webmas@localhost
DocumentRoot /var/www/nodeapp
SSLEngine on
SSLCertificateFile /path/to/cert
SSLCertificateKeyFile /path/to/key
ProxyRequests off
ProxyPass "/" "http://127.0.0.1:node_app_port/"
ProxyPassReverse "/" "http://127.0.0.1:node_app_port/"
ErrorLog ${APACHE_LOG_DIR}/nodeapp_error.log
CustomLog ${APACHE_LOG_DIR}/nodeapp_access.log combined
</VirtualHost>