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
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 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()
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);
}
}
}
}
}
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.