PDA

View Full Version : IP Limiting Additional Feature and Correction


trevius
09-09-2008, 06:50 AM
First, I noticed that setting the exempt status for accounts doesn't actually work to make that status exempt in the current version of IP Limiting. You have to set it 1 higher status on the account than what you set the rule to for it to be exempt. I believe the reason is this check here:

world/clientlist.cpp
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() <= (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0))) {


And I believe the fix is simple. Just change the <= into a < as shown here in RED:
if ((countCLEIPs->GetIP() == iIP) && ((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) || (RuleI(World, ExemptMaxClientsStatus) < 0))) {

That is a pretty minor fix, but a valid one IMO.

=========================================
Everything below this is extra code that is not necessarily needing to be put into the source

NOTE: The new additional feature code below was written by Derision NOT me. I wrote an original version that didn't work properly and Derision completely rewrote it and now it seems to test perfectly.

The new additional feature I added for the IP limiting is the option to allow an extra account status check which would allow a higher number of IP limited accounts to be set. So, if your normal IP limiting is set to 2, then you could set this new rule to 3 to allow accounts with higher status to have 3 accounts per IP. Yes, this could be done by giving the player 1 exempt account, but the reason for making this option is to remove the possibility for people to trick admins into giving them multiple exempt accounts for the purpose of cheating the IP limiting. One example might be a server that wants to allow families to have an extra account or 2 over the IP limit so they can play together. You don't want people tricking you into giving them 10 accounts so they can box massively and completely avoid the IP limiting rule. With this feature, you could set a secondary IP limit restriction for accounts with a different status. If you have status 0 accounts set to limit to 2 per household, you could set status 1 accounts to be limited to 4 per household (or however many you desire). And you can still set another status to be completely exempt from the rule.

I know, it is a little complicated lol. But I do think it would be useful on many servers.

Here is the new code with changes:

clientlist.cpp
//Lieka && Derision Edit Begin: Check current CLE Entry IPs against incoming connection

void ClientList::GetCLEIP(int32 iIP) {

ClientListEntry* countCLEIPs = 0;
LinkedListIterator<ClientListEntry*> iterator(clientlist);

int IPInstances = 0;
iterator.Reset();

while(iterator.MoreElements()) {

countCLEIPs = iterator.GetData();

// If the IP matches, and the connection admin status is below the exempt status,
// or exempt status is less than 0 (no-one is exempt)

if ((countCLEIPs->GetIP() == iIP) &&
((countCLEIPs->Admin() < (RuleI(World, ExemptMaxClientsStatus))) ||
(RuleI(World, ExemptMaxClientsStatus) < 0))) {

// Increment the occurences of this IP address

IPInstances++;

// If the number of connections exceeds the lower limit

if (IPInstances > (RuleI(World, MaxClientsPerIP))){

// If the Admin status of the connection is not eligible for the higher limit,
// or there is no higher limit (AddMaxClientStatus<0)

if ((countCLEIPs->Admin() < (RuleI(World, AddMaxClientsStatus)) ||
(RuleI(World, AddMaxClientsStatus) < 0))) {

// Remove the connection

countCLEIPs->SetOnline(CLE_Status_Offline);
iterator.RemoveCurrent();
continue;

}
// else they are eligible for the higher limit, but if they exceed that

else if (IPInstances > RuleI(World, AddMaxClientsPerIP)) {

// Remove the connection

countCLEIPs->SetOnline(CLE_Status_Offline);
iterator.RemoveCurrent();
continue;

}
}
}
iterator.Advance();
}
}
//Lieka & Derision Edit End

ruletypes.h
RULE_INT ( World, MaxClientsPerIP, -1 ) //Lieka Edit: Maximum number of clients allowed to connect per IP address if account status is < AddMaxClientsStatus. Default value: -1 (feature disabled)
RULE_INT ( World, ExemptMaxClientsStatus, -1 ) //Lieka Edit: Exempt accounts from the MaxClientsPerIP and AddMaxClientsStatus rules, if their status is >= this value. Default value: -1 (feature disabled)
RULE_INT ( World, AddMaxClientsPerIP, -1 ) //Trevius Edit: Maximum number of clients allowed to connect per IP address if account status is < ExemptMaxClientsStatus. Default value: -1 (feature disabled)
RULE_INT ( World, AddMaxClientsStatus, -1 ) //Trevius Edit: Accounts with status >= this rule will be allowed to use the amount of accounts defined in the AddMaxClientsPerIP. Default value: -1 (feature disabled)


Required SQL:
Insert into rule_values values (0, 'World:AddMaxClientsPerIP', -1);
Insert into rule_values values (0, 'World:AddMaxClientsStatus', -1);

And an example of how to set them:
World:MaxClientsPerIP 2 //Set IP Limit to 2 accounts
World:AddMaxClientsStatus 1 //Set Additional IP Limit Status of 1
World:AddMaxClientsPerIP 4 //Set Additional IP Limit to 4 Accounts
World:ExemptMaxClientsStatus 20 //Any account of 20 or more is exempt of IP Limiting

That is all that is needed. Though, the rule descriptions could probably be written so they are easier to understand. But, this is difficult for me to explain clearly in short lines like that.

It compiles perfectly. Though, I have yet to test to verify that it actually works as described, but I am pretty sure that it should. At the very least, I think the fix for the current IP Limiting at the top of this post should go into the official source code.

MNWatchdog
09-09-2008, 08:26 AM
I don't quiet understand why you're doing this they way you are, but how I would do it is make it so everyone gets the MaxClientsPerIP at the base admin status and 1 additional IP per level above that admin status base.

So, say a players base admin status is 10 and MaxClientsPerIP is set to 2, they would be able to log in 2 clients to IP, but at status of 11, 3 clients per IP, 12, 4 Clients per IP and so on.

This is far clearer than what you described and allows easy custom setting of IP limits.

Only downside is each account the person logs in with would have to be set with the same admin status.

trevius
09-09-2008, 06:36 PM
Feel free to submit some code for a better way to do it :)

I am not much of a coder, but this was a pretty easy way to do something that I needed on my own server. I figured other servers might be able to use it as well, which is why I submitted it. Most servers probably wouldn't need more than 1 or 2 levels of IP limiting. But I do agree that your idea is probably a little better way of handling it to allow more options. And I like having more options :)

After thinking more about it, the whole IP limiting code is slightly flawed in 1 major way. The problem is that it only checks the status of the current account trying to log in instead of checking the status of all accounts logged in from the same IP. So, even if you have an exempt account, if you don't log the exempt account in last after the others are all in, you won't be able to have more than whatever the IP Limit is set to. As long as you log in the exempt accounts after the others are logged in, you can log in more than the IP Limit.

So, what really needs to be done is there needs to be a check of the status of all accounts logged in from the same IP. Then, it needs to subtract the exempt accounts from the total IP Connections before doing the IP Limit restriction.

Here is an example of how it should work:

Account 1 = Status 0
Account 2 = Status 1
Account 3 = Status 2
Account 4 = Status 3
Account 5 = Status 4
Account 6 = Status 5

IP Limiting set to 2 for all status 0 accounts.
AddMaxClientStatus (for additional accounts) IP limiting set to status 1
IP Limiting Exempt set to status 5

Any account with higher than the AddMaxClientStatus would have 1 more connection allowed added to their total IP Limit. Anything between status 1 and 4 will increment the total accounts allowed by 1. So, status 1 would be limited to 3 accounts per IP, status 2 would be limited to 4 accounts per IP and so on.

When an account is logged in, it would pull all of the accounts connected on that IP. The first thing it would do would be to subtract any exempt accounts from the total IP Connections. Next, it would go down the list of other statuses and run a check:

(Account Status - AddMaxClientStatus + 1) = Total Additional Accounts Per IP. Of course you would have to check to make sure this is >= 0 otherwise any account below AddMaxClientStatus - 1 will go into the negative.

Now that we have the total additional accounts that should be allowed per IP for this account, we can just do (total accounts + MaxClientsPerIP) to get the total for this connection.

The last part would just need to be able to pull the next highest account status below the exempt setting for all accounts connected on that same IP. And that status is what would be used for all connections (other than the exempt ones) to decide how many connections are allowed.

This makes my head hurt a little to think about and to make sure it would word exactly the way that it should. But, I am fairly certain that this way would work. If someone can write some code that can check the status of all accounts connected per IP and then select the highest status that is below the exempt status, I am pretty sure I can write the rest of it. The rest is mostly just adding and subtracting and should be fairly simple.

If this was made, I think it would finalize the IP limiting feature options.

The only other issue with IP Limiting is for Windows Servers. Due to player ghosting on Windows, the IP Limiting feature can lock out players from being able to connect at all if they have a ghost in the world already. The best solution for this would obviously be to fix the player ghosting issue on Windows Servers (it doesn't happen on Linux). But, another solution would be to limit it so that only 1 character can be logged in per account like they do on EQLive. Then, if the same account is logged in again, it will boot any characters currently logged in or even at at character select on that same account. This would cause any ghosted characters to be booted from the world as soon as the same account hit "connect" from the server select. And this check would need to be done before the IP Limiting check to make sure that it boots the character being being IP blocked.

I am definitely learning alot about coding just reading through the source and making minor changes. But, I am still very much of a noob at it, so anything that can't be done by example from somewhere else in the code is above me. That is why I would need someone else to write code that would check the status of all accounts on the same IP connection and select the next highest status below the exempt status. But again, if someone does that, I should be able to do the rest to get this feature working 100% as it should.

trevius
09-09-2008, 11:06 PM
I edited the original code I submitted here a little. It wasn't working exactly as it was supposed to. But now it seems to be working as it is intended. I will report back if there are any other issues I see from testing it.

And, I wouldn't mind making the IP limiting code even better, but as I already said, I will need someone who would be able to write code that checks the status of all accounts logged in. Then that code would need to do 2 things. It would need to be able to get the highest account status, and if the highest status was >= to the exempt status setting, then it would also need to get the next highest account status.

MNWatchdog
09-10-2008, 12:31 AM
If I had any skill in C, I certainly would write some code submissions, alas, I dont. I can read most of it though.

As for fixing the character lockout issue caused by the IP limiter, I sent a email to Jibbawalker just this morning on how to fix that too, which Ill share here.

On the line where if checks if theres currently a character logged in at IPs from the logging in IP and then increments IPInstances, add a check to NOT increment that counter if the logging in character is currently in the world. When the new character logs in, the server should kick the already logged in character of the same name.

This should fix that issue.

PS I would have copied the code line I was talking about, but for some reason I cant select and copy text inside /code section on my Nokia 770 and Im just to lazy to scroll back and forth to copy it by hand on my 5 inch screen.

MNWatchdog
09-10-2008, 12:56 AM
Was just thinking that if you called the routine that boots a character whos is already in world and is now logging in before the IP limiter routine, it would solve that issue too.

trevius
09-10-2008, 05:09 AM
Ya, Jibba sent me your idea for the code fix for it. But, that wouldn't really work. The problem with it is that in the emu you can play more than 1 character per account at a time. So, if it was making you exempt from IP limiting if you have a character already logged in on that account, you could just get around it by playing multiple characters on the same account.

Though, your idea is close to a solution. The best way would be for it to check if the account is already logged in and then kick any character on that account so it can log in again. I already mentioned that idea in this thread:

But, another solution would be to limit it so that only 1 character can be logged in per account like they do on EQLive. Then, if the same account is logged in again, it will boot any characters currently logged in or even at at character select on that same account.

That is something I already suggested as a feature request in an earlier post as well here as well:
http://www.eqemulator.net/forums/showthread.php?t=25832

Ideally, it would be best if the account check and player kick was done before the IP Limiting check happened. I don't think it would work otherwise.

MNWatchdog
09-11-2008, 01:53 AM
I think you misundersteed what I was saying. What I am saying will work.

Im saying dont increment the IP counter if the character that is logging in is considered already logged in, thus allowing characters who are ghosted to be logged back in and not locked out by the IP limiter. This will not allow any bypassing of the IP limiter because people are logging in multiple characters from the same account.

Because of the bugs related to zoning multiple toons on that same account, you might as well make it so only one character per account can be logged in though.

Ideally, it would be best if the account check and player kick was done before the IP Limiting check happened. I don't think it would work otherwise.Yup. But either way should work.

cavedude
09-24-2008, 02:03 PM
Unstuck this one because it caused a world crash. Is there newer code available that works?

trevius
09-24-2008, 08:06 PM
It was stickied for the fix to go in, not really for the custom code part to go in. I went ahead and made a new post for the fix here:

http://www.eqemulator.net/forums/showthread.php?p=156812#post156812

And the custom code actually seems to work perfectly so far for me. At least the version in the top post here which has been edited from it's original version. It was rewritten by Derision and works perfectly as intended on my server so far. The original code did cause crashes, but the current one up there doesn't.

Nagus69
09-29-2008, 09:33 AM
Stupid question maybe - but does that mean that once this goes "live" i can no longer 2 or 3 box on EqEmu Servers?

ChaosSlayer
09-29-2008, 09:36 AM
Stupid question maybe - but does that mean that once this goes "live" i can no longer 2 or 3 box on EqEmu Servers?

this code gives server admin option of limiting boxing. what will be the actual limit on any specific server is up to that server admin. If your server never had boxing limit- most likely it will stay that way =)