Reputation: 1829
I am trying to secure my RpyC server connections through username and password. The documentation indeed shows an example, but it is too brief. No details were given on how exactly the password is passed from the client-side. Anyone figured out how to do that? Thanks in advance.
Upvotes: 1
Views: 599
Reputation: 1829
Answering my own question:
I had to override some internal methods of RPyC on the client side to achieve the desired behaviour. I don't know if much cleaner solution exists, but this seems to be a plausible one.
Server:
import rpyc
from rpyc.utils.authenticators import AuthenticationError
def magic_word_authenticator(sock):
if sock.recv(5).decode() != "Ma6ik":
raise AuthenticationError("wrong magic word")
return sock, None
class SecuredService(rpyc.Service):
def exposed_secured_op(self):
return 'Secret String'
rpyc.ThreadedServer(
service=SecuredService, hostname='localhost',
port=18812, authenticator=magic_word_authenticator
).start()
Client:
import rpyc
import traceback
class AuthSocketStream(rpyc.SocketStream):
@classmethod
def connect(cls, *args, authorizer=None, **kwargs):
stream_obj = super().connect(*args, **kwargs)
if callable(authorizer):
authorizer(stream_obj.sock)
return stream_obj
def rpyc_connect(host, port, service=rpyc.VoidService, config={}, ipv6=False, keepalive=False, authorizer=None):
s = AuthSocketStream.connect(
host, port, ipv6=ipv6, keepalive=keepalive,
authorizer=authorizer
)
return rpyc.connect_stream(s, service, config)
print('With correct authorizer')
conn1 = rpyc_connect(
'localhost', 18812, authorizer=lambda sock: sock.send('Ma6ik'.encode())
)
print(conn1.root.secured_op())
print('With wrong authorizer')
conn2 = rpyc_connect(
'localhost', 18812, authorizer=lambda sock: sock.send('Invalid'.encode())
)
try:
conn2.root
except Exception:
print(traceback.format_exc())
print('With no authorizer')
conn3 = rpyc_connect(
'localhost', 18812
)
try:
conn3.root
except Exception:
print(traceback.format_exc())
Client Console Log:
With correct authorizer
Secret String
With wrong authorizer
Traceback (most recent call last):
File "/home/client.py", line 40, in <module>
conn2.root
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 507, in root
self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 474, in sync_request
return self.async_request(handler, *args, timeout=timeout).value
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 101, in value
self.wait()
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 48, in wait
self._conn.serve(self._ttl)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 387, in serve
data = self._channel.poll(timeout) and self._channel.recv()
File "/usr/lib/python3.10/site-packages/rpyc/core/channel.py", line 55, in recv
header = self.stream.read(self.FRAME_HEADER.size)
File "/usr/lib/python3.10/site-packages/rpyc/core/stream.py", line 260, in read
raise EOFError("connection closed by peer")
EOFError: connection closed by peer
With no authorizer
Traceback (most recent call last):
File "/home/client.py", line 52, in <module>
conn3.root
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 507, in root
self._remote_root = self.sync_request(consts.HANDLE_GETROOT)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 474, in sync_request
return self.async_request(handler, *args, timeout=timeout).value
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 101, in value
self.wait()
File "/usr/lib/python3.10/site-packages/rpyc/core/async_.py", line 48, in wait
self._conn.serve(self._ttl)
File "/usr/lib/python3.10/site-packages/rpyc/core/protocol.py", line 387, in serve
data = self._channel.poll(timeout) and self._channel.recv()
File "/usr/lib/python3.10/site-packages/rpyc/core/channel.py", line 55, in recv
header = self.stream.read(self.FRAME_HEADER.size)
File "/usr/lib/python3.10/site-packages/rpyc/core/stream.py", line 260, in read
raise EOFError("connection closed by peer")
EOFError: connection closed by peer
Upvotes: 5