Netzwerk mit Firewall: TCP geht, UDP geht ggf. nicht?



  • Hi, ich bin gerade dabei ein Programm zu schreiben, welches Netzwerk verwendet. Meist verwendet man ja TCP oder UDP Verbindungen. Wenn der client zum Server sendet sind beide etwa gleich. Bei TCP muss nur zuerst ein Handshake gemacht werden (connect und accept).
    Beim Empfangen kann bei TCP diese Verbindung direkt genutzt werden. Bei UDP horcht der Client nach Eingängen (recvfrom).
    Der Client ist also "offen" für jegliche Eingänge auf einen Port. Egal ob es die Server IP ist oder andere.

    Kann es da bei Nutzern(clienten), die eine Firewall haben zu Problemen kommen, wenn ich UDP statt TCP verwende? Da sie bei UDP aktiv hören, bei TCP nur auf diese, mit denen sie schon gesprochen haben.
    Oder kann man beim Clienten irgendwie nur auf Nachrichten von einer bestimmten IP horchen?
    Oder nimmt man gewöhnlich alle Nachrichten an und schaut, ob sie vom Server sind?

    Ich habe das Beispiel von hier verwendet:
    https://www.cs.rutgers.edu/~pxk/417/notes/sockets/udp.html



  • Das sind im Prinzip 2 Fragen.

    Zum Firewall/routing:
    Im Prinzip läuft das ganz ähnlich wie bei TCP.
    Die ersten Pakete werden vom Client (IP-Client/Port-Client) zum bekannten Server gechickt. (IP-Server/Port-Server).
    Nun merkt sich der Server aber von welcher IP/Port das Paket kam und man wird das symmetrisch machen, dass der Server an die gleiche (IP-Client/Port-Client) zurückschickt.
    So kann ein Client-seitiger NAT-Router und/oder Firewall ebenfalls diese IP/Port-zuweisung dynamisch "erlernen", genau wie bei TCP, da über ihn schon Pakete rausgeschickt wurden und entsprechend weiterleiten.
    Hängt aber natürlcih von den Fähigkeiten bzw der Konfiguration des Routers ab.

    Zur Anwendung:
    Diese bekommt eh nur die Pakete die für sie bestimmt sind vom ausgewählten Server. Deshalb macht man "bind", auch bei UDP.
    Der Rest ist für die App transparent.

    PS: Sehe gerade dass "bind" implizit gemacht wird wenn man auf dem Socket schonmal "sendto" gemacht hat. Was ja für den Client der Fall ist.
    Siehe zb https://stackoverflow.com/questions/3057029/do-i-have-to-bind-a-udp-socket-in-my-client-program-to-receive-data-i-always-g



  • es gibt router die alle zeitlang die UDP verbindungen komplett loeschen, weshalb dann ein paar packete vom server nicht ankommen (weil das routing eventuel noch nicht aufgebaut ist). beim server gibt es ebenfalls ein wenig verwirrung, weil zwar die IP, aber nicht der port, stimmt.

    komplizierter wird es wenn ueber denselben router mehr als eine person spielt. Deswegen ist es gaengig, bei UDP, noch eine extra ID pro user zu vergeben, die dann eindeutig ist, selbst wenn der router eigenheiten hat.



  • scrontch schrieb:

    So kann ein Client-seitiger NAT-Router und/oder Firewall ebenfalls diese IP/Port-zuweisung dynamisch "erlernen", genau wie bei TCP, da über ihn schon Pakete rausgeschickt wurden und entsprechend weiterleiten.
    Hängt aber natürlcih von den Fähigkeiten bzw der Konfiguration des Routers ab.

    "kann" heißt nicht gleich "können müssen". So kann es auch Router geben, die das nicht können und somit TCP möglich machen aber UDP nicht?

    scrontch schrieb:

    Zur Anwendung:
    Diese bekommt eh nur die Pakete die für sie bestimmt sind vom ausgewählten Server. Deshalb macht man "bind", auch bei UDP.
    Der Rest ist für die App transparent.

    Das bind, bindet aber nur den Port (und die eigene IP) nicht den Server. Das recvfrom beim clienten kann durch unterschiedliche Server getriggert werden (sofern Firewall/router durchlässt). Die App kann also auch Pakete von anderen Servern bekommen. Man kann jedoch in der App überprüfen, ob die Nachrricht vom Server kam. Der Buffer wurde aber geschrieben. Da kann es zu Problemen kommen (overflow). Und man hat ggf Dinge im Speicher, die man nicht haben möchte. Oder DDoS-Attacken auch einfacher.

    scrontch schrieb:

    PS: Sehe gerade dass "bind" implizit gemacht wird wenn man auf dem Socket schonmal "sendto" gemacht hat. Was ja für den Client der Fall ist.
    Siehe zb https://stackoverflow.com/questions/3057029/do-i-have-to-bind-a-udp-socket-in-my-client-program-to-receive-data-i-always-g

    D.h. man könnte es weglassen? schadet aber nicht wenn mans trotzdem hinschreibt?
    .sin_addr.s_addr und .sin_port der client addresse sind dann aber nicht eindeutig definiert? Ohne sin_port ist dann auf Client und Server der gleiche Port. Mit bind könnten das verschiedene sein. soweit richtig?

    rapso schrieb:

    komplizierter wird es wenn ueber denselben router mehr als eine person spielt. Deswegen ist es gaengig, bei UDP, noch eine extra ID pro user zu vergeben, die dann eindeutig ist, selbst wenn der router eigenheiten hat.

    Serverseitig einfach mit ID. Aber wie bei Clienten? Wenn ich kein bind mache, horchen die beide am gleichen Port wie der Server und haben die gleiche IP. Wenn nun der Server and ihre IP mit ihren Port sendet:
    Wie kann man dann verhindern, dass sie nicht die falschen Nachrichten empfangen? Oder bekommen beide eine Kopie der Nachricht? Oder können die nicht gleichzeitig am selben Port horchen?



  • user42.23 schrieb:

    rapso schrieb:

    komplizierter wird es wenn ueber denselben router mehr als eine person spielt. Deswegen ist es gaengig, bei UDP, noch eine extra ID pro user zu vergeben, die dann eindeutig ist, selbst wenn der router eigenheiten hat.

    Serverseitig einfach mit ID. Aber wie bei Clienten? Wenn ich kein bind mache, horchen die beide am gleichen Port wie der Server und haben die gleiche IP. Wenn nun der Server and ihre IP mit ihren Port sendet:
    Wie kann man dann verhindern, dass sie nicht die falschen Nachrichten empfangen? Oder bekommen beide eine Kopie der Nachricht? Oder können die nicht gleichzeitig am selben Port horchen?

    die ID ist teil vom packet, die schicken client als auch server immer mit, so sieht der client, dass das packet an ihn gedacht ist, der server sieht dass es von dem client kommt.

    der router uebernimmt normalerweise das mapping der ports, lokal wird jeder PC an einem anderen port haengen, als auch extern mit unterschiedlichen ports zum server kommunizieren. diese "verbindung" merkt sich der router wenn der client das erste packet zum server schickt. (normalerweise)



  • rapso schrieb:

    die ID ist teil vom packet, die schicken client als auch server immer mit, so sieht der client, dass das packet an ihn gedacht ist, der server sieht dass es von dem client kommt.

    Sie ist also Teil des Headers? Wo wird sie gespeichert? Bzw. Wie kann man sie für eine Verbindung definieren?
    (Ist sie Teil des buffers löst sie das Problem nicht.)



  • user42.23 schrieb:

    rapso schrieb:

    die ID ist teil vom packet, die schicken client als auch server immer mit, so sieht der client, dass das packet an ihn gedacht ist, der server sieht dass es von dem client kommt.

    Sie ist also Teil des Headers? Wo wird sie gespeichert? Bzw. Wie kann man sie für eine Verbindung definieren?
    (Ist sie Teil des buffers löst sie das Problem nicht.)

    aus UDP sicht ist es im packet, es sollte teil deines headers sein.
    bei quake heisst die ID QPort:
    http://fabiensanglard.net/quakeSource/quakeSourceNetWork.php



  • rapso schrieb:

    lokal wird jeder PC an einem anderen port haengen

    das ist zwar wahrscheinlich, sicher jedoch nicht.



  • user42.23 schrieb:

    So kann es auch Router geben, die das nicht können und somit TCP möglich machen aber UDP nicht?

    Theoretisch ja. Aber mir ist bei meinen gesamten mehr als sechs oder so verschiedenen Internet Provider-Boxen (Modem+NAT Router) noch keine untergekommen die es nicht kann. Und das ist billiges End-User-Gerät. Auch das "droppen" von UDP Verbindungen hat keine gemacht.

    user42.23 schrieb:

    Das bind, bindet aber nur den Port (und die eigene IP) nicht den Server. Das recvfrom beim clienten kann durch unterschiedliche Server getriggert werden (sofern Firewall/router durchlässt). Die App kann also auch Pakete von anderen Servern bekommen.

    Ja, aber die blockt ja dann schon der Router! Denn die hatten ja keine entsprechende vorausgehende ausgehende Verbindung.
    (Der Router ordnet eingehende destIP+destPort/srcIP+srcPort den früheren srcIP+srcPort/destIP+destPort zu.)
    Falls doch was durchkommt (oder im LAN) hilft die von rapso vorgeschlagene ID.
    Aber hier schweifen wir dann eh nach Cybersecurity/hardening ab, was für das prinzipielle Funktionieren erstmal kein Thema ist. Dafür musst Du natürlich extra sorgen wenn deine App was schützenswertes ist.

    user42.23 schrieb:

    scrontch schrieb:

    PS: Sehe gerade dass "bind" implizit gemacht wird wenn man auf dem Socket schonmal "sendto" gemacht hat. Was ja für den Client der Fall ist.

    D.h. man könnte es weglassen? schadet aber nicht wenn mans trotzdem hinschreibt?
    .sin_addr.s_addr und .sin_port der client addresse sind dann aber nicht eindeutig definiert? Ohne sin_port ist dann auf Client und Server der gleiche Port. Mit bind könnten das verschiedene sein. soweit richtig?

    Hab jetzt keine Zeit das genau nachzuschauen, aber war das nicht so dass man bei bind und sendto den Quellport offen lassen kann und dann weist dir das System automatisch einen freien zu, den man dann zum senden weiterverwendet? So sollte mas es jedenfalls machen, jeder Client sollte einen zufälligen freien Port wählen. Damit ist eigentlich auch das Problem mit mehreren Clients hinter selbem Router abgedeckt.

    Porterhousesteak schrieb:

    rapso schrieb:

    lokal wird jeder PC an einem anderen port haengen

    das ist zwar wahrscheinlich, sicher jedoch nicht.

    Falls der unwahrscheinliche Fall eingetreten ist dass beide Clients denselben Port gewählt haben muss sich der Router darum kümmern wenigsten einen Port umzumappen. Also der Server sieht dann für den zweiten Client einen anderen Quellport. Und für den Client bleibt es transparent, der Router schreibt den Port für jedes ein-/ausgehende Paket jeweils um. Dast ist das Prinzip von NAT.



  • scrontch schrieb:

    Porterhousesteak schrieb:

    rapso schrieb:

    lokal wird jeder PC an einem anderen port haengen

    das ist zwar wahrscheinlich, sicher jedoch nicht.

    Falls der unwahrscheinliche Fall eingetreten ist dass beide Clients denselben Port gewählt haben muss sich der Router darum kümmern wenigsten einen Port umzumappen. Also der Server sieht dann für den zweiten Client einen anderen Quellport. Und für den Client bleibt es transparent, der Router schreibt den Port für jedes ein-/ausgehende Paket jeweils um. Dast ist das Prinzip von NAT.

    habe nie behauptet, dass das ein problem ist. 😕
    nur rapsos aussage musste korrigiert werden.
    ausserdem ist das nicht das prinzip von NAT.
    das ist das prinzip von PAT, oder CG-NAT.



  • rapso schrieb:

    user42.23 schrieb:

    Sie ist also Teil des Headers? Wo wird sie gespeichert? Bzw. Wie kann man sie für eine Verbindung definieren?
    (Ist sie Teil des buffers löst sie das Problem nicht.)

    aus UDP sicht ist es im packet, es sollte teil deines headers sein.
    bei quake heisst die ID QPort:
    http://fabiensanglard.net/quakeSource/quakeSourceNetWork.php

    Also wie ich das verstanden habe ist es Teil der Nachricht/buffers, welche vom Client zum Server geschickt wird. Quake packt es dann selbst in den Header der internen Übertragungen. Wenn sich nun der Port (aufgrund einer Router Eigenschaft/Bug) verändert, kann der Spieler denoch erkannt werden.

    Das hilft aber nicht bei folgenden:
    Wenn ein Nutzer z.B. ein zweites Spiel aufmacht (mit selben Port aber anderen QPort) können die Daten auf dem Quakeserver zwar richtig gelesen werden, jedoch wenn der Server etwas schickt kann es beim Falschen ankommen.

    Das kann man scheinbar nicht umgehen.