Skip to main content

sunrpc implements remote procedure calls according to RFC1057

Project description

sunrpc


sunrpc is a python library implementing RFC1057. The library from this repository is based on code snippets from various different other repositories. See the references section at the end of the document for a list of resources. The library is not complete yet and some operations and message types might be missing. However, it should already be sufficient to build and access simple RPC services like for example portmappers.

Installation


sunrpc can be installed via pip by running the following command:

[user@host ~]$ pip3 install --user sunrpc

Alternatively you can build the package from source running:

[user@host ~]$ pip3 install --user --upgrade build
[user@host ~]$ git clone https://github.com/usdAG/sunrpc
[user@host ~]$ cd sunrpc && python3 -m build
[user@host ~/sunrpc]$ pip3 install --user dist/*.whl

Usage


Creating servers and clients with sunrpc is pretty simple. The library uses an annotation based approach for creating the required RPC methods and abstracts the implementation details from the user. The following listing contains an example for an simple Hello World RPC Server:

from __future__ import annotations

from sunrpc.types import RpcStr
from sunrpc.server import TCPServer, rpc_server_obtain, rpc_server_return


class HelloWorldServer(TCPServer):
    '''
    RPC server that supports a single method expecting a string. Prints
    the string to stdout and answers with 'Hello World :D'.
    '''
    def __init__(self, host: str, port: str) -> None:
        '''
        Initialize the server and add the available method
        '''
        # 1337 is the programm number and 2 the version number supported by the server
        TCPServer.__init__(self, host, port, 1337, 2)

        # assign the procedure number 1 for self.hello_world
        self.add_method(1, self.hello_world)

    # define the hello_world RPC method that expects an string as input argument
    # and returns a string back to the client.
    @rpc_server_obtain(RpcStr)
    @rpc_server_return(RpcStr)
    def hello_world(self, message: str) -> str:
        '''
        Obtain the message from the client, print it and return 'Hello World :D'
        '''
        print(f'[+] The client said: {message}')
        return ['Hello World :D']


# create the server and start it. Calls are handeled automatically from here
server = HelloWorldServer('127.0.0.1', 4444)
server.bind()
server.listen()

The rpc_obtain_server and rpc_return_server decorators define the expected incoming argument types and return values for RPC methods. Each RPC methods need to be registered within the constructor and gets assigned a unique procedure ID. The client side code uses rpc_obtain_client and rpc_send_client to call RPC methods:

from __future__ import annotations

from sunrpc.types import RpcStr
from sunrpc.client import TCPClient, rpc_client_send, rpc_client_obtain


class HelloWorldClient(TCPClient):
    '''
    Client class that communicates to the HelloWorldServer.
    '''
    # hello_world calls the RPC method with procedure number 1 and sends one
    # RpcStr as argument. The result is an RpcStr returned by the server that
    # gets passed to the hello_world method.
    @rpc_client_send(1, RpcStr)
    @rpc_client_obtain(RpcStr)
    def hello_world(self, result: str) -> str:
        '''
        Send a string to the server and print the result.
        '''
        return result


# 1337 is the programm number and 2 the version number supported by the sever
client = HelloWorldClient('127.0.0.1', 4444, 1337, 2)
client.connect()

response = client.hello_world('Hello :D')
print(response)

For more complex usage examples, check the portmapper-client and portmapper-server implementations from the examples folder. There is also an example for building a server with asnycio.

Proxy RPC Traffic


The sunrpc.proxy namespace contains methods and classes for building RPC proxies. The following example demonstrates how to write a portmapper proxy, that forwards incoming portmap requests to the specified target:

from sunrpc.proxy import UDPProxy

class PortMapperProxy(UDPProxy):
    '''
    Example implementation for a portmapper proxy. Proxies traffic incoming portmapper
    traffic to the targeted portmapper and dumps transmitted data to stdout.
    '''
    def __init__(self, host: str, port: str, target: str, tport: int = 111) -> None:
        '''
        Initialize the proxy
        '''
        UDPProxy.__init__(self, host, port, 100000, 2, target, tport, dump = True)


# Just create a dummy proxy from localhost:4444 to localhost:111
server = PortMapperProxy('127.0.0.1', 4444, '127.0.0.1', 111)
server.bind()

print('[+] Portmapper proxy started :)')
server.listen()

When dump is set to True, a hexdump is created for each forwarded message. Moreover, hooks can be implemented to modify certain RPC requests.

References


The initial rpc implementation we used for this library can be found within the following repositories:

Project details


Download files

Download the file for your platform. If you're not sure which to choose, learn more about installing packages.

Source Distribution

sunrpc-1.0.0.tar.gz (55.9 kB view details)

Uploaded Source

Built Distribution

sunrpc-1.0.0-py3-none-any.whl (45.4 kB view details)

Uploaded Python 3

File details

Details for the file sunrpc-1.0.0.tar.gz.

File metadata

  • Download URL: sunrpc-1.0.0.tar.gz
  • Upload date:
  • Size: 55.9 kB
  • Tags: Source
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.10.7

File hashes

Hashes for sunrpc-1.0.0.tar.gz
Algorithm Hash digest
SHA256 3d84025a62c31a36bb2a34ec063d3966c6d7d4db62f6f65de4b2391d1b874eb9
MD5 47e430ec4d5922d7de96e3538aeffc7d
BLAKE2b-256 4e0bd5125dec2ed69efd2717295b76ee2b8179689d7169288e779e01510dffa0

See more details on using hashes here.

File details

Details for the file sunrpc-1.0.0-py3-none-any.whl.

File metadata

  • Download URL: sunrpc-1.0.0-py3-none-any.whl
  • Upload date:
  • Size: 45.4 kB
  • Tags: Python 3
  • Uploaded using Trusted Publishing? No
  • Uploaded via: twine/4.0.1 CPython/3.10.7

File hashes

Hashes for sunrpc-1.0.0-py3-none-any.whl
Algorithm Hash digest
SHA256 5b3ba6cbbf10bb51d95856ab1e196e7e384e956e7b48b44970ac52a747f4d0bd
MD5 e2f6c8af8224e3ff11cf207b8dfbaa9b
BLAKE2b-256 38f5e2738df0a0aebf6ed97d84d5e80cc78ffb521c08b04c65059ccad6e6439a

See more details on using hashes here.

Supported by

AWS AWS Cloud computing and Security Sponsor Datadog Datadog Monitoring Fastly Fastly CDN Google Google Download Analytics Microsoft Microsoft PSF Sponsor Pingdom Pingdom Monitoring Sentry Sentry Error logging StatusPage StatusPage Status page