Documentación de Steamworks
Steam Datagram Relay
Steam Datagram Relay (SDR) es la red virtual privada de juegos de Valve. Al usar nuestras API, no solo podrás pasar tu tráfico de juego a la red troncal de Valve que está dedicada a contenido de juego, sino que también obtienes acceso a nuestra red de retransmisores. Al usar nuestra red de retransmisión de tráfico proteges tus servidores y a tus jugadores de los ataque de denegación de servicio, ya que nunca se revelan las direcciones IP. Todo el tráfico que recibes es autenticado, cifrado y de frecuencia limitada. Además, para una cantidad sorprendentemente alta de jugadores podemos encontrar también una ruta más rápida en nuestra red, que en realidad mejora los tiempos de ping del jugador.

Esta red de retransmisión se puede usar tanto para tráfico de red entre pares como en servidores dedicados.

Requisitos generales y consejos para migrar código de red existente

A continuación tenemos información general a tomar en cuenta que es relevante para ambos P2P y la conectividad de un servidor dedicado.

Primero, cualquier lugar en donde los hosts de red se identifiquen por una IP pública (casi siempre este es el caso de los servidores de juegos) deberá cambiarse para usar un identificador diferente en su lugar. Hay muchas opciones para esto:
  • Para los clientes y los servidores de juego que inician sesión en Steam, normalmente utilizarás el id. de Steam.
  • Si tu servidor de juego no inicia sesión en Steam y estás utilizando un flujo de autenticación basado en tickets, puedes utilizar cualquier otro identificador que tenga sentido en tu caso. Ver SteamNetworkingIdentity.
  • En algunas bases de código es muy común suponer que los hosts de red y los servidores de juego se identifican usando una dirección IPv4, y cambiar ese supuesto requiere una cantidad de trabajo significativa. Ciertamente, Las API ISteamMatchmaking y ISteamMatchmakingServers de Steamworks tienen esta característica, al igual que algunos de nuestros juegos, como Team Fortress 2. En este caso puedes utilizar el sistema "Fake IP" de Steamworks. Un FakeIP es un IP que "parece" una dirección IPv4 válida para la mayoría de los propósitos, pero viene de un espacio de una dirección reservada que no se usa en internet. Al asignar un FakeIP a tu servidor, tu servidor todavía puede comunicarse usando una dirección IPv4 y casi todo "simplemente funcionará". Los sistemas ISteamNetworkingSockets y ISteamMatchmakingServers reconocen estos IP especiales y toman las medidas necesarias. Estos no son enrutables y no funcionarán para propósitos generales de internet (por ejemplo, no puedes hacerles ping). Consulta ISteamNetworkingSockets::BeginAsyncRequestFakeIP para obtener más información.

En segundo lugar, deberás modificar cualquier código de socket de bajo nivel para usar una de las API de Steamworks para conectividad.
  • Lo ideal es usar una de las interfaces de API enfocadas en conexiones, como ISteamNetworkingSockets, que devolverá HSteamNetConnection.
    (Ten en cuenta que estas API también son compatibles con el transporte UDP básico, lo cual es muy útil para hacer pruebas. Además, hay una versión de código abierto).
  • Algunas bases de códigos son escritas de una manera similar a UDP, donde los paquetes pueden ser enviados como ad-hoc a cualquier host remoto en cualquier momento, y no todos los mensajes son enviados a una "conexión" establecida. En estas situaciones, existen dos características de Steamworks que pueden ser útiles:
    • Utilizar ISteamNetworkingMessages para comunicarte con hosts identificados usando una API de tipo SteamNetworkingIdentity, tal como SteamID.
    • Utilizar ISteamNetworkingFakeUDPPort para comunicarse con hosts identificados que usen un FakeIP.

Requisitos para el uso de SDR en otras plataformas y tiendas

Una API de red y una solución DDoS para un juego multiplataforma no sirve de mucho si solo funciona en una plataforma. En la mayoría de los casos, cuando tus jugadores están en otras plataformas y tiendas pueden acceder a la red de retransmisión, siempre que tu juego cumpla unos requisitos básicos:
  • Disponer de una versión de tu juego distribuida en Steam.
  • Aceptar actualizar tu juego dentro de un tiempo razonable cuando se le solicite (digamos, unos pocos meses), en caso de que necesitemos publicar una correción de error o un parche de seguridad.
  • Entender que, desafortunadamente, no podemos prometer que este servicio esté siempre disponible para jugadores fuera de Steam. En el improbable caso que se necesite regresar a una versión anterior de este servicio, haremos todos lo posible para coordinarnos contigo para evitar interrumpir el servicio a tus jugadores, incluido el darte tiempo para planificar. El SDK tiene mecanismos internos tales como instruir a los clientes a recurrir a una conectividad de UDP directa o intentar una perforación NAT, pero también deberías tener esta posibilidad en mente.
  • Incluir algún tipo de servicio de emparejamiento (SDR llama a esto como tu "coordinador de juego"), el cual puede emitir credenciales de autenticación. Tenemos un SDK dedicado para esto. Ver más abajo.

Ponte en contacto con nosotros para obtener los SDK pertinentes e informarte de todos los detalles. Todavía estamos afinando detalles para encontrar la mejor manera de distribuir este código y, de momento, tal vez no podamos ofrecer compatibilidad entre plataformas para todos los asociados y todos los juegos.

A continuación puedes ver más detalles técnicos sobre la implementación de SDR en otras plataformas y tiendas.

Si no cumples los criterios mencionados arriba, no dudes en utilizar la versión de código abierto de la API para lo que quieras. Ten en cuenta que el código abierto no es compatible con el acceso a la red de retransmisión.

Juegos de red entre pares

Para el tráfico en redes entre pares en Steam, todo lo que hay que hacer para aprovechar el sistema SDR es utilizar API como ISteamNetworkingSockets::CreateListenSocketP2P y ISteamNetworkingSockets::ConnectP2P. Steam se encargará de todo lo demás. Para obtener información sobre la compatibilidad con otras plataformas y tiendas, consulta los requisitos técnicos adicionales que se mencionan a continuación.

Servidores dedicados en centros de datos conocidos

Las API de redes entre pares (P2P) funcionan sin problemas incluso cuando uno de los pares es un servidor dedicado. Pero hay una condición importante: si el servidor dedicado no está cerca de uno de los centros de datos en los que estamos ejecutando los retransmisores, la mejor ruta de retransmisión podría ser más lenta que la ruta IP predeterminada, resultando en una latencia peor que la del estado actual para algunos jugadores.

Para obtener una experiencia óptima en servidores dedicados, el servidor debe ejecutarse en un centro de datos conocido y que forme parte de la red SDR. Nos aseguraremos de que los retransmisores se están ejecutando cerca y de que la ruta de retransmisión no sea más lenta que la ruta IP predeterminada. Los servidores que se ejecutan en estos centros de datos conocidos se conectan a través de una API especial. Este tipo de casos se denomina «Servidor dedicado alojado» en el SDK. Ten en cuenta que esto no significa necesariamente que Valve sea el host de estos servidores o de los retransmisores. Puede que se trate de un centro de datos de terceros con el que tenemos una relación ya establecida y que es conocido dentro del sistema Steam Datagram Relay.

Si estás ejecutando servidores de juegos en un gran proveedor de servicios de hosting y estás interesado en usar SDR, ponte en contacto con nosotros. Intentaremos trabajar con tu proveedor de servicios de hosting para ejecutar los retransmisores en el centro de datos. Esa es la situación ideal, pero incluso si esto no es posible, puede que seamos capaces de añadir el centro de datos a nuestro sistema de configuración de red y simplemente usar retransmisores de Valve que estén cerca.

Si representas a una empresa proveedora de servicios de hosting de servidores dedicados y quieres formar parte de nuestra red para que tus clientes puedan sacar provecho de SDR, ¡contacta con nosotros! Aún no hemos implementado retransmisores en empresas proveedoras de servicios de hosting de terceros, aunque nos interesa hacerlo.

Flujo de conexión simple al servidor dedicado sin coordinador de juego

Si no tienes tu propia central de emparejamiento o un servicio de inicio de sesión (a veces se le llama "coordinador de juego") que asigne jugadores a los servidores, o si quieres hacerlo de manera sencilla, puedes conectarte a un servidor dedicado en un centro de datos conocido utilizando ISteamNetworkingSockets::CreateListenSocketP2P y ISteamNetworkingSockets::ConnectP2P. En este caso, la conexión comienza en el cliente como una conexión P2P ordinaria. Los mensajes de encuentro son enviados por Steam, si el jugador o el servidor pierden su conexión a Steam, la conexión no se puede establecer. Steam no restringe quién puede intentar conectarse, aparte de verificar que el jugador ha iniciado sesión en Steam y ya tiene el juego.

Flujo de conexión al servidor basado en tickets

Si tienes tu propio servicio de coordinador de juego, te recomendamos que utilices un flujo de conexión basado en tickets. Normalmente, el trabajo necesario es un poco mayor en comparación a un simple flujo de conexión de estilo P2P, y ofrece 2 ventajas importantes:
  • Solo emites tickets a jugadores que tienen permiso para intentar conectarse, así los intentos de conexión no deseados no llegarán a tu servidor.
  • Una vez que un jugador tenga un ticket, podrá conectarse al servidor incluso cuando pierda conexión a Steam, el servidor pierda conexión a Steam, el equipo del jugador falla o se reinicia, etc. Hacer que la reconexión a un servidor de juegos sea robusta para evitar estos fallos comunes es muy importante en cualquier juego que penalice a los jugadores por abandonarlo.

Una conexión basada en tickets a un servidor dedicado a través de SDR funciona así:
  • Cuando tu servidor de juego inicia sesión en el coordinador de juego, envía su SteamDatagramHostedAddress, que es una expresión opaca que incluye información física de enrutamiento. (Ver ISteamNetworkingSockets::GetHostedDedicatedServerAddress). También, ten en cuenta que tenemos algunas herramientas que puedes usar para ayudar con un inicio de sesión autenticado en tu coordinador de juego.
  • El servidor empieza escuchando el tráfico retransmitido utilizando ISteamNetworkingSockets::CreateHostedDedicatedServerListenSocket.
  • En un momento dado, tu cliente querrá entrar en un emparejamiento o conectarse a un servidor.
  • El cliente puede usar los métodos disponibles en la interfaz ISteamNetworkingUtils para obtener los tiempos de ping a los centros de datos y comprobar la conectividad. Probablemente vas a querer enviar esta información a tu coordinador de juego, para que pueda tomar las mejores decisiones sobre la asignación de jugadores a los centros de datos.
  • Cuando tu coordinador de juego esté listo para autorizar a un cliente a conectarse a un servidor, generará una SteamDatagramRelayAuthTicket y la firma con tu clave secreta. Este ticket autorizará a un cliente específico para que se comunique con un servidor de juego (gameserver) específico, durante una cantidad de tiempo limitada. También incluye la información de enrutamiento cifrada. El coordinador de juego envía el ticket al cliente.
  • El cliente almacena el ticket en una caché local. (Ver ISteamNetworkingSockets::ReceivedRelayAuthTicket para obtener más información, incluyendo por qué razón es útil la complicación adicional de la caché).
  • El cliente usa ISteamNetworkingSockets::ConnectToHostedDedicatedServer para conectarse al servidor. Ver ISteamNetworkingSockets para más detalles sobre cómo enviar y recibir mensajes.

Por el momento, la autenticación basada en tickets no está disponible en combinación con el sistema FakeIP.

SDK del coordinador de juego

"Coordinador de juego" es el término que usamos para referirnos a tus servicios de backend o de emparejamiento. Hay un pequeño SDK independiente que puedes vincular con tu coordinador de juego y usar para:
  • Emitir tickets para dar a los clientes acceso a servidores de juegos alojados detrás de la SDR
  • Analizar cadenas con PingLocation_t y calcular tiempos de ping entre estos objetos.
  • Emitir certificados de identidad a jugadores en otras plataformas y tiendas
  • Aprovechar otras características avanzadas.

El SDK está disponible aquí.

Autenticación usando el SDK del Coordinador de juego

SDR usa dos mecanismos de autenticación:

  • Los tickets de servidores alojados los genera tu coordinador de juego y autorizan a un cliente específico a comunicarse con un servidor dedicado determinado durante cierto período de tiempo. Los tickets de retransmisión solo se utilizan en escenario de uso del servidor dedicado. Ver SteamDatagramRelayAuthTicket.
  • Los certificados se usan en la forma tradicional de autenticación y realizan el intercambio de claves DH (Diffie-Hellman) para establecer un canal cifrado. Los certificados son un concepto de extremo a extremo y se pueden usar en todas las formas de la comunicación SteamNetworkingSockets, incluyendo la conectividad UDP directa o P2P. Ver SteamDatagram_CreateCert del SDK del coordinador de juego y ISteamNetworkingSockets::GetCertificateRequest.

Utilizamos una infraestructura de clave pública (PKI) propia para autenticar clientes y servidores. Los jugadores reciben certificados individuales a corto plazo, vinculados a su identidad específica de jugador. Steam se ocupa de esto. Para los servidores de juegos, normalmente usamos certificados a largo plazo que autorizan todo el centro de datos para un id. de aplicación concreto. Tú generarás esos certificados.

Antes de poder generar tickets y certificados, tendrás que generar un par de claves y enviarnos tu clave pública. Nosotros publicaremos un certificado firmado por nuestra clave maestra de autoridad de certificación —CA, por sus siglas en inglés—, que marca tu clave como una clave de confianza para tus aplicaciones. Luego, cuando estés sin conexción generarás un certificado para cada centro de datos donde quieras ejecutar servidores, usando nuestra herramienta de certificados y firmándolo con tu clave privada. Distribuirás esos certificados a tus servidores de juego a través de un canal seguro, pasándolos a tu servidor dentro del entorno (ver abajo).

También usarás tu clave para generar tickets cada vez que un jugador se conecte a un servidor de juego.

¡Mantén a salvo tu clave CA privada y las claves privadas de tus certificados! Si tu clave se filtra y hay que anularla y sustituirla, podrían producirse problemas e interrupciones en el servicio.

Implementación de SDR en otras plataformas y tiendas


Tus clientes en otras plataformas y tiendas no iniciarán sesión en Steam, así que para esos jugadores tendrás que proporcionar varios servicios que Steam proporciona a los jugadores de Steam.

Inicialización del coordinador del juego

  • Tu servicio de emparejamiento (mencionado como el «coordinador del juego») tendrá que estar enlazado con el SDK del coordinador del juego. El archivo de encabezado steamdatagram_gamecoordinator.h incluye más detalles. El SDK del coordinador del juego usa una API sencilla en C, así que debería de ser relativamente fácil integrarla con otros lenguajes.
  • Descarga la configuración de red en el momento de inicialización y busca actualizaciones aproximadamente cada hora. (Ver SteamDatagram_GameCoordinator_GetNetworkConfigURL y SteamDatagram_GameCoordinator_SetNetworkConfig). En el momento de escribir esta nota, la configuración de red es un pequeño archivo JSON de unos 26 K (9 K comprimidos). Este URL tiene una disponibilidad muy alta. Sin embargo, si quieres evitar posibles errores, puedes usar una versión descargada recientemente.
  • Necesitarás un par de claves autenticadas para tu juego. Envíanos la clave pública e inicializa el SDK del coordinador del juego con tu clave privada. (Consulta SteamDatagram_SetPrivateKey_Ed25519 para obtener más información).

Inicio de sesión del cliente

  • El cliente llamará a ISteamNetworkingSockets::GetCertificateRequest para obtener un blob y enviarlo a tu coordinador del juego junto con el mensaje de solicitud de inicio de sesión.
  • Cuando el coordinador del juego reciba la solicitud de inicio de sesión, genera un certificado para el cliente usando SteamDatagram_CreateCert.
  • Envía el certificado generado de vuelta al cliente en la respuesta de inicio de sesión. El cliente debe instalar su certificado usando ISteamNetworkingSockets::SetCertificate.
  • Se recomienda encarecidamente que en este momento también distribuyas la configuración de red a los clientes. El cliente aplicará la configuración de red usando SteamDatagram_SetNetworkConfig.

Los certificados tienen una fecha de vencimiento y recomendamos que uses un período de vencimiento de 48 horas. Si hay una posibilidad de que los clientes vayan a estar conectados durante más de 48 horas, entonces tendrás que renovar el certificado periódicamente. Se pueden aplicar nuevos certificados en cualquier momento, así que si no pasa nada si quieres emitir nuevos certificados más a menudo, por ejemplo, al principio de cada partida.

Cada cliente debe tener una identidad única. Si es posible, utiliza las identidades específicas de la plataforma. (Esto es obligatorio para los clientes de Steam). Sin embargo, si no es posible, puedes utilizar una identidad de «cadena genérica» que sea relevante para tu proceso de emparejamientos. Consulta SteamNetworkingIdentity.

Juegos de red entre pares

Las conexiones P2P requieren un servicio de «señalización». Se trata de un canal con mecanismo de entrega de mejor esfuerzo, ancho de banda bajo y sin sensibilidad a la latencia, que es capaz de enviar ocasionalmente los mensajes de encuentro que se usarán para gestionar el enrutamiento. Esto requiere que los clientes tengan una conexión continua a tu servicio de emparejamiento, para que puedas enviarles mensajes, por ejemplo, una conexión a través de protocolos WebSocket o TCP. Si los clientes solo se comunican con tu coordinador del juego usando un patrón de solicitud/respuesta, por ejemplo, a través de http, esto no funcionará. Solo tienes que proporcionar un mecanismo de entrega de «mejor esfuerzo», lo que significa que la biblioteca permite que se pierdan mensajes o que se envíen varias veces.

  • Para iniciar una conexión utiliza ISteamNetworkingSockets::ConnectP2PCustomSignaling. Tendrás que implementar una subclase de ISteamNetworkingConnectionSignaling, y cuando SendSignal reciba una llamada, el cliente debería enviar el mensaje a tu backend, y el backend debería realizar el mejor esfuerzo para entregar el mensaje. Cuando se crea una conexión por primera vez, un intercambio inicial de entre 4 y 10 mensajes es normal. Después, puede que tengas que entregar una señal para una conexión establecida si cambian las condiciones de enrutamiento.
  • Cuando un cliente reciba una señal, llama a ISteamNetworkingSockets::ReceivedP2PCustomSignal. La biblioteca descifrará el mensaje. Si se trata de una conexión existente, la señal se procesará internamente. Si la señal es para una nueva conexión, se realizará una llamada a ISteamNetworkingSignalingRecvContext::OnConnectRequest.

Consulta steamnetworkingcustomsignaling.h para obtener más información.

Ejecución de servidores en centros de datos conocidos

Esta sección documenta algunos detalles técnicos relacionados con la ejecución de servidores dedicados en centros de datos conocidos.

Variables de entorno

El servidor dedicado obtiene su configuración de variables de entorno. Ten en cuenta que en los centros de datos de Valve todos esos valores serán establecidos de forma automática.
  • SDR_LISTEN_PORT: el puerto UDP donde tu servidor recibe el tráfico de retransmisores. El servidor dedicado solo usa un único socket. Pero puedes tener más de un «socket de escucha» lógico si usas «puertos virtuales». Consulta ISteamNetworkingutils::CreateHostedDedicatedServerListenSocket. En nuestros centros de datos, normalmente usamos el rango 30xxx.
  • SDR_IP: tu servidor debe tener una dirección IP pública que pueda recibir tráfico «no solicitado» de retransmisores. Si el servidor solo tiene una interfaz con una dirección IP pública, entonces esa es la que se usará. De lo contrario, vas a necesitar decirle al servidor de juegos qué IP se ha de usar. El socket SDR estará ligado a INADDR_ANY, pero esta información se necesita para completar la SteamDatagramHostedAddress del servidor. Ten en cuenta específicamente que esto normalmente se establece en entornos de desarrollo, donde tu servidor queda detrás de un firewall corporativo. (Ver abajo). También puedes especificar un puerto, si el puerto público es distinto a SDR_LISTEN_PORT.
  • SDR_POPID: el código de 3 o 4 caracteres alfanuméricos (SteamNetworkingPOPID) del centro de datos, en producción. En el entorno de desarrollo, déjalo en blanco.
  • SDR_PRIVATE_KEY: la clave privada de tu certificado. Es un bloque OpenSSH PEM que comienza con «-----BEGIN OPENSSH PRIVATE KEY-----».
  • SDR_CERT: tu certificado firmado. Es un bloque de formato propietario parecido a PEM, que empieza con «-----BEGIN STEAMDATAGRAM CERT-----».
  • SDR_NETWORK_CONFIG: ruta completa a una copia reciente y local del archivo de configuración de la red SDR para tu aplicación. Si no se define esta variable, entonces para obtener la configuración de red, el servidor obtendrá una copia usando HTTP al iniciarse. Para un mejor rendimiento puedes descargar de forma regular, (por ejemplo, cada hora) la configuración más reciente y guardar una copia local, de modo que los altibajos de red no causen ningún problema. Así es como están configurados los servidores de Valve.

Ejecución en un entorno de desarrollo

Dado que ISteamNetworkingSockets admite la conectividad UDP simple, lo mejor es empezar por conseguir que tu código funcione a través de esta interfaz sobre UDP sin preocuparse de los retransmisores.

Te aconsejamos que el código de tu servidor use la presencia de la variable de entorno SDR_LISTEN_PORT para decidir si tu servidor debe escuchar a la red SDR. Puedes usar ISteamNetworkingSockets::GetHostedDedicatedServerPort para obtener el valor.

En el entorno de desarrollo, tienes que dejar SDR_POPID en blanco. Cuando SDR_LISTEN_PORT y SDR_POPID están en blanco, el POPID queda establecido como el código especial de 3 caracteres «dev».

En general se desactiva la autenticación para servidores en el entorno «dev». (Tanto los clientes como los retransmisores permitirán conexiones a servidores «dev» sin un certificado firmado, siempre que tengan un ticket firmado). Necesitarás otro mecanismo para autenticar con tu coordinador del juego. ¡Y tu coordinador del juego necesita tener cuidado al generar tickets para cualquier servidor que se presente como «dev»!

Tu servidor necesita ser capaz de recibir tráfico público no solicitado, lo que significa que si no tiene una dirección IP pública, tendrás que configurar un puerto más adelante en tu firewall. Y probablemente necesites establecer SDR_IP con la dirección IP pública apropiada (y el puerto, si es distinto a SDR_LISTEN_PORT).