AskOverflow.Dev

AskOverflow.Dev Logo AskOverflow.Dev Logo

AskOverflow.Dev Navigation

  • Início
  • system&network
  • Ubuntu
  • Unix
  • DBA
  • Computer
  • Coding
  • LangChain

Mobile menu

Close
  • Início
  • system&network
    • Recentes
    • Highest score
    • tags
  • Ubuntu
    • Recentes
    • Highest score
    • tags
  • Unix
    • Recentes
    • tags
  • DBA
    • Recentes
    • tags
  • Computer
    • Recentes
    • tags
  • Coding
    • Recentes
    • tags
Início / user-1124669

userid's questions

Martin Hope
userid
Asked: 2024-09-06 01:33:48 +0800 CST

Resolvido - Host Fedora, convidado Windows (QEMU/KVM): pontes virtuais NAT funcionam, exceto esta (USB/Ethernet)

  • 5

Visão geral rápida da situação

Tenho um host Fedora no qual há várias NICs e VMs (QEMU/KVM/LibVirt). Cada convidado acessa a internet por meio de uma ponte virtual que opera no modo NAT e encaminha o tráfego para um único dispositivo físico.

Por razões que estão além de mim, quando se trata deste adaptador USB/Ethernet (um telefone Android), não consigo fazê-lo funcionar como faço com outras NICs. O convidado recebe respostas DNS do host, então tenta acessar a internet e não obtém nada além de respostas do tipo ICMP host unreachable e TTL expired .

Uma descrição de como minha infraestrutura funciona

Aqui está um resumo de como isso geralmente funciona. O problemático trio guest/bridge/NIC virá depois (mas supostamente funciona da mesma forma).

O host

Uma estação de trabalho Fedora 40 x86_64.

➜  ~ uname -r 
6.10.6-200.fc40.x86_64

O hipervisor

QEMU/KVM, LibVirt, usando virt-manager ou virsh dependendo das necessidades.

➜  ~ qemu-kvm --version
QEMU emulator version 8.2.6 (qemu-8.2.6-3.fc40)
Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers
➜  ~ virsh --version=long
Virsh command line tool of libvirt 10.1.0
See web site at https://libvirt.org/

Compiled with support for:
 Hypervisors: QEMU/KVM LXC LibXL OpenVZ VMware VirtualBox ESX Hyper-V Test
 Networking: Remote Network Bridging Interface udev Nwfilter
 Storage: Dir Disk Filesystem SCSI Multipath iSCSI iSCSI-direct LVM RBD Gluster ZFS
 Miscellaneous: Daemon Nodedev SELinux Secrets Debug DTrace Readline
➜  ~ virt-manager --version
4.1.0

O convidado

Instalação limpa do Win10, ISO do MS, winFSP e Virtio-win-guest-tools instalados.

C:\Users\User>ver

Microsoft Windows [version 10.0.19045.4780]
PS C:\Windows\system32> winget list
Nom                                      ID                                       Version          Disponible    Source
-----------------------------------------------------------------------------------------------------------------------
WinFsp 2023                              WinFsp.WinFsp                            2.0.23075                      winget
Virtio-win-guest-tools                   ARP\Machine\X86\{c5ad265e-98e6-40bd-801… 0.1.262

Visão geral da configuração usual

Resumindo

Aqui está como eu costumo fazer as coisas. O host é conectado a um roteador por meio de uma NIC Ethernet física, vamos chamá-la de eth0 em my_network. Uma rede virtual é criada no virt-manager, vamos chamá-la de my_virt_net. Ela tem uma ponte virtual que opera no modo NAT e encaminha para o dispositivo físico eth0, vamos chamá-lo de virbr0. O convidado obtém uma interface de rede virtual correspondente àquela fonte de rede, configurada como um dispositivo virtIO, vamos chamá-la de vNIC0.

O vNIC do convidado recebe um IP via DHCP (libvirt executa uma instância DNSMASQ para cada um, eu acho?). Neste exemplo, estamos operando em 10.0.0.0/24, o gateway sendo 10.0.0.1.

Regras e rotas de IP são criadas para garantir que o tráfego do convidado passe pelo dispositivo certo. Libvirt cuida da criação de regras MASQUERADE no iptables.

Uma vez feito tudo isso, o convidado tem acesso à internet. O tráfego flui da seguinte maneira:

Guest <-> vNIC0 <-> virbr0 <-> vnet0 <-> eth0 <-> my_network <-> outside_world

Em detalhe

➜  ~ nmcli con show                        
NAME          UUID                                  TYPE       DEVICE      
my_network   3d72b049-b1a7-49e8-ab55-18edf0d79de9  ethernet   enp0s31f6  
➜  ~ ip addr
1: enp0s31f6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000
    link/ether 40:8d:5c:4d:e5:c0 brd ff:ff:ff:ff:ff:ff
    inet 192.168.1.1/24 brd 192.168.1.255 scope global dynamic noprefixroute enp0s31f6
       valid_lft 40431sec preferred_lft 40431sec
    inet6 2a01:e0a:18b:b670:3429:7bc3:6997:2e17/64 scope global dynamic noprefixroute 
       valid_lft 86265sec preferred_lft 86265sec
    inet6 fe80::ca7c:24c:ce13:2a22/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
2: virbr0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 52:54:00:ed:b3:89 brd ff:ff:ff:ff:ff:ff
    inet 10.0.0.1/24 brd 10.0.0.255 scope global virbr0
       valid_lft forever preferred_lft forever
3: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue master virbr0 state UNKNOWN group default qlen 1000
    link/ether fe:54:00:32:2f:3e brd ff:ff:ff:ff:ff:ff
    inet6 fe80::fc54:ff:fe32:2f3e/64 scope link proto kernel_ll 
       valid_lft forever preferred_lft forever
➜  ~ brctl show
bridge name bridge id       STP enabled interfaces
virbr0      8000.525400edb389   yes     vnet0
➜  ~ virsh net-list
 Name               State    Autostart   Persistent
-----------------------------------------------------
 my_virt_net        active   yes         yes

➜  ~ ip rule
0:  from all lookup local
100:    from all iif virbr0 lookup 100
32766:  from all lookup main
32767:  from all lookup default
➜  ~ ip route show table 100 
default dev enp0s31f6 scope link
➜  ~ ip route               
default via 192.168.1.254 dev enp0s31f6 proto dhcp src 192.168.1.1 metric 100 
10.0.0.0/24 dev virbr0 proto kernel scope link src 10.0.0.1 
192.168.1.0/24 dev enp0s31f6 proto kernel scope link src 192.168.1.1 metric 100 
➜  ~ iptables -t nat -L -v -n
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain OUTPUT (policy ACCEPT 0 packets, 0 bytes)
 pkts bytes target     prot opt in     out     source               destination         

Chain POSTROUTING (policy ACCEPT 19151 packets, 2171K bytes)
 pkts bytes target     prot opt in     out     source               destination         
21657 2313K LIBVIRT_PRT  0    --  *      *       0.0.0.0/0            0.0.0.0/0           

Chain LIBVIRT_PRT (1 references)
    0     0 RETURN     0    --  *      enp0s31f6  10.0.0.0/24          224.0.0.0/24        
    0     0 RETURN     0    --  *      enp0s31f6  10.0.0.0/24          255.255.255.255     
   19   988 MASQUERADE  6    --  *      enp0s31f6  10.0.0.0/24         !10.0.0.0/24          masq ports: 1024-65535
    4  5112 MASQUERADE  17   --  *      enp0s31f6  10.0.0.0/24         !10.0.0.0/24          masq ports: 1024-65535
    0     0 MASQUERADE  0    --  *      enp0s31f6  10.0.0.0/24         !10.0.0.0/24

Esta é uma configuração bem padrão, eu acho. Ela funciona bem para as minhas necessidades. As saídas que mostrei são simplificadas, já que tenho, de fato, vários convidados e NICs, mas você entendeu a ideia. É sempre a mesma configuração, e funciona.

Uma coisa a ser observada é que eu uso scripts /etc/NetworkManager/dispatcher.d/para adicionar ou remover regras de IP e rotas quando as interfaces ficam ativas ou inativas.

Então qual é o problema?

Aqui está o que está acontecendo. Quero usar um dispositivo USB/Ethernet (um telefone Android) conectado ao host e configurar o IP como qualquer outra NIC. Quero que esse telefone seja usado como um gateway para o mundo externo, por um e apenas um convidado, e o host, de preferência, não deve poder usá-lo. Minha configuração usual é ter tudo bem isolado.

O telefone é conectado ao host e configurado para ligar automaticamente o tethering USB. Ele é detectado como uma interface de rede e fornece uma concessão DHCP, como esperado:

➜  ~ ip addr
8: enp0s20f0u6: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UNKNOWN group default qlen 1000
    link/ether 46:7a:42:be:dc:85 brd ff:ff:ff:ff:ff:ff
    inet 192.168.171.52/24 brd 192.168.171.255 scope global dynamic noprefixroute enp0s20f0u6
       valid_lft 2302sec preferred_lft 2302sec
    inet6 2a02:8440:6103:24e4:d1fa:3bae:2f95:5b9d/64 scope global deprecated dynamic noprefixroute 
       valid_lft 1503sec preferred_lft 0sec
    inet6 2a02:8440:6315:5cc:8eb1:665a:abb2:6847/64 scope global dynamic noprefixroute 
       valid_lft 7108sec preferred_lft 7108sec
    inet6 fe80::faaa:5745:cf53:55cf/64 scope link noprefixroute 
       valid_lft forever preferred_lft forever
13: virbr3: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP group default qlen 1000
    link/ether 52:54:00:eb:85:6a brd ff:ff:ff:ff:ff:ff
    inet 10.0.3.1/24 brd 10.0.3.255 scope global virbr3
       valid_lft forever preferred_lft forever

Garantindo que temos conectividade com o mundo exterior:

➜  ~ traceroute -i enp0s20f0u6 www.google.com
traceroute to www.google.com (142.250.178.132), 30 hops max, 60 byte packets
 1  _gateway (192.168.171.21)  0.831 ms  0.711 ms  0.803 ms
 ...
 ...
 ...
 [REDACTED]
 ...
 ...
 ...
15  par21s22-in-f4.1e100.net (142.250.178.132)  49.062 ms  66.086 ms  65.975 ms

Então eu faço o de sempre. Eu crio uma rede virtual no virt-manager (modo NAT, encaminhamento para o dispositivo físico enp0s20f0u6 especificamente) e a conecto como um dispositivo virtIO ao convidado. Eu configuro regras de ip e rotas em um script que roda quando a interface é ativada ou desativada:

➜  ~ sudo nano /etc/NetworkManager/dispatcher.d/103-motoE14-handler.sh
#!/bin/bash

interface=$1
event=$2

if [ "$interface" = "enp0s20f0u6" ]; then
  case "$event" in
    up)
      ip rule add prio 103 iif virbr3 table 103
      ip route add default dev "$interface" table 103
      ;;
    down)
      ip rule del iif virbr3 table 103
      ip route del table 103 default dev "$interface"
      ;;
  esac
fi
➜  ~ sudo chmod +x /etc/NetworkManager/dispatcher.d/103-motoE14-handler.sh

Embora essa seja exatamente a mesma configuração para outros convidados e NICs, o convidado não tem conectividade com o mundo externo.

Verificações de sanidade

Só para esclarecer, fiz o seguinte, e muito mais, antes de postar:

  1. Tente outro telefone: não é bom.
  2. Tente outro convidado: no bueno.
  3. Acabar com a configuração, reconstruir do zero: nada bom.
  4. Tente outra NIC no convidado problemático: funciona.
  5. Experimente a NIC problemática no host: ela funciona.
  6. Tente com todas as outras NICs inativas e apenas esta restante, incluindo defini-la como o gateway padrão para todo o tráfego: nenhuma alteração.
  7. n-tuple verifica as regras de IP, rotas de IP, tabelas de IP: parece bom para mim.
  8. Verifique o firewall. Tudo parece bem para mim.
  9. Tente um novo convidado executando o Fedora 40: mesmo problema.
  10. Usar passagem USB: funciona, mas gostaria de gerenciar todas as minhas interfaces da mesma maneira.
  11. Use um modelo de dispositivo e1000e em vez de virtIO: não é bom.

Captura de tráfego de rede

Estou tentando ler os dumps TCP que capturo do host, na interface física, na ponte e na vnet, mas isso está além da minha compreensão de rede...

Observe o seguinte:

  1. "Fidel" é o nome do anfitrião.
  2. A placa de rede USB/Ethernet, também conhecida como telefone Android, é:
  • enp0s20f0u6 (nome da interface).
  • 46:7a:42:be:dc:85 (endereço MAC).
  • 192.168.171.21 (IP de gateway).
  1. 192.168.171.52 é o IPv4 alugado pela NIC ao host via DHCP.
  2. A ponte virtual é:
  • virbr3.
  • 52:54:00:eb:85:6a.
  • 10.0.3.1.
  1. A NIC virtual anexada ao convidado é:
  • 52:54:00:43:16:2f
  • 10.0.3.219

tcpdumpdo anfitrião: enp0s20f0u6

➜  ~ sudo tcpdump -e -E -f -i enp0s20f0u6 
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on enp0s20f0u6, link-type EN10MB (Ethernet), snapshot length 262144 bytes
18:48:37.824751 46:7a:42:be:dc:85 (oui Unknown) > a6:fe:e6:ee:73:2d (oui Unknown), ethertype IPv6 (0x86dd), length 106: 2a02-8440-6315-05cc-8eb1-665a-abb2-6847.rev.sfr.net.57013 > 2a02-8440-6315-05cc-0000-0000-0000-0033.rev.sfr.net.domain: 3959+ A? checkappexec.microsoft.com. (44)
18:48:37.838107 46:7a:42:be:dc:85 (oui Unknown) > Broadcast, ethertype ARP (0x0806), length 42: Request who-has 20.191.45.158 tell fidel, length 28
18:48:37.867576 46:7a:42:be:dc:85 (oui Unknown) > a6:fe:e6:ee:73:2d (oui Unknown), ethertype IPv6 (0x86dd), length 152: 2a02-8440-6315-05cc-8eb1-665a-abb2-6847.rev.sfr.net.57276 > 2a02-8440-6315-05cc-0000-0000-0000-0033.rev.sfr.net.domain: 10318+ PTR? 3.3.0.0.0.0.0.0.0.0.0.0.0.0.0.0.c.c.5.0.5.1.3.6.0.4.4.8.2.0.a.2.ip6.arpa. (90)
18:48:37.988238 a6:fe:e6:ee:73:2d (oui Unknown) > 46:7a:42:be:dc:85 (oui Unknown), ethertype IPv6 (0x86dd), length 232: 2a02-8440-6315-05cc-0000-0000-0000-0033.rev.sfr.net.domain > 2a02-8440-6315-05cc-8eb1-665a-abb2-6847.rev.sfr.net.57013: 3959 3/0/0 CNAME prod-atm-wds-apprep.trafficmanager.net., CNAME prod-agic-we-3.westeurope.cloudapp.azure.com., A 20.56.187.20 (170)

tcpdumpdo anfitrião: virbr3

➜  ~ sudo tcpdump -e -E -f -i virbr3              
dropped privs to tcpdump
tcpdump: verbose output suppressed, use -v[v]... for full protocol decode
listening on virbr3, link-type EN10MB (Ethernet), snapshot length 262144 bytes
19:14:19.404024 52:54:00:43:16:2f (oui Unknown) > 52:54:00:eb:85:6a (oui Unknown), ethertype IPv4 (0x0800), length 74: 10.0.3.219.62464 > fidel.domain: 54546+ A? www.google.com. (32)
19:14:19.414360 52:54:00:eb:85:6a (oui Unknown) > 52:54:00:43:16:2f (oui Unknown), ethertype IPv4 (0x0800), length 90: fidel.domain > 10.0.3.219.62464: 54546 1/0/0 A 216.58.213.68 (48)
19:14:19.427738 52:54:00:43:16:2f (oui Unknown) > 52:54:00:eb:85:6a (oui Unknown), ethertype IPv4 (0x0800), length 106: 10.0.3.219 > par21s18-in-f4.1e100.net: ICMP echo request, id 1, seq 13, length 72
19:14:19.427786 52:54:00:eb:85:6a (oui Unknown) > 52:54:00:43:16:2f (oui Unknown), ethertype IPv4 (0x0800), length 134: fidel > 10.0.3.219: ICMP time exceeded in-transit, length 100
19:14:19.429008 52:54:00:43:16:2f (oui Unknown) > 52:54:00:eb:85:6a (oui Unknown), ethertype IPv4 (0x0800), length 106: 10.0.3.219 > par21s18-in-f4.1e100.net: ICMP echo request, id 1, seq 14, length 72

O que eu vejo?

Quando o convidado solicita uma resolução de DNS, o host parece fornecê-la (e, de fato, a saída do traceroute no convidado do Windows mostra que o endereço IP de www.google.com foi encontrado, mas a rota não pode ser... rastreada).

Alguém tem sugestões sobre o que está acontecendo?

Editar: Tive que encurtar os resultados tcpdumpporque o StackExchange estava detectando minha postagem como spam... Fornecerei mais em postagens subsequentes, se necessário.

networking
  • 1 respostas
  • 18 Views

Sidebar

Stats

  • Perguntas 205573
  • respostas 270741
  • best respostas 135370
  • utilizador 68524
  • Highest score
  • respostas
  • Marko Smith

    Você pode passar usuário/passar para autenticação básica HTTP em parâmetros de URL?

    • 5 respostas
  • Marko Smith

    Ping uma porta específica

    • 18 respostas
  • Marko Smith

    Verifique se a porta está aberta ou fechada em um servidor Linux?

    • 7 respostas
  • Marko Smith

    Como automatizar o login SSH com senha?

    • 10 respostas
  • Marko Smith

    Como posso dizer ao Git para Windows onde encontrar minha chave RSA privada?

    • 30 respostas
  • Marko Smith

    Qual é o nome de usuário/senha de superusuário padrão para postgres após uma nova instalação?

    • 5 respostas
  • Marko Smith

    Qual porta o SFTP usa?

    • 6 respostas
  • Marko Smith

    Linha de comando para listar usuários em um grupo do Windows Active Directory?

    • 9 respostas
  • Marko Smith

    O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL?

    • 3 respostas
  • Marko Smith

    Como determinar se uma variável bash está vazia?

    • 15 respostas
  • Martin Hope
    Davie Ping uma porta específica 2009-10-09 01:57:50 +0800 CST
  • Martin Hope
    kernel O scp pode copiar diretórios recursivamente? 2011-04-29 20:24:45 +0800 CST
  • Martin Hope
    Robert ssh retorna "Proprietário incorreto ou permissões em ~/.ssh/config" 2011-03-30 10:15:48 +0800 CST
  • Martin Hope
    Eonil Como automatizar o login SSH com senha? 2011-03-02 03:07:12 +0800 CST
  • Martin Hope
    gunwin Como lidar com um servidor comprometido? 2011-01-03 13:31:27 +0800 CST
  • Martin Hope
    Tom Feiner Como posso classificar a saída du -h por tamanho 2009-02-26 05:42:42 +0800 CST
  • Martin Hope
    Noah Goodrich O que é um arquivo Pem e como ele difere de outros formatos de arquivo de chave gerada pelo OpenSSL? 2009-05-19 18:24:42 +0800 CST
  • Martin Hope
    Brent Como determinar se uma variável bash está vazia? 2009-05-13 09:54:48 +0800 CST

Hot tag

linux nginx windows networking ubuntu domain-name-system amazon-web-services active-directory apache-2.4 ssh

Explore

  • Início
  • Perguntas
    • Recentes
    • Highest score
  • tag
  • help

Footer

AskOverflow.Dev

About Us

  • About Us
  • Contact Us

Legal Stuff

  • Privacy Policy

Language

  • Pt
  • Server
  • Unix

© 2023 AskOverflow.DEV All Rights Reserve