Steam Datagram Relay (SDR) is Valve's virtual private gaming network. Using our APIs, you can not only carry your game traffic over the Valve backbone that is dedicated for game content, you also gain access to our network of relays. Relaying the traffic protects your servers and players from DoS attack, because IP addresses are never revealed. All traffic you receive is authenticated, encrypted, and rate-limited. Furthermore, for a surprisingly high number of players, we can also find a faster route through our network, which actually improves player ping times
This relay network can be used for both peer-to-peer traffic and dedicated servers.
General requirements and tips for porting existing network code
Here are some general things to be aware of that apply to both P2P and dedicated server connectivity.
First, any place where network hosts are identified by a public IP (almost always the case for gameservers) will need to be changed to use a different identifier instead. There are several options for this:
- For clients and gameservers that signin into Steam, you will usually the SteamID.
- If your gameserver does not signin to Steam, and you are using the ticket-based authentication flow, you can use any other identifier that is meaningful to you. See SteamNetworkingIdentity.
- In some codebases, the assumption that network hosts and gameservers are identified using an IPv4 address is ubiquitous, and changing this assumption is a significant amount of work. Indeed, the Steamworks ISteamMatchmaking and ISteamMatchmakingServers APIs have this property, as do some of our own games, such as Team Fortress 2. In this case, you can use the Steamworks "Fake IP" system. A FakeIP is an IP that "looks" like a valid IPv4 address for most purposes, but comes from a reserved address space that is not used on the Internet. By assigning your server a FakeIP, your server can still be addressed using an IPv4 address, and almost everything will "just work". The ISteamNetworkingSockets and ISteamMatchmakingServers systems recognize these special IPs and take appropriate action. They are not routable and do not work for general internet purposes (e.g. you cannot ping them). See ISteamNetworkingSockets::BeginAsyncRequestFakeIP for more info.
Second, you'll need to modify any low-level socket code to use one of the Steamworks APIs for connectivity.
- Ideally, you can use one of the connection-oriented API ISteamNetworkingSockets interfaces that returns an HSteamNetConnection.
(Note that these API also supports plain UDP transport, which is very useful for testing. Also, there's an opensource version.)
- Some codebases are written in a more UDP-like manner, where packets can be sent ad-hoc to any remote host at any time, and not all messages are sent to an established "connection". In these situations, there are two Steamworks features that might be useful.
Requirements for using SDR on other platforms and stores
A Networking API and DDoS solution for a cross-platform game is useless if it only works on one platform. In most cases, your players on other platforms and stores can access the relay network, provided that your game meets some basic conditions.
- Have a version of your game shipping on Steam.
- Agree to update your game within a reasonable time frame (say, a few months) when asked, if we need to ship a bugfix or security patch.
- Understand that, unfortunately, we cannot promise that this service will always be available to non-Steam players. In the unlikely event that we need to downgrade this service, we will do everything possible to work with you to avoid disruption to your players, including giving you time to make a plan. The SDK has built in mechanisms such that we can instruct clients to fall back to direct UDP connectivity or attempt NAT punch, but you should also keep this possibility in mind.
- Have some sort of matchmaking service (SDR refers to this as your "game coordinator") that can issue some authentication credentials. We have a separate SDK for this. See below.
Please contact us for the relevant SDKs and to talk about the fine print. We're still working through details of how to distribute this code, and at this time we might not be able to make cross-platform support available to all partners and all games.
See below for more technical information on implementing SDR on other platforms and stores.
If you don't meet the criteria above, feel free to use the opensource
version of the API for whatever you want. Note that the opensource code does not support accessing the relay network.
For peer-to-peer traffic on Steam, all you need to do to take advantage of SDR is to use APIs such as ISteamNetworkingSockets::CreateListenSocketP2P
. Steam will take care of everything else. For other platforms and stores, read more about additional technical requirements below.
Dedicated Servers in Known Data Centers
The peer-to-peer APIs work just fine even when one "peer" is a dedicated server! But there's one important catch: if your dedicated server is not near one of the data centers where we are running relays, then the best relayed route might be slower than the default IP route, and there will be at least some players whose latency is worse than the status quo.
For the optimal dedicated server experience, the server should be run in a known data center that is part of the SDR network. We make sure that relays are running nearby and the relayed route is never too much slower than the default IP route. Servers running in these known data centers connect using a special API. This use case is referred to in the SDK as "Hosted Dedicated Server". Note that this doesn't necessarily mean that Valve is hosting the servers or the relays -- it could be a third party data center that we have established a relationship with, and is known to the Steam Datagram Relay system.
If you are running game servers in a major hosting provider and are interested in using SDR, please get in touch with us. We'll try to work with your hosting company to run relays in the data center. That's the ideal situation, but even if this is not possible we may be able to add the data center to our network configuration system and just use Valve relays that are nearby.
If you are a dedicated server hosting company and want to join our network so that your customers can take advantage of SDR, please get in touch with us! We have not yet deployed relays in any third party hosting companies, however we are interested in doing this.
Simple Connection Flow to Dedicated Server Without Game Coordinator
If you don't have your own central matchmaking / login service (we sometimes call this the "game coordinator") that assigns players to servers, or just want to keep things as simple as possible, then you can connect to a dedicated server in a known data center using ISteamNetworkingSockets::CreateListenSocketP2P
. In this case, the connection begins on the client just like an ordinary P2P connection. Rendezvous messages are sent through Steam, so if the player or server loses their connection to Steam, the connection cannot be made. Also, Steam does not restrict who can attempt to connect, aside from verifying that the player is signed into Steam and owns the game.
Ticket-Based Server Connection Flow
If you do have your own game coordinator service, it is recommended to use a ticket-based connection flow. It's usually only a bit more work compared to a simple P2P-style connection flow, and it offers two important advantages:
- You only issue tickets to players who should be allowed to attempt to connect, so unwanted connection attempts do not even reach your server.
- Once a player has a ticket, they can connect to the server even if they lose connection to Steam, the server loses its connection to Steam, the player's computer crashes and reboots, etc. Making reconnection to the gameserver robust against these common failures is especially important for games that penalize players for leaving the game.
A ticket-based connection to a dedicated server over SDR works like this:
At this time, the ticket-based authentication is not available in combination with the FakeIP system.
Game Coordinator SDK
"Game Coordinator" is the term we use to refer to your backend / matchmaking services. There is a separate, small SDK that you can link with your game coordinator which can be used to:
- Issue tickets to give clients access to gameservers hosted behind SDR
- Parse PingLocation_t strings and calculate ping times between these objects
- Issue identity certificates for players on other platforms and stores
- Take advantage of certain other advanced features.
The SDK is available here
Authentication using the Game Coordinator SDK
SDR uses two authentication mechanisms:
- Hosted server tickets are issued by your game coordinator and authorize a specific client to talk to a specific dedicated server for a period of time. Relay tickets are only used for the dedicated server use case. See SteamDatagramRelayAuthTicket.
- Certificates are used in the traditional way to authenticate, and perform DH key exchange to establish an encrypted channel. Certificates are an end-to-end concept, and can be used in all forms of SteamNetworkingSockets communication, including direct UDP connectivity or P2P. See SteamDatagram_CreateCert from the Game Coordinator SDK and ISteamNetworkingSockets::GetCertificateRequest.
We use a proprietary public key infrastructure (PKI) to authenticate clients and servers. Players are issued individual, short-term certificates, tied to their specific player identity. Steam takes care of this. For gameservers, we typically use longer term certificates that authorize an entire data center for a particular AppID. You will issue those certificates.
Before you can issue tickets and certificates, you'll need to generate a keypair and send us your public key. We will publish a certificate signed by our master CA key that marks your key as trusted for your app(s). Then, offline you will generate a certificate for each data center where you want to run servers, using our certificate tool, and sign it with your private key. You'll distribute those certificates to your gameservers over a secure channel, passing it to your server in the environment (see below).
You'll also use your key to generate tickets, each time a player connects to a gameserver.
Keep your CA private key and the private keys of your certificates safe! If your key leaks and needs to be revoked and replaced, it could lead to a disruption.
Implementing SDR on other platforms and stores
Your clients on other platforms and stores will not sign into Steam, and so you will need to provide a few services for those players that Steam provides for Steam players.
Game coordinator initialization
- Your matchmaking service (referred to as the "game coordinator") will need to link with the game coordinator SDK. The header file steamdatagram_gamecoordinator.h has more details. The game coordinator SDK uses a plain C API, so it should be relatively easy to integrate with other languages.
- Download the network config at initialization time, and check for updates approximately once an hour. (See SteamDatagram_GameCoordinator_GetNetworkConfigURL and SteamDatagram_GameCoordinator_SetNetworkConfig.) The network configuration is a small JSON file, at the time of this writing, about 26K (9K compressed). This URL has very high availability, however if you wish to handle the possibility of failure, you can use a recently downloaded version.
- You'll need a keypair authenticated for your game. Send us the public key, and initialize the game coordinator SDK with your private key. (See SteamDatagram_SetPrivateKey_Ed25519 for more information.)
- The client will call ISteamNetworkingSockets::GetCertificateRequest to get a blob and send it along with the signon request message to your game coordinator.
- When the game coordinator receives the signon request, generate a certificate for the client using SteamDatagram_CreateCert.
- Send the generated certificate back to the client in the logon response. The client should install their certificate using ISteamNetworkingSockets::SetCertificate
- It is highly recommended that you also distribute the network configuration to clients at this time as well. The client will apply the network configuration using SteamDatagram_SetNetworkConfig.
Certificates have an expiry, and we recommend that you use an expiry of 48-hours. If clients might be connected for longer than 48 hours, then you will need to periodically renew the certificate. It is acceptable to apply a new certificate at any time, and so if you want to issue certificates more often, for example at the start of every match, that is OK.
Every client must have a unique identity. If possible, use the platform-specific identities. (For Steam clients, this is a requirement.) However, if this is not possible, you can use a "generic string" identity that is meaningful to your matchmaker. See SteamNetworkingIdentity
P2P connections require a "signaling" service. This is a low-bandwidth, non-latency-sensitive, best-effort-delivery channel capable of forwarding occasional rendezvous messages used to negotiate routing. This requires clients to have a persistent connection to your matchmaking service, such that you can push messages to them, such as a websocket or TCP connection. If clients only talk to your game coordinator using a request/response pattern, for example through http, that won't work. You only need to provide "best effort" delivery, meaning that the library is tolerant of messages dropping or being delivered multiple times.
- To initiate a connection, use ISteamNetworkingSockets::ConnectP2PCustomSignaling. You will need to implement a subclass of ISteamNetworkingConnectionSignaling, and when SendSignal is called, the client should send the message to your backend, and your backend should make its best effort to deliver the message to the peer. When a connection is first created, a initial exchange 4-10 messages is typical. Thereafter, you might be called to deliver a signal for an established connection if routing conditions change.
- When a client receives a signal, call ISteamNetworkingSockets::ReceivedP2PCustomSignal. The library will decode the message. If it is concerning an existing connection, the signal will be processed internally. If the signal is for a new connection, ISteamNetworkingSignalingRecvContext::OnConnectRequest will be called.
See steamnetworkingcustomsignaling.h for more details.
Running servers in known data centers
This section documents some technical details involved in running dedicated servers in known data centers.
The dedicated server gets its configuration from environment variables. Note that in Valve data centers, all of these values will be set automatically for you.
- SDR_LISTEN_PORT: The UDP port where your server will receive traffic from relays. The dedicated server only uses a single socket. (But you can have more than one logical "listen socket" by using "virtual ports". See ISteamNetworkingSockets::CreateHostedDedicatedServerListenSocket.) In our data centers, we typically use the 30xxx range.
- SDR_IP: Your server must have a public IP that can receive "unsolicited" traffic from relays. If the server only has one interface with a public IP, then this will be used. Otherwise, you will need to tell the gameserver what IP to use. The SDR socket will be bound to INADDR_ANY, but this information is needed to fill out the server's SteamDatagramHostedAddress. Note in particular that this will usually need to be set in dev environments, where your server is behind a corporate firewall. (See below.) You can also specify a port, if the public port differs from SDR_LISTEN_PORT.
- SDR_POPID: The 3- or 4-letter alphanumeric code (SteamNetworkingPOPID) of the data center, in production. In development environment, leave this blank.
- SDR_PRIVATE_KEY: The private key from your certificate. It's an OpenSSH PEM block that begins with "-----BEGIN OPENSSH PRIVATE KEY-----".
- SDR_CERT: Your signed certificate. It's a proprietary format PEM-like block that begins with "-----BEGIN STEAMDATAGRAM CERT-----".
- SDR_NETWORK_CONFIG: Full path to a local, recent copy of the SDR network configuration file for your app. If this variable is not set, then to obtain the network configuration the server will fetch the copy using HTTP at boot time. For optimal performance you can periodically (e.g. once an hour) download the latest configuration and save it locally, so that a network hiccup doesn't cause any disruption. This is how Valve servers are configured.
Running in a dev environment
supports plain UDP connectivity, it's usually best to start by getting your code working through this interface over UDP, without worrying about relays.
We suggest that your server code use the presence of the SDR_LISTEN_PORT environment variable to decide whether your server should listen for SDR. You can use ISteamNetworkingSockets::GetHostedDedicatedServerPort
to fetch the value.
In development, you will leave SDR_POPID blank. When SDR_LISTEN_PORT and SDR_POPID is blank, the POPID is set to the special 3-character code "dev".
In general, authentication is disabled for servers in the "dev" environment. (Clients and relays will both allow connections to "dev" servers without a signed cert, as long as they have a signed ticket.) You will need another mechanism to authenticate with your game coordinator. And your game coordinator needs to be careful when it issues tickets to any servers claiming to be in "dev"!
Your server needs to be able to receive unsolicited public traffic, which means that if it doesn't have a public IP, you'll need to setup a port forward in your firewall. And you'll probably need to set SDR_IP with the proper public IP (and port, if it differs from SDR_LISTEN_PORT).