So erzwingen Sie Split-Tunnel-Routing auf einem Mac für ein Cisco VPN

40

Weiß jemand, wie man die Routing-Tabelle (auf einem Mac) hackt, um das Erzwingen von VPN-Routing für alles über ein Cisco-VPN zu verhindern? Eigentlich möchte ich nur 10.121. * und 10.122. * Adressen über das VPN haben und alles andere direkt ins Internet.

Sathyajith Bhat
quelle

Antworten:

27

Folgendes funktioniert für mich. Führen Sie diese aus, nachdem Sie eine Verbindung zum Cisco VPN hergestellt haben. (Ich verwende den integrierten Cisco-Client von OS X, nicht den Cisco-Markenclient.)

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

Ersetzen Sie 10im ersten Befehl das Netzwerk, das sich auf der anderen Seite des Tunnels befindet.

Ersetzen 192.168.0.1Sie durch das Gateway Ihres lokalen Netzwerks.

Ich habe es in ein Bash-Skript geschrieben:

$ 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

Ich habe auch eine Erklärung gefunden, wie dies automatisch ausgeführt wird, wenn Sie das VPN verbinden, aber es ist spät am Freitag und ich habe keine Lust, es zu versuchen :)

Bearbeiten:

Ich habe seitdem den Job verlassen, bei dem ich das Cisco VPN verwendet habe, daher stammt dies aus dem Speicher.

Der 10erste Befehl ist das Netzwerk, das Sie über das VPN weiterleiten möchten. 10ist eine kurze Hand für 10.0.0.0/8. In Tuan Anh Trans Fall sieht es so aus, als wäre das Netzwerk 192.168.5.0/24.

Welches Gateway im zweiten Befehl angegeben werden soll, sollte Ihr lokales Gateway sein. Wenn Sie sich bei einem VPN anmelden, das Split-Tunneling verhindert, wird diese Richtlinie durchgesetzt, indem Sie Ihre Routing-Tabellen so ändern, dass alle Pakete über die virtuelle Schnittstelle weitergeleitet werden. Sie möchten also Ihre Standardroute auf die vor dem Einstieg in das VPN festgelegte Route zurücksetzen .

Der einfachste Weg, das Gateway herauszufinden, besteht darin, netstat -rnvor der Anmeldung am VPN die IP-Adresse rechts vom "Standard" -Ziel zu überprüfen. Zum Beispiel sieht es auf meiner Box jetzt so aus:

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

Mein Gateway ist 10.0.1.1- es befindet sich rechts vom "Standard" -Ziel.

Mark E. Haase
quelle
1
Kannst du mir mehr erklären? meine ifconfig gibt utun0 zurück: flags = 8051 <UP, POINTOPOINT, RUNNING, MULTICAST> mtu 1280 inet 192.168.5.102 -> 192.168.5.102 netmask 0xffffffff. Ich verstehe auch nicht, was ich durch die Nummer 10 oben ersetzen soll. Danke.
Tuan Anh Tran
@TuanAnhTran: Ich habe meine Antwort aktualisiert. Bitte lassen Sie mich wissen, ob das hilft.
Mark E. Haase
Für die neueste Version habe ich /Applications/VPNClient.app installiert und utun0 wird von ifconfig nicht aufgelistet. Ich sehe gif0, stf0 und fw0 Adapter. Wie bestimme ich, welcher Adapter der richtige ist? Ich sehe keinen Unterschied in der ifconfig-Ausgabe mit und ohne angeschlossenem VPN (außer MTU-Wert von en1).
Haridsv
1
Für diejenigen, die mit LaunchDaemons nicht vertraut sind, habe ich in meiner Antwort hier eine Anleitung geschrieben, in der beschrieben wird, wie Sie ein Skript aufrufen, das bei jeder VPN-Verbindung ausgeführt wird . (Übrigens +1 ausgezeichnete Antwort, aber ich brauchte ein bisschen mehr, um das Wesentliche zum Laufen zu bringen).
Dr. Jimbob
1
Leider funktioniert dies auf meinem Cisco AnyConnect-Client nicht.
Jeremyjjbrown
5

Mit den Informationen von mehaase habe ich ein Python-Skript geschrieben, das diesen Vorgang auf dem Mac wirklich vereinfacht. Wenn Sie es ausführen, speichert das Skript Ihre Firewall-Informationen, startet den AnyConnect-Client, wartet auf die Anmeldung und repariert dann die Routen und die Firewall. Führen Sie einfach das Skript vom 'Terminal' aus.

#!/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
quelle
4

Das Python-Skript in dieser vorherigen Antwort war hilfreich, es hat sich jedoch nicht um die Routen gekümmert, die AnyConnect verwendet hat, um andere Schnittstellen auf dem Gerät zu übernehmen (z. B. VMware-Schnittstellen). Es war auch nicht in der Lage, mehrere VPN-Netzwerke zu verwalten.

Hier ist das Skript, das ich benutze:

#!/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
quelle
Funktioniert das mit cisco anyconnect 3.1.0? Ich glaube nicht ... Haben Sie ein aktualisiertes Skript für 3.1.0? Vielen Dank!
Costa
2

Höchstwahrscheinlich sollte Ihr Administrator VPN-Verbindungen für die Verwendung des lokalen Routings für die Subnetze 10.121. * Und 10.122. * Einrichten und den Remotecomputer (Ihren Heimcomputer) die restlichen Anforderungen weiterleiten lassen. (Es spart ihnen Bandbreite und Haftung)

Verwenden Sie den "VPN-Client" von Cisco? OS OS X?

Wenn Sie das VPN von OS X verwenden (das über das Einstellungsfenster für das Netzwerk eingerichtet wird), sollten Sie auf "Erweitert" klicken und die Registerkarte "VPN on Demand" auswählen können. Stellen Sie dann die für die Verwendung des VPN erforderlichen Subnetze bereit.

Toymakerii
quelle
4
Der OS X-VPN-Client verfügt über eine separate "Cisco" -Option (getrennt von PPTP und L2TP), die nicht über die "VPN-on-Demand" -Option verfügt.
Mark E. Haase
2

Ich wollte eine native 'App', die ich bei der Anmeldung ausführen kann (und die ausgeführt wird / ausgeblendet bleibt ), um das Routing für geteilte Tunnel zu aktivieren, ähnlich einer Funktion von Locamatic . Vielleicht gabel ich Locamatic irgendwann und spiele damit. Ich kann dieses AppleScript auch auf Github hochladen. Ich wollte mich nicht mit einem Daemon anlegen, wie diese Antwort nahelegt.

In diesem Skript wird davon ausgegangen, dass VPN den Standardnamen VPN (Cisco IPSec)und die VPN-Route 10.10.10.1/22> hat 10.10.20.10. Diese müssen geändert / zusätzliche Routen hinzugefügt werden. Führen Sie terminal> aus, netstat -rnwenn eine VPN-Verbindung besteht (bevor Sie dieses Skript aktivieren), um VPN-hinzugefügte Routen anzuzeigen.

Dieses Skript generiert auch Benachrichtigungen im Growl-Stil im Notification Center :)

Bildbeschreibung hier eingeben

Ich hatte einige Probleme mit der Antwort von Mark E. Haase , als mein Cisco VPN das vorhandene Gateway von einer auf eine (für die en0-Schnittstelle spezifische) Route änderte und das VPN-Gateway als Route hinzufügte , wodurch zwei Standardgateways gelöscht und erneut hinzugefügt werden mussten das ursprüngliche Standard-GatewayUCScUGScIUCSUGSc

Gott sei Dank für StackExchange / google, dies ist mein erstes AppleScript und ich hätte es ohne ein paar Stunden Googeln nicht zusammenstellen können.

Vorschläge / Korrekturen / Optimierungen erwünscht!

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

als app speichern:

Split Tunnel App Einstellungen speichern

Rechtsklick> Paketinhalt anzeigen, Folgendes zu info.plist hinzufügen (dies verbirgt das App-Symbol vor dem Dock, was die Verwendung von Activity Monitor oder Terminal erforderlich macht> pkill -f 'Split Tunnel'um die App zu beenden, weglassen, wenn Sie ein Dock-Symbol möchten:

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

Erstellen Sie eine neue einzeilige routeNOPASSWDDatei (ohne Erweiterung) mit dem folgenden Code GENAU (dies kann den Sudo-Zugriff verhindern, wenn dies nicht korrekt ausgeführt wird. visudoWeitere Informationen finden Sie bei Google. Dadurch können die Sudo-Befehle im AppleScript OHNE Kennworteingabeaufforderung ausgeführt werden. Lassen Sie sie aus, wenn Sie möchten eine Passwortabfrage, wenn die Routing-Tabelle geändert werden muss):

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

Kopieren Sie diese Datei nach /etc/sudoers.d

Führen Sie die folgenden Befehle im Terminal aus (der zweite Befehl sudo routefordert zur Eingabe eines Kennworts auf - dies ermöglicht, dass die Befehle im AppleScript OHNE Aufforderung zur Kennworteingabe ausgeführt werden. Lassen Sie dies aus, wenn eine Kennwortaufforderung gewünscht wird, wenn das Skript die Routingtabelle ändert.)

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

Fügen Sie die App schließlich zu Systemeinstellungen> Benutzer und Gruppen> Anmeldeelemente hinzu

Split Tunnel Login Item

Goofologie
quelle
1

Sie sollten in der Lage sein, den Administrator des Routers, zu dem Sie eine Verbindung herstellen, zu fragen, um eine separate "Gruppe" einzurichten, die Split-Tunneling ausführt, und eine PCF-Datei mit dem Gruppennamen und dem Gruppenkennwort für diese Gruppe zu erhalten.

Vebjorn Ljosa
quelle
2
das wird nicht passieren :) Sie sind paranoid
1

Ich hatte das gleiche Problem und habe es dank @mehaase zum Laufen gebracht

Nachdem Sie das ~/vpn.shvon @mehaase beantwortete Skript erstellt haben, können Sie es mit den folgenden Schritten in ein ausführbares Anwendungsautomatisierungsskript einfügen:

  1. Erstellen Sie mit Automator eine neue Anwendung
  2. Fügen Sie unter Bibliothek> Dienstprogramme "AppleScript ausführen" hinzu
  3. Eingeben: do shell script "sudo ~/vpn.sh" with administrator privileges
  4. sparen

Möglicherweise müssen Sie auch chmod 700 ~/vpn.shvom Terminal aus ausgeführt werden, um dem Skript Ausführungsberechtigungen zu erteilen.

Nachdem Sie sich mit dem VPN verbunden haben, können Sie dieses Anwendungsskript einfach ausführen. Geben Sie Ihr Administratorkennwort ein und klicken Sie auf OK - Fertig. :)

Dwight Brown
quelle