Как дублировать TCP-трафик на один или несколько удаленных серверов для сравнительного анализа?

30

Инфраструктура: серверы в центре обработки данных, ОС - Debian Squeeze, веб-сервер - Apache 2.2.16


Ситуация:

Живой сервер используется нашими клиентами каждый день, что делает невозможным тестирование настроек и улучшений. Поэтому мы хотели бы дублировать входящий HTTP-трафик на работающем сервере на один или несколько удаленных серверов в режиме реального времени. Трафик должен быть передан на локальный веб-сервер (в данном случае Apache) И на удаленный сервер (ы). Таким образом, мы можем настраивать конфигурации и использовать другой / обновленный код на удаленном сервере (ах) для сравнительного анализа и сравнения с текущим живым сервером. В настоящее время веб-сервер прослушивает ок. 60 дополнительных портов помимо 80 и 443, из-за структуры клиента.


Вопрос: Как реализовать это дублирование на одном или нескольких удаленных серверах?

Мы уже попробовали:

  • Дубликатор agnoster - для этого потребуется один открытый сеанс на порт, что неприменимо. ( https://github.com/agnoster/duplicator )
  • Прокси-сервер kklis - только перенаправляет трафик на удаленный сервер, но не передает его на веб-сервер lcoal. ( https://github.com/kklis/proxy )
  • iptables - DNAT только перенаправляет трафик, но не передает его на локальный веб-сервер
  • iptables - TEE дублирует только серверы в локальной сети -> серверы не расположены в одной сети из-за структуры центра обработки данных
  • предложенные альтернативы, предложенные для вопроса «дублирование tcp-трафика с прокси-сервером» в stackoverflow ( /programming/7247668/duplicate-tcp-traffic-with-a-proxy ), оказались безуспешными. Как уже упоминалось, TEE не работает с удаленными серверами за пределами локальной сети. teeproxy больше не доступен ( https://github.com/chrislusf/tee-proxy ), и мы не смогли найти его где-то еще.
  • Мы добавили второй IP-адрес (который находится в той же сети) и присвоили ему eth0: 0 (основной IP-адрес назначен eth0). Не удалось объединить этот новый IP или виртуальный интерфейс eth0: 0 с функцией или маршрутами iptables TEE.
  • предложенные альтернативы, предложенные для вопроса «дублировать входящий tcp-трафик на сжатие Debian» ( дублирование входящего TCP-трафика на сжатие Debian ), не увенчались успехом. Сеансы cat | nc (cat / tmp / prodpipe | nc 127.0.0.1 12345 и cat / tmp / testpipe | nc 127.0.0.1 23456) прерываются после каждого запроса / подключения клиентом без какого-либо уведомления или журнала. Keepalive не изменил эту ситуацию. Пакеты TCP не были перенесены в удаленную систему.
  • Дополнительные попытки с с различными вариантами SOCAT (HowTo: http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/ , /programming/9024227/duplicate-input- unix-stream-to-multiple-tcp-clients-using-socat ) и аналогичные инструменты оказались безуспешными, поскольку предоставленная функция TEE будет выполнять запись только в FS.
  • Конечно, поиск и поиск этой «проблемы» или настройки также не увенчались успехом.

У нас заканчиваются варианты здесь.

Есть ли способ отключить принудительное использование «сервера в локальной сети» функции TEE при использовании IPTABLES?

Может ли наша цель быть достигнута путем различного использования IPTABLES или Routes?

Знаете ли вы другой инструмент для этой цели, который был протестирован и работает для этих конкретных обстоятельств?

Есть ли другой источник для tee-proxy (который бы соответствовал нашим требованиям, AFAIK)?


Заранее спасибо за ваши ответы.

----------

редактировать: 05.02.2014

Вот скрипт Python, который будет работать так, как нам нужно:

import socket  
import SimpleHTTPServer  
import SocketServer  
import sys, thread, time  

def main(config, errorlog):
    sys.stderr = file(errorlog, 'a')

    for settings in parse(config):
        thread.start_new_thread(server, settings)

    while True:
        time.sleep(60)

def parse(configline):
    settings = list()
    for line in file(configline):
        parts = line.split()
        settings.append((int(parts[0]), int(parts[1]), parts[2], int(parts[3])))
    return settings

def server(*settings):
    try:
        dock_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

        dock_socket.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)

        dock_socket.bind(('', settings[0]))

        dock_socket.listen(5)

        while True:
            client_socket = dock_socket.accept()[0]

            client_data = client_socket.recv(1024)
            sys.stderr.write("[OK] Data received:\n %s \n" % client_data)

            print "Forward data to local port: %s" % (settings[1])
            local_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            local_socket.connect(('', settings[1]))
            local_socket.sendall(client_data)

            print "Get response from local socket"
            client_response = local_socket.recv(1024)
            local_socket.close()

            print "Send response to client"
            client_socket.sendall(client_response)
            print "Close client socket"
            client_socket.close()

            print "Forward data to remote server: %s:%s" % (settings[2],settings[3])
            remote_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            remote_socket.connect((settings[2], settings[3]))
            remote_socket.sendall(client_data)       

            print "Close remote sockets"
            remote_socket.close()
    except:
        print "[ERROR]: ",
        print sys.exc_info()
        raise

if __name__ == '__main__':
    main('multiforwarder.config', 'error.log')

Комментарии для использования этого сценария:
Этот сценарий перенаправляет несколько настроенных локальных портов на другие локальные и удаленные серверы сокетов.

Конфигурация:
Добавьте в файл конфигурации строки port-forward.config со следующим содержимым:

Сообщения об ошибках хранятся в файле error.log.

Сценарий разделяет параметры файла конфигурации: разделяет
каждую строку конфигурации пробелами
0: локальный порт для прослушивания
1: локальный порт для пересылки на
2: удаленный IP-адрес сервера назначения
3: удаленный порт сервера назначения
и возврат настроек

Sise
источник
Является ли весь трафик HTTP?
longneck
да, весь трафик HTTP.
Сессия
1
Кстати. teeproxy доступен здесь: github.com/chrislusf/teeproxy
Tombart
1
Другая возможность: github.com/ebowman/splitter Scala / Netty.
Рич К.

Ответы:

11

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

Казимирас Алиулис
источник
Дублировать TCP невозможно - я с этим согласен. Дублирование трафика уровня 7 не так. Вы можете захватывать запросы от клиента и воспроизводить их на других серверах. Простой 1 запрос на воспроизведение сеанса TCP должен быть довольно простым. Постоянные соединения потребуют некоторых размышлений, поскольку вы рассчитываете время дополнительных запросов клиента.
Эван Андерсон
@Kazimieras Aliulis: не требуется связь с двумя отдельными серверами. клиент связывается с основным сервером = действующим сервером. Живой сервер обрабатывает клиентские запросы и отвечает клиенту. Помимо обработки и ответа клиенту основной сервер дублирует запросы на второй сервер = сервер тестирования. ответы от второго сервера к первичному серверу будут отбрасываться / игнорироваться на первичном сервере и не будут пересылаться клиенту.
Сеанс
@Evan Anderson: дублирование на уровне HTTP также было нашей первой идеей, но, например, прокси-сервер Apache или подобные инструменты или модули не позволяют одновременно обрабатывать запросы локально и дублировать их на удаленном хосте. Если у вас есть другие идеи, пожалуйста, совет! :) мы предпочитаем дублирование записи и повторного воспроизведения, чтобы получить мгновенные результаты сравнения.
Сессия
1
@Sise: вы можете попробовать написать свой собственный http-прокси, который передает трафик на два сервера. Это должно быть довольно легко сделать с помощью Python Twisted Framework twistedmatrix.com .
Казимерас Алиулис
@Kazimieras Aliulis: это определенно альтернатива! я никогда не слышал об этом. но проверка показывает, что он идеально подходит для нашей цели. Раньше мы не рассматривали python, но в настоящее время мы рассматриваем среду и возможности Twisted с общим python. Я сообщу, если мы добьемся успеха!
Сессия
20

Из того, что вы описываете, GOR, кажется, соответствует вашим потребностям. https://github.com/buger/gor/ "Воспроизведение HTTP-трафика в режиме реального времени. Воспроизведение трафика из рабочей среды в промежуточную среду и среду разработки." ?

Артур Лутц
источник
2
Это именно то , что я искал, большое спасибо, вы спасли меня, написав именно это, в Go! :-)
chmac
У nginx есть зеркальный модуль. nginx.org/en/docs/http/ngx_http_mirror_module.html
Джимми М.Г. Лим
7

Teeproxy может быть использован для репликации трафика. Использование действительно просто:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a производственный сервер
  • b тестовый сервер

Когда вы размещаете HAproxy (с roundrobin) перед вашим веб- сервером, вы можете легко перенаправить 50% своего трафика на сайт тестирования:

         /------------------> production
HAproxy /                 ^
        \                /
         \---- teeproxy -.....> test (responses ignored)
Tombart
источник
4

Как протокол @KazimierasAliulis, TCP, будучи протоколом с отслеживанием состояния, не поддается простой обработке копий пакетов на другом хосте.

Подбор пакетов на уровне завершения TCP и ретрансляция их в виде нового потока TCP является разумным. Инструмент дубликатора, с которым вы связались, выглядит как ваш лучший выбор. Он работает как TCP-прокси, позволяя конечному автомату TCP работать должным образом. Ответы от ваших тестовых машин будут просто отброшены. Это звучит так, как будто это отвечает всем требованиям именно того, чего вы хотите.

Мне непонятно, почему вы списали инструмент дублирования как неприемлемый. Вам придется запустить несколько экземпляров инструмента, так как он прослушивает только один порт, но, по-видимому, вы хотите ретранслировать каждый из этих различных портов прослушивания на разные порты внутренней системы. Если нет, вы можете использовать iptables DNAT, чтобы направить все прослушивающие порты в одну прослушивающую копию инструмента дублирования.

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

Эван Андерсон
источник
да, вы совершенно правы, инструмент дублирования агностера соответствовал бы нашим требованиям, за исключением ситуации с несколькими портами. Также отмена ответов тестовой машины полностью заполнена. Чтобы достичь цели максимально точной симуляции реальной / реальной ситуации, мы не можем связать все порты работающего сервера с одним портом на тестовой машине. Разные порты используются для разделения клиентских устройств на разных клиентов. Таким образом, мы должны открыть 60-70 сеансов этого инструмента дублирования. Это не очень практично, как вы можете себе представить.
Сеанс
@Sise - Компьютеры умеют делать утомительные вещи. Я думаю, что вы могли бы написать скрипт для разбора ваших конфигураций Apache и выплеснуть необходимые командные строки для запуска 60 - 70 экземпляров инструмента дубликатора. Я не могу себе представить, что инструмент дублирования очень ресурсоемкий, но, даже если бы это было так, вы могли бы запустить эти 60 - 70 экземпляров на другом компьютере и сделать некоторые хитрости в сети, чтобы получить трафик там. Мне, по крайней мере, это кажется совершенно практичным и довольно простым способом справиться с этим.
Эван Андерсон
1

Я пытаюсь сделать что-то подобное, однако, если вы просто пытаетесь смоделировать нагрузку на сервер, я бы посмотрел на что-то вроде инфраструктуры нагрузочного тестирования. В прошлом я использовал locust.io, и он очень хорошо работал для имитации нагрузки на сервер. Это должно позволить вам смоделировать большое количество клиентов и позволить вам поиграть с конфигурацией сервера без необходимости проходить через болезненный процесс перенаправления трафика на другой сервер.

snowbirdSkiBum
источник
0

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

В случае коммутаторов Cisco Catalyst это называется SPAN (более подробная информация здесь ). В среде Cisco вы даже можете использовать зеркальный порт на другом коммутаторе.

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

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

Джеймс
источник
мы думали об этом, я читал об альтернативе использования SPAN. Но поскольку серверы расположены в центре обработки данных стороннего поставщика, у нас ограниченные возможности, когда дело доходит до изменений оборудования. Я уже просил подключить 2 сервера на второй ник напрямую. Это действие в сочетании с локальной сетью только для этих двух серверов позволило бы мне использовать IPTABLES с TEE. Но чтобы воспользоваться этой альтернативой, нам нужно изменить внешние IP-адреса серверов, что является NoGo, поскольку клиентские устройства настроены для подключения к заданному IP-адресу.
Сессия
0

Я также написал обратный прокси / балансировщик нагрузки для аналогичной цели с Node.js (это просто для удовольствия, пока не готово к производству).

https://github.com/losnir/ampel

Он очень самоуверенный и в настоящее время поддерживает:

  • GET Использование кругового выбора (1: 1)
  • POSTИспользуя разделение запросов. Понятий «мастер» и «тень» не существует - первым отвечающим является тот сервер, который будет обслуживать запрос клиента, а затем все остальные ответы будут отброшены.

Если кто-то находит это полезным, я могу улучшить его, чтобы сделать его более гибким.

losnir
источник
Node.js - это очень странный выбор языка для такого приложения, которое требует очень высокой производительности. Я не уверен, что это когда-нибудь будет готово к производству.
Майкл Хэмптон
Вы абсолютно правы. Это не было предназначено, чтобы быть очень производительным - просто легко написать (для меня). Я думаю, что это зависит от требуемой нагрузки. Я смог достичь чуть более 1000rps на младшей машине (2 ядра).
Лоснир
0

У моей компании было аналогичное требование: клонировать пакет и отправить его на другой хост (мы запускали симуляторы рыночных данных и нуждались во временном решении, которое прослушивало бы поток TCP рыночных данных, принимало каждый пакет, а также отправляло клон каждого пакета на другой симулятор). сервер)

этот бинарный файл работает очень хорошо, это версия TCP Duplicator, но написанная на golang вместо jscript, поэтому он работает быстрее и работает как рекламируется,

https://github.com/mkevac/goduplicator

perfecto25
источник
-1

есть инструмент, созданный парнем из китайской компании, и, возможно, это то, что вам нужно: https://github.com/session-replay-tools/tcpcopy

Musikoder
источник
2
Привет и добро пожаловать в serverfault. Можете ли вы дать более подробный ответ? Что именно делает программа? Это написано на C ...?
bgtvfr