• There is NO official Otland's Discord server and NO official Otland's server list. The Otland's Staff does not manage any Discord server or server list. Moderators or administrator of any Discord server or server lists have NO connection to the Otland's Staff. Do not get scammed!

Block MC with same IP

What mechanism are you using? TFS? OTX? 0.x? TFS 1.x? You need to provide information about what you're using; it's impossible to know what you're working on without it—it's simple.

Additionally, the next time you post, make sure to specify the version of your mechanism, like TFS.

If it's TFS 1.x, Xiniki has developed a better system to block multi-clienting by IP, allowing only up to 2 IPs here.

 
LUA:
local AccPorIp = 3 -- Allowed connections

function onLogin(player)

    local mc = 0
    for _, verificar in ipairs(Game.getPlayers()) do
        if player:getIp() == verificar:getIp() then
            mc = mc + 1
            if mc > AccPorIp then return false end
        end
    end
 
    return true
end
 
it should be done in protocol, not in onLogin, because if you exit with pz or infight your character stay in game, and when someone login on logged in character it does not proc onLogin func from lua so you can just bypass it easly
 
it should be done in protocol, not in onLogin, because if you exit with pz or infight your character stay in game, and when someone login on logged in character it does not proc onLogin func from lua so you can just bypass it easly
So what? Can you play with the character that is exited? No, stop overthinking simple stuff.
 
@Stanos Your code looping all players that are currently online, every fucking single player that loggin in server trigger this loop, and later ppl crying "i have 10 players and my vps cant hold it."

@Perun You are 100% right.
 
So what? Can you play with the character that is exited? No, stop overthinking simple stuff.
You can play character that exited using other IP than detected in onLogin event.

You can open another Tibia Client and connect to character that is already in game. Character IP will change, but onLogin event won't be executed, so it won't limit number of characters logged from given IP.
You just need 2 IPs. Login into game with 1st IP, then login into logged-in character with 2nd IP. Your script will compare 1st IP with 2nd (current) IP of characters in game, so you may have 100 characters with 2nd IP in game, as there will be 0 characters with 1st IP in-game.

To limit number of connections per IP you would need to use onThink event to check number of players per IP and kick them, if there are too many logged from same IP - as Xikini's script does.
Or as @Perun said, you must use 'protocol', which means C++ ProtocolGame ex. ProtocolGame::connect to check MC for every connection, not just for every onLogin event.

To limit number of connections per IP on Linux, you can use firewall ex. for 2 connections per IP to port 7172:
Code:
iptables -A INPUT -p tcp --syn --dport 7172 -m connlimit --connlimit-above 2 --connlimit-mask 32 -j REJECT --reject-with tcp-reset
 
Does Roddet's C++ implementation have performance issues by looping through all online players on each login, similar to the Lua anti-MC script? Or is it reliable as is? Would using a cached IP counter in C++ or another approach be more efficient?

 
Does Roddet's C++ implementation have performance issues by looping through all online players on each login
It should not hit CPU usage hard. Loop over players online is super fast, even with 2000 online. Only problem can be access to IP and conversion to comparable format.
Of course, tracking IPs of connected players in some std::map<IP, count_of_connections> is faster, but code may be a bit complicated.

How it works on different distros:
  • up to TFS 1.6, IP was simple uint32_t. getIP() in Connection called some socket function to get IP from it, IDK what it did inside, maybe it called some system function to obtain IP of socket (slow), but maybe it already had socket IP in OTS RAM and just had to copy it (fast).
  • on TFS 1.6 they added IPv6 support and getIP() returns boost::asio::ip::address structure (with IPv4 or IPv6 inside), but socket.remote_endpoint() is called only once and cached in remoteAddress variable, so there is cache already.
  • Canary still uses uint32_t IP format and they already added internal cache in getIP() function, to call socket.remote_endpoint only once - when getIP() is called first time. Only CPU wasting part of getIP() is locking std::scoped_lock lock(connectionLock);, even when we only read cached variable.

Summary:
  • TFS up to 1.4 - simple code in getIP(), but not cached
  • TFS 1.6 - already caches IP in Connection class
  • canary - already caches IP in Connection class, may waste some CPU on connectionLock for every call to getIP()
 
Back
Top