• gmsv_gatekeeper - Lua controlled server authentication
    453 replies, posted
  • Avatar of slayer3032
  • [QUOTE=AzuiSleet;18907493]I've added gatekeeper.GetUserByAddress, I can't find an IClient or userid on the stack, so you have to use the address passed to PlayerPasswordAuth. [url]http://gmodmodules.googlecode.com/svn/trunk/gmsv_gatekeeper/Release/gmsv_gatekeeper.dll[/url] You should be aware that not returning immediately allows an attacker to run commands anyway, so you need to decide in the callback whether or not you want to kick them. The solution would be to pre-load the banlist on map load.[/QUOTE] Ah, thank you. Yea I understand, however the chances of them doing any major harm is slimmer if they can't sit in the server for like 20 seconds running commands or get to actually load into the server. It's a much better method to drop them rather than ban their ip, the problem was that if a client was banned on one server then decides to go to another server before the list is updated they could slip right in without the passwordauth hook being able to catch them so the only way to prevent that would be to query the database every few seconds which is rather wasteful and dumb even if it is a locally hosted database. The banlist would have been preloaded on mapload anyways otherwise it wouldn't exist for the first client. Now if I could only get all the clients to stop crashing out when people are kicked or banned randomly, it seems to happen with kickid and gatekeeper..
  • Avatar of ComWalk
  • [QUOTE=slayer3032;18907771] Yea I understand, however the chances of them doing any major harm is slimmer if they can't sit in the server for like 20 seconds running commands or get to actually load into the server.[/QUOTE] This is [i]not[/i] a safe assumption to make. If the client successfully authenticates (as in, its 'k' packet is accepted, which will happen if you accept the password), commands can immediately be sent to the server. 'Slimmer' is not good enough, especially given how easy this would be to abuse. [QUOTE=slayer3032;18907771]Ah, thank you. It's a much better method to drop them rather than ban their ip, the problem was that if a client was banned on one server then decides to go to another server before the list is updated they could slip right in without the passwordauth hook being able to catch them so the only way to prevent that would be to query the database every few seconds which is rather wasteful and dumb even if it is a locally hosted database. The banlist would have been preloaded on mapload anyways otherwise it wouldn't exist for the first client.[/QUOTE] The PlayerPasswordAuth hook should [b]not[/b] be used as your sole line of defense. The steamid it receives can be missing and it is theoretically possible for it to be maliciously manipulated. [b]Always[/b] verify the steamid again in the PlayerAuthed hook, as this is the 'blessed by valve' steamid. If anything, I would frequently query the ban table for new bans, deny a connection attempt if either the reported steamid (keep in mind, this will not always be provided) OR ip is banned, and then in PlayerAuthed check [b]again[/b] as well as run a threaded query as you do now in PlayerPasswordAuth to catch anybody trying to game the system. [QUOTE=slayer3032;18907771]Ah, thank you. Now if I could only get all the clients to stop crashing out when people are kicked or banned randomly, it seems to happen with kickid and gatekeeper..[/QUOTE] I'm going to need more details on this one. Every client connected is crashing? Gatekeeper does not affect connected and authenticated clients in any way. If it is possible to crash a client, it would be caused by a malformed kick message sent to gatekeeper.Drop. Why are you using kickid anyways? EDIT: In respose to your earlier post, the userid cannot be provided in PlayerPasswordAuth because the userid simply hasn't been allocated for the user yet. I suppose it could be possible to pass the userid next in line to be used, but it seems an ugly hack at best. AzuiSleet's UserByIPAddress function is as good as it is going to get as the IClient isn't assocated with a steamid until the steam callback is received.
  • Avatar of slayer3032
  • [QUOTE=ComWalk;18908567]This is [i]not[/i] a safe assumption to make. If the client successfully authenticates (as in, its 'k' packet is accepted, which will happen if you accept the password), commands can immediately be sent to the server. 'Slimmer' is not good enough, especially given how easy this would be to abuse.[/QUOTE] There isn't much else I could do other than do it the best I could. [QUOTE=ComWalk;18908567]The PlayerPasswordAuth hook should [b]not[/b] be used as your sole line of defense. The steamid it receives can be missing and it is theoretically possible for it to be maliciously manipulated. [b]Always[/b] verify the steamid again in the PlayerAuthed hook, as this is the 'blessed by valve' steamid.[/QUOTE] Good idea, I'll add that, thanks. [QUOTE=ComWalk;18908567]If anything, I would frequently query the ban table for new bans, deny a connection attempt if either the reported steamid (keep in mind, this will not always be provided) OR ip is banned, and then in PlayerAuthed check [b]again[/b] as well as run a threaded query as you do now in PlayerPasswordAuth to catch anybody trying to game the system.[/QUOTE] I don't host my database on the same computer, I really hate to needlessly query. I don't have any IPs banned and wasn't intending to put them into this script. [QUOTE=ComWalk;18908567]I'm going to need more details on this one. Every client connected is crashing? Gatekeeper does not affect connected and authenticated clients in any way. If it is possible to crash a client, it would be caused by a malformed kick message sent to gatekeeper.Drop. Why are you using kickid anyways?[/QUOTE] What I meant was when I tried going back to kickid it still crashed out clients, I'm thinking either Garry or valve is doing something sketchy with their code and it's trying to do something to the now null played. It's not your fault that it is doing this but I thought someone might be able to shed some more light on it. It crashes all the clients in the server, however my screen doesn't yet show the message on the screen either. It doesn't crash the player that was kicked too. [QUOTE=ComWalk;18908567]EDIT: In respose to your earlier post, the userid cannot be provided in PlayerPasswordAuth because the userid simply hasn't been allocated for the user yet. I suppose it could be possible to pass the userid next in line to be used, but it seems an ugly hack at best. AzuiSleet's UserByIPAddress function is as good as it is going to get as the IClient isn't assocated with a steamid until the steam callback is received.[/QUOTE] Chrisaster was telling me to use the gevents module to kick these clients but I figure that they would have already been able to run commands by then so I just stuck with banning their IP for a minute.
  • Avatar of ComWalk
  • Well, with AzuiSleet's addition of GetUserByAddress, you should be able to get everything working now. [QUOTE=slayer3032;18908812]There isn't much else I could do other than do it the best I could.[/QUOTE] Sorry if I seemed harsh; it's just important to note that if you want to stop commands from being run then you [b]cannot[/b] allow them to get past PlayerPasswordAuth. If that's not feasible to do, then at least don't get lulled into a false sense of security. [QUOTE=slayer3032;18908812]I don't host my database on the same computer, I really hate to needlessly query. I don't have any IPs banned and wasn't intending to put them into this script.[/QUOTE] I only mentioned IP banning because that is guaranteed to be correct in the PlayerPasswordAuth hook, so it's really the only thing that you can be certain about in the hook. It's still good as the first line of a multi-line defense. Going off on a tangent, I don't think you're giving your database server enough credit. If you update it every 5-10 seconds with a threaded query (set up to select only bans that have been added since the last check) I think you'll find your performance unaffected. I have a P2 333 that putts right along with a sizable database and can get hit with multiple queries per second. The distance between the servers will really only affect the time it takes for your callback to get called, but I'd say that it's better to have your cached banlist out of date by a few seconds than it is to never update it until after you could have already used it! (Especially since it would allow you to more effectively block commands from being run, which seems like a big concern) I suppose there's probably more to it than that, though.
  • Avatar of |FlapJack|
  • [QUOTE=ComWalk;18908567]The PlayerPasswordAuth hook should [b]not[/b] be used as your sole line of defense. The steamid it receives can be missing and it is theoretically possible for it to be maliciously manipulated. [b]Always[/b] verify the steamid again in the PlayerAuthed hook, as this is the 'blessed by valve' steamid.[/QUOTE] Didn't know about this - Good thing I hadn't started using gatekeeper in my admin mod before seeing this. Thanks.
  • Avatar of slayer3032
  • [QUOTE=ComWalk;18909251]Well, with AzuiSleet's addition of GetUserByAddress, you should be able to get everything working now.[/QUOTE] Yea, working on it right now. [QUOTE=ComWalk;18909251]Sorry if I seemed harsh; it's just important to note that if you want to stop commands from being run then you [b]cannot[/b] allow them to get past PlayerPasswordAuth. If that's not feasible to do, then at least don't get lulled into a false sense of security.[/QUOTE] It's okay, I understand. Most the the remaining commands just lag the server so this will do fine for now. If it gets to the point where that one chance that a player can get after being banned of a server is being abused I'll think of something else or refresh the table from the database. [QUOTE=ComWalk;18909251]I only mentioned IP banning because that is guaranteed to be correct in the PlayerPasswordAuth hook, so it's really the only thing that you can be certain about in the hook. It's still good as the first line of a multi-line defense.[/QUOTE] I thought about adding IPs to it but I'm not really sure, it might catch people with multiple accounts but the only people who might actually do anything malicious to your server probably would have multiple accounts, along with the average troll. I might think about it since you are right and it could easily catch people who do try to modify their steamid info and the various idiots with lots of accounts. [QUOTE=ComWalk;18909251]Going off on a tangent, I don't think you're giving your database server enough credit. If you update it every 5-10 seconds with a threaded query (set up to select only bans that have been added since the last check) I think you'll find your performance unaffected. I have a P2 333 that putts right along with a sizable database and can get hit with multiple queries per second. The distance between the servers will really only affect the time it takes for your callback to get called, but I'd say that it's better to have your cached banlist out of date by a few seconds than it is to never update it until after you could have already used it! (Especially since it would allow you to more effectively block commands from being run, which seems like a big concern) I suppose there's probably more to it than that, though.[/QUOTE] I realize that isn't very expensive to do more queries just to make sure but I don't see the the banlist being used highly in the first place, even if people get to the point where they can connect to the server anything they do will be in vain because if they manage to crash one of the other servers it will just restart in 20-30 seconds and they won't be able to touch the server again until their ban is gone. Spamming queries every 5-10 seconds for that one chance that a banned user to attack the other servers before the list is refreshed by someone connecting even if it is pretty cheap still seems like a waste to me. An added IP to check along with their SteamID might be useful but any resourceful script kiddie or idiot can reset their router/spoof a MAC address/use a VPN. A IP doesn't mean much more than a direct connection to that specific person and not a personal identification. At the point where IPs come in would be a better job for a human to put the pieces together trying to find alt accounts than a script. Even when commands come in I still have other things as a protection such as SLog or Cvar2. [editline]05:27AM[/editline] Actually, it seems as though almost every time a client is dropped while being in the server all the clients crash out. Gatekeeper.Drop() seems to do it more than kickid ever did... Argh, why is Garry's Mod doing this now, I think it started happening after that one update where Garry added the new voice hud item. I'll try to look into this more later, it's getting too late for me.
  • Avatar of Lau
  • [QUOTE=AzuiSleet;18907493]I've added gatekeeper.GetUserByAddress, I can't find an IClient or userid on the stack, so you have to use the address passed to PlayerPasswordAuth. [url]http://gmodmodules.googlecode.com/svn/trunk/gmsv_gatekeeper/Release/gmsv_gatekeeper.dll[/url] You should be aware that not returning immediately allows an attacker to run commands anyway, so you need to decide in the callback whether or not you want to kick them. The solution would be to pre-load the banlist on map load.[/QUOTE] Its no big deal if you know the commands to block and can just use slog to patch them. Plus, the addon I released is a WIP, and I'll take this topic's discussion of using PlayerPasswordAuth hook and using PlayerAuthed to make sure that players dont get past the filter. Thank you for your edit, i'll probably be using that instead now.
  • Avatar of leeetdude
  • error loading module 'gatekeeper' from file 'c:\_x\lua\includes\modules\gmsv_gatekeeper.dll': %1 is not a valid Win32 application. Edit: SVN Version. The 3.1 seems to work fine for me (the zip file)
  • Avatar of AzuiSleet
  • Sounds like a runtime issue, I compile everything with 2008 SP1, here's the redist: [url]http://www.microsoft.com/downloads/details.aspx?familyid=A5C84275-3B97-4AB7-A40D-3802B2AF5FC2&displaylang=en[/url]
  • Avatar of ComWalk
  • New version of gatekeeper has been released. Linux support has been added and some of the internals have been cleaned up. Anybody interested in the makefile can take a look at the repo; it goes into the linux_sdk/ directory of the source sdk after some obvious changes to the main makefile. Everything was built with gcc 4.3.
  • Avatar of |FlapJack|
  • Did you fix the memory messup where clients end up dropped with the gamemode name as a reason on connect?
  • Avatar of ComWalk
  • [QUOTE=|FlapJack|;21918665]Did you fix the memory messup where clients end up dropped with the gamemode name as a reason on connect?[/QUOTE] Given that it has not once been reported to me, no. I really doubt that gatekeeper is to blame. In this version, there isn't any strange memory voodoo going on during connect, and even the last version (which searched through the stack to find the call to ConnectClient) would never have stumbled across a pointer to the gamemode (the engine doesn't care about sv_gamemode and it has no reason to be on the stack for a connection attempt). If you can provide a way to reliably reproduce it, I'll look into it, but for now I'm fairly certain that fault lies with another module or script.
  • Avatar of slayer3032
  • gatekeeper.GetUserByAddress() doesn't seem to be working. When it should be kicking players on a secondary check it just returns nil. [editline]11:19PM[/editline] [code] > print(gatekeeper.GetUserByAdress)... nil > print(gatekeeper.Drop)... function: 02DD2850 [/code]
  • Avatar of ComWalk
  • [QUOTE=slayer3032;21936607]gatekeeper.GetUserByAddress() doesn't seem to be working. [code] > print(gatekeeper.GetUserByAdress)... nil > print(gatekeeper.Drop)... function: 02DD2850 [/code][/quote] You spelled GetUserByAddress incorrectly. [code] > print(gatekeeper.GetUserByAddress)... function: 026CD508 [/code] [QUOTE=slayer3032;21936607] When it should be kicking players on a secondary check it just returns nil. [/QUOTE] What should be kicking players? What secondary check? I'm not certain what function you are referring to... If you are talking about GetUserByAddress, it doesn't kick. None of the functions that do kick should return anything but nil. Testing it just now, both GetUserByAddress and Drop behave exactly as I would expect them to.
  • Avatar of |FlapJack|
  • Can't exactly replicate it. However, it did stop after removing gatekeeper. It only happened occasionally, on initial connect.
  • Avatar of slayer3032
  • Woops, well gatekeeper.GetUserByAddress seemed to have been returning nil when checking for any recent connections by banned players after my ban list is refreshed. I might have been using a really old version of gatekeeper some how, I'm not really sure.
  • Avatar of ComWalk
  • [QUOTE=|FlapJack|;21937021]Can't exactly replicate it. However, it did stop after removing gatekeeper. It only happened occasionally, on initial connect.[/QUOTE] Probably because the hook that was actually causing it was no longer being called. :smile: [QUOTE=slayer3032;21937221]Woops, well gatekeeper.GetUserByAddress seemed to have been returning nil when checking for any recent connections by banned players after my ban list is refreshed. I might have been using a really old version of gatekeeper some how, I'm not really sure.[/QUOTE] Yeah, it would have to be an older version for that to happen. It's added to the table in the same way and in the same place as the other functions, so if the other functions are there, it should be there.
  • Avatar of ComWalk
  • I've updated gatekeeper to work with the source 2009 version of gmod. Do [b]not[/b] attempt to use 4.1 with a server that isn't running the beta as it will probably crash on startup (or on first connect). This version should be compatible with the next update, whenever it comes out. Linux binaries will follow as soon as gmod linux binaries for source 2009 are released.
  • Avatar of ComWalk
  • GateKeeper has been updated with code necessary for the detection and removal of clients that using tools such as Tranquility to spoof their steamid. Not perfect, but the best solution available until valve patches it for good (not long now that they have a working POC in their hands).
  • Avatar of VoiDeD
  • The related lua code for making use of these new GateKeeper features is available here: [url]http://www.facepunch.com/showthread.php?t=962042[/url]
  • Avatar of infinitywrai
  • The latest version of gatekeeper has been misreporting the number of players. I clearly had 15 players in-game and connecting (reported by HLSW, and any viewing tool) but gatekeeper:GetNumClients().total was reporting a few players less than that. This happens every time.
  • Avatar of ComWalk
  • [QUOTE=infinitywrai;23035332]The latest version of gatekeeper has been misreporting the number of players. I clearly had 15 players in-game and connecting (reported by HLSW, and any viewing tool) but gatekeeper:GetNumClients().total was reporting a few players less than that. This happens every time.[/QUOTE] Just found the cause of this; one of the IServer functions had its behavior changed. I'll try to have the fix out later today. EDIT: Try [url=http://code.google.com/p/gmodmodules/downloads/detail?name=gmsv_gatekeeper4.1%2Bantitranq.zip&can=2&q=]this[/url]
  • Avatar of Killer_Steel
  • Can't remember if this was mentioned or not. Can this module in any way be used for kicking people from the server once they're connected? Or do I have to use ply:Kick()?
  • Avatar of ComWalk
  • [QUOTE=Killer_Steel;23042038]Can't remember if this was mentioned or not. Can this module in any way be used for kicking people from the server once they're connected? Or do I have to use ply:Kick()?[/QUOTE] Yes, see the documentation for gatekeeper.Drop. It was not only mentioned, but very explicitly used in the example code. Instead of ply:Kick(), you're able to do [lua]gatekeeper.Drop(ply:UserID(), "bye.")[/lua] And, since it can't really be repeated often enough, [b]DO NOT use the player's entity after calling gatekeeper.Drop[/b].
  • Avatar of raBBish
  • [QUOTE=Killer_Steel;23042038]Can't remember if this was mentioned or not. Can this module in any way be used for kicking people from the server once they're connected? Or do I have to use ply:Kick()?[/QUOTE] [lua]gatekeeper.Drop( ply:UserID(), "I'm a big fat idiot" )[/lua] [editline]02:41AM[/editline] :ninja:
  • Avatar of Killer_Steel
  • Thanks. Was just checking so I wouldn't end up crashing the server using a method the way it wasn't intended. And I'm ignoring that comment, raBBish.
  • Avatar of raBBish
  • [QUOTE=Killer_Steel;23043087]And I'm ignoring that comment, raBBish.[/QUOTE] Oh sorry, that wasn't directed at anybody. I was just watching Simpsons (Angry Dad episode) when writing it and I just wrote the first thing I heard :v:
  • Avatar of Killer_Steel
  • Funny how that happens, actually. When yer listening to a conversation and IM chatting at the same time, then you just write a random word from whatever you're listening to.