простое решение для прокси-сервера udp

StackOverflow https://stackoverflow.com/questions/1803329

  •  05-07-2019
  •  | 
  •  

Вопрос

Я ищу решение, которое может проксировать мои пакеты udp.У меня есть один клиент, отправляющий udp-пакеты на сервер.Соединение между ними очень плохое, и у меня много потерь пакетов.Одним из решений является создание нового прокси-сервера, который будет просто перенаправлять все пакеты с клиента на сервер назначения.Новый прокси-сервер имеет хорошее соединение с обоими местоположениями.

До сих пор я нашел Простой UDP-прокси/канал

Есть ли какие-то инструменты для этой цели?

Ваше здоровье

Это было полезно?

Решение 2

Вот код Python, написанный для этой цели:

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] '

Я использовал эти два сценария, чтобы проверить это.

import socket

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

и

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()

Другие советы

Однажды я также написал для этого скрипт на Python.Это идет в обе стороны:

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

Использование: udp-relay.py localPort:remoteHost:remotePort

Затем укажите вашему UDP-приложению localhost:localPort и все пакеты будут возвращаться на remoteHost:remotePort.

Все пакеты, отправленные обратно из remoteHost:remotePort будет возвращен приложению, при условии, что оно прослушивает порт, с которого только что отправили пакеты.

Эта версия отправляет один ответ обратно.Это хорошо только для одного клиента.

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] '

Вот работающий TCP или UDP Redirector / UDP Proxy / UDP Pipe / TCP Proxy / TCP Pipe


Я создал много разных моделей баунсеров соединений UDP Proxy, и все они, похоже, теряют соединение при использовании стандартного класса Sockets, но при использовании классов UDPClient эта проблема полностью ушла.

UDP-прокси состоит всего из 25 строк кода, но мощность и стабильность зашкаливают.

Ниже приведены примеры того, как это сделать как в TCP, так и в 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);
                }
            }

        }
    }
}
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top