Hucaru / Valhalla

A Golang MapleStory (v28) server
MIT License
274 stars 71 forks source link

General question about security? #32

Closed leojplin closed 4 years ago

leojplin commented 4 years ago

Hi, I have been reading the code for fun and for reference. And I would like to ask few questions to clarify my understand if you would allow me.

I can see that we are creating three types of server: login, world, channel, and each are connected together. How do we prevent users from directly connecting to channel server without going to login/world first? I actually just tried it and it does seem to be able to connect, but I didn't go further to see whether I can actually "abuse" it. If we don't want this to be able to happen, how do we enforce the correct order of connecting, or making sure the user is authenticated when connecting to channel serveer?

On another note, what is the purpose of connecting all three types of servers together. I don't think the connection is actually used in the codebase.

Thanks!

Hucaru commented 4 years ago

How do we prevent users from directly connecting to channel server without going to login/world first?

The following check found in the channel server should prevent you from bypassing the login server: https://github.com/Hucaru/Valhalla/blob/master/server/channel_player.go#L25

World server connects to login server and sends information about channels available, population, messages, ribbons. In the future it will handle things such as whispers, party, buddy, guild chat/notifications between channels. Another way to organise the servers would be to have the world server and channels be one application. This simplifies some of the design decisions at the cost of:

  1. A crash in the channel could crash the whole world
  2. You cannot host channels on separate physical machines
  3. Can update channel servers without bringing the whole world down
  4. There are probably other advantages I can't think of right now.
leojplin commented 4 years ago

This is great insight about why separate the server types!

I want to follow up on the bypassing login server. I don't believe there is code to check for user/password at the playerConnect method. So does this mean if I could somehow know someone else has logged in but has not selected the character, and I also happen to know the character ID (which shouldn't be communicated to client unless I went through the login flow), then I am technically allowed to go into game with the character without being challenged for a password or being from the same connection?

I have also been reading the Java based source code, and it seems like they prevent this from by using TCP session. They store which session is associated with which account from the very beginning, so all subsequent requests can check for the current client/account. This is possible because all of login/world/channel are hosted in the same process with different ports only. However, and maybe I am still misunderstanding it slightly, shouldn't TCP session have unique (dst addr, dsr port, src addr, src port) tuple? Even with same process and different ports, the TCP connection should have different values for this tuple, thus resulting in different sessions.

Thanks again for any input!

Hucaru commented 4 years ago

The way I have it currently implemented is that a migration id is only set once a user tries to migrate (selects a character or changes channel). You would have to connect to the channel using the correct character id at the exact time someone either changed channel or selected a character from the login server.

To be nearly 100% certain every time a user logs in you could have the login server store last connected ip address in the database that is then used as a lookup by the channel server.

leojplin commented 4 years ago

Got it, Thanks!