Laden...

TCP hole punching: Zielcomputer lehnt Verbindung ab

Erstellt von 3r0rXx vor 7 Jahren Letzter Beitrag vor 7 Jahren 3.240 Views
3r0rXx Themenstarter:in
55 Beiträge seit 2014
vor 7 Jahren
TCP hole punching: Zielcomputer lehnt Verbindung ab

Guten Abend liebe Community,

ich versuche vergeblich TCP Hole Punching anzuwenden.
Folgendes Szenario:

Gegeben ist ein Server ( Mediator) dass auf einkommende Clients wartet.
Verbinden sich zwei Clients sendet der Server jeweils beiden Clients die Ip des jeweiligen anderen Clients ( samt Port) .
Dann starten die Clients ihrerseits einen Listener dass auf den Port lauscht mit dem es zum Server verband.

Nachdem die Listener gestartet worden versuchen beide Clients sich zu verbinden...
Problem: Verbindung werde vom Zielcomputer abgelehnt.

Habe ich etwas missverstanden?

Code für den Client:

class Program
    {
        static void Main(string[] args)
        {

            TcpClient client = new TcpClient();
            client.Connect(new IPEndPoint(IPAddress.Parse("WAN"), 8000));
            BinaryReader binW = new BinaryReader(client.GetStream());
            Console.WriteLine(client.Client.LocalEndPoint);
            new Thread(new ThreadStart(() =>
            {
                while (true)
                {
             
                    string text = binW.ReadString();
                    string ip = text.Split(':')[0];
                    int port = int.Parse(text.Split(':')[1]);
                    Console.WriteLine("Received..");
                    client.Close();
                    TcpClient hole_punched = new TcpClient();
                    hole_punched.Connect(new IPEndPoint(IPAddress.Parse(ip), port));

                    BinaryWriter binWriter = new BinaryWriter(hole_punched.GetStream());
                    binWriter.Write("Hello World Punched!");
                    Console.ForegroundColor = ConsoleColor.Green;
                    Console.WriteLine("Sent!");
                    Console.ForegroundColor = ConsoleColor.Gray;

                }
            })).Start();


            TcpListener localServer = new TcpListener((IPEndPoint)client.Client.LocalEndPoint);
 
            localServer.Start();

            while (true)
            {
                var incoming = localServer.AcceptTcpClient();
                BinaryReader binReader = new BinaryReader(incoming.GetStream());
                Console.WriteLine(binReader.ReadString());

            }



        }

Code für den Mediator:

    class Program
    {
        static void Main(string[] args)
        {

            TcpListener listener = new TcpListener(new IPEndPoint(IPAddress.Any, 8000));
            listener.Start();

            Console.WriteLine("Server is running sucessfully!");

            List<Client> clients = new List<Client>();

            while (true)
            {
                var incoming = listener.AcceptTcpClient();
                Console.ForegroundColor = ConsoleColor.Green;
                Console.WriteLine("Client connected: " + incoming.Client.RemoteEndPoint);
                Console.ForegroundColor = ConsoleColor.Gray;


 
                for (int i = 0; i < clients.Count; i++)
                {
                    try
                    {
                        clients[i].Writer.Write(incoming.Client.RemoteEndPoint + "");
                    }
                    catch
                    {
                        clients.RemoveAt(i);
                        Console.ForegroundColor = ConsoleColor.Red;
                        Console.WriteLine("Client disconnected!");
                        Console.ForegroundColor = ConsoleColor.Gray;
                    }
                }
                Client c = new Client(incoming);
                for (int i = 0; i < clients.Count; i++)
                {
                    c.Writer.Write(clients[i].InClient.Client.RemoteEndPoint + "");
                }

                clients.Add(c);


            }

        }
    }

    public class Client
    {
        public BinaryWriter Writer;
        public BinaryReader Reader;

        public TcpClient InClient;
        
        public Client(TcpClient client)
        {
            InClient = client;
            Writer = new BinaryWriter(InClient.GetStream());
            Reader = new BinaryReader(InClient.GetStream());
        }


    }

Kennt ihr ein Kompromiss?
Lieben lieben Dank!

'Tis not too late to seek a newer world.

286 Beiträge seit 2011
vor 7 Jahren

Klingt stumpf aber: Firewall?

"Verbindung werde vom Zielcomputer abgelehnt" ist eine klassische "Firewall-ist-nicht-einverstanden"-Fehlermeldung.

Ich würde mal überprüfen, ob die entsprechenden Freigaben vorhanden sind. Evtl ist auch besonders übereifriger Virenschutz am Werk.

2+2=5( (für extrem große Werte von 2)

16.842 Beiträge seit 2008
vor 7 Jahren

Holepunching ist dazu da, dass man die Firewall eben nicht bearbeiten muss... 😉

3r0rXx Themenstarter:in
55 Beiträge seit 2014
vor 7 Jahren

Gerade das will man doch umgehen... haha

'Tis not too late to seek a newer world.

C
2.122 Beiträge seit 2010
vor 7 Jahren

Gleich vorweg, ich hab das selbst noch nie gemacht. Was ich hier schreibe ist also nur ein Gedanke aber kein 100% Tip.
Internet weiß sicher auch so manches darüber.

Dann starten die Clients ihrerseits einen Listener dass auf den Port lauscht mit dem es zum Server verband.

Ich denke hier sitzt der Denkfehler. Wenn der Client auf dem Port mit dem Server redet, weiß die Firewall dass auf diesem Port vom Server eine Antwort kommt und lässt diese Datenpakete durch. Daten vom anderen Clientrechner an den Port lässt sie nicht durch.

Probiers mal so. Client A erstellt eine neue Verbindung (nicht die mit der A mit dem Server spricht) und ermittelt den Sendeport dieser Verbindung. Über den Server teilt Client A Client B diesen Port mit. Client B öffnet dann die Verbindung zu Client A an diesen Port und schickt ihm etwas. Firewall B ist somit offen für Daten von A. Bei kommt noch nichts an, weil die Firewall von A noch nichts durchleitet. Dazu muss B seinen Port wieder über den Server an A melden. A schickt nun B etwas, somit ist die Firewall A auch offen.

D
985 Beiträge seit 2014
vor 7 Jahren

Persönlich habe ich dem TCP noch keine gehauen, aber wenn ich mir den Artikel TCP hole punching durchlese, dann würde ich behaupten das der Code-Ansatz so nicht richtig ist.

Zudem gibt es Situationen (abhängig vom Gateway) wo eine Verbindung nicht möglich ist.

3r0rXx Themenstarter:in
55 Beiträge seit 2014
vor 7 Jahren

Der Code ist definitiv falsch.

@Chilic
Das ist das was ich so missverstehe.

Client A erstellt eine neue Verbindung (nicht die mit der A mit dem Server spricht) und ermittelt den Sendeport dieser Verbindung. Über den Server teilt Client A Client B diesen Port mit. Client B öffnet dann die Verbindung zu Client A an diesen Port und schickt ihm etwas.

Zu wem? Erneut zum Server?
Und was nachdem der Sendeport gesendet wurde?
Auf diesem Port [mit einem TCPListener] lauschen?

Lieben Dank!

'Tis not too late to seek a newer world.