Resolve shard IP hostnames before sending them to the client - #324
Resolve shard IP hostnames before sending them to the client#324MettleSphee wants to merge 2 commits into
Conversation
The FusionFall client only understands literal IPv4 addresses in the shard select packet, so a hostname configured as the shard IP (e.g. a dynamic-DNS address) is now resolved to IPv4 by the server before it is sent to the client. The address is resolved once at startup, before the sandbox engages (the login server thread is not allowed to open new sockets afterwards), and re-resolved on every character select on builds where runtime DNS lookups are possible (Windows, and Linux builds without the seccomp sandbox), so dynamic-DNS changes are picked up without a restart. Also guards against overflowing the 16-byte g_FE_ServerIP field and documents hostname support in config.ini.
|
Although I have only lazily tested before, I have now done the test on each of the build artifacts provided by the GitHub Actions workflows. The OpenFusion game client gets the correct IP from the server in the following scenarios:
|
|
Thanks for the PR. There's some stuff to think about here, though, as this is a little tricker than it seems. We actually implemented DNS resolution of the shard host before, but ultimately opted not to check it in for one good reason: resolving hostnames from the perspective of the server can yield different results than resolving from the perspective of the client, especially on a local network. This is something that can trip up server owners very easily. For example, if I'm running the server on a LAN and I put the server's host name in as the shard IP, it'll resolve to This case is extremely common as most of our users who want private servers run the server on a LAN or VPN network. Saying "oh, you can just put the computer name in" would be wrong in these cases, and makes the feature a footgun instead of actually helpful. Public server owners might be able to benefit, but they're already tech-savvy enough to know the concrete IP of their shard and will almost always opt to use that to avoid introducing potential issues caused by DNS outages or other flakiness ("it's always DNS"). Other notes:
|
|
(It's also worth nothing that this will not respect any of the host entries on the client's machine) |
|
The main idea of mine with this change was to help out the few server owners who want to cheap out on having domains and, instead, use something like a dynamic DNS or a public proxy, in the case of having either CG-NAT or random IPs from the ISP instead of a static one, mainly because it's such a pain to keep manually changing the shard's IP if/when the ISP decides to change the IP (power outage of the connection, restarting the router etc). As such, I admit that I haven't though of the differences in client vs server DNS resolutions nor actually using the computer name as a domain. It would probably be a better change if this was an option only for the more experienced users (i.e. add a "domain" field in the config file with the warnings you mentioned earlier). One other solution would've been to create a script that externally updates the shard's IP from the config file, and then reboots the server to apply the changes. It would also be an okay solution, but wasteful because, when the IP change would occur, the server hardware would require a restart on its own, in most cases. I do agree that the GCR workflow deserves its own PR and discussions, although it might not be too big of a change other than a longer deployment on each build (if that is an issue). I'm looking forward to discussing this further, if anyone's willing. |
|
We could maybe add a Boolean setting that enables DNS resolution of the shard host (disabled by default). Looping in @dongresource to see if he has an opinion here. |
|
Another question came up to me as I've been thinking about this: with the way this is modeled, doesn't the DynamicDNS case die out since you'd have to restart the server whenever the IP changes? And that's not something you can know easily besides the client failing to connect. Is there a way we can safely allow the DNS resolution through the sandbox instead of doing the one-time resolution at startup? |
|
I don't really think so (for the first question), the cases I do know of the IP resetting are usually outages, whether the power fails (and servers get rebooted anyway), the ISP has an outage (and in this case, most servers only have one component, so an IP redirection is a problem only for the DNS/domain resolver). Another case would be manually rebooting the router, but in that case the server owner would know to update the Dynamic DNS manually, and therefore of the current limitation with the shard server, given we assume how experienced server owners have to be in this scenario. As for the sandbox part, I genuinely don't know. The only thing coming to my mind would be the one earlier, to remove the need for the server to deal with DNS resolution, because I haven't thoroughly looked into how the server works... |
For a simplified description: Adds domain support in the config.ini file for the IP field (resolves domains on server launch, and sends the resolved IP to become the SHARD server's new IP), and adds a workflow build for GitHub's container registry (ghcr.io). Works with domains defined in hosts file and those from a DNS provider.
The FusionFall client only understands literal IPv4 addresses in the shard select packet, so a hostname configured as the shard IP (e.g. a dynamic-DNS address) is now resolved to IPv4 by the server before it is sent to the client.
The address is resolved once at startup, before the sandbox engages (the login server thread is not allowed to open new sockets afterwards), and re-resolved on every character select on builds where runtime DNS lookups are possible (Windows, and Linux builds without the seccomp sandbox), so dynamic-DNS changes are picked up without a restart.
Also guards against overflowing the 16-byte g_FE_ServerIP field and documents hostname support in config.ini.