47 votes

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

Je ne sais pas si vous savez comment pirater la table de routage (sur un Mac) pour éviter de forcer le routage VPN pour tout ce qui passe par un VPN Cisco. En gros, ce que je veux faire, c'est n'avoir que les adresses 10.121.* et 10.122.* sur le VPN et tout le reste directement sur internet.

6voto

user652641 Points 61

L'utilisation de la informations de mehaase, J'ai écrit un script en Python qui simplifie vraiment ce processus sur Mac. Lorsque vous l'exécutez, le script enregistre les informations relatives au 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")

5voto

munr0 Points 21

Le script de Python dans cette réponse précédente a été utile, mais elle n'a pas pris en compte les routes qu'AnyConnect utilisait pour prendre en charge d'autres interfaces sur l'appareil (telles que les interfaces VMware). Il n'était pas non plus en mesure 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

3voto

goofology Points 480

Je voulais une application native que je puisse lancer à l'ouverture de la session (et continuer à la lancer ou la cacher) pour activer le routage Split Tunnel, similaire à une fonction de Locamatic . Peut-être que je vais forker Locamatic à un moment donné et jouer avec. Il se peut aussi que je télécharge cet AppleScript sur Github. Je ne voulais pas m'encombrer d'un démon comme este suggère.

Ce script suppose que le VPN a la valeur par défaut de VPN (Cisco IPSec) et la route VPN est 10.10.10.1/22 > 10.10.20.10 . Ceux-ci devront être modifiés ou des itinéraires supplémentaires devront être ajoutés. Exécutez le terminal > netstat -rn lorsque le VPN est connecté (avant d'activer ce script) pour voir les routes ajoutées au VPN.

Ce script génère également des notifications de type growl dans le centre de notification :)

enter image description here

J'ai rencontré quelques problèmes avec Mark E. Haase 's répondre car mon Cisco VPN modifie la passerelle existante d'une passerelle de UCSc à un UGScI (spécifique à l'interface en0) et ajoute la passerelle VPN en tant que route UCS ce qui nécessite la suppression de deux passerelles par défaut et l'ajout de la route d'origine. UGSc passerelle par défaut

Merci pour StackExchange/google, c'est mon premier AppleScript et je n'aurais pas été capable de l'assembler 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 :

Split Tunnel app save settings

clic droit>show package contents, ajouter ce qui suit à info.plist (cela cache l'icône de l'application dans le dock, ce qui nécessite l'utilisation d'Activity Monitor ou du terminal). pkill -f 'Split Tunnel' pour quitter l'application, omettre si vous VOULEZ une icône de dock :

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

créer une nouvelle ligne routeNOPASSWD (sans extension) en utilisant EXACTEMENT le code suivant (cela peut empêcher l'accès sudo si c'est mal fait, google visudo pour plus d'informations - cela permet aux commandes sudo de l'AppleScript de s'exécuter SANS demande de mot de passe, à omettre si vous VOULEZ une demande de mot de passe lorsque la table de routage doit être modifiée) :

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

copier ce fichier sur /etc/sudoers.d

exécuter les commandes suivantes dans le terminal (la deuxième commande demandera le mot de passe - cela permet à l'utilisateur d'accéder à l'ordinateur) sudo route dans l'AppleScript à exécuter SANS demande de mot de passe, omettre si une demande de mot de passe est souhaitée lorsque script modifie la table de routage)

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

enfin, ajouter l'application aux Préférences système > Utilisateurs et groupes > éléments de connexion

Split Tunnel Login Item

2voto

Sani Huttunen Points 10433

Il est plus que probable que votre administrateur veuille configurer les connexions VPN de manière à utiliser le routage local pour les sous-réseaux 10.121.* et 10.122.* et à laisser la machine distante (votre machine personnelle) acheminer toutes les autres requêtes. (cela leur permet d'économiser de la bande passante et de la responsabilité).

Utilisez-vous le "VPN C" de Cisco ?

i

1voto

Tom Lokhorst Points 7733

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

SistemesEz.com

SystemesEZ est une communauté de sysadmins où vous pouvez résoudre vos problèmes et vos doutes. Vous pouvez consulter les questions des autres sysadmins, poser vos propres questions ou résoudre celles des autres.

Powered by:

X