Make loginserver intelligently determine if the client is requesting from a RFC 1918 network instead of using a config string match

This commit is contained in:
Akkadius 2019-07-05 03:38:12 -05:00
parent 2c922876a9
commit feea52f79e
8 changed files with 155 additions and 52 deletions

View File

@ -35,6 +35,7 @@ SET(common_sources
inventory_profile.cpp inventory_profile.cpp
inventory_slot.cpp inventory_slot.cpp
ipc_mutex.cpp ipc_mutex.cpp
ip_util.cpp
item_data.cpp item_data.cpp
item_instance.cpp item_instance.cpp
json_config.cpp json_config.cpp
@ -159,6 +160,7 @@ SET(common_headers
inventory_profile.h inventory_profile.h
inventory_slot.h inventory_slot.h
ipc_mutex.h ipc_mutex.h
ip_util.h
item_data.h item_data.h
item_fieldlist.h item_fieldlist.h
item_instance.h item_instance.h

View File

@ -1,53 +1,57 @@
/* EQEMu: Everquest Server Emulator /**
* EQEmulator: Everquest Server Emulator
Copyright (C) 2001-2016 EQEMu Development Team (http://eqemulator.net) * Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
This program is free software; you can redistribute it and/or modify * This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by * it under the terms of the GNU General Public License as published by
the Free Software Foundation; version 2 of the License. * the Free Software Foundation; version 2 of the License.
*
This program is distributed in the hope that it will be useful, * This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY except by those people which sell it, which * but WITHOUT ANY WARRANTY except by those people which sell it, which
are required to give you total support for your newly bought product; * are required to give you total support for your newly bought product;
without even the implied warranty of MERCHANTABILITY or FITNESS FOR * without even the implied warranty of MERCHANTABILITY or FITNESS FOR
A PARTICULAR PURPOSE. See the GNU General Public License for more details. * A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
You should have received a copy of the GNU General Public License * You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software * along with this program; if not, write to the Free Software
Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*/ *
*/
#pragma once #pragma once
#include <algorithm> #include <algorithm>
#include <cmath> #include <cmath>
namespace EQEmu namespace EQEmu {
{ template<typename T>
template <typename T> T Clamp(const T &value, const T &lower, const T &upper)
T Clamp(const T& value, const T& lower, const T& upper) { {
return std::max(lower, std::min(value, upper)); return std::max(lower, std::min(value, upper));
} }
template <typename T> template<typename T>
T ClampLower(const T& value, const T& lower) { T ClampLower(const T &value, const T &lower)
{
return std::max(lower, value); return std::max(lower, value);
} }
template <typename T> template<typename T>
T ClampUpper(const T& value, const T& upper) { T ClampUpper(const T &value, const T &upper)
{
return std::min(value, upper); return std::min(value, upper);
} }
template <typename T> template<typename T>
bool ValueWithin(const T& value, const T& lower, const T& upper) { bool ValueWithin(const T &value, const T &lower, const T &upper)
{
return value >= lower && value <= upper; return value >= lower && value <= upper;
} }
template <typename T1, typename T2, typename T3> template<typename T1, typename T2, typename T3>
bool ValueWithin(const T1& value, const T2& lower, const T3& upper) { bool ValueWithin(const T1 &value, const T2 &lower, const T3 &upper)
return value >= (T1)lower && value <= (T1)upper; {
return value >= (T1) lower && value <= (T1) upper;
} }
} /*EQEmu*/ } /*EQEmu*/

72
common/ip_util.cpp Normal file
View File

@ -0,0 +1,72 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#include "ip_util.h"
/**
* @param ip
* @return
*/
uint32_t IpUtil::IPToUInt(const std::string &ip)
{
int a, b, c, d;
uint32_t addr = 0;
if (sscanf(ip.c_str(), "%d.%d.%d.%d", &a, &b, &c, &d) != 4) {
return 0;
}
addr = a << 24;
addr |= b << 16;
addr |= c << 8;
addr |= d;
return addr;
}
/**
* @param ip
* @param network
* @param mask
* @return
*/
bool IpUtil::IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask)
{
uint32_t ip_addr = IpUtil::IPToUInt(ip);
uint32_t network_addr = IpUtil::IPToUInt(network);
uint32_t mask_addr = IpUtil::IPToUInt(mask);
uint32_t net_lower = (network_addr & mask_addr);
uint32_t net_upper = (net_lower | (~mask_addr));
return ip_addr >= net_lower && ip_addr <= net_upper;
}
/**
* @param ip
* @return
*/
bool IpUtil::IsIpInPrivateRfc1918(const std::string &ip)
{
return (
IpUtil::IsIpInRange(ip, "10.0.0.0", "255.0.0.0") ||
IpUtil::IsIpInRange(ip, "172.16.0.0", "255.240.0.0") ||
IpUtil::IsIpInRange(ip, "192.168.0.0", "255.255.0.0")
);
}

36
common/ip_util.h Normal file
View File

@ -0,0 +1,36 @@
/**
* EQEmulator: Everquest Server Emulator
* Copyright (C) 2001-2019 EQEmulator Development Team (https://github.com/EQEmu/Server)
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; version 2 of the License.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY except by those people which sell it, which
* are required to give you total support for your newly bought product;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR
* A PARTICULAR PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*/
#ifndef EQEMU_IP_UTIL_H
#define EQEMU_IP_UTIL_H
#include "types.h"
#include "iostream"
class IpUtil {
public:
static uint32_t IPToUInt(const std::string &ip);
static bool IsIpInRange(const std::string &ip, const std::string &network, const std::string &mask);
static bool IsIpInPrivateRfc1918(const std::string &ip);
};
#endif //EQEMU_IP_UTIL_H

View File

@ -68,7 +68,6 @@ int main()
server.options.WorldTrace(server.config.GetVariableBool("general", "world_trace", false)); server.options.WorldTrace(server.config.GetVariableBool("general", "world_trace", false));
server.options.DumpInPackets(server.config.GetVariableBool("general", "dump_packets_in", false)); server.options.DumpInPackets(server.config.GetVariableBool("general", "dump_packets_in", false));
server.options.DumpOutPackets(server.config.GetVariableBool("general", "dump_packets_out", false)); server.options.DumpOutPackets(server.config.GetVariableBool("general", "dump_packets_out", false));
server.options.LocalNetwork(server.config.GetVariableString("general", "local_network", "192.168.1."));
server.options.RejectDuplicateServers(server.config.GetVariableBool("general", "reject_duplicate_servers", false)); server.options.RejectDuplicateServers(server.config.GetVariableBool("general", "reject_duplicate_servers", false));
server.options.AutoCreateAccounts(server.config.GetVariableBool("general", "auto_create_accounts", true)); server.options.AutoCreateAccounts(server.config.GetVariableBool("general", "auto_create_accounts", true));
server.options.AutoLinkAccounts(server.config.GetVariableBool("general", "auto_link_accounts", true)); server.options.AutoLinkAccounts(server.config.GetVariableBool("general", "auto_link_accounts", true));

View File

@ -103,16 +103,6 @@ public:
*/ */
inline int GetEncryptionMode() const { return encryption_mode; } inline int GetEncryptionMode() const { return encryption_mode; }
/**
* Sets local_network.
*/
inline void LocalNetwork(std::string n) { local_network = n; }
/**
* Return the value of local_network.
*/
inline std::string GetLocalNetwork() const { return local_network; }
/** /**
* Sets account table. * Sets account table.
*/ */

View File

@ -25,6 +25,7 @@
#include "../common/eqemu_logsys.h" #include "../common/eqemu_logsys.h"
#include "../common/eqemu_logsys_fmt.h" #include "../common/eqemu_logsys_fmt.h"
#include "../common/ip_util.h"
extern LoginServer server; extern LoginServer server;
extern bool run_server; extern bool run_server;
@ -137,7 +138,8 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *client, uint3
if (world_ip.compare(client_ip) == 0) { if (world_ip.compare(client_ip) == 0) {
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
} }
else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) { else if (IpUtil::IsIpInPrivateRfc1918(client_ip)) {
LogLoginserver("Client is requesting server list from a local address [{0}]", client_ip);
packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24; packet_size += (*iter)->GetLongName().size() + (*iter)->GetLocalIP().size() + 24;
} }
else { else {
@ -177,7 +179,7 @@ EQApplicationPacket *ServerManager::CreateServerListPacket(Client *client, uint3
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1); data_pointer += ((*iter)->GetLocalIP().size() + 1);
} }
else if (client_ip.find(server.options.GetLocalNetwork()) != std::string::npos) { else if (IpUtil::IsIpInPrivateRfc1918(client_ip)) {
memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size()); memcpy(data_pointer, (*iter)->GetLocalIP().c_str(), (*iter)->GetLocalIP().size());
data_pointer += ((*iter)->GetLocalIP().size() + 1); data_pointer += ((*iter)->GetLocalIP().size() + 1);
} }

View File

@ -24,6 +24,7 @@
#include "config.h" #include "config.h"
#include "../common/eqemu_logsys.h" #include "../common/eqemu_logsys.h"
#include "../common/eqemu_logsys_fmt.h" #include "../common/eqemu_logsys_fmt.h"
#include "../common/ip_util.h"
extern LoginServer server; extern LoginServer server;
@ -556,17 +557,13 @@ void WorldServer::Handle_NewLSInfo(ServerNewLSInfo_Struct *new_world_server_info
if (server.options.IsRejectingDuplicateServers()) { if (server.options.IsRejectingDuplicateServers()) {
if (server.server_manager->ServerExists(long_name, short_name, this)) { if (server.server_manager->ServerExists(long_name, short_name, this)) {
Log(Logs::General, Error("World tried to login but there already exists a server that has that name");
Logs::Error,
"World tried to login but there already exists a server that has that name.");
return; return;
} }
} }
else { else {
if (server.server_manager->ServerExists(long_name, short_name, this)) { if (server.server_manager->ServerExists(long_name, short_name, this)) {
Log(Logs::General, Error("World tried to login but there already exists a server that has that name");
Logs::Error,
"World tried to login but there already exists a server that has that name.");
server.server_manager->DestroyServerByName(long_name, short_name, this); server.server_manager->DestroyServerByName(long_name, short_name, this);
} }
} }
@ -783,7 +780,8 @@ void WorldServer::SendClientAuth(
if (client_address.compare(world_address) == 0) { if (client_address.compare(world_address) == 0) {
client_auth.local = 1; client_auth.local = 1;
} }
else if (client_address.find(server.options.GetLocalNetwork()) != std::string::npos) { else if (IpUtil::IsIpInPrivateRfc1918(client_address)) {
LogLoginserver("Client is authenticating from a local address [{0}]", client_address);
client_auth.local = 1; client_auth.local = 1;
} }
else { else {