2016-12-07 77 views
1

考慮到下面的示例腳本,我正在將一個TCP連接從一臺服務器管道連接到另一臺服務器,這很好。在兩個網絡服務器之間發送連接元數據

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')) 

我面臨的問題是,我需要轉移到其他服務器通過原始套接字的IP地址(如:socket.remoteAddress)。 它不需要覆蓋目標的socket.remoteAddress,只是以某種方式檢索原始IP。

這裏是我正在測試這一點:

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

導致:

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

注意,target服務器接收front服務器的IP地址,我完全理解爲什麼。

不幸的是,我不能使用data,因爲它可能會被客戶端完全加密。

+0

X-轉發-的是一個HTTP頭,並沒有任何與TCP流不幸。該流可能會被加密,在這種情況下,我無法檢查它是HTTP,TLS還是其他。 – WooDzu

+0

您無需關心數據是否已加密。你可以用uint32格式化ip來預先加載數據。當後端接收到代理數據時,刪除前置IP並解析它。 – Jerry

+0

這實際上是有趣的想法。不是最乾淨的,但絕對值得一去。謝謝傑裏 – WooDzu

回答

0

思考更多關於不需要關注數據的解決方案,這兩個服務器都知道打開連接到目標的套接字端口的一個重要事實。前連接套接字爲socket.localPort,目標服務器套接字爲socket.remotePort

這一事實使人們有可能建立一個端口/ IP映射:

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

另一個更清晰的方法是,您可以在socket.proxy連接期間發送實際的remoteAddress,然後在目標服務器上記住它。這樣,您不必爲數據添加開銷。

此外,在您的原始代碼中,您正在每個'data'事件上與目標服務器建立新的套接字連接。我不認爲這是有意的,但是這樣,如果流量很高,您很快就會達到打開的文件限制。

所以我建議你只有一次到目標服務器的套接字連接,當你有一個新的套接字連接到前端服務器。在這之後,你的代碼應該是這樣的:

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

爲了檢查連接數到你的服務器,你可以使用server.getConnections。這樣,你可以防止事情脫離界限。

希望這會有所幫助。

+0

非常感謝!我正在測試這種方法。 「同樣在你的原始代碼中,你正在爲每個'data'事件創建一個到目標服務器的新套接字連接,我不認爲這是有意的」實際上,因爲我有多個目標服務器,我只能從中獲取在前端服務器上接收第一個字節。 – WooDzu

+0

但是,如果在前端服務器收到的數據/請求出現在多個塊中,並且每個塊都到不同的目標服務器,則可能會出現一些情況,即您的加密數據可能會損壞。你可能已經處理了這種情況。我只是想大聲:) –

+0

我認爲發送到後端服務器的IP應該是長度固定的,後端假設第一個n字節數據是IP地址。因爲tcp是一個流協議。當前端向後端寫入兩個數據包時,後端可能會以原始格式接收它們,或者全部連接在一起,從而大量增加程序。 – Jerry

相關問題