2016-12-07 3 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 получает IP-адрес сервера front, и я полностью понимаю, почему.

К сожалению, я не могу использовать data, поскольку он может быть полностью зашифрован клиентом.

+0

х-экспедитором-за это заголовок HTTP и не имеет ничего общего с TCP потоки, к сожалению. Поток может быть зашифрован, и в этом случае я не могу проверить, является ли это HTTP, TLS или что-то еще. – WooDzu

+0

Вам не нужно заботиться о том, зашифрованы ли данные или нет. Вы можете просто добавить данные с помощью uint32 formated 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

Другим понятным подходом может быть то, что вы можете отправить фактическое remoteAddress во время соединения socket.proxy и затем запомнить его на целевом сервере. Таким образом, вам не придется добавлять служебные данные.

Также в вашем исходном коде вы создаете новое соединение сокетов для целевого сервера на каждом событии данных. Я не думаю, что это намеренно, но таким образом, вы скоро достигнете предела открытого файла, если трафик высок.

Поэтому я предлагаю вам подключить сокет к целевому серверу только один раз, когда у вас есть новое подключение сокета к переднему серверу. После этого, ваш код должен выглядеть следующим образом:

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

Спасибо большое! Сейчас я тестирую этот подход. «Также в вашем исходном коде вы делаете новое соединение сокетов для целевого сервера на каждом мероприятии« данные ». Я не думаю, что это намеренно« На самом деле это так, поскольку у меня есть несколько целевых серверов, из которых я могу забрать только получая первые байты на переднем сервере. – WooDzu

+0

Но тогда могут быть случаи, когда ваши зашифрованные данные могут быть повреждены, если данные/запрос, полученные на переднем сервере, поступают в несколько фрагментов, и каждый фрагмент отправляется на другой целевой сервер. Возможно, вы уже справились с этой ситуацией. Я просто думаю вслух :) –

+0

Я думаю, что ip, отправленный на сервер backend, должен быть фиксированным по длине, а бэкэнд предполагает, что первые n-байтовые данные являются ip-адресом. Поскольку tcp является проточным протоком. Когда front-end записывает два пакета на бэкэнд, Бэкэнд может получить их в исходном формате или все вместе, таким образом, массировать программу. – Jerry

Смежные вопросы