Como forçar o roteamento de túnel dividido no Mac para uma VPN da Cisco

40

Alguém sabe como hackear a tabela de roteamento (em um mac) para derrotar o forçamento do roteamento VPN para tudo sobre uma VPN cisco? praticamente o que eu quero fazer é ter apenas endereços 10.121. * e 10.122. * pela VPN e tudo mais diretamente para a Internet.

Sathyajith Bhat
fonte

Respostas:

27

O seguinte funciona para mim. Execute-os após conectar-se à Cisco VPN. (Estou usando o cliente Cisco interno do OS X, não o cliente da marca Cisco.)

sudo route -nv add -net 10 -interface utun0
sudo route change default 192.168.0.1

Substitua 10no primeiro comando pela rede que está do outro lado do túnel.

Substitua 192.168.0.1pelo gateway da sua rede local.

Coloquei em um script bash, assim:

$ cat vpn.sh 
#!/bin/bash

if [[ $EUID -ne 0 ]]; then
    echo "Run this as root"
    exit 1
fi

route -nv add -net 10 -interface utun0
route change default 192.168.0.1

Também encontrei uma explicação sobre como executar isso automaticamente quando você conecta a VPN, mas é tarde na sexta-feira e não tenho vontade de tentar :)

Editar:

Desde então, deixei o trabalho em que estava usando a Cisco VPN, portanto isso é de memória.

O 10no primeiro comando é a rede que você deseja rotear pela VPN. 10é mão curta para 10.0.0.0/8. No caso de Tuan Anh Tran, parece que a rede é 192.168.5.0/24.

Quanto a qual gateway especificar no segundo comando, ele deve ser seu gateway local. Quando você faz login em uma VPN que evita o túnel dividido, ela aplica essa política alterando suas tabelas de roteamento para que todos os pacotes sejam roteados na interface virtual. Então, você deseja alterar sua rota padrão para a que era antes de acessar a VPN .

A maneira mais fácil de descobrir o gateway é executar netstat -rnantes de fazer login na VPN e olhar o endereço IP à direita do destino "padrão". Por exemplo, aqui está o que parece na minha caixa agora:

Internet:
Destination        Gateway            Flags        Refs      Use   Netif Expire
default            10.0.1.1           UGSc           29        0     en1
10.0.1/24          link#5             UCS             3        0     en1
10.0.1.1           0:1e:52:xx:xx:xx   UHLWIi         55   520896     en1    481
10.0.1.51          7c:c5:37:xx:xx:xx  UHLWIi          0     1083     en1    350
10.0.1.52          127.0.0.1          UHS             0        0     lo0

Meu gateway é 10.0.1.1- fica à direita do destino "padrão".

Mark E. Haase
fonte
11
Você pode me explicar um pouco mais? meu ifconfig retorna utun0: flags = 8051 <UP, POINTOPOINT, RUNNING, MULTICAST> mtu 1280 inet 192.168.5.102 -> 192.168.5.102 máscara de rede 0xffffffff. Também não entendo o que devo substituir pelo número 10 acima. Obrigado.
Tuan Anh Tran
@TuanAnhTran: Eu atualizei minha resposta. Por favor, deixe-me saber se isso ajuda.
precisa
Para a versão mais recente, tenho o /Applications/VPNClient.app instalado e não vejo utun0 listado pelo ifconfig. Vejo os adaptadores gif0, stf0 e fw0. Como determino qual é o adaptador correto? Não vejo diferença na saída do ifconfig com e sem o vpn conectado (exceto o valor MTU de en1).
precisa
11
Para aqueles que não estão familiarizados com o LaunchDaemons, escrevi um guia na minha resposta aqui, descrevendo como chamar um script para executar sempre que você se conectar à VPN . (A propósito, marque uma resposta excelente com +1, mas eu precisava de um pouco mais para fazer a essência funcionar).
amigos estão dizendo sobre dr jimbob
11
Infelizmente isso não funciona no meu cliente Cisco AnyConnect.
jeremyjjbrown
5

Usando as informações do mehaase, escrevi um script Python que realmente simplifica esse processo no Mac. Quando você o executa, o script salva suas informações de firewall, lança o cliente AnyConnect, aguarda o login e, em seguida, corrige as rotas e o firewall. Basta executar o script no 'terminal'.

#!/usr/bin/python

# The Cisco AnyConnect VPN Client is often configured on the server to block
# all other Internet traffic. So you can be on the VPN <b>OR</b> you can have
# access to Google, etc.
#
# This script will fix that problem by repairing your routing table and
# firewall after you connect.
#
# The script does require admin (super user) access. If you are prompted for
# a password at the start of the script, just enter your normal Mac login
# password.
#
# The only thing you should need to configure is the vpn_ip_network.
# Mine is 10.x.x.x so I just specify '10' but you could be more specific
# and use something like '172.16'
vpn_ip_network = '10'

import sys
import subprocess


def output_of(cmd):
    lines = subprocess.Popen(cmd if isinstance(cmd, list) else cmd.split(' '), stdout=subprocess.PIPE, stderr=subprocess.STDOUT).communicate()[0]
    try:
        lines = lines.decode('utf-8')
    except Exception:
        pass
    return [line.strip() for line in lines.strip().split('\n')]

sys.stdout.write("Mac Account Login ")
good_firewall_ids = set([line.partition(' ')[0] for line in output_of('sudo ipfw -a list')])
sys.stdout.write('Firewall Saved.\n')

gateway = None
for line in output_of('route get default'):
    name, delim, value = line.partition(':')
    if name == 'gateway':
        gateway = value.strip()
        p = subprocess.Popen(['/Applications/Cisco/Cisco AnyConnect VPN Client.app/Contents/MacOS/Cisco AnyConnect VPN Client'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT)
        was_disconnected = False
        while True:
            line = p.stdout.readline()
            if line == '' or p.poll():
                sys.stdout.write("Never connected!\n")
                break
            try:
                line = line.decode('utf-8')
            except Exception:
                pass
            if 'Disconnected' in line:
                sys.stdout.write('Waiting for you to enter your VPN password in the VPN client...\n')
                was_disconnected = True
            if 'Connected' in line:
                if was_disconnected:
                    subprocess.Popen(['sudo','route','-nv','add','-net',vpn_ip_network,'-interface','utun0'], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).wait()
                    subprocess.Popen(['sudo','route','change','default',gateway], stdout=subprocess.PIPE, stderr=subprocess.STDOUT).wait()
                    unfriendly_firewall_ids = list(set([line.partition(' ')[0] for line in output_of('sudo ipfw -a list')])-good_firewall_ids)
                    extra = ''
                    if unfriendly_firewall_ids:
                        subprocess.Popen('sudo ipfw delete'.split(' ') + unfriendly_firewall_ids, stdout=subprocess.PIPE, stderr=subprocess.STDOUT).wait()
                        sys.stdout.write("VPN connection established, routing table repaired and %d unfriendly firewall rules removed!\n" % len(unfriendly_firewall_ids))
                    else:
                        sys.stdout.write("VPN connection established and routing table repaired!\n")
                else:
                    try:
                        subprocess.Popen.kill(p)
                        sys.stdout.write('VPN was already connected. Extra VPN client closed automatically.\n')
                    except Exception:
                        sys.stdout.write('VPN was already connected. Please close the extra VPN client.\n')
                break
        break
else:
    sys.stdout.write("Couldn't get gateway. :-(\n")
user652641
fonte
4

O script Python nesta resposta anterior foi útil, no entanto, não tratou das rotas que o AnyConnect usou para controlar outras interfaces no dispositivo (como interfaces VMware). Também não foi capaz de lidar com várias redes VPN.

Aqui está o script que eu uso:

#!/bin/bash

HOME_NETWORK=192.168
HOME_GATEWAY=192.168.210.1
WORK_NETWORKS="X.X.X.X/12 10.0.0.0/8 X.X.X.X/16"

# What should the DNS servers be set to?
DNS_SERVERS="10.192.2.45 10.216.2.51 8.8.8.8"

##
## Do not edit below this line if you do not know what you are doing.
##
function valid_ip()
{
    local  ip=$1
    local  stat=1

    if [[ $ip =~ ^[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}\.[0-9]{1,3}$ ]]; then
        OIFS=$IFS
        IFS='.'
        ip=($ip)
        IFS=$OIFS
        [[ ${ip[0]} -le 255 && ${ip[1]} -le 255 \
            && ${ip[2]} -le 255 && ${ip[3]} -le 255 ]]
        stat=$?
    fi
    return $stat
}

# Nuke any DENY firewall rules
for RULE in `sudo ipfw list | grep deny | awk '{print $1}' | xargs`; do sudo ipfw delete $RULE; done

# Delete any routes for the home network that Anyconnect might have made
sudo route delete -net ${HOME_NETWORK}
sudo route add -net ${HOME_NETWORK} ${HOME_GATEWAY}

# Get the AnyConnect interface
ANYCONNECT_INTERFACE=`route get 0.0.0.0 | grep interface | awk '{print $2}'`

# Add the work routes
for NETWORK in ${WORK_NETWORKS}; do
    sudo route -nv add -net ${NETWORK} -interface ${ANYCONNECT_INTERFACE}
done

# Set the default gateway
sudo route change default ${HOME_GATEWAY}

# Mass route changes
for NET in `netstat -nr | grep -e ^${HOME_NETWORK} | grep utun1 | awk '{print $1}' | xargs`; do 
    if valid_ip ${NET}; then
        echo "Changing route for network"
        sudo route change ${NET} ${HOME_GATEWAY}
    else
        echo "Changing route for host"
        sudo route change -net ${NET} ${HOME_GATEWAY}
    fi      
done

# Set the nameservers
sudo scutil << EOF
open
d.init
d.add ServerAddresses * ${DNS_SERVERS}
set State:/Network/Service/com.cisco.anyconnect/DNS
quit
EOF
Kate Grey
fonte
Isso funciona com o Cisco anyconnect 3.1.0? Eu acho que não ... Você tem um script atualizado para 3.1.0? Obrigado!
costa
2

É muito provável que seu administrador deseje configurar conexões VPN para usar o roteamento local para as sub-redes 10.121. * E 10.122. * E deixe o controle remoto (sua máquina doméstica) rotear todo o restante das solicitações. (economiza largura de banda e responsabilidade)

Você está usando o "VPN Client" da Cisco? OS OS?

se você usar a VPN do OS X (configurada através do Painel de Preferências de Rede), poderá clicar em "avançado" e selecionar a guia "VPN sob demanda". depois forneça as sub-redes necessárias para a VPN usar.

Toymakerii
fonte
4
O cliente OS X vpn possui uma opção "Cisco" separada (separada de PPTP e L2TP) que não possui as opções "VPN on Demand".
Mark E. Haase
2

Eu queria um 'aplicativo' nativo que eu possa executar no logon (e continuar executando / oculto) para ativar o roteamento do Split Tunnel, semelhante a uma função da Locamatic . Talvez eu bata na Locamatic em algum momento e brinque com ela. Também posso enviar este AppleScript para o Github. Eu não queria mexer com um daemon, como esta resposta sugere.

Este script assume que a VPN tem VPN (Cisco IPSec)nome padrão e a rota da VPN é 10.10.10.1/22> 10.10.20.10. Isso precisará ser alterado / rotas adicionais adicionadas. Execute o terminal> netstat -rnquando a VPN estiver conectada (antes de ativar este script) para ver as rotas adicionadas à VPN.

Esse script também gera notificações no estilo de rosnado no Notification Center :)

insira a descrição da imagem aqui

Encontrei alguns problemas com a resposta de Mark E. Haase , pois minha VPN da Cisco modifica o gateway existente de uma rota para (en0 específica da interface) e adiciona o gateway da VPN como uma rota, exigindo a exclusão de dois gateways padrão e a adição de volta. o gateway padrão originalUCScUGScIUCSUGSc

Graças a Deus pelo StackExchange / google, este é o meu primeiro AppleScript e eu não seria capaz de montá-lo sem algumas horas de pesquisa no Google.

Sugestões / correções / otimizações são bem-vindas!

AppleScript ( GitHubGist ):

global done
set done to 0

on idle
    set status to do shell script "scutil --nc status "VPN (Cisco IPSec)" | sed -n 1p"
    # do shell script "scutil --nc start "VPN (Cisco IPSec)"
    if status is "Connected" then
        if done is not 1 then
            display notification "VPN Connected, splitting tunnel"
            set gateway to do shell script "( netstat -rn | awk '/default/ {if ( index($6, \"en\") > 0 ){print $2} }' ) # gets non-VPN default gateway"
            do shell script "sudo route delete default" # deletes VPN-assigned global (UCS) default gateway
            do shell script "sudo route delete default -ifscope en0" # deletes en0 interface-specific (UGScI) LOCAL non-vpn gateway that prevents it being re-added as global default gateway
            do shell script "sudo route add default " & gateway # re-adds LOCAL non-vpn gateway (from get command above) as global default gateway
            do shell script "sudo route add 10.10.10.1/22 10.10.20.10" # adds VPN route
            display notification "VPN tunnel has been split"
            set done to 1
        end if
    else
        if done is not 2 then
            display notification "VPN Disconnected"
            set done to 2

        end if
    end if
    return 5
end idle

salvar como um aplicativo:

Configurações de salvamento do aplicativo Split Tunnel

clique com o botão direito do mouse em> mostrar o conteúdo do pacote, adicione o seguinte a info.plist (isso oculta o ícone do aplicativo da dock, exigindo o uso do Activity Monitor ou do terminal> pkill -f 'Split Tunnel'para sair do aplicativo, omita se você QUER um ícone de dock:

<key>LSBackgroundOnly</key>
<string>1</string>

crie um novo routeNOPASSWDarquivo de uma linha (sem extensão) usando o código a seguir EXATAMENTE (isso pode impedir o acesso ao sudo se for feito incorretamente, procure visudomais informações no google - isso permite que os comandos sudo no AppleScript sejam executados SEM um prompt de senha, omita se você QUER um prompt de senha quando a tabela de roteamento precisar ser alterada):

%admin ALL = (ALL) NOPASSWD: /sbin/route

copie este arquivo para /etc/sudoers.d

execute os seguintes comandos no terminal (o segundo comando solicitará a senha - isso permite que os sudo routecomandos no AppleScript sejam executados SEM solicitar a senha, omita se um prompt de senha for desejado quando o script estiver alterando a tabela de roteamento)

chmod 440 /private/etc/sudoers.d/routeNOPASSWD
sudo chown root /private/etc/sudoers.d/routeNOPASSWD

finalmente, adicione o aplicativo a Prefs do sistema> Usuários e grupos> itens de login

Item de login do túnel dividido

goofology
fonte
1

Você deve solicitar ao administrador do roteador ao qual está se conectando para configurar um "grupo" separado que faz o tunelamento dividido e fornece um arquivo PCF que contém o nome e a senha do grupo.

Vebjorn Ljosa
fonte
2
isso não vai acontecer :) Eles são paranóicos
1

Eu tive o mesmo problema e consegui isso graças a @mehaase

Depois de criar o ~/vpn.shcomo respondido por @mehaase, você pode colocar isso em um script de automação de aplicativo executável, seguindo estas etapas:

  1. Usando o Automator, crie um novo aplicativo
  2. Adicione "Executar um AppleScript" em Biblioteca> Utilitários
  3. Entrar: do shell script "sudo ~/vpn.sh" with administrator privileges
  4. Salve 

Você também pode precisar executar chmod 700 ~/vpn.shno Terminal para conceder privilégios de execução ao script.

Após conectar-se à VPN, você pode simplesmente executar este script de aplicativo. Digite sua senha de administrador e clique em OK - Concluído. :)

Dwight Brown
fonte