Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

UDP Proxy server using python 3.6 async

I'm curious to see how I can create a UDP proxy server using the async module. I tried earlier today with Twisted, but wasn't making much headway. I did find some simple solutions here on stackoverflow using sockets directly, but i'm wondering if this is possible using the async lib.

For clarity, what I'm looking for is:

Step 1: client A (can be many) speaks to proxy B Step 2: proxy B sends the request along to server C. Step 3: Server C responds to proxy B Sep 4: Proxy B responds to client A.

Here's what I have so far:

import asyncio

class EchoServerProtocol(asyncio.DatagramProtocol):
    def connection_made(self, transport):
        self.transport = transport

    def datagram_received(self, data, addr, args=None):
        message = data
        server_addr = ('localhost', 27015)
        print('Received %r from %s' % (message, addr))
        print('Send %r to %s' % (message, server_addr))
        self.transport.sendto(data, server_addr)

loop = asyncio.get_event_loop()
print("Starting UDP server")
# One protocol instance will be created to serve all client requests
listen = loop.create_datagram_endpoint(
    EchoServerProtocol,
    local_addr=('0.0.0.0', 27016),
)
transport, protocol = loop.run_until_complete(listen)

try:
    loop.run_forever()
except KeyboardInterrupt:
    pass

transport.close()
loop.close()

The above is basically this:

https://docs.python.org/3/library/asyncio-protocol.html#udp-echo-server-protocol

What I have will get you to step 3, but of course fails at step 4. It sends it back to server C.

You will note that one of the other protocol examples, EchoServerClientProtocol, creates a new instance for each connection. I assume I need to create a new instance for every connection, I believe, because then I can store the original address in the instance, and return that. I assume this doesn't apply to create_datagram_endpoint, or I can't figure out how to do it.

There might be a better approach though.

like image 359
James R Avatar asked Aug 04 '26 11:08

James R


1 Answers

You need a local endpoint for server B, plus a remote endpoint to server C for each client A.

Here is a possible implementation.

Also, you might be interested in this module providing high-level UDP endpoints for asyncio.

like image 167
Vincent Avatar answered Aug 06 '26 03:08

Vincent



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!