Multiple clients on the same IP?

BlitzMax Forums/BlitzMax Programming/Multiple clients on the same IP?

Richard Betson(Posted 2014) [#1]
Hi,

I am using Bnetex for my networking library and I am wondering how I can have several clients work over the same IP address. I was thinking that I could send packets from the server with a client ID and a client with that ID would accept the incoming packet but I am not sure this will work. Is this a viable way to support multiple client on the same IP address? Is there a better way?

Thanks,
- Rich -


Wiebo(Posted 2014) [#2]
Maybe accept packets on different IP ports?


BlitzSupport(Posted 2014) [#3]
Yeah, I also think you'd need multiple ports for this.


Richard Betson(Posted 2014) [#4]
Hi,

OK.. I guess that will work and is easier to address code wise for me. I'll have to look at the cost of doing this resource wise on BnetEX but it is possible to listen on a range of ports. It just might be a little costly CPU resource wise on the server.

Thanks for the help.
- Rich -


Brucey(Posted 2014) [#5]
As far as I am aware, your server will listen on a given port, say 25000.
Along comes client1, and attempts a connection to the server on port 25000. Server responds and the two agree on a free port number over which they can communicate (well, the server says, "let's move our communication to port 18559")
Another client attempts to connect on port 25000. Server responds again, and assigns port 21558 for that connection...

... and so on.

This is certainly what goes on in my day job - on big servers with 1000's of simultaneous client connections.
I assume it works the same way in a game?


Scaremonger(Posted 2014) [#6]
There are a lot of application that do this and they are a nightmare for Firewall administrators. When you open a port on a firewall you do so for the direction of the initial conversation but using this type of port-factory means that you have to open additional ports and by opening them you may be opening the door for a hacker utilising a vulnerability.

However; If you are going to employ this mechanism, make sure that the "working" port is opened from the server TO the client and not the other way around. This means that once your client receives the port to use from the server, it should then listen for the server to call-back.

By implementing it this way the firewall protecting your server will have outbound ports open rather than lots of inbound ones and this should help to protect it.

Alternatively, as you initially suggested; Keep a connection ID. You can also use socket.remoteip() and socket.remoteport() to identify the client.

Si...


Derron(Posted 2014) [#7]
You do not need to support multiple Ports.

You can - but mostly you just run into the firewall trap (force your users to do port mapping).

Port Mapping is only needed for "central servers". All other use hole punching (client sends "i wanna join" to server, client2 sends "i host" to server - server now knows client and client2's ips/used ports - and voila... they can connect to each other without port forwarding <-- description was the easy way).

Like Brucey already said:
If you use UDP (with bnetex) you do not know what port you are using for sending. You only know what port you are targeting.
That is why eg. for the old Warcraft III you needed portmapping to your setup client-port as soon as you wanted to host on Battle.net.

So with UDP you open a connection to IP1:Port123 and then just wait for a timeout (locally measured, not line wise) or a packet. The packet then could contain your sender port (this is how I do it). Using this method, you can run 2 clients on one PC - both use a different communication / outgoing port but the same target-port.

Means - Brucey already told what happens: multiple outgoing ports (the clients), one incoming port (server side). The server does not need to have one "port" for each connection, he can separate them by their IP:port-combination.

But - as you already mentioned - you could send your "clientID" in each packet (I do this in some packets too) but it should not be needed. I just do it during "lobby action" (setting up players of a game, spreading around their data using broadcast-adresses, ...).

For easyness: use a "server port" (there a server listens to incoming connections), the clients will setup the ports on their own. Using this method, you only need to do router-port-forwarding as soon as you want to host. Using that method, your home could host multiple games (with differing ports). If you want to host 2 games on one port you will run into trouble (exception is a "host/server"-app which can host multiple games at once). If you have 2 computers in a LAN connected to WAN, they must use different ports for hosting. Your router wont know which packet for "wanIP:port" is targeting host1 or host2). In that case you use hole punching to a "lobby server". You host a game on host1 - it announces to lobbyserver (and gets the senderPort), now host2 hosts a game and announces (senderPort2). With that information the lobbyserver can spread around a list of hosted games:
wanIP:senderPort1
wanIP:senderPort2

People would be able to connect their clients to that Port.



bye
Ron


Richard Betson(Posted 2014) [#8]
All good stuff,

As Brucey suggests it's best to have one port set to listen on and then assign a client a port that it will use. This works great for the resource end as the server is listening on one port and perhaps sending game data on a second default port for single client/IP setups. This I like and I do not see a problem with assigning multiple clients to a port from the same or other IP addresses and as suggested the clients can send data on a default port and receive data on another.

I had intended to go with a dedicated headless Linux server and I still will probably do that but I think I may start out with a dual server/client application that can be used on a home setup. It will support a lesser number of clients (only limited by upstream bandwidth) but will also be easier for those less technically able. My game ( www.phoenixusc.com ) is already coded to support this as it uses an authoritative server so both the client and server use the same game engine/framework.

Another hurdle will be assigning firewall policies to Windows, MAC and Linux which I'm not sure how to do but I suspect that a proper install application might be able to help. The port forwarding end of things is a bit sticky but I suspect that those running servers will have experience with this and can easily assign a rang of ports for the server. The clients will not need to do this and just needs a firewall policy.

So, all good and very helpful.

Thanks,


Derron(Posted 2014) [#9]
I just wrote a longer post - but fglrx.so crashed and with it the whole desktop ... think Mint16 was released way to buggy.


Ok in short: use hole punching if you want to avoid manual port forwarding (with a lobby in the middle of the "meeting each other" process).

As an "outgoing" port cannot be used by multiple processes you can identify a user by the "ip:senderPort"-combination.

If a game is starting, give that game an identifier - together with some "client specific" parts you can create a code on each players client which identifies it properly.
If you now get disconnected from that game - you can (you still know the hosts "IP:hostPort"-combination) knock again and beg for reentering the game. Using this approach you can rid of games which get useless if a gamers connection drops somehow (or routing gone bad - so timeouts kick the player).


bye
Ron


*(Posted 2014) [#10]
For EdzupNetworkSystem i used a client id basically the client connected and verified his account then the server sent its ID after that all communications on packets was using the id.

its on the code archives if ha want to pull it apart and take a look


Richard Betson(Posted 2014) [#11]
Waz up EdzUp[GD],

I believe I am using some of your int/float to string code form that and will credit you for sure. ;) I will take another look at that as it was pure gold as I recall.

So you are not assigning an incoming port to the client and are still able to handle multiple clients on the same IP (aside from a default incoming port)?

- Rich -


*(Posted 2014) [#12]
What i do is get the port requested on the connection iirc, after that its then validated passively (ie the user has to provide the username and password) if its ok the server then sends ok or fail. After that is sorted it validates the user assigns a id and sends that to the client then all communication is with the id. My network system waits for the client to acknowledge the id as well :)


Derron(Posted 2014) [#13]
You do not need to assign clientIDs ... except you want other clients to be able to take over a connection (this could be wanted).

Like said: each port on a computer can only be assigned one time. So if 192.168.0.1:1000 is connected, you cannot connect again with 192.168.0.1:1000. If you try to connect you will use another free port - maybe 1001.


For cheaters both ways are not secure enough (you can fake the "senderIP/port" and manipulate the clientID). For them you need to use things like userspecific hashes. If you use inter-client-communication (clientA directly sends packets to clientB) you should avoid sending him that hash. You could do individual connection-pair-hashes. But they should be salted then (for each client another salt) so that another client could not recalculate the bases from the hash he got from the other client receiving messages from the other client.

Most important thing is: make it the way it is "easy" for you to implement. Cheaters will find their way or holes in your code.


bye
Ron


*(Posted 2014) [#14]
My system stopped some of the hacking by checking the server port the client is attached to this in some ways stops fake packets.


Derron(Posted 2014) [#15]
The packet already can contain a faked header (sender ip and port) ... so this just stops hacking in some other clientIDs into a clients .exe.

Albeit better than nothing it could make the programme feel more secure than it is in reality.


bye
Ron


*(Posted 2014) [#16]
Yeah true but it stops the casual hacker, nothing stops the determined hacker as the recent years IT news has proven :)


Richard Betson(Posted 2014) [#17]
Hi,

I have designed I guess what I would call an hybrid authoritative server. In a twitch style game like mine there are some problems in using a 100% authoritative server namely the 'snap back' effect of having a client replay moves that it may have missed. Totally unacceptable in a top down shooter as the clients display view is linked to the ships position and it's nearly impossible to smooth that out enough so that it is not noticeable. Add in that working across different platforms the client and server are never going to run in completely congruent state.

In my case the server keeps a complete state of the game using the same exact map, physics and frameworks on both the server and client. So the server always knows where every client actor is and what they are doing and can monitor all clients at once. I do rely on the clients updating their position periodically and this and other data is sent encrypted (RC4). Typically you do not want the client reporting position data but since the server maintains a complete game state the position data is checked against the servers game state letting the server make the call on weather or not the new position update is valid. If it is not the client is sent a position update. If a client is cheating it is really only cheating itself as the server will not accept erroneous data. Typically this works very well for fast action games and coupled with steaming move (left, right, thrust, fire) data is reliable and handles latency well. Since the server has a complete state of the game it can make the call on kills, player or bullet position, energy levels and more. The only data that it needs from the client is the sequence of moves and a periodic position update.

Guarding against spoofing the server by man in the middle, IP or port is a problem and I think the solution is to keep to an authoritative server model as it's hard to fool the server. The IP and port can be faked but limiting clients by account can help here as only one account per client can be used. In a free to play model a person can have potenially several accounts but even so I can not see to many ways to beat an authoritative server.

At any rate the solution for multiple clients on the same IP as I see it is to have a common outgoing port and assigning a incoming port. My server will sort out the clients by ID and know what ports to use. If a client tries to spoof the ID the server will know by an encrypted key unique to each client and assigned on connection. Not fool proof but pretty good.

- Rich -


Derron(Posted 2014) [#18]
I dont know how to say without repeating myself: It should not be possible to have multiple clients on the same host using the same port for outgoing connections simultaneously.

@hybrid authoritative server
As soon as a game is deterministic, this should not be needed. All the server has to know is the input of the clients:
left,right,left is still "left" - for all clients. So as soon as "replay" is possible, you know that your game runs in a deterministic way - and therefor does not need that much "powerful servers".

That is why "damageDone = attack + Rnd(1,5)" isn't the best idea (as you then have to sync the randomizer value of the client in this state - aka mersenne twister or another pseudo-randomizer.


But like said: as long as it works - do not pay that much attention to it except you want to have millions of players.


bye
Ron


Wings(Posted 2014) [#19]
if you use ordinary tcpip no problem running on same host... with tcp udp you are in trubble :)