Múltiplos OpenVPN Clients & Binding Interfaces com bind.so - Não funciona

1

Editar
Eu resolvi o problema escrevendo um script para gerar tabelas e regras de roteamento, depois de seguir o link do @MariusMatutiae para uma introdução ao policy routing .

Estou tentando executar dois clientes OpenVPN no meu Raspberry Pi executando o Minibian e vincular um aplicativo específico (get_iplayer) a uma das VPNs usando bind.so como explicado aqui e aqui . Eu originalmente segui o guia aqui , instalando iproute e baixando e compilando bind.so conforme instruído lá.

As VPNs
Estou usando arquivos de configuração fornecidos pelo Private Internet Access.

Uma VPN aponta para o servidor da Suíça, usa udp e eu configurei a opção dev tun0 , pois eu desejo que esse seja o túnel principal pelo qual todo o tráfego passa, exceto o que declaro explicitamente através do uso de %código%. Este túnel funciona bem, todo o tráfego parece passar por ele.

A segunda VPN aponta para o servidor London, UK, usa tcp e tem a opção bind.so set para atuar como o segundo túnel. Este túnel parece funcionar bem quando executado por si mesmo . Eu posso executar o get_iplayer corretamente.

O problema ocorre quando eu executo as duas instâncias ao mesmo tempo. Nenhum tráfego parece passar pela interface dev tun1 , mesmo quando tento usar bind.so e a abordagem tun1 conforme explicado nos links acima.

bind.so
Até onde eu sei, eu compilei bind.so apropriadamente, copiei para LD_PRELOAD , etc. Frustrantemente, eu consegui trabalhar uma vez mas eu não tenho ideia de como isso ocorreu.

Comandos
Eu tenho usado /usr/lib para encontrar o endereço do gateway; Estou confiante de que estou usando o endereço IP correto. por exemplo:

$ ip route
0.0.0.0/1 via 10.30.1.17 dev tun1 
0.0.0.0/1 via 10.198.1.5 dev tun0 
default via 192.168.1.254 dev eth0 
10.30.1.1 via 10.30.1.17 dev tun1 
10.30.1.17 dev tun1  proto kernel  scope link  src 10.30.1.18 
10.198.1.1 via 10.198.1.5 dev tun0 
10.198.1.5 dev tun0  proto kernel  scope link  src 10.198.1.6 
104.238.169.140 via 192.168.1.254 dev eth0 
128.0.0.0/1 via 10.30.1.17 dev tun1 
128.0.0.0/1 via 10.198.1.5 dev tun0 
179.43.177.66 via 192.168.1.254 dev eth0 
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.84 

Em seguida, execute:

BIND_ADDR="10.30.1.17" LD_PRELOAD=/usr/lib/bind.so get_iplayer --type=tv

resulta em nenhuma conexão e nada no log da VPN do Reino Unido.

Parar a VPN da Suíça e executar o mesmo comando get_iplayer resulta em uma conexão e informações sendo baixadas. ip route fornece o seguinte:

$ ip route
0.0.0.0/1 via 10.30.1.17 dev tun1 
default via 192.168.1.254 dev eth0 
10.30.1.1 via 10.30.1.17 dev tun1 
10.30.1.17 dev tun1  proto kernel  scope link  src 10.30.1.18
104.238.169.119 via 192.168.1.254 dev eth0 
128.0.0.0/1 via 10.30.1.17 dev tun1 
192.168.1.0/24 dev eth0  proto kernel  scope link  src 192.168.1.84

Portanto, não há nenhuma mudança no endereço IP ou qualquer coisa estranha acontecendo, tanto quanto eu posso dizer com o roteamento ao abrir ou fechar as diferentes VPNs.

Não sei porque ip route parece não ter efeito. Não há saída para o terminal para mostrar se ele é bem-sucedido ou não, e não tenho certeza de onde procurar um log, se ele está emitindo alguma coisa (a saída no terminal é para o comando, ou seja, get_iplayer).

Obviamente, eu poderia executar tarefas / scripts cron para abrir e fechar as VPNs para permitir que eu executasse o get_iplayer com sucesso / através da VPN do Reino Unido, mas prefiro manter ambas as VPNs abertas, ter todo o meu tráfego passando pelo bind.so interface e use apenas tun0 para get_player quando eu precisar com tun1 .

Alguém pode me ajudar? Se não pudermos resolver esse problema, alguma ajuda para escrever tabelas ou regras de roteamento específicas para o processo get_iplayer seria ótima.

Obrigado.

    
por confusedpublic 09.11.2015 / 13:53

1 resposta

0

bind.so não é responsável por este problema, que é em vez de roteamento: em cada tabela de roteamento pode haver apenas um gateway padrão, mas cada instância de uma VPN tenta definir o gateway (e o roteamento em geral) como é mais adequado, resultando em tabelas com linhas como:

  0.0.0.0/1 via 10.30.1.17 dev tun1 
  0.0.0.0/1 via 10.198.1.5 dev tun0 

O que é o kernel para fazer isso? Deve encaminhar através do tun0 ou do tun1? A resposta é: ele realmente não direciona, seu pc não pode se conectar.

Formas:

  1. Configure duas tabelas de roteamento, com uma regra instruindo o kernel a usar qualquer uma delas. Isso é chamado policy or source routing , você encontra uma breve introdução a ele aqui . Isso é complicado, não por causa do roteamento de política per se (que é fácil), mas porque você terá que configurar o roteamento de uma das duas instâncias do OpenVPN por conta própria, para garantir que o roteamento regras são adicionadas à outra tabela de roteamento. Mas isso pode ser feito, porque o OpenVPN fornece uma declaração ,

--route-nopull

When used with --client or --pull, accept options pushed by server EXCEPT for routes.

que permite configurar o roteamento de acordo com suas necessidades.

  1. Configure um namespace de rede onde você inicia uma uma instância do OpenVPN e os programas que a usam. Você encontra uma introdução aos namespaces de rede aqui . Isso também requer algum trabalho, mas é principalmente um trabalho mecânico. Se você quiser, o script a seguir (muito simplório!) Que eu escrevi funciona imediatamente.

EDITAR

Como você está trabalhando em uma sessão ssh, tive que modificar um pouco o meu script.

Você pode iniciá-lo com

     newnsssh NameOfNNS start

mas você ainda estará dentro do namespace de rede padrão, abreviado como NNS. Antes de acessá-lo, é melhor abrir um terminal:

     xterm &

Isso abrirá um terminal gráfico fornecido conectado ao RPI por meio de

    ssh -Y me@rpi

e desde que a variável de ambiente $DISPLAY esteja definida como:

  export DISPLAY=localhost:10.0

Depois de abrir o xterm , vá até ele e emita o seguinte comando:

   sudo ip netns exec NameOfNNS bash

O novo prompt está no novo NNS; para verificar,

    ip netns identify $$

Se nada for retornado, você está no NNS padrão , caso contrário você será mostrado NameOfNNS. Agora você pode iniciar o OpenVPN

      openvpn --config /path/to/config/file &
      su YourName

e você está feito. Agora de dentro deste xterm todos os programas serão roteados por esta instância do OpenVPN, enquanto todos os programas iniciados fora deste xterm serão iniciados fora do OpenVPN, ou através da outra instância do OpenVPN, se você tiver decretado outro.

Quando terminar, basta fechar o xterm e, na sessão ssh,

    newnsssh NameOfNNS stop

Isso é tudo.

#!/bin/bash

#
# This script will setup an internal network 10.173.N.0/24; if this causes
# any conflict, change the statement below.

export IP_BASE=10.173

# It will open an xterm window in the new network namespace; if anything
# else is required, change the statement below.


# The script will temporarily activate ip forwarding for you. If you
# do not wish to retain this feature, you will have to issue, at the 
# end of this session, the command
# echo 0 > /proc/sys/net/ipv4/ip_forward 
# yourself. 

export WHEREIS=/usr/bin/whereis

# First of all, check that the script is run by root:

[ "root" != "$USER" ] && exec sudo $0 "$@"

if [ $# != 2 ]; then 
    echo "Usage $0 name action"
    echo "where name is the network namespace name,"
    echo " and action is one of start| stop| reload."
    exit 1
 fi

 # Do we have all it takes?

 IERROR1=0
 IERROR2=0

 export IP=$($WHEREIS -b ip | /usr/bin/awk '{print $2}')
 export IPTABLES=$($WHEREIS -b iptables | /usr/bin/awk '{print $2}')

 if [ x$IP = x ] ; then
    echo "please install the iproute2 package"
    IERROR1=1
 fi

 if [ x$IPTABLES = x ] ; then
    echo "please install the iptables package"
    IERROR2=1
 fi


 if [[ $IERROR1 == 0 && $IERROR2 == 0 ]] 
    then
    :   
 else
    exit 1
 fi


 prelim() {

 # Perform some preliminary setup. First, clear the proposed 
 # namespace name of blank characters; then create a directory
 # for logging info, and a pid file in it. Lastly, 
 # enable IPv4 forwarding. 

    VAR=$1
    export NNSNAME=${VAR//[[:space:]]}

    export OUTDIR=/var/log/newns/$NNSNAME

    if [ ! -d $OUTDIR ]; then
        /bin/mkdir -p $OUTDIR
    fi
    export PID=$OUTDIR/pid$NNSNAME


    ICOUNTER=1
    export Nns=$ICOUNTER 
    if [ $Nns == 1 ]; then
        echo 1 > /proc/sys/net/ipv4/ip_forward
    fi
}

start_nns() {

# Check whether a namespace with the same name already exists. 

$IP netns list | /bin/grep $1 2> /dev/null
if [ $? == 0 ]; then 
    echo "Network namespace $1 already exists,"
    echo "please choose another name"
    exit 1
fi

# Here we take care of DNS

/bin/mkdir -p /etc/netns/$1
echo "nameserver 8.8.8.8" > /etc/netns/$1/resolv.conf
echo "nameserver 8.8.4.4" >> /etc/netns/$1/resolv.conf

# The following creates the new namespace, the veth interfaces, and
# the bridge between veth1 and a new virtual interface, tap0.
# It also assigns an IP address to the bridge, and brings everything up

$IP netns add $1
$IP link add veth-a$1 type veth peer name veth-b$1
$IP link set veth-a$1 up
$IP tuntap add tap$1 mode tap user root
$IP link set tap$1 up
$IP link add br$1 type bridge
$IP link set tap$1 master br$1
$IP link set veth-a$1 master br$1
$IP addr add $IP_BASE.$Nns.1/24 dev br$1
$IP link set br$1 up

# We need to enable NAT on the default namespace

$IPTABLES -t nat -A POSTROUTING -j MASQUERADE

# This assigns the other end of the tunnel, veth2, to the new 
# namespace, gives it an IP address in the same net as the bridge above, 
# brings up this and the (essential) lo interface, sets up the 
# routing table by assigning the bridge interface in the default namespace
# as the default gateway, creates a new terminal in the new namespace and 
# stores its pid for the purpose of tearing it cleanly, later. 

$IP link set veth-b$1 netns $1
$IP netns exec $1 $IP addr add $IP_BASE.$Nns.2/24 dev veth-b$1
$IP netns exec $1 $IP link set veth-b$1 up
$IP netns exec $1 $IP link set dev lo up
$IP netns exec $1 $IP route add default via $IP_BASE.$Nns.1 
ln -s /proc/1/ns/net /var/run/netns/default 2> /dev/null
#   $IP netns exec $1 bash & $IP netns exec $1 echo "$!" > $PID
}

stop_nns() {

# Check that the namespace to be torn down really exists

$IP netns list | /bin/grep $1 2>&1 1> /dev/null
if [ ! $? == 0 ]; then 
    echo "Network namespace $1 does not exist,"
    echo "please choose another name"
    exit 1
fi

# This kills the terminal in the separate namespace, 
# removes the file and the directory where it is stored, and tears down
# all virtual interfaces (veth1, tap0, the bridge, veth2 is automatically
# torn down when veth1 is), and the NAT rule of iptables. 


rm /var/run/netns/default
$IP link set br$1 down
$IP link del br$1
$IP netns del $1
$IP link set veth-a$1 down
$IP link del veth-a$1
$IP link set tap$1 down
$IP link del tap$1
$IPTABLES -t nat -D POSTROUTING -j MASQUERADE
/bin/rm /etc/netns/$1/resolv.conf
    /bin/rmdir /etc/netns/$1
}


case $2 in
  start)
    prelim "$1"
    start_nns $NNSNAME
    ;;
  stop)
    prelim "$1"
    stop_nns $NNSNAME
    ;;
  reload)
    prelim "$1"
    stop_nns $NNSNAME
    prelim "$1"
    start_nns $NNSNAME
    ;;
 *) 
 # This removes the absolute path from the command name

    NAME1=$0
    NAMESHORT=${NAME1##*/}

    echo "Usage:" $NAMESHORT "name action,"
    echo "where name is the name of the network namespace,"
    echo "and action is one of start|stop|reload"
    ;;
esac
    
por 09.11.2015 / 16:25