godotengine / godot-proposals

Godot Improvement Proposals (GIPs)
MIT License
1.12k stars 69 forks source link

Allow WebSocketServer to bind to a specific address. #40

Closed crazychenz closed 4 years ago

crazychenz commented 5 years ago

My Problem I'm working on a game that is designed to be multiplayer or single player. To keep things consistent and simple, the game always has a server. If the user wants single player, only their local client connects, otherwise their local client and any external client can connect. At the moment I am specifically using the WebSocketServer and WebSocketClient objects in GDScript with Godot 3.1.1 Stable on Windows 10.

The issue is that at the moment, I would like to take advantage of the system socket library's ability to only listen on a specific address. For example, if I wanted to launch a single player only session, I would only bind to the localhost (127.0.0.1). If I was launching a server on a computer connected to the internet and a internal only network, perhaps I only want to bind to the network interface connected to the internal network.

Can this be worked around with a script? Short Answer: No, this is a security issue. Long Answer: At the moment I am compensating for the lack of this feature by implementing a firewall in GDScript. At this point, we've already opened the application to the network for access. The GDScript firewall can prevent honest users from accidentally accessing a forbidden service, but a less than honest user can actually have the application thrash during a single player session as a Denial of Service attack. This can be avoided by pushing all of that noise into the kernel and let the system deal with it by only binding to the subnets that need to be bound to.

Thoughts On Solutions / Implementation As far as implementation, I see no reason why the current behavior needs to change. Just need to add an optional argument to WebSocketServer.listen() that does not assume IPADDR_ANY (0.0.0.0) as the address to bind to.

Doing a quick (static) look at the actual code in master, it looks like WSLServer(from modules/websocket/wsl_server.h) has a TCP_Server reference called _server. When we call listen on the GDScript WebSocketServer, we're effectively calling _server->listen(port, IPADDR_ANY) because of TCP_Server's listen signature (from core/io/tcp_server.h):

Error listen(uint16_t p_port, const IP_Address &p_bind_address = IP_Address("*"));

So basically, the solution is to add an optional parameter to GDScript's WebSocketServer's listen call to include an address to bind to and pass this address object to the TCP_Server.listen() call.

Faless commented 4 years ago

Sorry for the late update, this can now be done (in 3.2) via the bind_ip property. See https://github.com/godotengine/godot/pull/34539