Eu sou um novato total, esta é minha primeira experiência com redes de kernel. Estou tentando criar uma ponte entre duas tap
interfaces e tentar enviar tráfego. É mais um experimento do que qualquer propósito específico.
$ brctl showstp br0
br0
bridge id 8000.46846e0c0ff9
designated root 8000.46846e0c0ff9
root port 0 path cost 0
max age 20.00 bridge max age 20.00
hello time 2.00 bridge hello time 2.00
forward delay 15.00 bridge forward delay 15.00
ageing time 300.00
hello timer 1.98 tcn timer 0.00
topology change timer 0.00 gc timer 115.04
flags
tap1 (1)
port id 8001 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8001 forward delay timer 10.34
designated cost 0 hold timer 0.98
flags
tap2 (2)
port id 8002 state forwarding
designated root 8000.46846e0c0ff9 path cost 100
designated bridge 8000.46846e0c0ff9 message age timer 0.00
designated port 8002 forward delay timer 0.00
designated cost 0 hold timer 0.98
flags
Eu tenho a ponte br0
criada, com ambos tap1
e tap2
adicionada. Eu tenho um programa que injeta pacotes ARP tap1
usando o libpcap
. O Wireshark mostra corretamente os pacotes que entram tap1
. No entanto, nenhum pacote aparece em tap2
. Tentei adicionar a seguinte regra em ebtables:
sudo ebtables -I INPUT --log --log-level debug
Nenhum pacote aparece nos logs. Agradeço qualquer contribuição.
EDIT: Adicionando mais informações. Injetar pacotes falsos é de fato a aplicação. Minha intenção aqui é simular, totalmente em software e sem VMs, como os pacotes são encaminhados através da pilha do kernel do Linux. Não estou criando novos namespaces de rede. Talvez seja esse o problema?
Eu só tenho dois processos. O processo de "leitura" possui um descritor de arquivo aberto tap2
e tenta lê-lo constantemente. O processo de gravação tem um descritor de arquivo aberto tap1
e aguarda o prompt do usuário para enviar a consulta ARP. A consulta ARP possui um endereço IP de origem aleatório. O endereço MAC de origem é definido como o endereço MAC de tap1
. Aqui está a saída do tcpdump:
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on tap1, link-type EN10MB (Ethernet), capture size 262144 bytes
^[[A07:19:57.752990 ARP, Request who-has google-public-dns-a.google.com tell 0.0.248.17, length 28
0x0000: ffff ffff ffff ba9c 0589 16ad 0806 0001
0x0010: 0800 0604 0001 ba9c 0589 16ad 0000 f811
0x0020: 0000 0000 0000 0808 0808
Configurei tap1
e tap2
não tenho endereços IP. Esse poderia ser o problema?
brctl addbr br0
ip tuntap add name tap1 mode tap
ip tuntap add name tap2 mode tap
brctl addif br0 tap1
brctl addif br0 tap2
ifconfig tap1 0.0.0.0 up
ifconfig tap2 0.0.0.0 up
ifconfig br0 10.0.1.1 netmask 255.255.255.0 broadcast 10.0.1.255
ip link set br0 up
ip link set tap1 up
ip link set tap2 up
Com base na resposta, verifiquei anexar vários aplicativos ao tap2
. Percebo o seguinte: quando nenhum aplicativo está usando tap1
or tap2
, ambas as interfaces não têm o sinalizador LOWER_UP definido.
4: br0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <NO-CARRIER,BROADCAST,MULTICAST,PROMISC,UP> mtu 1500 qdisc pfifo_fast master br0 state DOWN mode DEFAULT group default qlen 500
Quando inicio os aplicativos, o sinalizador LOWER_UP fica definido:
4: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP mode DEFAULT group default
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
25: tap1: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether ba:9c:05:89:16:ad brd ff:ff:ff:ff:ff:ff
26: tap2: <BROADCAST,MULTICAST,PROMISC,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP mode DEFAULT group default qlen 500
link/ether 46:84:6e:0c:0f:f9 brd ff:ff:ff:ff:ff:ff
Lamento que isso esteja sendo demorado, só espero que haja informações suficientes para entender o problema.
Responder1
Por precaução, porque você disse que é um novato total: uma interface tun (camada 3) ou tap (camada 2) é o ponto final da interface de rede de um aplicativo, e o aplicativo pode ler e gravar pacotes dessa interface de rede. O que você cria ip tuntap add ...
ou o que está desatualizado tunctl
énomes persistentespara esses endpoints, e normalmente você ainda executará o aplicativo, e ele não fará nada a menos que você execute o aplicativo.
Como o aplicativo interage com a interface de rede por uma questão de design, não há necessidade de "injetar" pacotes com um aplicativo de terceiros, a menos que você queira dizer com "injetar" essa interação normal que descrevi.
Além disso, se você quiser brincar com redes, recomendo usarnamespaces de redeeveth pares. Basicamente, você pode configurar vários computadores virtuais em seu computador que podem imitar a comunicação entre computadores reais em uma rede.
Então, se você quiser fazer isso e não quiser brincar com seu próprio aplicativo criando e recebendo pacotes, você não precisa de uma interface tun/tap.
Dito isso, acabei de testar sua configuração, com uma pequena variação porque você não disse o que usa para "injetar" pacotes: usei dois socat
s para criar para tocar no endpoint tap0a
e tap1a
, depois fiz uma ponte entre eles e usei outros dois socat
s em dois namespaces diferentes para criar os pacotes corretos para mim. Eles precisam estar em um namespace diferente, pois os pacotes locais sempre serão entregues via loopback lo
.
E, como esperado, os dispositivos de ponte funcionam perfeitamente.
Então suponho que o problema esteja no pacote que você está injetando: endereço Ethernet errado ou nenhuma transmissão. Edite sua pergunta com tcpdump -xx ...
saída ao injetar o pacote ARP.
Ou possivelmente você gostaria de criar namespaces de rede e conectar dois pontos de extremidade de dois pares veth? Isso é muito mais simples.
Editar
O pacote ARP parece bom. Parece que não há nenhum aplicativo conectado ao tap2
. Se você fizer isso ip link
, não deverá ver um LOWER_UP
sinalizador para tap2
. Adivinha: A ponte detecta que o dispositivo está apenas parcialmente ativo e não envia pacotes para esta porta.
Tente substituí-lo por um tap
quetemum aplicativo conectado a ele, algo como
sudo socat TUN:10.0.2.2/24,tun-name=tapx,tun-type=tap,iff-up - | hexdump -C
(o 10.0.2.2/24
endereço não faz nada, mas socat
não funcionará se você não especificar um endereço) e em outro terminal
sudo ip link set tapx master br0
(que substitui brctl addif
), injete seu pacote várias vezes e veja se você obtém um hexdump na primeira janela. Verifique também LOWER_UP
com ip link show dev tapx
.
Aliás, ifconfig
e brctl
estão desatualizados. Use ip
e bridge
em vez disso.
Não atribuir endereços IP às portas da ponte não importa, porque as portas da pontenão tenho endereços IP(se alguns deles forem atribuídos a eles antes de serem escravizados por uma ponte, eles serão ignorados). Veja, por exemploaqui.
Responder2
Lutei muito com isso e acho que cheguei a uma solução. Ou, pelo menos, uma melhor compreensão do que está acontecendo.
É importante ter em mente que a única maneira de entregar um pacote a uma interface tap no lado de recepção ("RX") é escrevendo esse pacote no descritor de soquetecriado pelo processo que abriu a torneira(através de open("/dev/net/tun",...)
e ioctl
). Apenas um processo pode ter esse descritor de arquivo por vez. Se um dispositivo de toque estiver aberto e outro processo tentar reabrir outro dispositivo de toque com o mesmo nome, essa chamada de sistema falhará.
Então, quando você tiver qualquer outro processo, como wireshark, abrindo um soquete bruto e depois ligandoquepara tap0
, ele só é capaz de gravar tráfegoforado sistema (da perspectiva do kernel). Ou seja, o wireshark deve bater no TX
contador tap0
e apenas RX
os pacotes serão encaminhados para a interface em ponte.
Você pode verificar os contadores de cada um, como:
#!/bin/bash
for if in tap{0,1}; do
stats=/sys/class/net/$if/statistics/
rx=$(cat $stats/rx_packets)
tx=$(cat $stats/tx_packets)
echo "$if: rx=$rx, tx=$tx"
done
que gera algo como:
tap0: rx=0, tx=6
tap1: rx=0, tx=5
Então, no seu caso específico, suspeito que o problema esteja aqui:
Eu tenho um programa que injeta
ARP
pacotestap1
usando libpcap. O Wireshark mostra corretamente os pacotes que entramtap1
. No entanto, nenhum pacote aparece emtap2
.
Como você está injetando pacotes ARP no tap1? Presumo que o wireshark não esteja ligando fd = open("/dev/net/tun", ...)
e ioctl(fd, TUNSETIFF, ...)
, portanto, os pacotes enviados serão TX e, portanto, não serão interligados.
Você precisará do programa que é aberto tap0
para gravar pacotes no tap0
descritor de arquivo de para que esses pacotes sejam encaminhados br0
e exibidos em tap1
.