Dynamische Portweiterleitung basierend auf Hostname oder Ursprungs-IP

7

Ich bin ein Programmierer, der versucht, einige Dinge außerhalb meiner Domäne herauszufinden:

Angenommen, ich habe einen Computer und Clients stellen TCP-Verbindungen (aber nicht http!) Her. Ich möchte Clients basierend auf dem Hostnamen, mit dem sie eine Verbindung herstellen, zu ihren eigenen Ports umleiten. Beispielsweise stellt client1 eine Verbindung zu client1.myserver.com her und ist mit Port 1234 verbunden. Client2.myserver.com -> 1235, client3.myserver.com -> 1236 usw.

Ich möchte dynamisch steuern, wie Ports x für Host y tatsächlich auf Port z auf meinem physischen Computer zeigen.

Beim Googeln dieser Informationen werden Verweise auf Firewalls, Proxys und Reverse-Proxys angezeigt. Welche Software brauche ich eigentlich? Ermöglicht vorhandene Software solche Änderungen bei Bedarf (ich habe gehört, dass Firewall-Änderungen einen Tag erfordern)?

Wenn ich eine solche Ebene selbst schreiben wollte (da sie möglicherweise etwas anwendungsspezifisch ist), könnte dies in Java oder node.js erfolgen (ich meine, könnte dies mit einer API auf höherer Ebene erfolgen oder muss ich anfangen, die IP auseinanderzunehmen? Pakete)? Wie würde ich wissen, mit welchem ​​Hostnamen der Client verbunden ist, da alle Hostnamen auf demselben Computer aufgelöst werden?

Ich freue mich auch über Hinweise auf Lesematerial.

user23398
quelle

Antworten:

11

Auf IP-Ebene gibt es keinen Hostnamen. Ein Hostname ist eine Abstraktion einer IP-Adresse auf Anwendungsebene und hat auf der Internet- oder Transportebene keine Bedeutung.

Beim gemeinsam genutzten HTTP-Hosting wird dieser Trick bei der Verarbeitung der HTTP- Konversation abstrahiert , die nach dem Start der TCP-Konversation erfolgt. Aus diesem Grund war für das Ausführen eines SSL-Servers so lange eine dedizierte IP-Adresse erforderlich, da die SSL-Konversation vor der HTTP-Konversation stattfindet (dies wurde inzwischen in neueren TLS-Versionen behoben, in denen HOSTNAME jetzt als Teil der SSL-Aushandlung aufgenommen werden kann ).

Für eine HTTP-Instanz mit gemeinsamem Hosting werden die Protokolle in ungefähr dieser Reihenfolge ausgehandelt:

TCP -> SSL -> HTTP

Jedes Protokoll kann erst gestartet werden, wenn die früheren abgeschlossen sind. Bis vor kurzem waren Hostnamen nur im letzten Schritt der Kette bekannt, weshalb es an der Webserver-Software lag, eine Eins-zu-Eins-Zuordnung von Hostnamen zu IP zu handhaben.

Bei einer dynamischen Portweiterleitung ist dies nur möglich, wenn das Anwendungsprotokoll die Hostnamen irgendwie kennt. Einige Geräte (Software oder Hardware) übernehmen die anfängliche TCP-Verbindung mit Clients und die ersten Schritte des Anwendungsprotokolls (was auch immer das ist) und leiten die Verbindung basierend auf dem Empfang an ihr endgültiges Ziel weiter.

Die genauen erforderlichen Schritte variieren je nach Anwendungsprotokoll. Einige, wie z. B. HTTP, enthalten einen HOSTNAME-Header, der den Hostnamen angibt, mit dem der Client voraussichtlich sprechen wird. Andere, wie einige Microsoft-Protokolle, nutzen DNS-basierte SRV-Einträge, um eine genaue Kombination aus IP und Port zu ermitteln . Da es sich so anhört, als würden Sie Ihr eigenes Anwendungsprotokoll von Anfang an entwerfen, würde ich empfehlen, dem Beispiel von HTTP zu folgen und einen HOSTNAME-Header in Ihre anfänglichen Protokollverhandlungsschritte aufzunehmen.

sysadmin1138
quelle
Ich habe ein wenig darüber nachgedacht, weil es für mein Entwickler-Setup sehr schön wäre, und denke, dass dies möglich sein könnte , wenn: Sie ein virtuelles Netzwerk mit einer IP-Adresse für jeden Hostnamen erstellt haben, den Sie zuordnen möchten, und lokales DNS so einrichten, dass es zeigt Jeder Hostname an seiner virtuellen Netzwerk-IP hatte dann nur wenige Dienste, die den Standardport des Protokolls auf jeder dieser IPs abhörten, die wussten, an welchen realen Port sie weiterleiten mussten, wenn sie Datenverkehr erhielten. Das ist alles Zeug, über das ich wenig weiß, und es scheint viel zu komplex zu sein, es einfach aus der Hand zu versuchen, aber ich dachte, ich würde nach der Chance fragen, dass jeder, der mehr weiß, dies liest
Nr.
2

Sie können dies am einfachsten mithilfe von SRV-Einträgen in Ihrem DNS erreichen:

http://en.wikipedia.org/wiki/SRV_record

Chris Thorpe
quelle
1
Ich frage mich, wohin all die positiven Stimmen gehen. Dies sollte die akzeptierte Antwort sein.
Ardee Aram
Verwenden die meisten SSH- oder HTTP-Protokolle den SRV-Datensatz, um den Port zu bestimmen? Oder erfordert dies spezielle Client-Software?
Richard
Ich sehe nicht, wie SRV-Datensätze im obigen Szenario helfen könnten. Sie können nur verwendet werden, um eine Anforderung an einem bestimmten Port an einen anderen Host umzuleiten (genau wie MX-Datensätze, jedoch allgemeiner). Sie helfen nicht, wenn Sie versuchen, Anforderungen hinter einem Nat-Gateway basierend auf dem Hostnamen weiterzuleiten. Und sie ändern nicht den Port, den der Client für die Anforderung verwendet.
Andreas
1

Können Sie klarer beschreiben, was Sie versuchen und warum? Das "Warum" wird sehr helfen. Was sind die Kunden? Was ist das Protokoll?

Es gibt viele Möglichkeiten, dies basierend auf den Protokollen und Datenströmen zu tun.

Betrachten Sie die Injektion von pf, iptables oder ebtables, siehe "ssh blacklist" für Beispiele. Informationen zur allgemeinen Umleitung finden Sie in LVS, HAproxy und anderen Load Balancern.

Ein alter Trick ist ein "Weck" -System. Dies funktioniert hervorragend für SSH oder andere verschlüsselte Protokolle, die die Ermittlung der Quelldomäne CPU-intensiver machen (Decodieren des Headers). Dadurch wird nur ein einziger Port ausgeführt, wenn niemand verbunden ist.

  • SSH in einen einzelnen offenen Port (keine Terminalunterstützung erforderlich)
  • Melden Sie sich als userX beim System an (vorzugsweise mit Schlüsseln). Dadurch wird ein Skript ausgeführt, das eine andere Instanz des Servers an Port XXXXX startet und dem Client mit der neuen Portnummer antwortet
  • Die Nachricht "Port XXXXX ist offen" wird zurück an den Client übertragen, die erste SSH-Sitzung wird geschlossen
  • Der Client oder die Client-App stellt dann über den jetzt geöffneten Port XXXXX erneut eine Verbindung her
  • Wenn der Client die Verbindung trennt, wird die alternative Instanz an Port XXXXX geschlossen und / oder Port XXXXX geschlossen.

Bestimmte Ports können basierend auf Schlüsseln / Benutzern, Reverse Lookup, Nachrichtenübermittlung usw. zugewiesen werden. Einige lassen die Instanzen einfach laufen und öffnen / schließen sie mithilfe der pf / iptables-Firewall-Injektion. Andere erweitern dies mithilfe einer Firewall-Regel, um den Dienststart auszulösen, und es wird kein anfänglicher SSH (oder ein anderer Dienst) ausgeführt, bis ein angegebener Port mit einem bestimmten Pakettyp gepingt wird. Ich bevorzuge eine "kürzlich übereinstimmende" benutzerdefinierte Firewall-Regel, um Streupakete zu blockieren und die Serverinstanzen für eine weniger dynamische Interaktion mit der Firewall zu stoppen / zu starten.

Diese Idee kann mit jedem Protokoll und Dienst funktionieren, der codiert oder skriptgesteuert werden kann.

Lesematerial für TCP / IP-Netzwerke: Alles, was von W. Richard Stevens geschrieben oder empfohlen wurde. http://www.kohala.com/start/

Verwenden Sie SSH-Tunnel nicht als Notlösung in der Entwicklung. Diese könnten alles erreichen, was Sie ohne Code benötigen. Was ist deine App? Sollte die Kommunikation nicht sicher sein? Wie wollen Sie Skript-Kiddie-Hacker auf die schwarze Liste setzen? Das ist mehr, was Sie schreiben und debuggen müssen. Sie sollten Ihren Code ohnehin unterteilen, also entwickeln Sie alles andere mithilfe von SSH als Transport, Portweiterleitung, Verschlüsselung, Verwendungsprotokollierung, Blacklisting usw. Wenn alles andere erledigt ist, schreiben Sie Ihren eigenen Netzwerkprotokollmechanismus, um SSH zu ersetzen. Für Benutzer auf dem Gateway-SSH-Server ist kein Terminalzugriff erforderlich, um Tunnel verwenden zu können.

Joe
quelle