IPtables - roteia algum tráfego através do túnel

0

Digamos que temos máquinas com duas interfaces: ens160 e wg0 .

Digamos que temos rotas como abaixo: %código% Nossa primeira máquina tem ips: 172.29.248.134, 192.168.2.2

Existe uma segunda máquina: 172.29.248.128/25 dev ens160 proto kernel scope link src 172.29.248.134 192.168.2.0/24 dev wg0 proto kernel scope link src 192.168.2.2

A primeira máquina pode conectar-se à segunda máquina em ambos os IPs, 172.29.244.20 e 192.168.2.1.

Agora, o que quero alcançar é, quando a primeira máquina estiver tentando acessar 172.29.244.20, passar pela interface endpoint: 172.29.244.20:51820 allowed ips: 192.168.2.1/32 . Algo como reescrever o IP de destino para este IP específico, de 172.29.244.20 a 192.168.2.1

É possível? Se sim, podemos também reescrevê-lo na segunda máquina, então se ele receber alguma coisa na interface wg0 de 192.168.2.2, o ip de origem deve ser alterado de volta para 172.29.248.134 e passado para wg0 ?

Pode ser feito apenas com ens160 ? Ou precisamos de ip route ?

@dirkt Obrigado, isso normalmente funcionaria e eu tentei, mas parece que a situação é um pouco mais complicada. Na verdade, todo mais complicado, porque eu estou tentando configurar criptografia entre máquinas para o cluster Kubernetes, mas devido a problemas com o plugin de rede (Calico), de alguma forma mais transparente do que diretamente usando 192.168.2.0/24. Basicamente, há encapsulamento IP-in-IP sobre o túnel VPN da camada 3 e muitas regras do iptables. wg0 é a interface Wireguard (VPN), tem 192.168.2.0/24 sub-rede. Eu uso 192.168.2.1/32 para especificar um único IP para VPN, porque eu quero criar uma rede de malha. Não consigo especificar 192.168.2.0/24 para IPs permitidos, porque wireguard não permite a mesma sub-rede para vários peers.

Agora eu vejo que encaminhar todo o trafico para esse ip via iptables pode ser idiotice, pois consigo ver com wg0 na maquina enviando ping funciona corretamente (as requisicoes ICMP sao visiveis), mas nada mostra no recebimento da maquina tcpdump .

Eu perguntei sobre isso no IRC wireguard e o problema provavelmente é: wg0

Ok, mas pode haver uma solução aqui, na documentação . The problem is that outgoing traffic to the other wireguard endpoint is no longer routed over ens160. But looped into the wireguard interface.

Eu encontrei o artigo sobre esse "problema recursivo de VPN", mas minhas habilidades de rede são bastante pobre. O que devo fazer para encaminhar o tráfego para FwMark — a 32-bit fwmark for outgoing packets. If set to 0 or "off", this option is disabled. May be specified in hexadecimal by prepending "0x". Optional. , exceto os pacotes marcados com fwmark específico?

    
por Adiqq 24.03.2018 / 00:05

2 respostas

0

Você deixou de fora uma descrição completa da sua rede, então eu assumirei que o host A (o primeiro) e o host B (o segundo) estão diretamente conectados ao mesmo segmento em wg0 no host A com 192.168.2.2/24 , e o host B com 92.168.2.1/?? (o /32 que você tem é provavelmente um erro - cada host no segmento deve ter a mesma máscara de rede, então você provavelmente quer dizer /24 ). Se isso não estiver correto, edite sua pergunta com uma descrição da sua rede, máscaras de rede e IPs nos pontos de extremidade.

Em seguida, se você deseja rotear, use os recursos de roteamento do kernel. Não sei por que tantas pessoas pensam que iptables é para roteamento. Não é, não importa o que você lê na internet. Se o roteamento normal não for suficiente, use o roteamento de políticas. Se o roteamento de políticas não for suficiente, você pode pensar em fazer coisas engraçadas com iptables .

Os recursos de roteamento do kernel são otimizados para tomar decisões de roteamento rapidamente. Isso não é verdade para iptables .

(desculpe pelo discurso, mas isso é uma implicância minha).

Portanto, no seu caso, tudo o que você precisa fazer é adicionar uma rota em A para informar A que ela deve rotear via 192.168.2.2 ao tentar entrar em contato com 72.29.244.20 :

ip route add 72.29.244.20/32 via 192.168.2.2 dev wg0

Em seguida, os pacotes com o endereço de destino 72.29.244.20 serão enviados para 192.168.2.2 , ou seja, o host B. Quando o host B receber esses, ele descobrirá que já tem uma interface com esse endereço e os aceita.

Você pode até pensar em ampliar 72.29.244.20/32 para 72.29.244.0/24 ou o que for, se houver outros hosts nesse intervalo que possam ser acessados de maneira mais conveniente ao longo desta rota.

    
por 24.03.2018 / 09:55
0

Problema e objetivo

Os pacotes que fazem parte do envelope WireGuard (os pacotes UDP que transportam a carga criptografada) não estão sujeitos ao próprio encapsulamento do encapsulamento, usando o mesmo IP dentro do túnel como fora do túnel.

Método

Como a pilha de roteamento (ip route, ip rule ...) está trabalhando na camada 3 (IP) e não na camada 4 (UDP, usada pelo envelope), isso não pode ser resolvido apenas com a pilha de roteamento sem ajuda extra para distinguir os pacotes de envelope dos pacotes de "dados".

Felizmente é possível marcar um pacote com uma marca (puramente internamente, no skbuff do pacote, claro que não no fio). A tag pode ser reutilizada como fwmark para a pilha de roteamento. As facilidades (que eu conheço) capazes de marcar pacotes são iptables, nftables ... e o próprio WireGuard.

Como o Wireguard, no entanto, pode marcar pacotes após o encapsulamento, não há necessidade de usar o iptables / nftables como ajuda extra para o roteamento.

Atualmente, há uma limitação irritante no wireguard (que certamente existe por boas razões, provavelmente relacionadas à sua manipulação de roteamento): não consegui encontrar uma maneira de definir dois peers com os mesmos valores permitidos ips. Portanto, não é possível definir simplesmente:

AllowedIps = 172.29.244.0/25,172.29.248.128/25

em todos os endpoints. Tentar isso excluirá os ips permitidos nos pontos de extremidade anteriores com o mesmo valor. Definir qualquer outro intervalo de sobreposição (por exemplo, alterar a máscara) será aceito, mas impedirá que alguns dos pares de sobreposição funcionem. Claro que permitir apenas o IP do terminal remoto único funciona. Essa é a única maneira de a malha inteira funcionar corretamente.

Solução

Distinguir entre pacotes de envelope e pacotes encapsulados com uma marca. Não é necessário informar qual porta UDP deve ser, o WireGuard trata essa parte. Use esta marca para fazer uma "exceção à exceção" para a escolha da rota.

Escolhas feitas

De acordo com o comentário do OP, não é necessário encaminhamento de pacotes, portanto, nenhum encaminhamento foi testado.

A escolha feita aqui é marcar os pacotes que não entrarão no túnel com a ajuda do WireGuard (uma outra solução de trabalho, usando iptables em vez de WireGuard para marcar pacotes, poderia fazer o oposto e marcar os pacotes que entram no túnel).

Instruções

Exemplo de configuração:

# ip -4 -br addr show dev ens160
ens160@if7       UP             172.29.248.132/25 
# ip route
default via 10.0.3.1 dev eth0 
10.0.3.0/24 dev eth0 proto kernel scope link src 10.0.3.147 
172.29.244.0/25 via 172.29.248.129 dev ens160 
172.29.248.128/25 dev ens160 proto kernel scope link src 172.29.248.132 

# wg show wg0
interface: wg0
  public key: 7FsVTBuIDNQsWj9flHWwMt+kCaE8urEE9bCwcvz6CBM=
  private key: (hidden)
  listening port: 51820

peer: +NJdQr+piwid1iuC58rbnXFgGo/vZ9d8Gs3xvl3/TxI=
  endpoint: 172.29.248.134:51820
  allowed ips: (none)
  transfer: 14.74 KiB received, 34.35 KiB sent

peer: KrZWEupjHGoHTywwWhg4XXQSyFl/disav7/pyhOK/1Q=
  endpoint: 172.29.244.20:51820
  allowed ips: (none)
  transfer: 11.06 KiB received, 15.65 KiB sent

Como no final tudo pode passar pelo túnel reutilizando os mesmos IPs, a rede 192.168.2.0/24 não é mais usada. Como nenhuma regra de roteamento fará referência a esses IPs, eles podem até ser removidos: o wg0 terá um IP zero (ainda é aceitável mantê-los se desejado):

# ip addr flush dev wg0

Configure o wg0 para marcar os pacotes de envelope com algum valor arbitrariamente escolhido (aqui 9):

# wg set wg0 fwmark 9

Configure cada host do WireGuard para aceitar o IP do terminal no túnel, esse é o objetivo:

# wg show wg0|awk 'BEGIN { RS="\n\n" } /^peer/ { printf "wg set wg0 peer %s allowed-ips %s\n",$2,$4 }'|cut -d: -f1 | sh

O que agora dá:

# wg show wg0
interface: wg0
  public key: 7FsVTBuIDNQsWj9flHWwMt+kCaE8urEE9bCwcvz6CBM=
  private key: (hidden)
  listening port: 51820
  fwmark: 0x9

peer: +NJdQr+piwid1iuC58rbnXFgGo/vZ9d8Gs3xvl3/TxI=
  endpoint: 172.29.248.134:51820
  allowed ips: 172.29.248.134/32
  transfer: 14.74 KiB received, 34.35 KiB sent

peer: KrZWEupjHGoHTywwWhg4XXQSyFl/disav7/pyhOK/1Q=
  endpoint: 172.29.244.20:51820
  allowed ips: 172.29.244.20/32
  transfer: 11.06 KiB received, 15.65 KiB sent

Adicione rotas na tabela de roteamento (escolhida arbitrariamente) 200, especificando o IP do host como fonte (para evitar que um IP de uma interface não relacionada seja infelizmente escolhido) ...

... apenas uma vez, rotas para ambas as LANs, mas isso exigirá o uso do WireGuard para qualquer tráfego IP com qualquer par nas LANs:

# localip=$(ip -4 -br addr show dev ens160|awk '{ print $3 }'|cut -d/ -f1)
# ip route add 172.29.244.0/25   dev wg0 table 200 src $localip
# ip route add 172.29.248.128/25 dev wg0 table 200 src $localip

O que dá:

# ip route show table 200
172.29.244.0/25 dev wg0 scope link src 172.29.248.132 
172.29.248.128/25 dev wg0 scope link src 172.29.248.132 

... adicione rotas por pares:

# localip=$(ip -4 -br addr show dev ens160|awk '{ print $3 }'|cut -d/ -f1)
# wg show wg0|awk 'BEGIN { RS="\n\n" } /^peer/ { printf "ip route add %s dev wg0 table 200 src %s\n",gensub(":.*$","",1,$4),localip }' localip=$localip | sh

O que dá em vez disso aqui:

# ip route show table 200
172.29.244.20 dev wg0 scope link src 172.29.248.132 
172.29.248.134 dev wg0 scope link src 172.29.248.132 

Corrija antecipadamente os problemas de galinha e ovo que seriam introduzidos pela regra após este, usando diretamente a tabela de roteamento principal para os pacotes marcados por WireGuard (aqueles pacotes 51820 / UDP):

# ip rule add priority 32000 fwmark 9 lookup main

"Inserir" após uma consulta à tabela 200. Na verdade, somente os pacotes com as rotas definidas acima para o WireGuard corresponderão e usarão o túnel por meio do wg0, outros pacotes continuarão para a tabela principal (normal):

# ip rule add priority 32100 lookup 200

Essa é a regra 32100 e a tabela 200 que substituem o roteamento usual feito dentro do wg0 quando os IPs são definidos nele.

O que agora dá:

# ip rule
0:  from all lookup local 
32000:  from all fwmark 0x9 lookup main 
32100:  from all lookup 200 
32766:  from all lookup main 
32767:  from all lookup default 

Infelizmente, o filtro de caminho inverso agora é acionado para o tráfego de entrada não-WireGuard proveniente da interface normal (aqui ens160) quando wg0 agora seria esperado. Isso inclui pacotes de resposta ARP necessários para encontrar pares na mesma LAN, bem como o gateway para a outra LAN (não tenho uma boa explicação sobre isso). Então rp_filter deve ser configurado para o modo solto para a interface normal (aqui ens160):

echo 2 > /proc/sys/net/ipv4/conf/ens160/rp_filter

Com essas configurações repetidas nos outros peers, todos os peers podem se comunicar entre si usando seu próprio IP, como se não houvesse túnel (em uma malha potencialmente usando até n * (n-1) / 2 túneis).

Exemplo: o host recebe um único ping e responde:

# tcpdump -n -s0 -i wg0 -p
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on wg0, link-type RAW (Raw IP), capture size 262144 bytes
05:22:51.553463 IP 172.29.244.20 > 172.29.248.132: ICMP echo request, id 2083, seq 1, length 64
05:22:51.553525 IP 172.29.248.132 > 172.29.244.20: ICMP echo reply, id 2083, seq 1, length 64

Enquanto no roteador, o tráfego criptografado visto é (com alguma sobrecarga, provavelmente porque não houve atividade recente):

# tcpdump -n -s0 -i br248 -p
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on br248, link-type EN10MB (Ethernet), capture size 262144 bytes
05:22:51.553317 ARP, Request who-has 172.29.248.132 tell 172.29.248.129, length 28
05:22:51.553358 ARP, Reply 172.29.248.132 is-at 2e:02:6e:cf:6d:4f, length 28
05:22:51.553383 IP 172.29.244.20.51820 > 172.29.248.132.51820: UDP, length 128
05:22:51.553583 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 128
05:22:51.554112 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 148
05:22:51.555198 IP 172.29.244.20.51820 > 172.29.248.132.51820: UDP, length 92
05:22:51.555748 IP 172.29.248.132.51820 > 172.29.244.20.51820: UDP, length 32
    
por 30.03.2018 / 06:00