Изолированная тестовая сеть на сервере Linux с веб-сервером (lightttpd) и (curl) клиентами
Я пишу инструмент тестирования, который требует, чтобы известный трафик собирался с сетевой карты (используя libpcap), а затем передавался в приложение, которое мы пытаемся протестировать.
Я пытаюсь настроить веб-сервер (в данном случае lighttpd) и клиент (curl), работающий на одной машине в изолированной тестовой сети. Сценарий будет управлять всей установкой, и цель состоит в том, чтобы иметь возможность указать количество клиентов, а также набор файлов для каждого клиента для загрузки с веб-сервера.
Мой первоначальный подход состоял в том, чтобы просто использовать интерфейс loopback (lo)... запустить веб-сервер на 127.0.0.1, чтобы клиенты извлекали свои файлы из http://127.0.0.1
и запустить мой инструмент на основе libpcap в интерфейсе lo. Это работает нормально, за исключением того факта, что петлевой интерфейс не эмулирует настоящий интерфейс Ethernet. Основная проблема заключается в том, что все пакеты имеют несовместимые размеры... 32 КБ и более, и несколько случайные... также невозможно уменьшить MTU на lo (ну, вы можете, но это не имеет никакого эффекта!).
Я также попытался запустить его на своем реальном интерфейсе (eth0), но, поскольку это внутренний веб-клиент, взаимодействующий с внутренним веб-сервером, трафик никогда не покидает интерфейс, поэтому libpcap никогда его не видит.
Итак, я повернулся к Tun/ Tap. Я использовал socat, чтобы связать два интерфейса tun вместе с tcp-соединением, так что у меня было:
10.0.1.1/24 <-> tun0 <-socat-> tcp connection <-socat-> tun1 <-> 10.0.2.1/24
Это похоже на действительно удачное решение... устройства tun/ tap эмулируют настоящие устройства Ethernet, поэтому я могу запустить свой веб-сервер на tun0 (10.0.1.1) и инструмент захвата на tun0 и привязать своих клиентов к tun1 (10.0.2.1)... я даже могу использовать tc, чтобы применить правила формирования трафика к этому трафику и создать виртуальную глобальную сеть внутри моего linux-бокса... но это просто не работает...
Вот команды socat, которые я использовал:
$ socat -d TCP-LISTEN:11443,reuseaddr TUN:10.0.1.1/24,up &
$ socat TCP:127.0.0.1:11443 TUN:10.0.2.1/24,up &
Который производит 2 интерфейса TUN (tun0
а также tun1
), с их соответствующими IP-адресами.
Если я бегу ping -I tun1 10.0.1.1
нет ответа, но когда я tcpdump -n -i tun0
Я вижу, что эхо-запросы ICMP направляются на другую сторону, просто нет признаков ответа.
# tcpdump -i tun0 -n
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tun0, link-type RAW (Raw IP), capture size 65535 bytes
16:49:16.772718 IP 10.0.2.1 > 10.0.1.1: ICMP echo request, id 4062, seq 5, length 64
<--- insert sound of crickets here (chirp, chirp)
Так что я упускаю что-то очевидное или это неправильный подход? Есть ли что-то еще, что я могу попробовать (например, 2 физических интерфейса, eth0 и eth1???).
Самый простой способ - это просто использовать 2 машины, но я хочу, чтобы все это было автономным, чтобы все это можно было создавать с помощью сценариев и автоматизировать на одной машине без каких-либо других зависимостей...
ОБНОВИТЬ:
Нет необходимости соединять 2 socat с tcp-соединением, это возможно (и предпочтительно для меня) сделать так:
socat TUN:10.0.1.1/24,up TUN:10.0.2.1/24,up &
Та же проблема все еще существует, хотя...
1 ответ
Итак, я нашел решение, используя сетевые пространства имен Linux (netns). Здесь есть полезная статья о том, как ее использовать: http://code.google.com/p/coreemu/wiki/Namespaces
Это то, что я сделал для моей настройки....
Сначала загрузите и установите CORE: http://cs.itd.nrl.navy.mil/work/core/index.php
Далее запустите этот скрипт:
#!/bin/sh
core-cleanup.sh > /dev/null 2>&1
ip link set vbridge down > /dev/null 2>&1
brctl delbr vbridge > /dev/null 2>&1
# create a server node namespace container - node 0
vnoded -c /tmp/n0.ctl -l /tmp/n0.log -p /tmp/n0.pid > /dev/null
# create a virtual Ethernet (veth) pair, installing one end into node 0
ip link add name veth0 type veth peer name n0.0
ip link set n0.0 netns `cat /tmp/n0.pid`
vcmd -c /tmp/n0.ctl -- ip link set n0.0 name eth0
vcmd -c /tmp/n0.ctl -- ifconfig eth0 10.0.0.1/24 up
# start web server on node 0
vcmd -I -c /tmp/n0.ctl -- lighttpd -f /etc/lighttpd/lighttpd.conf
# create client node namespace container - node 1
vnoded -c /tmp/n1.ctl -l /tmp/n1.log -p /tmp/n1.pid > /dev/null
# create a virtual Ethernet (veth) pair, installing one end into node 1
ip link add name veth1 type veth peer name n1.0
ip link set n1.0 netns `cat /tmp/n1.pid`
vcmd -c /tmp/n1.ctl -- ip link set n1.0 name eth0
vcmd -c /tmp/n1.ctl -- ifconfig eth0 10.0.0.2/24 up
# bridge together nodes using the other end of each veth pair
brctl addbr vbridge
brctl setfd vbridge 0
brctl addif vbridge veth0
brctl addif vbridge veth1
ip link set veth0 up
ip link set veth1 up
ip link set vbridge up
Это в основном устанавливает 2 виртуальные / изолированные / именованные сети на вашем хосте Linux, в данном случае, узел 0 и узел 1. Веб-сервер запускается на узле 0.
Все, что вам нужно сделать сейчас, это запустить curl на узле 1:
vcmd -c /tmp/n1.ctl -- curl --output /dev/null http://10.0.0.1
И отслеживать трафик с помощью tcpdump:
tcpdump -s 1514 -i veth0 -n
Кажется, это работает очень хорошо... все еще экспериментирует, но похоже, что это решит мою проблему.