
Tengo clientes que se conectan a mi servidor de juegos WebSockets para jugar un juego de navegador en línea. Los servidores de juegos se crean y destruyen cuando los jugadores inician juegos, por lo que cada servidor puede tener una dirección IP diferente que no puedo controlar.
Necesito que WebSockets sea seguro (WSS), así que tengo un proxy nginx con un certificado SSL. El cliente recibe la IP del servidor del juego, pero en lugar de conectarse directamente (inseguro), pasa a través de mi servidor nginx con la IP del servidor del juego como parámetro de consulta.
Aquí está el problema: ahora cualquiera puede usar mi servidor nginx para utilizar cualquier IP que elija. Lo que necesito es una manera de asegurar que nginx solo esté haciendo proxy amiservidores de juegos.
No tengo control de las IP del servidor del juego ya que es un host externo, pero soy dueño del código del servidor del juego. Mi proxy nginx está alojado en mí, pero los servidores del juego están alojados en un proveedor.
Mi plan era tener una clave secreta compartida en el servidor del juego y nginx y cifrar todo el tráfico con eso, pero estoy luchando por descubrir cómo se puede hacer.
Esto es lo que he hecho hasta ahora (basado enen esta esencia):
Creé mi propio certificado de CA autofirmado:
openssl genrsa -des3 -out rootCA.key 4096
openssl req -x509 -new -nodes -key rootCA.key -sha256 -days 1024 -out rootCA.crt
Creé un certificado para el servidor del juego:
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
Hice lo mismo para el servidor nginx ( ¿es necesario? Nota: no es necesario):
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
Mi configuración de nginx es algo como esto:
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;
}
}
}
Mi servidor de juegos es un servidor WebSockets que usa gameserver.key
y gameserver.csr
.
Sin embargo, cuando lo intento, los registros de errores de nginx muestran:
upstream SSL certificate verify error: (18:self signed certificate) while SSL handshaking to upstream
No estoy seguro de si esto puede funcionar y ¿en qué me equivoqué? Elsolo articuloDescubrí que mencionar este error sugiere que el certificado del servidor del juego no es confiable, pero no puedo entender por qué.
Tampoco estoy seguro de qué valor debería ponerle al Common Name
crear certificados (ya que cada servidor de juego tiene su propia IP) y si esto es un problema o no.
Respuesta1
Lo que sugeriría es configurar una autoridad de certificación interna para los backends y exigir que sus backends puedan verificarse con esa autoridad de certificación; puede iniciar estos certificados para incluir su IP o anular la IP con un nombre de host común (lo que creo que sería satisfacer).
- cree una CA solo interna, llámela "Gameserver Backend"
- cree un certificado de servidor solo interno, llámelo "gameserver.auth.backend"
- use gameserver.auth.backend como su certificado en su programa de nodo websocket
- dígale a nginx que valide con eso, anulando el nombre común con el que especificó (en lugar de la 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;
}
}
}