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

Рисунок 1. Обзор архитектуры TCPCopy.
Как показано на рисунке 1, TCPCopy состоит из двух компонентов: tcpcopy и intercept. Компонент tcpcopy работает на онлайн-сервере, захватывая живые запросы, в то время как intercept работает на вспомогательном сервере, выполняя такие задачи, как передача информации об ответах обратно в tcpcopy. Само тестовое приложение работает на целевом сервере.
По умолчанию tcpcopy использует raw-сокеты для захвата пакетов на сетевом уровне (изображены оранжевыми стрелками на рисунке). Он обрабатывает такие процессы, как симуляция TCP-взаимодействия, управление задержками в сети и симуляция взаимодействия на верхних уровнях. Затем он отправляет пакеты на целевой сервер с помощью raw-сокетов (показаны светло-красными стрелками на рисунке).
Единственная необходимая задача на целевом сервере — настройка правил маршрутизации для направления ответных пакетов (показаны светло-зелёными стрелками на рисунке) на вспомогательный сервер.
Роль компонента intercept заключается в пересылке заголовка ответа (по умолчанию) обратно в tcpcopy. Он захватывает ответные пакеты, извлекает информацию заголовка ответа и отправляет эту информацию в tcpcopy через выделенный канал (обозначен голубыми стрелками на рисунке). Получив заголовок ответа, tcpcopy использует эту информацию для изменения атрибутов онлайн-пакетов и продолжает отправлять последующие пакеты.
Важно отметить, что ответы с целевого сервера направляются на вспомогательный сервер, который работает как чёрная дыра.
Для intercept у вас есть два варианта:
git clone git://github.com/session-replay-tools/intercept.git.Для tcpcopy у вас также есть два варианта:
git clone git://github.com/session-replay-tools/tcpcopy.git.intercept:cd intercept./configure makeintercept:make installintercept--single
Запустить intercept в нераспределённом режиме.
--with-pfring=PATH
Укажите путь к исходникам библиотеки PF_RING.
--with-debug
Скомпилировать intercept с поддержкой отладки, логи сохраняются в файл.
tcpcopy на онлайн-сервереtcpcopy: cd tcpcopy./configure maketcpcopy: make installtcpcopy--offline
Воспроизвести TCP-потоки из pcap-файла.
--pcap-capture
Захватывать пакеты на канальном уровне.
--pcap-send
Отправлять пакеты на канальном уровне вместо IP-уровня.
--with-pfring=PATH
Укажите путь к исходникам библиотеки PF_RING.
--set-protocol-module=PATH
Настроить tcpcopy на работу с внешним модулем протокола.
--single
Если и intercept, и tcpcopy сконфигурированы с опцией --single, только один экземпляр tcpcopy будет работать с intercept, что повышает производительность.
Предположим, что и tcpcopy, и intercept сконфигурированы с помощью ./configure.
На целевом сервере, где работают серверные приложения:
Настройте правила маршрутизации, чтобы направлять ответные пакеты на вспомогательный сервер. Например, если 61.135.233.161 — это IP-адрес вспомогательного сервера, используйте следующую команду маршрутизации, чтобы направить все ответы от клиентов из диапазона 62.135.200.x на вспомогательный сервер:
route add -net 62.135.200.0 netmask 255.255.255.0 gw 61.135.233.161
На вспомогательном сервере, где запущен intercept (требуется root-права или возможность CAP_NET_RAW):
./intercept -F <filter> -i <device>
Обратите внимание, что формат фильтра такой же, как у pcap-фильтра. Например:
./intercept -i eth0 -F 'tcp and src port 8080' -d
В этом примере intercept будет захватывать ответные пакеты от TCP-приложения, слушающего порт 8080, используя сетевое устройство eth0.
Пожалуйста, учтите, что ip_forward не включён на вспомогательном сервере.
На исходном онлайн-сервере (требуется root-права или возможность CAP_NET_RAW):
./tcpcopy -x localServerPort-targetServerIP:targetServerPort -s <intercept server> [-c <ip range>]
CAP_NET_RAW (например, setcap CAP_NET_RAW=ep tcpcopy)../configure --with-resp-payload для intercept не может использоваться вместе с опцией ./configure для tcpcopy.ip_forward не включён на вспомогательном сервере../tcpcopy -h или .Несколько факторов могут влиять на TCPCopy, как подробно описано в следующих разделах.
По умолчанию tcpcopy использует интерфейс raw-сокета для захвата пакетов на сетевом уровне на онлайн-сервере. При высокой нагрузке ядро системы может отбрасывать некоторые пакеты.
Если настроено с --pcap-capture, tcpcopy захватывает пакеты на канальном уровне и может фильтровать пакеты в ядре. Использование PF_RING с захватом pcap может уменьшить потерю пакетов.
Для оптимального захвата рассмотрите возможность зеркалирования входящих пакетов через коммутатор и распределения трафика между несколькими машинами с помощью балансировщика нагрузки.
tcpcopy по умолчанию использует интерфейс raw-сокета для отправки пакетов на сетевом уровне на целевой сервер. Чтобы избежать проблем с ip_conntrack или повысить производительность, используйте --pcap-send для отправки пакетов на канальном уровне.
Пакеты, отправленные tcpcopy, могут столкнуться с проблемами до достижения целевого сервера. Если исходный IP-адрес является IP конечного пользователя (по умолчанию), устройства безопасности могут отбрасывать пакет как недействительный или поддельный. Чтобы проверить это, используйте tcpdump на целевом сервере. Если пакеты успешно отправляются в пределах одного сегмента сети, но не между сегментами, возможно, пакеты отбрасываются на полпути.
Чтобы решить эту проблему, разверните tcpcopy, целевые приложения и intercept в одном сегменте сети. Альтернативно, используйте прокси в том же сегменте для пересылки пакетов на целевой сервер в другом сегменте.
Развёртывание приложения целевого сервера на виртуальной машине в том же сегменте всё ещё может вызывать эти проблемы.
Целевой сервер может использовать rpfilter для проверки легитимности исходных IP-адресов, отбрасывая пакеты, считающиеся поддельными. Если пакеты захватываются tcpdump, но не обрабатываются, проверьте настройки rpfilter и при необходимости измените или удалите их. Другие проблемы, такие как настройки iptables, также могут влиять на tcpcopy.
Приложения на целевом сервере могут не обрабатывать все запросы своевременно. Ошибки или ограничения в приложении могут привести к задержкам ответов или необработанным запросам в буфере сокета.
Убедитесь, что ip_forward отключён на вспомогательном сервере, чтобы предотвратить маршрутизацию пакетов и обеспечить его работу как чёрной дыры.
Сначала используйте telnet на онлайн-сервере для подключения к порту тестового сервера. Это проверит доступность сетевого пути. Если соединение не удаётся, решите эту проблему, прежде чем переходить к следующей диагностике.
Предположим, что во время теста с tcpcopy приложение на тестовом сервере не получает никаких запросов. Определите, достигает ли начальный пакет рукопожатия (т.е. SYN-пакет) тестового сервера.
1.1 Захвачены только SYN-пакеты:
Если вы используете tcpdump на тестовом сервере и видите, что реплицированные SYN-пакеты приходят, это указывает, что они достигли канального уровня тестового сервера. Если netstat не показывает соединений для приложения, значит пакеты были отброшены на IP-уровне. Проверьте, настроен ли rpfilter — если да, удалите эту настройку, и проблема обычно решается. Если rpfilter не настроен, убедитесь, что нет конфликтов в настройках iptables и при необходимости скорректируйте соответствующие правила.
1.2 За SYN следует RST-пакет: Если за SYN-пакетом сразу следует пакет сброса (RST) (с интервалом менее 1 секунды в одной сессии), это указывает на проблему маршрутизации или конфликт, из-за которого ответный пакет отправляется напрямую реальному клиенту.
1.3 Тестовый сервер отвечает вторым пакетом рукопожатия: Захватите пакеты на вспомогательном сервере, чтобы проверить, достиг ли его второй пакет рукопожатия.
Если пакет не достиг вспомогательного сервера, это говорит о том, что настройка маршрутизации неэффективна, и поэтому intercept не может захватить второй пакет рукопожатия, что препятствует дальнейшему воспроизведению. Возможное решение — запустить intercept непосредственно на тестовом сервере (примечание: оставьте настройку маршрутизации без изменений и убедитесь, что параметр -c в tcpcopy не установлен на IP-адрес, который tcpcopy использует для подключения к intercept, иначе tcpcopy не сможет подключиться к intercept).
Если второй пакет рукопожатия захвачен, проверьте, включён ли ip_forward. Если да, отключите эту настройку, так как она может привести к отправке ответных пакетов напрямую клиенту, что помешает тесту.
2.1 Пакеты tcpcopy захвачены на онлайн-сервере:
Если вы захватываете перенаправленные пакеты tcpcopy с помощью tcpdump на онлайн-сервере, но пакеты не достигают тестового сервера, это указывает, что они были отброшены по пути. Попробуйте использовать параметр -c в tcpcopy, чтобы изменить IP-адрес клиента на допустимый. В крайнем случае установите IP клиента равным IP-адресу машины, на которой запущен tcpcopy (примечание: могут возникнуть проблемы с NAT, и если intercept работает на тестовом сервере, убедитесь, что параметр -c в tcpcopy не установлен на IP-адрес, который tcpcopy использует для подключения к intercept, иначе tcpcopy не сможет подключиться к intercept).
2.2 Пакеты tcpcopy не захвачены на онлайн-сервере:
Если в логе tcpcopy не найдена информация all clt:xx, это указывает, что tcpcopy не может захватывать пакеты на IP-уровне. В этом случае используйте опцию --pcap-capture для захвата пакетов на канальном уровне. Установите параметр -F (например, 'tcp and dst port 80 and dst host 10.100.1.2') и параметр -i (сетевой интерфейс), чтобы обойти захват на IP-уровне.
Если в логе tcpcopy видно all clt:xx, где xx > 0, это означает, что tcpcopy успешно захватил пакет, но он был отфильтрован IP-уровнем на онлайн-сервере. Проверьте ограничения iptables на выходной цепочке и другие настройки. Если проблема в iptables и её нельзя изменить на онлайн-сервере, используйте опцию --pcap-send для отправки пакетов с канального уровня.
Обнаружили ошибку или хотите запросить функцию? Пожалуйста, откройте новый issue. Перед созданием issue поищите существующие.
Если этот проект оказался полезным, подумайте о пожертвовании:
Copyright 2025 по лицензии BSD.
Несколько человек внесли важный вклад в написание этого документа, просматривая черновики и предоставляя отзывы. Я особенно благодарен за вклад Hongshen Wang.
--with-tcmalloc
Использовать tcmalloc вместо malloc.
--with-debug
Скомпилировать tcpcopy с поддержкой отладки, логи сохраняются в файл.
Например (предположим, что 61.135.233.160 — это IP-адрес целевого сервера):
./tcpcopy -x 80-61.135.233.160:8080 -s 61.135.233.161 -c 62.135.200.x
В этом примере tcpcopy захватывает пакеты на порту 80 с текущего сервера, изменяет IP-адрес клиента на один из диапазона 62.135.200.x и отправляет эти пакеты на порт 8080 целевого сервера (61.135.233.160). Он также подключается к 61.135.233.161, чтобы запросить intercept пересылать ответные пакеты. Параметр -c необязателен, но здесь используется для упрощения правил маршрутизации.
./intercept -h