Rede de teste isolada em um servidor Linux executando um servidor web (lightttpd) e clientes (curl)

StackOverflow https://stackoverflow.com//questions/12671587

Pergunta

Estou escrevendo uma ferramenta de teste que requer que o tráfego conhecido seja capturado de uma NIC (usando libpcap) e depois inserido no aplicativo que estamos tentando testar.

O que estou tentando configurar é um servidor web (neste caso, lighttpd) e um cliente (curl) rodando na mesma máquina, em uma rede de teste isolada.Um script conduzirá toda a configuração, e o objetivo é ser capaz de especificar um número de clientes, bem como um conjunto de arquivos para cada cliente baixar do servidor web.

Minha abordagem inicial foi simplesmente usar a interface loopback (lo)...execute o servidor web em 127.0.0.1, faça com que os clientes busquem seus arquivos http://127.0.0.1, e execute minha ferramenta baseada em libpcap na interface lo.Isso funciona bem, exceto pelo fato de a interface de loopback não emular uma interface Ethernet real.O principal problema com isso é que os pacotes são todos de tamanhos inconsistentes...32kbytes e maiores, e um tanto aleatórios...também não é possível diminuir o MTU em lo (bem, você pode, mas não tem efeito!).

Também tentei executá-lo em minha interface real (eth0), mas como é um cliente web interno conversando com um servidor web interno, o tráfego nunca sai da interface, então o libpcap nunca o vê.

Então mudei para tun/tap.Usei socat para vincular duas interfaces tun a uma conexão tcp, então, na verdade, tive:

10.0.1.1/24 <-> tun0 <-socat-> tcp connection <-socat-> tun1 <-> 10.0.2.1/24

Esta parece ser uma solução muito legal ...dispositivos tun/tap emulam dispositivos Ethernet reais, para que eu possa executar meu servidor web em tun0 (10.0.1.1) e minha ferramenta de captura em tun0, e vincular meus clientes a tun1 (10.0.2.1)...Posso até usar tc para aplicar regras de modelagem a esse tráfego e criar uma WAN virtual dentro da minha caixa Linux...mas simplesmente não funciona...

Aqui estão os comandos socat que usei:

$ 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 &

Que produz 2 interfaces tun (tun0 e tun1), com seus respectivos endereços IP.

Se eu correr ping -I tun1 10.0.1.1, não há resposta, mas quando eu tcpdump -n -i tun0, vejo as solicitações de eco ICMP chegando ao outro lado, mas nenhum sinal de resposta voltando.

# 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)

Então, estou perdendo algo óbvio ou essa é a abordagem errada?Há algo mais que eu possa tentar (por exemplo2 interfaces físicas, eth0 e eth1???).

A maneira mais fácil é usar apenas 2 máquinas, mas eu quero tudo isso independente, para que tudo possa ser programado e automatizado em uma única máquina, sem outras dependências...

ATUALIZAR:

Não há necessidade de os 2 socats estarem conectados com uma conexão tcp, é possível (e preferível para mim) fazer isso:

socat TUN:10.0.1.1/24,up TUN:10.0.2.1/24,up &

O mesmo problema ainda existe ...

Foi útil?

Solução

OK, encontrei uma solução usando namespaces de rede Linux (netns).Há um artigo útil sobre como usá-lo aqui: http://code.google.com/p/coreemu/wiki/Namespaces

Isso é o que fiz para minha configuração....

Primeiro, baixe e instale o CORE: http://cs.itd.nrl.navy.mil/work/core/index.php

Em seguida, execute este script:

#!/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

Isso basicamente configura 2 redes virtuais/isoladas/com espaçamento de nomes em seu host Linux, neste caso, nó 0 e nó 1.Um servidor web é iniciado no nó 0.

Tudo que você precisa fazer agora é executar curl no nó 1:

vcmd -c /tmp/n1.ctl -- curl --output /dev/null http://10.0.0.1

E monitore o tráfego com tcpdump:

tcpdump -s 1514 -i veth0 -n

Isso parece funcionar muito bem ...ainda estou experimentando, mas parece que vai resolver meu problema.

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top