How to Host a Public IPv4 Game Server With IPv6 Public Address

Recently, I’ve wanted to play an old game, specifically an online co-op mod for the original Half-Life. My friend and I have faced a problem I haven’t seen in a while: opening ports for incoming connections. It’s necessary to host a game outside just your local network.

Most guides on the Internet are a little outdated, but I’ve done it several times as a child, so surely I can do it now, right? To my surprise, when I went into the settings of my home router, I couldn’t find any port forwarding settings. No DMZ and UPnP either. What gives? Are modern routers given out by ISPs so bad that you can’t even host a server anymore in your own home?

Disclaimer: this article was written from a point of view of a person who wanted to solve a very specific problem and spent little time studying networks and IPv6. Hence, take my opinions and the technical details in this article with a grain of salt, and don’t cite me (too much).

The Great Benefit of IPv6 for Gamers

After a bit of research, turns out it’s not the ISP that’s at fault, it’s the rest of the world. Due to the shortage of 32-bit IPv4 addresses, many ISPs implemented IPv6 by now. From what little I’ve learnt in one evening, the advantages of IPv6 over IPv4 seem enormous so it’s surprising that the adoption is so slow that even Steam itself doesn’t work in an IPv6-only network.

What’s especially surprising to me is that it’s the gamers that would benefit the most from IPv6 and yet it’s the game industry which seems the most reluctant to acknowledge the existence of IPv6. The majority isn’t complaining so nobody cares, probably because dedicated servers are not exactly popular right now and not even possible to host by the public in most modern games.

Hence, even though ISPs have run out of 32-bit addresses to give out for average consumers (businesses can still get them) and are basically forced to provide IPv6 network, they still need to somehow give access to the IPv4 network. Otherwise, a lot of websites and services (like Steam) won’t work for their clients, which is a lose-lose situation for everyone. Fortunately, there exist solutions for the transitioning period. Of course, they have their own drawbacks, but they mostly work.

What is so beneficial about IPv6 for gamers? The fact that all devices have its own globally unique IPv6 address. Quite possibly even more than one! 128-bit addresses allow for so many possibilities that it will be really hard to run out of addresses. This fact alone greatly simplifies things when it comes to opening ports, and in turn simplifies the process of hosting a game server. Or, in fact, any server.

The whole “port forwarding” thing that was necessary for IPv4? You don’t need it for IPv6.

It was only necessary in the first place because of the limitations of IPv4. Typically, your ISP only gave you one public IPv4 address for the whole home network. Why? Imagine if every computer, every phone and every printer had to have its own public IPv4 address, they would run out of them very quickly, maybe even before IPv6 would be a thing. 32 bits just cannot encode so many addresses, hence the need for NAT and hard separation of public and private IP addresses.

Fortunately, most people mainly care about outgoing connections. A device like a phone or a computer sends a packet to the home router, and the router sends it to the world (through ISP). The device itself is not visible to the outside world, it is “hiding” behind one public IPv4 address, as is every other device in the local network. The devices in home network can freely talk to each other. However, from the outside perspective, they all might as well be one big device.

Problems with this approach start when you want to host an IPv4 server on your computer, because then you also start to care about incoming connections. What is the router to do when it receives a mysterious incoming packet from the outside world on a port, say, 1234? Which device in the local network wants it? It doesn’t know, so it discards it. The port is closed, the router does not let in any packets. They might be dangerous, too.

When the younger us “opened ports” by following some random guides on the Internet (probably without having much of an idea what exactly we were doing), we had to specify to the router what to do with an incoming connection. For example, by specifying the local IPv4 address of our computer on which our obviously awesome Counter-Strike 1.6 server is running. After that, the router knows that packets sent to port 1234 should be forwarded to our particular computer. Only then can the game server application receive the incoming packets and appropriately respond.

With IPv6, all this nonsense above can be avoided. Your personal computer is already visible to the outside world and has its own personal globally unique address. As does your phone. And your printer. Any device connected to the IPv6 network has a globally unique address. Devices can even generate their unique addresses all by themselves, all they need is their globally unique physical MAC address, which existed even during IPv4 times.

But wait, isn’t it a little scary? Anyone can connect to your devices. Anyone.

Fear not, because that’s not really true. There are security measures in place. In your OS, and in your router, and in the protocol itself. The most relevant part in this article is the firewall. It exists by default in your home router and it simply discards most incoming connections. Even if someone knows your public IPv6 address, they can’t do much with it unless you specifically allow it. This is actually similar to port forwarding. We need to add a rule to the firewall which basically says “if someone tries to connect to this 1234 port on the device with this IPv6 address, let them through”.

The Problem With Hosting a Server

So I added the firewall rule to let through connections to my computer on a specified port, run a game server on this port, and invited my friends to join. But it didn’t work. Is the previous section a big fat lie? Is port forwarding still needed after all?

Kind of. First of all, games like Counter-Strike or Half-Life are old and weren’t updated to support IPv6. In fact, even a relatively new game like OpenRA doesn’t support IPv6, at least yet. Unfortunately, IPv6 isn’t backwards compatible with IPv4, so networking in old software would quite probably stop working if we completely got rid of IPv4 completely.

So, the aforementioned game servers work only in the IPv4 world. The same can be said about the game clients. Since the server doesn’t have a public IPv4 address, the client must be given the IPv6 address in order to connect. This is pointless, however, because the client doesn’t understand IPv6 anyway. Even if it did, the game server also doesn’t support IPv6 so it only listens for packets sent through IPv4.

Wait, didn’t I said earlier that ISPs solved the transitioning problem? IPv4 still works, right? Or we wouldn’t be able to even launch Steam, or browse half of the Internet, or play Counter-Strike at all. As I said earlier, the solutions indeed exist but they are not perfect. Which is why you are unlikely to find a port forwarding setting in your home router, at least not today.

As an example, the solution which I guess my ISP uses is called Dual-Stack Lite. The way it works, as I understand, is that every home network is an IPv6 network and an IPv4 network at the same time, but the IPv4 network is only local. When a device wants to connect to some server on the Internet through the IPv4 protocol, the IPv4 packets actually get wrapped up in IPv6 packets before being sent to the ISP’s core. The ISP then maps your IPv6 network address to a single public IPv4 address by using some kind of a NAT table. This IPv4 address can/is apparently shared by multiple different customers. The packets are unwrapped and given the shared IPv4 address as the source in the header, and only after sent to the outside world. This way the IPv4 server can receive the packet, and even reply to the right device thanks to session/traffic flow identification on the ISP side.

It works well for most consumers. They probably won’t even notice the difference between connecting to a website with IPv4 or IPv6. I definitely didn’t until recently.

Unfortunately, DS-Lite becomes a problem when someone wants to host an IPv4 server. Since the public IPv4 address is shared between multiple home networks and not even guaranteed to be static, the game server cannot be uniquely addressed from the Internet. We could still forward ports, but the forwarding would have to be configured on the ISP side. Setting up port forwarding for our little game server is most probably out of the question. Even if we asked so nicely that the ISP would agree to do the port forwarding, what would happen if more than one client declared they need the same port? I suppose there are also technical limitations.

Back to IPv4?

The simplest solution is to call our ISP and ask if perhaps they have a public IPv4 address to spare. If we’re lucky, they might even give it to us without problems.

However, as time goes on, this might become harder and even impossible. Depending on the country and ISP, they might give away those only to business users, which certainly pay much more than an average Joe. In some cases, especially in regions outside of Europe and North America, they might not even have any public IPv4 addresses, business or not. Besides, do we really want to go back to the old times of IPv4 instead of embracing the new better technology? Everyone will have to move to IPv6 at some point anyway.

What will probably never move on is the old software, like games. As IPv6 becomes more popular, we might see better and more accessible solutions for hosting servers for retro games, or we might lose the ability to host them on modern network stacks forever.

At this moment, though, I was not able to find any solution not involving a public IPv4 address one way or another. However, it doesn’t require changing your ISP or asking them to switch you to IPv4-only network.

IPv4 to IPv6 Port Forwarding on VPS

The root of the problem is the lack of the public IPv4 address for which we can configure port forwarding. What if we had one?

A separate machine connected to perhaps a different ISP, which has its own unique public IPv4 address. With access to such a machine, we could just host the server on the machine and be done with it. However, the machine may be too weak, or the old server software might not run on it or be just too hard to setup. For example, the machine could be running on Linux, and the game server software is Windows-only. We can still benefit from that sweet public IPv4 address though.

This machine, for example a cheap VPS, can act as a middleman between clients (the players) and the server. The clients can connect to the VPS by using its public IPv4 address. The VPS can then forward the packets to our computer, which only has an IPv6 public address.

If the game server can already listen to IPv6 connections, we’ve already solved a problem. Some people may only have access to the IPv4 network, and we just made it possible for them to connect to our IPv6 server. This is not enough for an IPv4-only server though.

We can add another middleman, this time running on the same machine as the server. The middleman can be a relatively simple application which listens for IPv6 connections on the specified ports and sends the packets to the local IPv4 socket that the game server listens to.

We must also not forget to set up such forwarding the other way since the server needs to send data too. Hence, the whole tunnel must be bidirectional.

Conceptually, that’s it. Simple enough, set up a VPS to forward IPv4 packets to the IPv6 computer, and forward IPv6 packets on the computer to the IPv4 socket of the game server. And the other way around. It will work, but it also has some significant drawbacks.

Firstly, we have to have the VPS with a public IPv4 address. This costs money. It’s not an issue if you already have one. And depending on how much is it worth it for you, you can buy a cheap one for just the forwarding since it shouldn’t require too much resources.

Preferably, the VPS should have a good Internet connection and be close geographically to both the game server and the players in order to minimize latency. That’s another drawback, this solution introduces a middleman which naturally leads to more latency. Each packet has to first go through the VPS before it is forwarded to/from the server. Although, VPSs usually have a higher quality Internet connection than usual home networks, combine that with the right location and the overhead shouldn’t be much of an issue.

Thirdly, setting it all up is not straightforward. It’s not (at least yet) a common use case. It took me some time and split hair to figure out how to do that. So it’s not a solution for an average Joe, but arguably you stop being an average Joe the moment you want to host a server and learn the difference between IPv4 and IPv6.

And fourthly, from the perspective of the game server, every client will be connecting from the same IP being the IP of the VPS. IP bans are therefore not possible on the game server side. It will also be harder to identify players. So it’s a solution for a home server to play with trusted group of friends, but not for a serious server. Then again, hosting a serious public server on your own personal computer is probably a bad idea anyway.

Example

Let’s sum this all up with an example. I want to host a Half-Life server on my computer. Not by using HLDS, no, but by simply starting a game straight from the game client.

From the public documentation, I learn that the Half-Life server only requires the 27015 UDP port to work, at least by default. I assume the server can be started on almost any port, but let’s just use the default 27015 for simplicity. It might also require other ports but in this case only for features for which I don’t care about.

Firstly, let’s open the home router’s settings to add an appropriate IPv6 firewall rule to let clients in. The details of how to do that vary greatly between devices so I consulted the manual of my router.

I log in to my home router by typing its local address 192.168.0.1 into the browser. After logging in with the admin password, I add an appropriate rule in the Security > IP and Port Filtering section. I choose the settings to allow any source IPs on any ports to be able to connect to the specific destination described by a public IPv6 address of my computer on the 27015 port.

Screenshot from my home router settings for setting up IPv6 firewall rule for inbound connections.

Note that I am opening more than one port. The second port will be needed later. This can be almost any port really, I’ve chosen 27016 for convenience of not having to set up a separate rule as a contiguous range of ports can be specified in one rule.

I’ve allowed for both TCP and UDP protocols just in case but UDP should suffice. I don’t want to open too many holes in the firewall for security reasons.

With that done, my computer should be accessible from the Internet. To verify that it indeed worked I’ve decided to run a simple HTTP server and try to connect to it from my VPS.

To run the HTTP server I use Python with a simple command run inside an empty directory because I don’t want to expose any of my files to the public.

python -m http.server 27015 --bind ::

Note that I specified the port and bound it to the :: special IPv6 address. The command basically means “listen to HTTP connections coming to any of IPv6 addresses of this computer only on port 27015”.

I find out what is my IPv6 address with a command like ifconfig (in Linux) or ipconfig (in Windows), then I connect to my VPS by SSH and try to connect to my computer by telnet.

telnet MY_IPV6_ADDRESS 27015

If this command failed then I’d make sure the firewall rule is set up correctly and that IPv6 is configured on the VPS.

Since it worked, I can now focus on the hard part which is forwarding. There are probably many ways to set this up. I use the tool called socat which can do exactly what I need and thus shall be the aforementioned middleman.

On the VPS, I create a bidirectional tunnel from IPv4:27015 UDP to IPv6:27016 UDP socket.

socat -T60 UDP4-LISTEN:27015,fork UDP6:[MY_IPV6_ADDRESS]:27016 &

The T option sets the timeout duration in seconds. This is in order to close a connection if nothing happens for a long time.

The ampersand at the end will make it so that socat is run in the background.

On the computer, I create a bidirectional tunnel from IPv6:27016 UDP to IPv4:27015 UDP socket, which is being listened to by the game server.

socat -T60 UDP6-LISTEN:27016,fork UDP4:MY_LOCAL_IPV4_ADDRESS:27015 &

The second port is necessary because two applications can’t listen on the same port at the same time. Either the game server or socat, depending which one was running first, would complain that “the address is already in use” if I asked them both to listen on the 27015 port. But socat is now listening on the 27016 port so it’s fine.

That is all. Time to start the Half-Life server on the 27015 port (which is the default) and give friends the IPv4 address of the VPS.

Note that the server won’t be visible on the list of servers because it doesn’t connect to the master server. So direct connection by IP address is necessary. In case of games based on Half-Life the connection can be made by typing the following command in the developer console inside the game:

connect MY_VPS_IPV4_ADDRESS; passwd SERVER_PASSWORD

Conclusion

I’ve spent a few hours trying out different commands, searching the Internet for hints how to set this up and even fired up Wireshark on both server and client to monitor the network traffic to debug why it doesn’t work. I’m glad I managed to finally make it work.

I haven’t found much information about such an apparently niche use case so I wrote this article in order to share what I’ve just learnt in hope that it will help somebody. In the very least, it will help myself in the future when I forget how did I manage to set it up.

I only wanted to be able to host game servers temporarily on my machine without having to go through the pain of setting up dedicated servers and/or switching to IPv4. Hopefully, in the future, there will appear better and more accessible solutions, because even when IPv6 becomes the standard, some people will still want to play old multiplayer games.