Question

I am looking for solution that can proxy my udp packets. I have one client sending udp packets to a server. Connection between them is very bad and I get lot of packet loss. One solution is to have a new proxy server that will just redirect all packets from client to destination server. The new proxy server has good connection to both locations.

So far I have found Simple UDP proxy/pipe

Are there some tools for such purpose ?

Cheers

Was it helpful?

Solution 2

Here is Python code written for this purpose:

import socket
from threading import Thread

class Proxy(Thread):
    """ used to proxy single udp connection 
    """
    BUFFER_SIZE = 4096 
    def __init__(self, listening_address, forward_address):
        print " Server started on", listening_address
        Thread.__init__(self)
        self.bind = listening_address
        self.target = forward_address

    def run(self):
        # listen for incoming connections:
        target = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        target.connect(self.target)

        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            s.bind(self.bind)
        except socket.error, err:
            print "Couldn't bind server on %r" % (self.bind, )
            raise SystemExit
        while 1:
            datagram = s.recv(self.BUFFER_SIZE)
            if not datagram:
                break
            length = len(datagram)
            sent = target.send(datagram)
            if length != sent:
                print 'cannot send to %r, %r !+ %r' % (self.target, length, sent)
        s.close()


if __name__ == "__main__":
    LISTEN = ("0.0.0.0", 8008)
    TARGET = ("localhost", 5084)
    while 1:
        proxy = Proxy(LISTEN, TARGET)
        proxy.start()
        proxy.join()
        print ' [restarting] '

I used this two scripts to test it.

import socket

target = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
target.connect(("localhost", 8008))
print 'sending:', target.send("test data: 123456789")

and

import socket

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.bind(("localhost", 5084))
while 1:
    datagram = s.recv(1024)
    if not datagram:
        break
    print repr(datagram)

s.close()

OTHER TIPS

I also wrote a Python script for this one day. This one goes both ways:

https://github.com/EtiennePerot/misc-scripts/blob/master/udp-relay.py

Usage: udp-relay.py localPort:remoteHost:remotePort

Then, point your UDP application to localhost:localPort and all packets will bounce to remoteHost:remotePort.

All packets sent back from remoteHost:remotePort will be bounced back to the application, assuming it is listening on the port it just sent packets from.

This version sends one reply back. It's good for one client only.

import socket
from threading import Thread

class Proxy(Thread):
    """ used to proxy single udp connection 
    """
    BUFFER_SIZE = 4096 
    def __init__(self, listening_address, forward_address):
        print " Server started on", listening_address
        Thread.__init__(self)
        self.bind = listening_address
        self.target = forward_address

    def run(self):
        # listen for incoming connections:
        target = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        target.connect(self.target)

        s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
        try:
            s.bind(self.bind)
        except socket.error, err:
            print "Couldn't bind server on %r" % (self.bind, )
            raise SystemExit
        while 1:
            (datagram,addr) = s.recvfrom(self.BUFFER_SIZE)
            if not datagram:
                break
            length = len(datagram)
            sent = target.send(datagram)
            if length != sent:
                print 'cannot send to %r, %r !+ %r' % (self.s, length, sent)
            datagram = target.recv(self.BUFFER_SIZE)
            if not datagram:
                break
            length = len(datagram)
            sent = s.sendto(datagram,addr)
            if length != sent:
                print 'cannot send to %r, %r !+ %r' % (self.s, length, sent)
        s.close()


if __name__ == "__main__":
    LISTEN = ("0.0.0.0", 5093)
    TARGET = ("10.12.2.26", 5093)
    while 1:
        proxy = Proxy(LISTEN, TARGET)
        proxy.start()
        proxy.join()
        print ' [restarting] '

Here is a working TCP or UDP Redirector / UDP Proxy / UDP Pipe / TCP Proxy / TCP Pipe


I created many different models of UDP Proxy connection bouncers and they all seem to lose connection using the standard Sockets class, but using UDPClient classes this problem completely went away.

The UDP Proxy is only 25 lines of code but the power and stability is off the charts

Below is examples how to do it in both TCP and UDP

using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Net.Sockets;
using System.Diagnostics;
using System.Net;
using System.Threading;

namespace ConsoleApplication1
{
    class Program
    {
        static void Main(string[] args)
        {
            string Address= "*PUT IP ADDRESS HERE WHERE UDP SERVER IS*";
            int UDPPort = *PUT UDP SERVER PORT HERE*;
            UdpRedirect _UdpRedirect = new UdpRedirect() { _address = Address, _Port = UDPPort};
            Thread _Thread = new Thread(_UdpRedirect.Connect);
            _Thread.Name = "UDP";
            _Thread.Start();

            int TCPPort = *PUT TCP PORT HERE FOR TCP PROXY*;       
            TcpRedirect _TcpRedirect = new TcpRedirect(Address, TCPPort);            
        }
    }
    class UdpRedirect
    {
        public string _address;
        public int _Port;
        public UdpRedirect()
        {
        }

        public void Connect()
        {
            UdpClient _UdpClient = new UdpClient(_Port);
            int? LocalPort = null;
            while (true)
            {
                IPEndPoint _IPEndPoint = null;
                byte[] _bytes = _UdpClient.Receive(ref _IPEndPoint);
                if (LocalPort == null) LocalPort = _IPEndPoint.Port;
                bool Local = IPAddress.IsLoopback(_IPEndPoint.Address);
                string AddressToSend = null;
                int PortToSend = 0;
                if (Local)
                {
                    AddressToSend = _address;
                    PortToSend = _Port;
                }
                else
                {
                    AddressToSend = "127.0.0.1";
                    PortToSend = LocalPort.Value;
                }
                _UdpClient.Send(_bytes, _bytes.Length, AddressToSend, PortToSend);
            }
        }
    }
    class TcpRedirect
    {
        public TcpRedirect(string _address, int _Port)
        {

            TcpListener _TcpListener = new TcpListener(IPAddress.Any, _Port);
            _TcpListener.Start();
            int i = 0;
            while (true)
            {
                i++;
                TcpClient _LocalSocket = _TcpListener.AcceptTcpClient();
                NetworkStream _NetworkStreamLocal = _LocalSocket.GetStream();

                TcpClient _RemoteSocket = new TcpClient(_address, _Port);
                NetworkStream _NetworkStreamRemote = _RemoteSocket.GetStream();
                Console.WriteLine("\n<<<<<<<<<connected>>>>>>>>>>>>>");
                Client _RemoteClient = new Client("remote" + i)
                {
                    _SendingNetworkStream = _NetworkStreamLocal,
                    _ListenNetworkStream = _NetworkStreamRemote,
                    _ListenSocket = _RemoteSocket
                };
                Client _LocalClient = new Client("local" + i)
                {
                    _SendingNetworkStream = _NetworkStreamRemote,
                    _ListenNetworkStream = _NetworkStreamLocal,
                    _ListenSocket = _LocalSocket
                };
            }
        }
        public class Client
        {
            public TcpClient _ListenSocket;
            public NetworkStream _SendingNetworkStream;
            public NetworkStream _ListenNetworkStream;
            Thread _Thread;
            public Client(string Name)
            {
                _Thread = new Thread(new ThreadStart(ThreadStartHander));
                _Thread.Name = Name;
                _Thread.Start();
            }
            public void ThreadStartHander()
            {
                Byte[] data = new byte[99999];
                while (true)
                {
                    if (_ListenSocket.Available > 0)
                    {
                        int _bytesReaded = _ListenNetworkStream.Read(data, 0, _ListenSocket.Available);
                        _SendingNetworkStream.Write(data, 0, _bytesReaded);
                        Console.WriteLine("(((((((" + _bytesReaded + "))))))))))" + _Thread.Name + "\n" + ASCIIEncoding.ASCII.GetString(data, 0, _bytesReaded).Replace((char)7, '?'));
                    }
                    Thread.Sleep(10);
                }
            }

        }
    }
}
Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top