
我有客戶端連接到我的 WebSockets 遊戲伺服器來玩線上瀏覽器遊戲。遊戲伺服器在玩家開始遊戲時創建和銷毀,因此每個伺服器可以有一個我無法控制的不同IP位址。
我需要 WebSockets 是安全的(WSS),所以我有一個帶有 SSL 憑證的 nginx 代理程式。客戶端接收遊戲伺服器的 IP,但不是直接連線(不安全),而是透過我的 nginx 伺服器,將遊戲伺服器 IP 作為查詢參數。
問題是:現在任何人都可以使用我的 nginx 伺服器來代理他們選擇的任何 IP。我需要的是確保 nginx 僅代理的方法我的遊戲伺服器。
我無法控制遊戲伺服器 IP,因為它是外部主機,但我擁有遊戲伺服器代碼。我的 nginx 代理由我託管,但遊戲伺服器由提供者託管。
我的計劃是在遊戲伺服器和 nginx 上有一個共享金鑰,並用它加密所有流量,但我正在努力找出如何做到這一點。
這是我到目前為止所做的事情(基於在這個要點上):
我創建了自己的自簽名 CA 憑證:
openssl genrsa -des3 -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt
我為遊戲伺服器創建了一個憑證:
openssl genrsa -out gameserver.key 2048
openssl req -new -key gameserver.key -out gameserver.csr
openssl x509 -req -in gameserver.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out gameserver.crt -days 500 -sha256
我對 nginx 伺服器做了同樣的事情(需要嗎?注意:不需要):
openssl genrsa -out nginx.key 2048
openssl req -new -key nginx.key -out nginx.csr
openssl x509 -req -in nginx.csr -CA rootCA.crt -CAkey rootCA.key -CAcreateserial -out nginx.crt -days 500 -sha256
我的 nginx 設定是這樣的:
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
# these are for game client
ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;
location / {
if ( $arg_host != "" ) {
proxy_pass https://$arg_host:$arg_port;
}
proxy_ssl_certificate nginx.crt;
proxy_ssl_certificate_key nginx.key;
proxy_ssl_trusted_certificate rootCA.crt;
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}
}
gameserver.key
我的遊戲伺服器是一個使用和 的WebSockets 伺服器gameserver.csr
。
但是,當我嘗試時,nginx 錯誤日誌顯示:
upstream SSL certificate verify error: (18:self signed certificate) while SSL handshaking to upstream
我不確定這是否可行,以及我哪裡出錯了?這唯一的文章我發現提到此錯誤表明遊戲伺服器憑證不受信任,但我不明白為什麼。
我也不確定Common Name
創建證書時應該賦予什麼值(因為每個遊戲伺服器都在自己的 IP 上)以及這是否是一個問題。
答案1
我建議為後端設定內部憑證授權機構,並要求您的後端可以透過該憑證授權單位進行驗證,您可以引導這些憑證以包含它們的 IP,或使用通用主機名稱覆蓋 IP(我認為這會就夠了)。
- 創建一個僅限內部的 CA,將其稱為“遊戲伺服器後端”
- 建立一個僅供內部使用的伺服器證書,將其命名為“gameserver.auth.backend”
- 使用 gameserver.auth.backend 作為 websocket 節點程式上的憑證
- 告訴 nginx 進行驗證,用您指定的名稱(而不是 IP)覆蓋通用名稱
http {
map $http_upgrade $connection_upgrade {
default upgrade;
'' close;
}
server {
listen 443 ssl;
# these are for game client
ssl_certificate /etc/letsencrypt/live/mywebsite.com/fullchain.pem;
ssl_certificate_key /etc/letsencrypt/live/mywebsite.com/privkey.pem;
location / {
if ( $arg_host != "" ) {
proxy_pass https://$arg_host:$arg_port;
}
proxy_ssl_verify on;
proxy_ssl_verify_depth 2;
proxy_ssl_name gameserver.auth.backend;
proxy_ssl_server_name on;
proxy_ssl_trusted_certificate GameserverCA.crt;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection $connection_upgrade;
proxy_set_header Host $host;
proxy_read_timeout 86400;
}
}
}