Jak wymusić routing podzielonego tunelu na Macu do Cisco VPN

40

Czy ktoś wie, jak zhakować tabelę routingu (na komputerze Mac), aby pokonać wymuszanie routingu VPN dla każdej rzeczy przez sieć VPN firmy Cisco? właściwie to, co chcę zrobić, to mieć tylko adresy 10.121. * i 10.122. * przez VPN i wszystko inne prosto do Internetu.

Sathyajith Bhat
źródło

Odpowiedzi:

27

Poniższe działa dla mnie. Uruchom je po połączeniu z Cisco VPN. (Używam wbudowanego klienta Cisco systemu OS X, a nie klienta marki Cisco).

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

Zastąp 10w pierwszym poleceniu siecią znajdującą się po drugiej stronie tunelu.

Zastąp 192.168.0.1bramą sieci lokalnej.

Umieszczam go w skrypcie bash, takim jak ten:

$ 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

Znalazłem też wyjaśnienie, jak uruchomić to automatycznie po podłączeniu VPN, ale w piątek jest późno i nie mam ochoty tego próbować :)

Edytować:

Od tego czasu porzuciłem pracę, w której korzystałem z Cisco VPN, więc pochodzi to z pamięci.

10W pierwszym poleceniu jest sieć, którą chcesz trasie nad VPN. 10jest krótką ręką dla 10.0.0.0/8. W przypadku Tuan Anh Tran wygląda na to, że sieć jest 192.168.5.0/24.

Jeśli chodzi o to, którą bramę określić w drugim poleceniu, powinna to być brama lokalna. Gdy logujesz się do sieci VPN, która zapobiega tunelowaniu dzielonemu, wymusza tę zasadę, zmieniając tabele routingu, tak aby wszystkie pakiety były kierowane przez interfejs wirtualny. Więc chcesz zmienić domyślną trasę z powrotem na to, co było przed wejściem do VPN .

Najłatwiejszym sposobem na netstat -rnznalezienie bramki jest uruchomienie przed zalogowaniem się do sieci VPN i sprawdzenie adresu IP po prawej stronie „domyślnego” miejsca docelowego. Na przykład oto, jak teraz wygląda na moim pudełku:

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

Moja brama to 10.0.1.1- znajduje się na prawo od „domyślnego” miejsca docelowego.

Mark E. Haase
źródło
1
Czy możesz mi coś więcej wyjaśnić? mój ifconfig zwraca utun0: flags = 8051 <UP, POINTOPOINT, RUNNING, MULTICAST> mtu 1280 inet 192.168.5.102 -> 192.168.5.102 maska ​​sieci 0xffffffff. Nie rozumiem też, co powinienem zastąpić numerem 10 powyżej. Dziękuję Ci.
Tuan Anh Tran
@TuanAnhTran: Zaktualizowałem swoją odpowiedź. Daj mi znać, jeśli to pomoże.
Mark E. Haase
W najnowszej wersji mam /Applications/VPNClient.app i nie widzę utun0 na liście ifconfig. Widzę adaptery gif0, stf0 i fw0. Jak ustalić, który adapter jest odpowiedni? Nie widzę żadnej różnicy w wyjściu ifconfig z podłączonym VPN i bez niego (z wyjątkiem wartości MTU en1).
haridsv
1
Dla osób, które nie są zaznajomione z LaunchDaemons, w mojej odpowiedzi napisałem przewodnik opisujący, jak wywołać skrypt, który ma być uruchamiany przy każdym połączeniu z VPN . (Nawiasem mówiąc, +1 doskonała odpowiedź, ale potrzebowałem trochę więcej, aby sedno działało).
dr jimbob
1
Niestety nie działa to na moim kliencie Cisco AnyConnect.
jeremyjjbrown
5

Korzystając z informacji z mehaase, napisałem skrypt w języku Python, który naprawdę upraszcza ten proces na komputerze Mac. Po uruchomieniu skrypt zapisze informacje o zaporze, uruchomi klienta AnyConnect, zaczeka na logowanie, a następnie napraw trasy i zaporę. Wystarczy uruchomić skrypt z „terminalu”.

#!/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")
użytkownik652641
źródło
4

Skrypt Pythona w poprzedniej odpowiedzi był pomocny, jednak nie zajmował się trasami, za pomocą których AnyConnect przejmował inne interfejsy na urządzeniu (takie jak interfejsy VMware). Nie był także w stanie obsłużyć wielu sieci VPN.

Oto skrypt, którego używam:

#!/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
źródło
Czy to działa z cisco anyconnect 3.1.0? Nie sądzę, że tak ... Czy masz zaktualizowany skrypt dla wersji 3.1.0? Dzięki!
costa
2

Bardziej niż prawdopodobne, że administrator powinien skonfigurować połączenia VPN w celu korzystania z lokalnego routingu dla podsieci 10.121. * I 10.122. * I pozwolić, aby zdalny (komputer domowy) kierował wszystkie pozostałe żądania. (oszczędza to przepustowość i odpowiedzialność)

Czy używasz „klienta VPN Cisco”? OS OS X?

jeśli korzystasz z VPN OS X (skonfigurowanego przez okienko preferencji sieciowych), powinieneś być w stanie kliknąć „zaawansowane” i wybrać zakładkę „VPN na żądanie”. następnie podaj niezbędne podsieci do korzystania z sieci VPN.

Toymakerii
źródło
4
Klient VPN OS X ma osobną opcję „Cisco” (oddzielną od PPTP i L2TP), która nie ma opcji „VPN na żądanie”.
Mark E. Haase
2

Chciałem mieć natywną „aplikację”, którą mogę uruchomić przy logowaniu (i nadal działać / ukryć), aby włączyć routing Split Tunnel, podobny do funkcji Locamatic . Być może kiedyś rozwidlę Locamatic i będę się nim bawić. Mogę również przesłać ten AppleScript do Github. Nie chciałem zadzierać z demonem, jak sugeruje ta odpowiedź.

Ten skrypt zakłada, że ​​VPN ma domyślną VPN (Cisco IPSec)nazwę, a trasa VPN to 10.10.10.1/22> 10.10.20.10. Będą musiały zostać zmienione / dodane dodatkowe trasy. Uruchom terminal> netstat -rnpo podłączeniu VPN (przed włączeniem tego skryptu), aby zobaczyć trasy dodane przez VPN.

Ten skrypt generuje również powiadomienia w stylu warczenia w Centrum powiadomień :)

wprowadź opis zdjęcia tutaj

Wpadłem na pewne problemy z Mark E. Haase „s odpowiedzi jako mój modyfikuje Cisco VPN istniejącej bramy od A UCScdo UGScI(en0 interfejsu określonej trasie) i dodaje bramą VPN jako UCStrasy, konieczność usunięcia dwóch bram domyślnych oraz dodawanie plecy oryginalna UGScbrama domyślna

Dzięki Bogu za StackExchange / google, to jest mój pierwszy AppleScript i nie byłbym w stanie go złożyć bez kilku godzin googlingu.

Sugestie / poprawki / optymalizacje mile widziane!

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

zapisz jako aplikację:

Ustawienia zapisywania aplikacji Split Tunnel

kliknij prawym przyciskiem myszy> pokaż zawartość pakietu, dodaj następujące informacje do info.plist (ukrywa to ikonę aplikacji przed dokiem, co wymaga użycia Monitora aktywności lub terminala>, pkill -f 'Split Tunnel'aby zamknąć aplikację, pomiń, jeśli CHCESZ ikonę stacji dokującej:

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

utwórz nowy routeNOPASSWDplik jednowierszowy (bez rozszerzenia) DOKŁADNIE (może to uniemożliwić dostęp do sudo, jeśli zostanie wykonane nieprawidłowo, google, visudoaby uzyskać więcej informacji - pozwala to na uruchamianie poleceń sudo w AppleScript BEZ monitu o hasło, pomiń, jeśli CHCESZ monit o hasło, kiedy należy zmienić tabelę routingu):

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

skopiuj ten plik do /etc/sudoers.d

uruchom następujące polecenia w terminalu (drugie polecenie wyświetli monit o hasło - pozwala to sudo routena uruchamianie poleceń w AppleScript BEZ pytania o hasło, pomiń, jeśli monit o hasło jest wymagany, gdy skrypt zmienia tablicę routingu)

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

na koniec dodaj aplikację do Prefektów systemu> Użytkownicy i grupy> elementy logowania

Element logowania do tunelu Split

goofologia
źródło
1

Powinieneś być w stanie poprosić administratora routera, z którym się łączysz, o skonfigurowanie oddzielnej „grupy”, która dzieli tunelowanie i daje plik PCF zawierający nazwę grupy i hasło grupy dla tej grupy.

Vebjorn Ljosa
źródło
2
tak się nie stanie :) Są paranoikami
1

Miałem ten sam problem i działałem dzięki @mehaase

Po utworzeniu ~/vpn.shodpowiedzi udzielonej przez @mehaase możesz umieścić ją w uruchamialnym skrypcie automatyzatora aplikacji, wykonując następujące kroki:

  1. Za pomocą Automatora utwórz nową aplikację
  2. Dodaj „Uruchom AppleScript” w Bibliotece> Narzędzia
  3. Wchodzić: do shell script "sudo ~/vpn.sh" with administrator privileges
  4. Zapisać

Może być również konieczne uruchomienie chmod 700 ~/vpn.shz terminala, aby dać skryptowi uprawnienia do wykonywania.

Po połączeniu z VPN możesz po prostu uruchomić ten skrypt aplikacji. Wprowadź hasło administratora i kliknij OK - Gotowe. :)

Dwight Brown
źródło