Rota tráfego através de VPN para alguns IPs ocasionalmente

1

Gostaria de encaminhar o tráfego para alguns endereços específicos através da VPN. Fácil o suficiente, pode-se simplesmente adicionar uma rota:

ip route add <destination ip> dev tun0 scope link

Aqui vem o problema: eu não quero rotear o tráfego all através da VPN, apenas alguns . Idealmente, gostaria de "mapear" um IP (por exemplo, um endereço 10.x.x.x) que "apontaria" para o IP de destino real, mas seria roteado pela VPN. Tanto quanto eu entendo, isso equivale a adicionar uma rota (como acima) e, em seguida, realizar o equivalente de DNAT em uma cadeia POSTROUTING.

Basicamente, eu gostaria de fazer um truque de NAT sujo ao contrário (ou seja, no cliente em vez do servidor) .

(Eu gostaria de criar um proxy HTTP simples que roteie o tráfego através da VPN somente se a URL corresponder a um determinado padrão. A solução final seria influenciar o roteamento de uma determinada conexão diretamente de um programa de espaço do usuário, mas Eu acho que isso é impossível.)

Digamos que eu queira direcionar algum tráfego para, digamos, 8.8.8.8 a tun0 , mas ainda quero que algum tráfego para 8.8.8.8 passe por eth0 . Por exemplo, a imagem 8.8.8.8 hospedou vários sites e eu quero tunelar o tráfego para apenas alguns sites.

Eu gostaria de configurar um endereço "falso", digamos, 10.1.2.3 . Qualquer tráfego direcionado do meu computador para 10.1.2.3 iria para 8.8.8.8 , mas seria roteado por tun0 em vez da tabela de roteamento principal.

Eu consegui configurar parcialmente: primeiro escolhi para um intervalo de IP, digamos 10.1.0.0/16 . Do que eu marquei pacotes na cadeia OUTPUT para esse intervalo com, digamos, 0x40 :

sudo iptables -A OUTPUT -t mangle --dst 10.1.0.0/16 -j MARK --set-mark 64

Em seguida, adiciono regras DNAT para mapear os IPs "falsos" desse intervalo para o destino real. Isso pode ser provavelmente automatizado:

sudo iptables -A OUTPUT -t nat --dst 10.1.2.3 -j DNAT --to 8.8.8.8

Com base na marca, eu roteio os pacotes por uma tabela de roteamento diferente:

sudo ip rule add fwmark 64 lookup vpn
sudo ip route add default dev tun0 scope global proto static table vpn

Infelizmente, ainda não consigo pingar 10.1.2.3 . Se eu remover a regra MARK, recebo resposta, então a parte DNAT funciona como esperado.

    
por Kristóf Marussy 07.01.2014 / 20:47

2 respostas

1

Houve dois problemas com minha configuração de roteamento original:

  1. Como indicado na resposta de Gabe, MARK in OUTPUT não pode influenciar a decisão de roteamento, apenas a decisão de redirecionamento após o NAT.

    Isso resultou em ter o endereço de origem errado nos pacotes de saída, porque o endereço de origem é atribuído pela decisão de roteamento e é deixado sozinho pelo reencaminhamento. Eu finalmente decidi que a melhor solução é lidar com isso com uma ação MASQUERADE baseada na marca:

    iptables -A POSTROUTING -t nat -m mark --mark 64 -j MASQUERADE

  2. O Linux tem um filtro de pacotes reverso.

    Veja, por exemplo, um comentário no link para ver o efeito do filtro em cenários de roteamento relacionados à VPN.

    Se um pacote do endereço de origem A for recebido na interface I , ele será descartado, a menos que um pacote para o endereço de destino A tenha sido roteado para a interface I . Naturalmente, respostas de, e. 8.8.8.8 entrada para tun0 será descartada, pois o roteamento normal rotearia os pacotes para 8.8.8.8 a eth0 na ausência da marca.

    Pode-se desativar o filtro de pacotes com

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

    mas isto é considerado prejudicial, uma vez que agora os pacotes forjados pretendem vir de, e. 127.0.0.1 poderia atingir a máquina através de tun0 . Podemos configurar regras de firewall apropriadas para evitar essa violação de segurança. Note que a exploração da vulnerabilidade acima mencionada exigiria comprometimento do próprio servidor VPN (apenas desabilitamos o filtro rp para tun0 ), então, na minha opinião, não é um risco muito grande de qualquer maneira.

Um ótimo efeito colateral dessa configuração é que tun0 nunca é explicitamente mencionado nas regras do iptables. Agora posso adicionar qualquer tipo de informação de roteamento à tabela de roteamento vpn e criar IPs "falsos" que a obedeçam (embora seja preciso lembrar do filtro rp). Por exemplo, a configuração é igualmente útil para VPNs baseadas em PPTP, modificando uma única entrada da tabela de roteamento.

    
por 08.01.2014 / 18:47
1

Não sei se entendi como você está visualizando a solução baseada em roteamento IP, mas tenho uma sugestão para o seu problema real:

I would like to create a simple HTTP proxy that routes traffic through the VPN only if the URL matches a given pattern.

A maneira mais fácil de conseguir isso é pelo encadeamento de proxy (condicional). No caso mais simples, por exemplo, com o squid você configuraria um pai cache_peer e definiria o cache_peer_domain para .netflix.com ou qualquer outra coisa - link é um bom ponto de partida para configurar isto; com o mod_proxy do apache, você usaria a diretiva ProxyRemote (e possivelmente NoProxy , dependendo nos detalhes da sua configuração).

Respondendo seu exemplo baseado em IP: Eu acredito que o único problema com a regra MARK é que ela está na cadeia errada; deve ser PREROUTING, não OUTPUT. Citando a partir da página iptables(1) man:

MARK
   This target is used to set the Netfilter mark value associated with
   the packet.  It can, for example, be used in conjunction with rout‐
   ing based on fwmark (needs iproute2). If you plan on doing so, note
   that the mark needs to be set in the PREROUTING chain of the mangle
   table to affect routing.
    
por 08.01.2014 / 12:02