DataLab icon indicating copy to clipboard operation
DataLab copied to clipboard

Remote control: reject connections not originating from `localhost`

Open PierreRaybaut opened this issue 1 year ago • 0 comments

Issue Description

In our current implementation of the DataLab XML-RPC server, we have utilized Python's standard library to establish a foundation for remote control functionality. However, a critical enhancement is needed to bolster the security of this interface. Our goal is to ensure that the server exclusively authorizes connections that originate from localhost, effectively rejecting any requests made from remote or non-local IP addresses. This is a vital security measure to prevent unauthorized access to the DataLab XML-RPC server.

Tasks

  • [ ] Authorize exclusively connections originating from localhost, by default
  • [ ] Add an option to DataLab's configuration file and to the settings dialog box to enable/disable this option (enabled by default)

Proposed Solution

To address this requirement, I propose the implementation of a subclass derived from Python's xmlrpc.server.SimpleXMLRPCServer, which would incorporate a method to verify incoming requests based on the client's IP address. By overriding the verify_request method, we can inspect the client_address and ascertain whether the connection is being made from 127.0.0.1 (IPv4) or ::1 (IPv6), which are the IP addresses corresponding to localhost. Connections from any other IP addresses should be rejected.

Below is a concise example demonstrating how we might implement this enhancement:

import xmlrpc.server

class SecureXMLRPCServer(xmlrpc.server.SimpleXMLRPCServer):
    def verify_request(self, request, client_address):
        # Allow only localhost connections
        return client_address[0] in ('127.0.0.1', '::1')

def my_function(x, y):
    return x + y

# Instantiate the server to listen on localhost port 8000
server = SecureXMLRPCServer(("localhost", 8000), allow_none=True)
server.register_introspection_functions()
# Register a simple test function
server.register_function(my_function, 'add')

print("Serving XML-RPC on localhost port 8000...")
try:
    server.serve_forever()
except KeyboardInterrupt:
    print("\nKeyboard interrupt received, exiting.")
    server.server_close()

This modification ensures that our XML-RPC server will only process requests originating from localhost, enhancing its security by preventing unauthorized external access. This solution is designed to be a straightforward addition to our existing server setup, requiring minimal changes for a significant increase in security.

Additional Considerations

  • Testing: It's crucial to rigorously test this updated server implementation in various environments to ensure that it behaves as expected and does not inadvertently block legitimate requests.

PierreRaybaut avatar Mar 26 '24 16:03 PierreRaybaut