
У меня есть клиенты, подключающиеся к моему игровому серверу WebSockets для онлайн-браузерной игры. Игровые серверы создаются и уничтожаются, когда игроки начинают игру, и поэтому каждый сервер может иметь свой IP-адрес, который я не могу контролировать.
Мне нужно, чтобы WebSockets были безопасными (WSS), поэтому у меня есть прокси nginx с сертификатом SSL. Клиент получает 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;
}
}
}
Мой игровой сервер — это сервер WebSockets, использующий gameserver.key
и 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 Backend»
- создайте только внутренний сертификат сервера, назовите его «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;
}
}
}