Як дублювати трафік TCP на одному або декількох віддалених серверах для цілей порівняння?


30

Інфраструктура: Сервери в Центрі обробки даних, ОС - Debian Squeeze, Веб-сервер - Apache 2.2.16


Ситуація:

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


Питання: Як можна реалізувати це дублювання на одному або декількох віддалених серверах?

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

  • копіювач agnoster - для цього потрібен один відкритий сеанс на порт, який не застосовується. ( https://github.com/agnoster/duplicator )
  • kklis proxy - передає трафік лише на віддалений сервер, але не передає його на веб-сервер 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-адресу (яка знаходиться в одній мережі) і призначили її et0: 0 (первинна IP-адреса призначена eth0). Не вдалося поєднати цей новий IP або віртуальний інтерфейс eth0: 0 з функцією iptables TEE або маршрутами.
  • запропоновані альтернативи, передбачені питанням "дублювати вхідний трафік tcp на debian сціснути" ( Дублікат вхідного трафіку TCP на Debian Squeeze ), не вдалися. Сеанси кота | nc (cat / tmp / prodpipe | nc 127.0.0.1 12345 та cat / tmp / testpipe | nc 127.0.0.1 23456) перериваються після кожного запиту / підключення клієнтом без будь-якого повідомлення або журналу. Кіпалів не змінив цю ситуацію. Пакети TCP не транспортувалися у віддалену систему.
  • Додаткові спроби з різними параметрами socat (HowTo: http://www.cyberciti.biz/faq/linux-unix-tcp-port-forwarding/ , /programming/9024227/duplicate-input- unix-stream-to-multiple-tcp-client-using-socat ) та подібні інструменти були невдалими, оскільки надана TEE функція запише лише в FS.
  • Звичайно, невдало також і гуглінг, і пошук цієї "проблеми" чи налаштування.

Тут у нас не вистачає варіантів.

Чи існує спосіб відключення виконання "сервера в локальній мережі" функції TEE при використанні IPTABLES?

Чи можна досягти нашої мети за рахунок різного використання IPTABLES або маршрутів?

Чи знаєте ви інший інструмент для цієї мети, який був випробуваний і працює в цих конкретних обставинах?

Чи є інше джерело для 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: віддалений порт сервера призначення
та параметри повернення


Чи весь трафік HTTP?
longneck

так, увесь трафік становить HTTP.
Sise

1
btw. teeproxy доступний тут: github.com/chrislusf/teeproxy
Tombart

1
Інша можливість: github.com/ebowman/splitter Scala / Netty.
Річ К.

Відповіді:


11

Це неможливо. TCP - це повний протокол. Комп'ютер із кінцевим користувачем бере участь у кожному кроці з'єднання, і він ніколи не відповість двом окремим серверам, які намагаються зв’язатися з ним. Все, що ви можете зробити - це зібрати весь http-запит на веб-сервері чи якомусь проксі-сервері та повторно їх відтворити. Але це не дасть і точної сумісності або умов трафіку на реальному сервері.


Скопіювати TCP неможливо - я згоден з цим. Дублювання трафіку рівня 7 не є. Ви можете захоплювати запити від клієнта і відтворювати їх на інших серверах. Простий 1 запит на відтворення сеансу TCP повинен бути досить простим. Постійні зв’язки потребують певної думки, наскільки час ви додаткові запити клієнта.
Еван Андерсон

@Kazimieras Aliulis: не потрібно спілкуватися з двома окремими серверами. клієнт спілкується з первинним сервером = живим сервером. сервер в реальному часі обробляє запити клієнта і відповідає клієнту. окрім обробки та відповіді клієнту, основний сервер - це дублювання запитів на другий сервер = тестуючий сервер. відповіді з другого сервера на первинний сервер будуть відкинуті / проігноровані на первинному сервері і не будуть передані клієнту.
Sise

@Evan Anderson: дублювання на рівні HTTP також було нашою першою ідеєю, але, наприклад, proche proxy або подібні інструменти або модулі не дозволяють одночасно обробляти запити локально і дублювати його на віддалений хост. якщо у вас є якась інша ідея, будь ласка поради! :) Ми віддаємо перевагу дублювання під час запису та відтворення, щоб отримати миттєві результати порівняння.
Sise

1
@Sise: ви можете спробувати написати власний http-проксі, який передає трафік на два сервери. Це можна зробити досить легко з python Twisted Framework twistedmatrix.com .
Казімір Аліуліс

@Kazimieras Aliulis: це, безумовно, альтернатива! я ніколи про це не чув. але перевірка цього показує, що він би цілком відповідав нашому призначенню. Раніше ми не розглядали python, але зараз ми розглядаємо Twisted фреймворк та можливості із загальним python. Я звітну, якщо нам це вдасться!
Sise

20

З того, що ви описуєте, GOR, здається, відповідає вашим потребам. https://github.com/buger/gor/ "Повторне відтворення трафіку HTTP в режимі реального часу. Відтворення трафіку від виробничого до стаціонарного та розробленого середовищ." ?


2
Це саме те , що я шукав, велике спасибі, ви врятували мене, написавши саме це, у Go! :-)
chmac

nginx має дзеркальний модуль. nginx.org/en/docs/http/ngx_http_mirror_module.html
Jimmy MG Lim

7

Teeproxy може використовуватися для реплікації трафіку. Використання дуже просто:

./teeproxy -l :80 -a localhost:9000 -b localhost:9001
  • a сервер виробництва
  • b тестуючий сервер

Якщо ви поставите HAproxy (з roundrobin) перед веб-сервером, ви зможете легко перенаправити 50% вашого трафіку на тестуючий сайт:

         /------------------> production
HAproxy /                 ^
        \                /
         \---- teeproxy -.....> test (responses ignored)

4

Як зазначає @KazimierasAliulis, TCP, будучи протоколом, що охоплює ситуацію, не піддається просто вибуху копій пакетів на іншому хості.

Підбір пакетів на рівні завершення TCP та ретрансляція їх як нового потоку TCP є розумним. Інструмент дублювання, з яким ви пов’язали, виглядає як найкраща ставка. Він працює як проксі-сервер TCP, що дозволяє машині стану TCP працювати належним чином. Відповіді ваших тестових машин будуть просто відкинуті. Це звучить так, що відповідає рахунку за те, що ви точно хочете.

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

Якщо додатки, які ви протестуєте, не є брудними, я думаю, що у вас виникнуть проблеми з цією методологією тестування, що стосується термінів і стану внутрішнього застосування. Те, що ви хочете зробити, звучить оманливо просто - Я очікую, що ви знайдете безліч крайових справ.


так, ви абсолютно праві, інструмент копіювання agnoster відповідав би нашим вимогам, за винятком ситуації з кількома портами. Також відхилення відповідей випробувальної машини заповнене. Щоб досягти нашої мети максимально точно змоделювати реальну / живу ситуацію, ми не зможемо зв’язати всі порти на живому сервері до одного порту на тестовій машині. Для поділу клієнтських пристроїв на різних клієнтів використовуються різні порти. Таким чином, ми повинні відкрити 60-70 сеансів цього інструменту копіювання. Це не дуже практично, як ви можете собі уявити.
Sise

@Sise - Комп’ютери добре роблять нудні речі. Я думаю, ви можете написати сценарій, щоб проаналізувати свої конфігурації Apache і виплюнути необхідні командні рядки для запуску 60 - 70 екземплярів інструменту копіювання. Я не можу уявити, що інструмент дублювання дуже ресурсомісткий, але, навіть якби він був, ви можете запустити ці 60 - 70 екземплярів на іншій машині та зробити деякі мережеві хитрощі, щоб отримати там трафік. Принаймні, мені це здається абсолютно практичним і досить простим способом вирішити це.
Еван Андерсон

1

Я намагаюся зробити щось подібне, однак, якщо ви просто намагаєтеся імітувати навантаження на сервер, я би розглядав щось на зразок навантажувальної системи. Раніше я використовував locust.io, і він дуже добре працював для імітації навантаження на сервер. Це повинно дозволяти вам імітувати велику кількість клієнтів і дозволяти вам грати з конфігурацією сервера без необхідності проходити через болісний процес переадресації трафіку на інший сервер.


0

Що стосується "ми б хотіли дублювати вхідний трафік HTTP на прямому сервері на один або декілька віддалених серверів у режимі реального часу", існує один із способів, про який не було сказано вище, - це налаштування дзеркального порту на комутаторі, до якого він підключений.

У випадку комутаторів Cisco Catalyst це називається SPAN (більше інформації тут ). У середовищі Cisco ви навіть можете мати дзеркальний порт на іншому комутаторі.

Але мета цього полягає в аналізі трафіку, тому він буде однонаправленим - ключове слово в цитованому тексті в першому пункті вище: вхідне . Я не думаю, що порт дозволить дозволити будь-який зворотний трафік, і якби це було, як би ви попрацювали з повторюваним зворотним трафіком? Це, ймовірно, просто спричинить хаос у вашій мережі.

Отже ... просто хотів додати до свого списку одну можливість, але з застереженням, що це дійсно буде для руху в одну сторону. Можливо, ви можете поставити концентратор на цей дзеркальний порт і мати дублікати відповідей сервера, які передає якийсь локальний клієнтський симулятор, який би підбирав ініційовані сеанси та відповідав на них, але тоді ви б дублювали вхідний трафік на свій дублікат сервера ... напевно, не те, що ви хочу.


ми думали про це, я читав про альтернативу використання SPAN. Але оскільки сервери розташовані в центрі обробки даних сторонніх постачальників, ми маємо обмежені можливості, коли мова йде про апаратні зміни. Я вже просив підключити 2 сервери на другому ніці безпосередньо. Ця дія в поєднанні з локальною мережею лише для цих двох серверів дозволить мені використовувати IPTABLES з TEE. Але для досягнення цієї альтернативи нам знадобиться змінити зовнішні IP-адреси серверів, що є NoGo, оскільки клієнтські пристрої налаштовані для підключення до встановленого IP.
Sise

0

Я також написав зворотний проксі / балансир завантаження для подібної мети з Node.js (це просто для задоволення, а не виробництво готове на даний момент).

https://github.com/losnir/ampel

Він дуже впевнений, і на даний момент підтримує:

  • GET Використання круглобільного вибору (1: 1)
  • POSTВикористання розділення запиту. Немає поняття "майстер" і "тінь" - перший бекенд, який відповідає, це той, який буде обслуговувати запит клієнта, а потім усі інші відповіді будуть відкинуті.

Якщо хтось вважає це корисним, я можу вдосконалити його, щоб бути більш гнучким.


Node.js - це дуже дивний вибір мови для такого додатка, який вимагає дуже високої продуктивності. Я не впевнений, що це колись буде готове виробництво.
Майкл Хемптон

Ти абсолютно правий. Це не мало бути високоефективним - просто легко написати (для мене). Я думаю, це залежить від необхідного навантаження. Мені вдалося досягти трохи більше 1000 об. / С. На низькому кінці машини (2 ядра).
losnir

0

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

цей бінарний файл працює дуже добре, його версія TCP Duplicator, але написана в голанг замість jscript, тому його шлях швидше, і працює як рекламується,

https://github.com/mkevac/goduplicator


-1

є інструмент, створений хлопцем з китайської компанії, і, можливо, це те, що вам потрібно: https://github.com/session-replay-tools/tcpcopy


2
Привіт, ласкаво просимо до сервера за замовчуванням. Чи можете ви надати більш детальну відповідь? Що саме робить програма? Це написано на С ...?
bgtvfr
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.