Назад | Перейти на главную страницу

ngx_stream_core_module и конечный пользовательский IP

Допустим, у меня есть служба, работающая на уровне необработанного TCP, и я хочу добавить к ней балансировку нагрузки. Я пытался использовать ngx_stream_core_module. Хотя TCP-потоки действительно передаются на внутренние серверы через прокси, я обнаружил некоторые проблемы, которые не могу решить.

  1. Моя служба написана на node.js, и это распространенный метод настройки диспетчера процессов, например pm2, который перезапускает узел в случае, если он потребляет слишком много памяти. Но это, очевидно, отключит всех подключенных клиентов. Я ожидал, что nginx будет подключать пользователей к следующему серверу в восходящем потоке (ну, может быть, это тоже> 2016, но), но мое соединение просто закрывается.

  2. Для работы моей службы требуются IP-адрес конечного пользователя и удаленный порт, но в сокете приложения remoteAddress и remotePort указывают на локальный экземпляр nginx. Т.е. когда я печатаю его в буфер, я вижу 127.0.0.1, когда соединение проксируется, и мой реальный ip, когда я подключаюсь к узлу напрямую. Я вижу, что nginx поддерживает некоторые переменные конфигурации (начиная с версии 1.11.2), и $ remote_addr среди них. Но я не вижу никакой информации, как передать эту переменную в апстрим. proxy_set_header директива недоступна внутри потока и выглядит нормально, поскольку в TCP нет никаких «заголовков». Это вообще возможно?

  3. Я не DevOps, а программист, поэтому слышал о haproxy, но понятия не имею, может ли он решить эти две проблемы. Может это?

Для тестирования я использовал тупой сервер echo node.js, где вся рабочая часть сужена до

server.on('connection', socket => {
    socket.write(`Hello from ${instance}, ${socket.remoteAddress}:${socket.remotePort}\n`);
});

И соответствующая часть моей конфигурации nginx:

stream {
    upstream echo {
        server localhost:9000;
        server localhost:9001;
    }

    server {
        listen 8080;
        proxy_connect_timeout 1s;
        proxy_timeout 2h;
        proxy_pass echo;
    }
}

Наконец, я использовал netcat для проверки.

// direct connect
~|⇒  nc 95.85.15.120 9000
Hello, ::ffff:86.110.174.98:65408

// proxied connect
~|⇒  nc 95.85.15.120 8080
Hello, ::ffff:127.0.0.1:44056

Здесь документы модуля.

  1. Это не то, что могло бы работать с TCP, потому что это наверняка сломает почти любой протокол, работающий поверх. Например, что, если соединение будет разорвано посреди какого-либо сообщения или команды?

  2. Ты можешь использовать протокол прокси для передачи исходных IP-адресов, но они должны поддерживаться вашим сервером.

    Или вы можете настроить привязка к IP-адресам клиентов:

     proxy_bind $remote_addr transparent;