Comment forcer le routage de tunnel divisé sur Mac vers un VPN Cisco

40

Tout le monde sait comment pirater la table de routage (sur un mac) pour éviter le forçage du routage VPN pour chaque chose sur un VPN cisco? En gros, ce que je veux faire, c’est d’avoir seulement 10.121. * et 10.122. * adresses sur le VPN et tout le reste directement sur Internet.

Sathyajith Bhat
la source

Réponses:

27

Ce qui suit fonctionne pour moi. Exécutez-les après vous être connecté au VPN Cisco. (J'utilise le client Cisco intégré d'OS X, pas le client de marque Cisco.)

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

Remplacez 10dans la première commande le réseau situé de l'autre côté du tunnel.

Remplacez 192.168.0.1par la passerelle de votre réseau local.

Je l'ai mis dans un script bash, comme ceci:

$ 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

J'ai également trouvé une explication sur la manière de l' exécuter automatiquement lorsque vous vous connectez au VPN, mais il est tard vendredi et je n'ai pas envie de l'essayer :)

Modifier:

Depuis, j'ai quitté le travail où j'utilisais le réseau privé virtuel Cisco. C'est donc en mémoire.

La 10première commande est le réseau que vous souhaitez router sur le VPN. 10est la main courte pour 10.0.0.0/8. Dans le cas de Tuan Anh Tran, il semble que le réseau soit 192.168.5.0/24.

Quant à la passerelle à spécifier dans la deuxième commande, ce devrait être votre passerelle locale. Lorsque vous vous connectez à un VPN qui empêche le tunneling fractionné, il applique cette stratégie en modifiant vos tables de routage afin que tous les paquets soient routés sur l'interface virtuelle. Par conséquent, vous souhaitez rétablir votre itinéraire par défaut, tel qu’il était avant d’être connecté au VPN .

Le moyen le plus simple de comprendre la passerelle consiste à s'exécuter netstat -rnavant de vous connecter au VPN et à regarder l'adresse IP à droite de la destination "par défaut". Par exemple, voici à quoi cela ressemble sur ma boîte en ce moment:

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

Ma passerelle est 10.0.1.1- elle se trouve à droite de la destination "par défaut".

Mark E. Haase
la source
1
Pouvez-vous expliquer un peu plus pour moi? mon ifconfig retourne utun0: flags = 8051 <UP, POINTOPOINT, RUNNING, MULTICAST> mtu 1280 inet 192.168.5.102 -> 192.168.5.102 masque de réseau 0xffffffff. Aussi, je ne comprends pas ce que je devrais remplacer par le chiffre 10 ci-dessus. Merci.
Tuan Anh Tran
@TuanAnhTran: J'ai mis à jour ma réponse. S'il vous plaît laissez-moi savoir si cela aide.
Mark E. Haase
Pour la dernière version, j'ai /Applications/VPNClient.app installé et je ne vois pas utun0 répertorié par ifconfig. Je vois les adaptateurs gif0, stf0 et fw0. Comment déterminer quel est le bon adaptateur? Je ne vois aucune différence dans la sortie ifconfig avec et sans vpn connecté (sauf pour la valeur MTU de en1).
haridsv
1
Pour ceux qui ne sont pas familiers avec LaunchDaemons, j’ai écrit ici un guide décrivant comment appeler un script à exécuter à chaque fois que vous vous connectez à un réseau VPN . (Au fait, +1 excellente réponse, mais il me fallait un peu plus pour que l'essentiel fonctionne).
dr jimbob
1
Malheureusement, cela ne fonctionne pas sur mon client Cisco AnyConnect.
jeremyjjbrown
5

En utilisant les informations de mehaase, j'ai écrit un script Python qui simplifie vraiment ce processus sur Mac. Lorsque vous l'exécutez, le script enregistre vos informations de pare-feu, lance le client AnyConnect, attend la connexion, puis corrige les routes et le pare-feu. Il suffit de lancer le script à partir de '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")
utilisateur652641
la source
4

Le script Python de cette réponse précédente était utile, mais il ne tenait pas compte des itinéraires utilisés par AnyConnect pour prendre en charge d'autres interfaces sur le périphérique (telles que les interfaces VMware). Il n'était pas non plus capable de gérer plusieurs réseaux VPN.

Voici le script que j'utilise:

#!/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 Gray
la source
Est-ce que cela fonctionne avec cisco anyconnect 3.1.0? Je ne pense pas que ce soit le cas ... Avez-vous un script mis à jour pour la version 3.1.0? Merci!
costa
2

Il est fort probable que votre administrateur souhaite configurer des connexions VPN pour utiliser le routage local pour les sous-réseaux 10.121. * Et 10.122. * Et laisser la machine distante (votre ordinateur personnel) acheminer le reste des demandes. (cela leur évite de la bande passante et de la responsabilité)

Utilisez-vous le "client VPN" de Cisco? OS OS X?

Si vous utilisez le VPN d'OS X (configuré via la sous-fenêtre des préférences de réseau), vous devriez pouvoir cliquer sur "avancé" et sélectionner l'onglet "VPN à la demande". puis fournissez les sous-réseaux nécessaires au VPN.

Toymakerii
la source
4
Le client vpn OS X possède une option "Cisco" distincte (distincte de PPTP et L2TP) qui ne dispose pas des options "VPN à la demande".
Mark E. Haase
2

Je voulais une application native que je puisse exécuter à l'ouverture de session (et continuer à s'exécuter / masquée) pour activer le routage Split Tunnel, similaire à une fonction de Locamatic . Peut-être que je bifurquerai à un moment donné Locamatic et que je jouerai avec. Je peux aussi télécharger ce AppleScript sur Github. Je ne voulais pas jouer avec un démon comme le suggère cette réponse.

Ce script suppose que VPN a un VPN (Cisco IPSec)nom par défaut et que l'itinéraire VPN est 10.10.10.1/22> 10.10.20.10. Celles-ci devront être changées / des itinéraires supplémentaires ajoutés. Exécutez le terminal> netstat -rnlorsque le VPN est connecté (avant d'activer ce script) pour voir les itinéraires ajoutés au VPN.

Ce script génère également des notifications de style Growl dans le Centre de notifications :)

entrez la description de l'image ici

Je suis tombé sur quelques problèmes avec Mark E. Haase de réponse que mes modifie VPN Cisco la passerelle existante d'un UCScà un UGScIitinéraire (spécifique d'interface en0) et ajoute la passerelle VPN comme UCSitinéraire, ce qui nécessite la suppression de deux passerelles par défaut et rajoutant la UGScpasserelle par défaut d' origine

Dieu merci pour StackExchange / google, il s’agit de mon premier AppleScript et je n’aurais pas pu le mettre en place sans quelques heures de recherche sur Google.

Suggestions / corrections / optimisations bienvenues!

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

enregistrer en tant qu'application:

Paramètres de sauvegarde de l'application Split Tunnel

clic droit> afficher le contenu du paquet, ajouter ce qui suit à info.plist (cela masque l'icône de l'application du dock, nécessitant l'utilisation d'Activity Monitor ou d'un terminal> pkill -f 'Split Tunnel'pour quitter l'application, omettez si vous VOULEZ une icône de dock:

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

créez un nouveau routeNOPASSWDfichier d' une ligne (sans extension) en utilisant EXACTEMENT le code suivant (cela peut empêcher un accès sudo s'il est mal effectué, google visudopour plus d'informations - ceci permet aux commandes sudo du AppleScript de s'exécuter SANS invite de mot de passe, omettre si vous VOULEZ une invite de mot de passe lorsque la table de routage doit être modifiée):

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

copier ce fichier dans /etc/sudoers.d

lancez les commandes suivantes dans le terminal (la deuxième commande demandera le mot de passe - ceci permet aux sudo routecommandes du script AppleScript de s'exécuter SANS invite de mot de passe; omettre si une invite de mot de passe est souhaitée lorsque le script modifie la table de routage)

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

Enfin, ajoutez l'application dans Préférences système> Utilisateurs et groupes> Éléments de connexion.

Elément de connexion de tunnel divisé

goofology
la source
1

Vous devriez pouvoir demander à l'administrateur du routeur auquel vous vous connectez de configurer un "groupe" distinct qui effectue le tunneling fractionné et vous donne un fichier PCF contenant le nom du groupe et le mot de passe du groupe pour ce groupe.

Vebjorn Ljosa
la source
2
ça ne va pas arriver :) Ils sont paranoïaques
1

J'ai eu le même problème et cela a fonctionné grâce à @mehaase

Après avoir créé la ~/vpn.shréponse as @mehaase, vous pouvez l'insérer dans un script exécutable d'automate d'application en procédant comme suit:

  1. Utiliser Automator pour créer une nouvelle application
  2. Ajouter "Exécuter un AppleScript" sous Bibliothèque> Utilitaires
  3. Entrer: do shell script "sudo ~/vpn.sh" with administrator privileges
  4. sauver

Vous devrez peut-être également exécuter à chmod 700 ~/vpn.shpartir de Terminal pour accorder au script des privilèges d'exécution.

Une fois connecté au VPN, vous pouvez simplement exécuter ce script d'application. Entrez votre mot de passe administrateur et cliquez sur ok - Terminé. :)

Dwight Brown
la source