SSL 權限錯誤:帶有 HTTPS 的 Node.js + Let's Encrypt SSL + Apache + 非 Root 用戶

SSL 權限錯誤:帶有 HTTPS 的 Node.js + Let's Encrypt SSL + Apache + 非 Root 用戶

我設定了 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>

相關內容