2016-12-07 1 views
1

Angesichts der Beispiel-Skript unten bin ich eine TCP-Verbindung von einem Server zu einem anderen, die funktioniert gut.Senden von Verbindungsmetadaten zwischen zwei Net-Servern

net = require "net" 
log = console.log 

# This server needs to receive custom data eg. (remoteAddress or an uuid) 
target = net.createServer (socket) -> 
    log('Target connection from ' + socket.remoteAddress) 
target.listen(10000, '0.0.0.0',() -> log('Target ready')) 

# User-facing server that pipes to the target server 
front = net.createServer (socket) -> 
    log('Front connection from ' + socket.remoteAddress) 
    socket.on 'data', (data) -> 
    socket.proxy = net.createConnection 10000,() -> 
     socket.proxy.write(data) 
     socket.pipe(socket.proxy).pipe(socket) 

front.listen(8006, '0.0.0.0',() -> log('Front ready')) 

Das Problem, das ich bin vor ist, dass ich die IP-Adresse übergeben müssen (zB. socket.remoteAddress) der ursprünglichen Fassung auf den anderen Server. Es muss socket.remoteAddress des Zieles nicht überschrieben werden, nur die ursprüngliche IP auf die eine oder andere Weise abrufen.

Hier ist, wie ich dies zu testen:

$ telnet 172.0.0.50 8006 
Trying 172.0.0.50... 
Connected to 172.0.0.50. 
Escape character is '^]'. 
SendingData 

die Ergebnisse:

Target ready 
Front ready 
Front connection from 172.0.0.1 
Target connection from 127.0.0.1 

Beachten Sie, dass die target-Server die IP-Adresse des front Server empfängt, und ich völlig verstehen, warum.

Ich kann die data leider nicht verwenden, da sie vom Client vollständig verschlüsselt werden könnte.

+0

x-Forwarder-für ist ein HTTP-Header und nichts mit TCP leider Strömen zu tun hat. Der Stream könnte verschlüsselt sein. In diesem Fall kann ich nicht prüfen, ob es sich um HTTP, TLS oder etwas anderes handelt. – WooDzu

+0

Sie müssen sich nicht darum kümmern, ob die Daten verschlüsselt sind oder nicht. Sie könnten die Daten einfach mit der formatierten iutin32-IP voranstellen. Und wenn das Backend die Proxy-Daten empfängt, entfernen Sie die vorhergehende IP-Adresse und parsen Sie sie. – Jerry

+0

Das ist eigentlich eine interessante Idee. Nicht der sauberste, aber definitiv einen Versuch wert. Danke Jerry – WooDzu

Antwort

0

Wenn Sie mehr über eine Lösung nachdenken, die sich nicht mit Daten auseinandersetzen muss, gibt es eine wichtige Tatsache, dass beide Server über den Socket-Port Bescheid wissen, der die Verbindung zum Ziel geöffnet hat. Welches ist socket.localPort der vorderen Anschlussbuchse und socket.remotePort des Sockets des Zielservers.

machen diese Tatsache es möglich, einen Port/ip Karte zu bauen:

net = require "net" 
log = console.log 

portMap = {} 

# This server needs to receive custom data eg. (remoteAddress or an uuid) 
target = net.createServer (socket) -> 
    socket.once 'data', (data) -> 
    socket.id = portMap[socket.remotePort] 
    log('Target connection from ' + socket.id); 

target.listen(10000, '0.0.0.0',() -> log('Target ready')) 

# User-facing server that pipes to the target server 
front = net.createServer (socket) -> 
    log('Front connection from ' + socket.remoteAddress) 
    socket.once 'data', (data) -> 
    socket.proxy = net.createConnection 10000,() -> 
     portMap[socket.proxy.localPort] = socket.remoteAddress; 
     socket.proxy.write(data) 
     socket.pipe(socket.proxy).pipe(socket) 

front.listen(8006, '0.0.0.0',() -> log('Front ready')) 
1

Ein weiterer sauberer Ansatz könnte sein, dass Sie während der socket.proxy-Verbindung den tatsächlichen remoteAddress senden und dann auf dem Zielserver speichern können. Auf diese Weise müssen Sie den Daten keinen Overhead hinzufügen.

Auch in Ihrem ursprünglichen Code machen Sie eine neue Socket-Verbindung zum Zielserver bei jedem "Daten" -Ereignis. Ich denke nicht, dass es beabsichtigt ist, aber auf diese Weise werden Sie bald das offene Dateilimit erreichen, wenn der Traffic hoch ist.

So würde ich vorschlagen, dass Sie eine Socket-Verbindung zum Zielserver nur einmal herstellen, wenn Sie eine neue Socket-Verbindung zum Front-Server haben. Danach sollten Sie den Code wie folgt aussehen:

var net = require("net"); 
const log = console.log; 

target = net.createServer(function(socket) { 
    log('Target connection from ' + socket.remoteAddress); 
    socket.once('data', function(data){ 
    socket.id = data.toString(); // Now, use socket.id whenever you want at the target server. 
    }); 
}); 

target.listen(10000, '0.0.0.0', function() { 
    log('Target ready'); 
}); 

var front = net.createServer(function(socket) { 
    log('Front connection from ' + socket.remoteAddress); 
    socket.proxy = net.createConnection(10000, function() { 
    socket.proxy.write(socket.remoteAddress); 
    }); 
    socket.pipe(socket.proxy).pipe(socket); 
}); 

front.listen(8006, '0.0.0.0', function() { 
    log('Front ready'); 
}); 

Für die Anzahl der Verbindungen zu Ihrem Server überprüfen, können Sie server.getConnections verwenden. Auf diese Weise können Sie verhindern, dass die Dinge aus dem Rahmen gehen.

Hoffe, das hilft.

+0

Vielen Dank! Ich teste diesen Ansatz jetzt. "Auch in Ihrem ursprünglichen Code machen Sie bei jedem 'Daten'-Ereignis eine neue Socket-Verbindung zum Zielserver. Ich denke nicht, dass es beabsichtigt ist." Tatsächlich ist es, da ich mehrere Zielserver habe, von denen ich nur abholen kann Empfangen von ersten Bytes auf dem Front-Server. – WooDzu

+0

Es kann jedoch in einigen Fällen vorkommen, dass Ihre verschlüsselten Daten beschädigt werden, wenn die Daten/Anforderungen, die auf dem Front-Server eingehen, in mehreren Chunks enthalten sind und jeder Chunk an einen anderen Zielserver gesendet wurde. Sie haben diese Situation möglicherweise schon behandelt. Ich denke gerade laut :) –

+0

Ich denke, dass die IP, die an den Backend-Server gesendet wird, längenfixiert sein sollte, und Backend nimmt an, dass die ersten N-Byte-Daten die IP-Adresse sind. Weil Tcp ein Stream-Protokoll ist. Wenn das Front-End zwei Pakete an das Backend schreibt, kann das Backend diese im Originalformat empfangen oder alle zusammengefügt werden, um das Programm zu erweitern. – Jerry

Verwandte Themen