C# UDP Proxy / Pipe

2020-08-04 09:54发布

问题:

Any example design code in C# or VB.NET ?

Looking for a UDP Pipe example in .NET

I downloaded Simple UDP proxy/pipe 0.4.1 by Luigi Auriemma

Which is in C++..

it works perfectly.. but I want to make my own implemention in .NET.. so I can sniff packets directly.

回答1:

Fixed it here is the solution if anyone wants to learn how I fixed it.. Please note this is probably the only UDP Proxy on all of google if you stumbled upon this.. that is coded in C#.. easily ported to VB.NET with online .NET converter

Be happy this code works ;)

Sure it's not efficient because it doesn't use events.. like ReceiveAsync/EndReceive.

Only downfall to not using Aysnchronize events.. is that you see below the working code.. will have to be stuck in a infinite loop.. and it will burn your CPU cycles.. easily fixed with a Thread.Sleep(10).. (don't set to high or you will have udp lag)

using System;
using System.Collections.Generic;
using System.Text;
using System.Net.Sockets;
using System.Net;

namespace UdpProxy
{
    class Program
    {
        public static IPEndPoint m_listenEp = null;
        public static EndPoint m_connectedClientEp = null;
        public static IPEndPoint m_sendEp = null;
        public static Socket m_UdpListenSocket = null;
        public static Socket m_UdpSendSocket = null;


        static void Main(string[] args)
        {

            // Creates Listener UDP Server
            m_listenEp = new IPEndPoint(IPAddress.Any, 7900);
            m_UdpListenSocket = new Socket(m_listenEp.Address.AddressFamily, SocketType.Dgram, ProtocolType.Udp);
            m_UdpListenSocket.Bind(m_listenEp);

            //Connect to zone IP EndPoint
            m_sendEp = new System.Net.IPEndPoint(IPAddress.Parse("REMOTE_IP_GOES_HERE"), 7900);
            m_connectedClientEp = new System.Net.IPEndPoint(IPAddress.Any, 7900);

            byte[] data = new byte[1024];

            while (true)
            {
                if (m_UdpListenSocket.Available > 0)
                {

                    int size = m_UdpListenSocket.ReceiveFrom(data, ref m_connectedClientEp); //client to listener

                    if (m_UdpSendSocket == null)
                    {
                        // Connect to UDP Game Server.
                        m_UdpSendSocket = new Socket(AddressFamily.InterNetwork, SocketType.Dgram, ProtocolType.Udp);
                    }

                    m_UdpSendSocket.SendTo(data, size, SocketFlags.None, m_sendEp); //listener to server.

                }

                if (m_UdpSendSocket != null && m_UdpSendSocket.Available > 0)
                {
                    int size = m_UdpSendSocket.Receive(data); //server to client.

                    m_UdpListenSocket.SendTo(data, size, SocketFlags.None, m_connectedClientEp); //listner

                }
            }


            // Wait for any key to terminate application
            Console.ReadKey();
        }
    }
}

I always look back at this answer when I start a new UDP Proxy project and the above code has issues with certain UDP Servers where it loses connections, (on a connectless protocol) ya I have no idea how it happens but I fixed it with using UDPClient instead of Sockets

Here is a different variant of the 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 loose 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

C# Code below

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

        }
    }
}

VB.NET Code Below

Imports System.Collections.Generic
Imports System.Linq
Imports System.Text
Imports System.Net.Sockets
Imports System.Diagnostics
Imports System.Net
Imports System.Threading

Namespace ConsoleApplication1
    Class Program
        Private Shared Sub Main(args As String())
            Dim Address As String = "*PUT IP ADDRESS HERE WHERE UDP SERVER IS*"
            Dim UDPPort As Integer = *PUT UDP SERVER PORT HERE*
            Dim _UdpRedirect As New UdpRedirect() With { _
                Key ._address = Address, _
                Key ._Port = UDPPort _
            }
            Dim _Thread As New Thread(AddressOf _UdpRedirect.Connect)
            _Thread.Name = "UDP"
            _Thread.Start()

            Dim TCPPort As Integer = *PUT TCP SERVER PORT HERE*
            Dim _TcpRedirect As New TcpRedirect(Address, TCPPort)
        End Sub
    End Class
    Class UdpRedirect
        Public _address As String
        Public _Port As Integer
        Public Sub New()
        End Sub

        Public Sub Connect()
            Dim _UdpClient As New UdpClient(_Port)
            Dim LocalPort As System.Nullable(Of Integer) = Nothing
            While True
                Dim _IPEndPoint As IPEndPoint = Nothing
                Dim _bytes As Byte() = _UdpClient.Receive(_IPEndPoint)
                If LocalPort Is Nothing Then
                    LocalPort = _IPEndPoint.Port
                End If
                Dim Local As Boolean = IPAddress.IsLoopback(_IPEndPoint.Address)
                Dim AddressToSend As String = Nothing
                Dim PortToSend As Integer = 0
                If Local Then
                    AddressToSend = _address
                    PortToSend = _Port
                Else
                    AddressToSend = "127.0.0.1"
                    PortToSend = LocalPort.Value
                End If
                _UdpClient.Send(_bytes, _bytes.Length, AddressToSend, PortToSend)
            End While
        End Sub
    End Class
    Class TcpRedirect
        Public Sub New(_address As String, _Port As Integer)

            Dim _TcpListener As New TcpListener(IPAddress.Any, _Port)
            _TcpListener.Start()
            Dim i As Integer = 0
            While True
                i += 1
                Dim _LocalSocket As TcpClient = _TcpListener.AcceptTcpClient()
                Dim _NetworkStreamLocal As NetworkStream = _LocalSocket.GetStream()

                Dim _RemoteSocket As New TcpClient(_address, _Port)
                Dim _NetworkStreamRemote As NetworkStream = _RemoteSocket.GetStream()
                Console.WriteLine(vbLf & "<<<<<<<<<connected>>>>>>>>>>>>>")
                Dim _RemoteClient As New Client("remote" + i) With { _
                    Key ._SendingNetworkStream = _NetworkStreamLocal, _
                    Key ._ListenNetworkStream = _NetworkStreamRemote, _
                    Key ._ListenSocket = _RemoteSocket _
                }
                Dim _LocalClient As New Client("local" + i) With { _
                    Key ._SendingNetworkStream = _NetworkStreamRemote, _
                    Key ._ListenNetworkStream = _NetworkStreamLocal, _
                    Key ._ListenSocket = _LocalSocket _
                }
            End While
        End Sub
        Public Class Client
            Public _ListenSocket As TcpClient
            Public _SendingNetworkStream As NetworkStream
            Public _ListenNetworkStream As NetworkStream
            Private _Thread As Thread
            Public Sub New(Name As String)
                _Thread = New Thread(New ThreadStart(AddressOf ThreadStartHander))
                _Thread.Name = Name
                _Thread.Start()
            End Sub
            Public Sub ThreadStartHander()
                Dim data As [Byte]() = New Byte(99998) {}
                While True
                    If _ListenSocket.Available > 0 Then
                        Dim _bytesReaded As Integer = _ListenNetworkStream.Read(data, 0, _ListenSocket.Available)
                        _SendingNetworkStream.Write(data, 0, _bytesReaded)
                        Console.WriteLine("(((((((" + _bytesReaded + "))))))))))" + _Thread.Name + vbLf + ASCIIEncoding.ASCII.GetString(data, 0, _bytesReaded).Replace(CChar(7), "?"C))
                    End If
                    Thread.Sleep(10)
                End While
            End Sub

        End Class
    End Class
End Namespace