Como permitir o acesso da LAN local enquanto conectado à Cisco VPN?

75

Como posso manter o acesso à LAN local enquanto conectado à Cisco VPN?

Ao se conectar usando o Cisco VPN, o servidor deve instruir o cliente a impedir o acesso local à LAN.

Supondo que esta opção do lado do servidor não pode ser desativada, como pode permitir o acesso da LAN local enquanto conectado a um cliente VPN da Cisco?

Eu costumava pensar que era simplesmente uma questão de rotas adicionadas que capturam o tráfego da LAN com uma métrica mais alta, por exemplo:

  Network 
Destination      Netmask        Gateway       Interface  Metric
   10.0.0.0  255.255.0.0       10.0.0.3        10.0.0.3      20  <--Local LAN
   10.0.0.0  255.255.0.0  192.168.199.1  192.168.199.12       1  <--VPN Link

E tentar excluir a rota 10.0.x.x -> 192.168.199.12 não tem efeito:

>route delete 10.0.0.0
>route delete 10.0.0.0 mask 255.255.0.0
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1 if 192.168.199.12
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1 if 0x3

E, embora ainda possa ser simplesmente um problema de roteamento, as tentativas de adicionar ou excluir rotas falham.

Em que nível o cliente Cisco VPN está fazendo o que, na pilha de rede, substitui a capacidade de um administrador local de administrar sua máquina?

O Cisco VPN Client não pode estar usando mágica. Ainda é software em execução no meu computador. Qual mecanismo está usando para interferir na rede da minha máquina? O que acontece quando um pacote IP / ICMP chega na rede? Onde na pilha de rede o pacote é comido?

Veja também

Editar: coisas que ainda não experimentei:

>route delete 10.0.*

Atualização: Como a Cisco abandonou o antigo cliente, em favor do AnyConnect (VPN baseada em HTTP SSL), essa questão, não resolvida, pode ser deixada como uma relíquia do histórico.

No futuro, podemos tentar resolver o mesmo problema com o novo cliente .

    
por Ian Boyd 17.05.2011 / 16:23

9 respostas

52

O problema com o Anyconnect é que ele primeiro modifica a tabela de roteamento, depois cuida e corrige manualmente. Eu encontrei uma solução para isso. Funciona com a versão 3.1.00495, 3.1.05152, 3.1.05170 e provavelmente com qualquer outra coisa na família 3.1. Pode funcionar com outras versões, pelo menos uma ideia semelhante deve funcionar, supondo que o código não seja reescrito. Felizmente para nós, a Cisco colocou a babysitter chamada "baby is awake" em uma biblioteca compartilhada. Então a ideia é que nós previnamos a ação do vpnagentd via LD_PRELOAD.

  1. Primeiro, criamos um arquivo hack.c :

    #include <sys/socket.h>
    #include <linux/netlink.h>
    
    int _ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv()
    {
      int fd=50;          // max fd to try
      char buf[8192];
      struct sockaddr_nl sa;
      socklen_t len = sizeof(sa);
    
      while (fd) {
         if (!getsockname(fd, (struct sockaddr *)&sa, &len)) {
            if (sa.nl_family == AF_NETLINK) {
               ssize_t n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
            }
         }
         fd--;
      }
      return 0;
    }
    
  2. Depois compile assim:

    gcc -o libhack.so -shared -fPIC hack.c
    
  3. Instale libhack.so no caminho da biblioteca da Cisco:

    sudo cp libhack.so  /opt/cisco/anyconnect/lib/
    
  4. Derrube o agente:

    /etc/init.d/vpnagentd stop
    
  5. Certifique-se de que realmente esteja inoperante

    ps auxw | grep vpnagentd
    

    Se não, kill -9 apenas para ter certeza.

  6. Depois, corrija /etc/init.d/vpnagentd adicionando LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so onde o vpnagentd está sendo invocado para que fique assim:

    LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so /opt/cisco/anyconnect/bin/vpnagentd
    
  7. Agora inicie o agente:

    /etc/init.d/vpnagentd start
    
  8. Corrigir iptables, porque AnyConnect mexe com eles:

    iptables-save | grep -v DROP | iptables-restore
    

    Você pode querer fazer algo mais avançado aqui para permitir o acesso apenas a determinados hosts da LAN.

  9. Agora corrija as rotas como quiser, por exemplo:

    route add -net 192.168.1.0 netmask 255.255.255.0 dev wlan0
    
  10. Verifique se eles realmente estão lá:

    route -n
    

Uma versão anterior e mais simples desse hack deu uma função que apenas "retornava 0"; - Esse pôster observou que "O único efeito colateral que eu observei até agora é que o vpnagentd está usando 100% da CPU como relatado pela parte superior, mas a CPU é de apenas 3% do usuário e 20% do sistema, e o sistema é perfeitamente responsivo Eu o acertei, parece estar fazendo duas seleções em um loop quando ocioso retornando de ambos rapidamente, mas ele nunca lê ou escreve - suponho que a chamada que cortei com LD_PRELOAD deveria ter sido lida. para fazer isso, mas é bom o suficiente para mim até agora. Se alguém tiver uma solução melhor, por favor, compartilhe. "

O problema com o hack trivial é que um núcleo de cpu único é 100% o tempo todo, reduzindo efetivamente a contagem de threads de cpu de hardware em um - seja sua conexão vpn ativa ou não. Notei que as seleções que o código estava fazendo estavam em um soquete netlink, que envia dados vpnagentd quando a tabela de roteamento é alterada. O vpnagentd continua percebendo que há uma nova mensagem no netlink socket e chama o routeCallBackHandler para lidar com isso, mas como o hack trivial não limpa a nova mensagem, ela continua sendo chamada repetidas vezes. o novo código fornecido acima libera os dados do netlink para que o loop infinito que causou 100% do cpu não aconteça.

Se algo não funcionar, faça gdb -p $(pidof vpnagentd) , uma vez anexado:

b socket
c
bt

e veja em qual chamada você está. Depois, apenas adivinhe qual deles você quer cortar, adicione-o ao hack.c e recompile.

    
por 05.02.2013 / 01:07
11

Isso é muito complicado, mas se você criar uma VM mínima usando o VMWare Player ou similar e executar o cliente Cisco AnyConnect VPN nele, talvez seja possível configurar o roteamento como desejar usando os adaptadores de rede virtual VMWare ou Basta usar a VM para acessar todos os recursos necessários por meio dos arquivos Cisco SSL VPN e "arrastar / soltar" para / de sua máquina real.

    
por 24.12.2011 / 15:43
5

Shrew Soft VPN fez o truque para mim, também, como Ian Boyd sugerido.

Pode importar perfis de clientes Cisco VPN. Eu usei o Cisco VPN Client versão 5.0.05.0290, e depois de instalar o Shrew VPN (versão 2.1.7) e importar o perfil da Cisco, consegui acessar a LAN local enquanto estava conectado à VPN corporativa sem nenhuma configuração adicional da conexão Shrew VPN (ou software).

    
por 05.03.2013 / 14:17
5

Obrigado ao Sasha Pachev pelo bom hack acima.

vpnagentd também mexe com o resolvedor sobrescrevendo as alterações feitas em /etc/resolv.conf . Eu resolvi isso ganhando a corrida contra ele:

#!/bin/bash

dnsfix() {
    [ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
    while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup #>/dev/null
    do
         cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
    done
    chattr +i /etc/resolv.conf
    diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null 
}

while ! dnsfix
do
    echo "Retrying..."
    chattr -i /etc/resolv.conf
done

Não se esqueça de chattr -i /etc/resolv.conf ao desconectar.

Estou tentando resolvê-lo interceptando o retorno de chamada, como para o método de rotas acima, mas ainda não consigo encontrar o retorno de chamada ou o método correspondente.

Atualização1 / 2: um strace revelou que vpnagentd está usando a inotify API para monitorar as alterações no arquivo do resolvedor. De lá em diante, foi em declive. Aqui está o hack adicional:

int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
  return 0;
}

Isso é um pouco exagerado, já que desabilita o arquivo all procurando pelo agente. Mas parece funcionar bem.

O script wrapper do cliente vpn integra toda a funcionalidade (atualizada para incluir este hack adicional). chattr não é mais usado / necessário.

Atualização 3: configurações de nome de usuário / senha corrigidas no script. Agora ele usa um arquivo vpn.conf com o formato descrito abaixo (e permissões somente raiz).

#!/bin/bash

# Change this as needed
CONF="/etc/vpnc/vpn.conf"
# vpn.conf format
#gateway <IP>
#username <username>
#password <password>
#delete_routes <"route spec"...> eg. "default gw 0.0.0.0 dev cscotun0"
#add_routes <"route spec"...> eg. "-net 192.168.10.0 netmask 255.255.255.0 dev cscotun0" "-host 10.10.10.1 dev cscotun0"

ANYCONNECT="/opt/cisco/anyconnect"

usage() {
    echo "Usage: $0 {connect|disconnect|state|stats|hack}"
    exit 1
}

CMD="$1"
[ -z "$CMD" ] && usage

ID='id -u'

VPNC="$ANYCONNECT/bin/vpn"

dnsfix() {
    [ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
    while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null
    do
         cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
    done
#    chattr +i /etc/resolv.conf
    diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null 
}

case "$CMD" in
    "connect")
        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        HOST='grep ^gateway $CONF | awk '{print $2}''
        USER='grep ^user $CONF | awk '{print $2}''
        PASS='grep ^password $CONF | awk '{print $2}''
        OLDIFS=$IFS
        IFS='"'
        DEL_ROUTES=('sed -n '/^delete_routes/{s/delete_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF')
        ADD_ROUTES=('sed -n '/^add_routes/{s/add_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF')
        IFS=$OLDIFS

        /usr/bin/expect <<EOF
set vpn_client "$VPNC";
set ip "$HOST";
set user "$USER";
set pass "$PASS";
set timeout 5
spawn \$vpn_client connect \$ip
match_max 100000
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    ">> The VPN client is not connected." { exit 0};
    ">> state: Disconnecting" { exit 0};
    "Connect Anyway?"
}
sleep .1
send -- "y\r"
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    "Username:"
}
sleep .1
send -- "\$user\r"
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    "Password: "
}
send -- "\$pass\r";
expect eof
EOF
        sleep 2
        # iptables
        iptables-save | grep -v DROP | iptables-restore

        # routes
        for ROUTE in "${DEL_ROUTES[@]}"
        do
#            echo route del $ROUTE
            route del $ROUTE
        done
        for ROUTE in "${ADD_ROUTES[@]}"
        do
#            echo route add $ROUTE
            route add $ROUTE
        done

        # dns
        while ! dnsfix
        do
            echo "Try again..."
#            chattr -i /etc/resolv.conf
        done

        echo "done."
        ;;
    "disconnect")
#        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        # dns
#        chattr -i /etc/resolv.conf

        $VPNC disconnect
        ;;
    "state"|"stats")
        $VPNC $CMD
        ;;
    "hack")
        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        /etc/init.d/vpnagentd stop
        sleep 1
        killall -9 vpnagentd 2>/dev/null
        cat - >/tmp/hack.c <<EOF
#include <sys/socket.h>
#include <linux/netlink.h>

int _ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv()
{
  int fd=50;          // max fd to try
  char buf[8192];
  struct sockaddr_nl sa;
  socklen_t len = sizeof(sa);

  while (fd) {
     if (!getsockname(fd, (struct sockaddr *)&sa, &len)) {
        if (sa.nl_family == AF_NETLINK) {
           ssize_t n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
        }
     }
     fd--;
  }
  return 0;
}

int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
  return 0;
}
EOF
        gcc -o /tmp/libhack.so -shared -fPIC /tmp/hack.c
        mv /tmp/libhack.so $ANYCONNECT
        sed -i "s+^\([ \t]*\)$ANYCONNECT/bin/vpnagentd+LD_PRELOAD=$ANYCONNECT/lib/libhack.so $ANYCONNECT/bin/vpnagentd+" /etc/init.d/vpnagentd
        rm -f /tmp/hack.c
        /etc/init.d/vpnagentd start
        echo "done."
        ;;
    *)
        usage
        ;;
esac
    
por 28.01.2015 / 19:51
4

Minha empresa ainda usa essa vpn. O cliente vpnc simplesmente altera as configurações do iptables dessa maneira:

# iptables-save
# Generated by iptables-save v1.4.10 on Sun Jun 17 14:12:20 2012
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT DROP [0:0]
-A INPUT -s 123.244.255.254/32 -d 192.168.0.14/32 -j ACCEPT 
-A INPUT -i tun0 -j ACCEPT 
-A INPUT -i lo0 -j ACCEPT
-A INPUT -j DROP 
-A OUTPUT -s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT 
-A OUTPUT -o tun0 -j ACCEPT 
-A OUTPUT -o lo0 -j ACCEPT 
-A OUTPUT -j DROP 
COMMIT

Filtra tudo, exceto o tráfego vpn.

Basta obter o filtro em um arquivo com iptables-save, adicionar linhas de acesso INPUT e OUTPOUT que correspondam às suas necessidades e reaplicar o arquivo com o iptables-restore.

por exemplo, para acessar uma rede local em 192.168.0

# Generated by iptables-save v1.4.10 on Sun Jun 17 14:12:20 2012
*filter
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT DROP [0:0]
-A INPUT -s 123.244.255.254/32 -d 192.168.0.14/32 -j ACCEPT 
-A INPUT -s 192.168.0.0/24 -d 192.168.0.14/32 -j ACCEPT      #local in
-A INPUT -i tun0 -j ACCEPT 
-A INPUT -i lo0 -j ACCEPT 
-A INPUT -j DROP 
-A OUTPUT -s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT 
-A OUTPUT -s 192.168.0.14/32 -d 192.168.0.0/24 -j ACCEPT     #local out
-A OUTPUT -o tun0 -j ACCEPT 
-A OUTPUT -o lo0 -j ACCEPT 
-A OUTPUT -j DROP 
COMMIT
    
por 17.06.2012 / 15:37
3

Alguma notícia sobre isso?

At what level is Cisco VPN client driver doing what in the networking stack that takes overrides a local administrator's ability to administer their machine?

Concordo plenamente e fiquei pensando sobre a mesma coisa.

De qualquer forma, é um aplicativo que requer privilégios de administrador para instalar e, embora seja executado, pode muito bem filtrar o que você faz ...

Minhas tentativas no Windows também falharam:

route change 0.0.0.0 mask 0.0.0.0 192.168.1.1 metric 1
 OK!

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      192.168.1.1    192.168.1.230     21 <-- LAN
          0.0.0.0          0.0.0.0    192.168.120.1    192.168.120.3      2 <-- VPN

Haha. Nenhuma métrica abaixo de 20 aqui parece.

    
por 23.07.2011 / 21:49
3

Não sei se entendi direito, mas primeiro esclareci meu entendimento:

Você tem uma LAN local (por exemplo, digamos 10.0.0.0/16 e um Cisco VPN Server remoto (por exemplo, 64.0.0.0/16). Você deseja se conectar ao servidor VPN através do cliente Cisco VPN e no entanto, você precisa ter o acesso à LAN, neste caso você deseja separar o 10.0.xx / 16 inteiro da conexão VPN). A seguinte rota deve ser adicionada em um cliente Mac:

/sbin/route add -net 10.0 -interface en1

em que en1 é a interface através da qual você está conectado à sua LAN. Eu sei que você pode adicionar a mesma coisa no Windows e no Linux também.

    
por 06.11.2011 / 12:44
2

Como não posso adicionar comentários, postarei aqui. Estou executando no Windows.

A solução usando Virtual Machine e executar AnyConnect dentro da VM e depois usar a VM como um mediador entre o ambiente de trabalho e a rede da empresa não funcionará se o departamento de TI "amado" fizer o roteamento de 0.0.0.0 através de VPN e até mesmo sua rede local (incluindo isso entre seu PC local e VM) é roteado através da VPN (sic!).

Tentei aplicar a solução postada pelo @Sasha Pachev, mas acabei corrigindo o .dll para que ele retornasse 0 no início da função. Eventualmente, depois de alguma luta com a biblioteca dinâmica, eu consegui modificar as tabelas de roteamento de acordo com minhas necessidades, mas aparentemente isso não é suficiente!

Mesmo que minhas regras pareçam estar corretas para conseguir dividir o tunelamento, ainda recebo Falha geral. Você se deparou com um problema semelhante que conseguiu resolvê-lo?

  • Meu gateway para a internet é 192.168.163.2
  • Meu gateway para a rede da empresa é 10.64.202.1 (assim, todo o 10. . . * sub-rede que eu trato como "comapny's")

Esta é a aparência da minha tabela de roteamento agora (após modificações manuais enquanto a VPN está ativada)

masoresultadodopingestáseguindo

C:\Users\Mike>ping-n110.64.10.11Replyfrom10.64.10.11:bytes=32time=162msTTL=127C:\Users\Mike>ping-n18.8.8.8PING:transmitfailed.Generalfailure.C:\Users\Mike>ping-n1192.168.163.2Generalfailure.

Apenasparareferência,vejaabaixocomoatabeladerotasseparecequandoaVPNédesconectada(inalterada)

eéassimqueatabelaseparecequandoaVPNestáconectada(inalterada)Nessecaso,quandoestoutentandopingar8.8.8.8simplesmenterecebotempolimite(jáqueofirewalldaempresanãopermitequeotráfegosaiadaintranet)

    
por 28.02.2014 / 11:12
0

Tente remover as entradas com o gateway 10.64.202.13 veja se ping 8.8.8.8 funciona e, em seguida, adicione-as de volta uma a uma e identifique qual delas está causando o problema.

Como você corrigiu a DLL? Eu não posso nem mesmo modificar a tabela de roteamento porque ela continua adicionando o 0.0.0.0 com o gateway VPN de volta.

    
por 01.05.2014 / 05:42