From d078df0b8522f9239b16a901b37e8f525987a75b Mon Sep 17 00:00:00 2001 From: wraitii Date: Mon, 8 Feb 2021 15:47:34 +0000 Subject: [PATCH] Get the public IP from the lobby if not using STUN. Follow-up to 1a8de6d2b8. This makes it again possible to host without STUN via the lobby. The lobby bot will answer the host "Register" command with the external IP. This is only sent to the host, avoiding IP leakage. There is a small window in which a client might try to join and the public IP isn't up, and the request goes through, but that seems rather unlikely to be a problem in practice. Refs #5913 Differential Revision: https://code.wildfiregames.com/D3490 This was SVN commit r24858. --- source/lobby/StanzaExtensions.cpp | 2 +- source/lobby/XmppClient.cpp | 19 +++++++++++++++++-- source/network/StunClient.cpp | 5 ----- source/network/StunClient.h | 2 -- .../network/scripting/JSInterface_Network.cpp | 17 +++++------------ 5 files changed, 23 insertions(+), 22 deletions(-) diff --git a/source/lobby/StanzaExtensions.cpp b/source/lobby/StanzaExtensions.cpp index 3774baf5ac..985b1effe2 100644 --- a/source/lobby/StanzaExtensions.cpp +++ b/source/lobby/StanzaExtensions.cpp @@ -129,7 +129,7 @@ GameListQuery::GameListQuery(const glooxwrapper::Tag* tag) if (!tag || tag->name() != "query" || tag->xmlns() != XMLNS_GAMELIST) return; - const glooxwrapper::Tag* c = tag->findTag_clone("query/game"); + const glooxwrapper::Tag* c = tag->findTag_clone("query/command"); if (c) m_Command = c->cdata(); glooxwrapper::Tag::free(c); diff --git a/source/lobby/XmppClient.cpp b/source/lobby/XmppClient.cpp index f25871ae2d..6f081ace8a 100644 --- a/source/lobby/XmppClient.cpp +++ b/source/lobby/XmppClient.cpp @@ -430,8 +430,6 @@ void XmppClient::SendIqRegisterGame(const ScriptInterface& scriptInterface, JS:: GameListQuery* g = new GameListQuery(); g->m_Command = "register"; glooxwrapper::Tag* game = glooxwrapper::Tag::allocate("game"); - // Add a fake ip which will be overwritten by the ip stamp XMPP module on the server. - game->addAttribute("ip", "fake"); // Iterate through all the properties reported and add them to the stanza. std::vector properties; @@ -861,6 +859,23 @@ bool XmppClient::handleIq(const glooxwrapper::IQ& iq) } if (gq) { + if (iq.from().full() == m_xpartamuppId && gq->m_Command == "register" && g_NetServer && !g_NetServer->GetUseSTUN()) + { + if (gq->m_GameList.empty()) + { + LOGWARNING("XmppClient: Received empty game list in response to Game Register"); + return true; + } + std::string publicIP = gq->m_GameList.front()->findAttribute("ip").to_string(); + if (publicIP.empty()) + { + LOGWARNING("XmppClient: Received game with no IP in response to Game Register"); + return true; + } + g_NetServer->SetConnectionData(publicIP, g_NetServer->GetPublicPort(), false); + return true; + } + for (const glooxwrapper::Tag* const& t : m_GameList) glooxwrapper::Tag::free(t); m_GameList.clear(); diff --git a/source/network/StunClient.cpp b/source/network/StunClient.cpp index a6a84fbe66..cb673c60cd 100644 --- a/source/network/StunClient.cpp +++ b/source/network/StunClient.cpp @@ -371,11 +371,6 @@ bool STUNRequestAndResponse(ENetHost& transactionHost) ParseStunResponse(buffer); } -bool StunClient::GetPublicIp(CStr8& ip, u16 port) -{ - return FindStunEndpointHost(ip, port); -} - bool StunClient::FindStunEndpointHost(CStr8& ip, u16& port) { ENetAddress hostAddr{ENET_HOST_ANY, static_cast(port)}; diff --git a/source/network/StunClient.h b/source/network/StunClient.h index 6d6a8e6f08..baf5dd26b1 100644 --- a/source/network/StunClient.h +++ b/source/network/StunClient.h @@ -40,8 +40,6 @@ bool FindStunEndpointHost(CStr8& ip, u16& port); bool FindStunEndpointJoin(ENetHost& transactionHost, StunClient::StunEndpoint& stunEndpoint); void SendHolePunchingMessages(ENetHost& enetClient, const std::string& serverAddress, u16 serverPort); - -bool GetPublicIp(CStr8& ip, u16 port); } #endif // STUNCLIENT_H diff --git a/source/network/scripting/JSInterface_Network.cpp b/source/network/scripting/JSInterface_Network.cpp index 70a852ca0d..0bf2b9d067 100644 --- a/source/network/scripting/JSInterface_Network.cpp +++ b/source/network/scripting/JSInterface_Network.cpp @@ -88,22 +88,15 @@ void JSI_Network::StartNetworkHost(ScriptInterface::CmptPrivate* pCmptPrivate, c bool hasLobby = !!g_XmppClient; g_NetServer = new CNetServer(hasLobby); // In lobby, we send our public ip and port on request to the players, who want to connect. - // In both cases we need to ping stun server to get our public ip. If we want to host via stun, - // we need port as well. + // In either case we need to know our public IP. If using STUN, we'll use that, + // otherwise, the lobby's reponse to the game registration stanza will tell us our public IP. if (hasLobby) { CStr ip; if (!useSTUN) - { - if (!StunClient::GetPublicIp(ip, serverPort)) - { - ScriptRequest rq(pCmptPrivate->pScriptInterface); - ScriptException::Raise(rq, "Failed to get public ip."); - SAFE_DELETE(g_NetServer); - return; - } - g_NetServer->SetConnectionData(ip, serverPort, false); - } + // Don't store IP - the lobby bot will send it later. + // (if a client tries to connect before it's setup, they'll be disconnected) + g_NetServer->SetConnectionData("", serverPort, false); else { u16 port = serverPort;