วิธีบังคับให้แยกการกำหนดเส้นทางช่องสัญญาณบน Mac ไปยัง Cisco VPN


40

มีใครรู้วิธีแฮ็กตารางเส้นทาง (บนเครื่อง mac) เพื่อเอาชนะการบังคับใช้เส้นทาง VPN สำหรับทุกสิ่งผ่าน cisco VPN หรือไม่ สิ่งที่ฉันต้องการจะทำมีเพียง 10.121. * และ 10.122. * ที่อยู่ผ่าน VPN และทุกอย่างตรงไปที่อินเทอร์เน็ต

คำตอบ:


27

งานต่อไปนี้สำหรับฉัน รันสิ่งเหล่านี้หลังจากเชื่อมต่อกับ Cisco VPN (ฉันใช้ไคลเอ็นต์ Cisco ในตัวของ OS X ไม่ใช่ไคลเอ็นต์ตราสินค้าของ Cisco)

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

แทนที่10ในคำสั่งแรกด้วยเครือข่ายที่อยู่อีกด้านหนึ่งของอุโมงค์

แทนที่192.168.0.1ด้วยเกตเวย์เครือข่ายท้องถิ่นของคุณ

ฉันใส่มันลงในสคริปต์ทุบตีเช่นนี้

$ 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

ฉันยังพบคำอธิบายเกี่ยวกับวิธีการเรียกใช้สิ่งนี้โดยอัตโนมัติเมื่อคุณเชื่อมต่อ VPN แต่มันล่าช้าในวันศุกร์และฉันไม่รู้สึกอยากลองเลย :)

แก้ไข:

ฉันออกจากงานที่ฉันใช้ Cisco VPN มาตั้งแต่ตอนนี้มาจากหน่วยความจำ

10ในคำสั่งแรกเป็นเครือข่ายที่คุณต้องการไปยังเส้นทางที่ผ่าน VPN มือสั้น10 10.0.0.0/8ในกรณี Tuan Anh ของทราน,192.168.5.0/24ดูเหมือนว่าเครือข่ายเป็น

สำหรับเกตเวย์ที่จะระบุในคำสั่งที่สองควรเป็นเกตเวย์ท้องถิ่นของคุณ เมื่อคุณเข้าสู่ VPN ที่ป้องกันการแยกช่องสัญญาณจะบังคับใช้นโยบายนั้นโดยการเปลี่ยนตารางเส้นทางของคุณเพื่อให้แพ็กเก็ตทั้งหมดถูกกำหนดเส้นทางบนอินเทอร์เฟซเสมือน ดังนั้นคุณจึงต้องการที่จะเปลี่ยนเส้นทางกลับเริ่มต้นของคุณกับสิ่งที่มันเป็นก่อนที่จะได้รับใน VPN

วิธีที่ง่ายที่สุดที่จะคิดออกเกตเวย์คือการทำงานnetstat -rnก่อนที่จะเข้าสู่ VPN และดูที่อยู่ IP ทางด้านขวาของปลายทาง "เริ่มต้น" ตัวอย่างเช่นนี่คือสิ่งที่ดูเหมือนในกล่องของฉันตอนนี้:

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

เกตเวย์ของฉันคือ10.0.1.1- อยู่ทางขวาของปลายทาง "ค่าเริ่มต้น"


1
คุณช่วยอธิบายให้ฉันฟังหน่อยได้ไหม? ifconfigของฉันคืนค่า utun0: ค่าสถานะ = 8051 <UP, POINTOPOINT, RUNNING, MULTICAST> mtu 1280 inet 192.168.5.102 -> 192.168.5.102 netmask 0xffffffff นอกจากนี้ฉันไม่เข้าใจสิ่งที่ฉันควรแทนที่ด้วยหมายเลข 10 ด้านบน ขอขอบคุณ.
Tuan Anh Tran

@TuanAnhTran: ฉันได้รับคำตอบของฉันแล้ว โปรดแจ้งให้เราทราบหากสิ่งนั้นช่วยได้
Mark E. Haase

สำหรับเวอร์ชั่นล่าสุดฉันติดตั้ง /Applications/VPNClient.app แล้วและฉันไม่เห็น utun0 แสดงรายการโดย ifconfig ฉันเห็นอะแดปเตอร์ gif0, stf0 และ fw0 ฉันจะตรวจสอบว่าอะแดปเตอร์ที่ถูกต้องคืออะไร? ฉันไม่เห็นความแตกต่างในเอาต์พุต ifconfig ที่มีและไม่มีการเชื่อมต่อ vpn (ยกเว้นค่า MTU ของ en1)
haridsv

1
สำหรับผู้ที่ไม่คุ้นเคยกับ LaunchDaemons ผมเขียนคู่มือในคำตอบของฉันที่นี่อธิบายถึงวิธีการที่จะเรียกสคริปต์เพื่อทำงานทุกครั้งที่คุณเชื่อมต่อกับ VPN (โดยวิธีการ +1 คำตอบที่ดี แต่ฉันต้องการอีกเล็กน้อยเพื่อให้ได้ส่วนสำคัญทำงาน)
dr jimbob

1
น่าเศร้าที่นี่ไม่สามารถใช้งานกับไคลเอนต์ Cisco AnyConnect ของฉัน
jeremyjjbrown

5

ฉันใช้ข้อมูลจาก mehaaseฉันเขียนสคริปต์ Python ที่ทำให้กระบวนการนี้ง่ายขึ้นบน Mac เมื่อคุณเรียกใช้สคริปต์จะบันทึกข้อมูลไฟร์วอลล์ของคุณเปิดไคลเอนต์ AnyConnect รอการเข้าสู่ระบบจากนั้นแก้ไขเส้นทางและไฟร์วอลล์ เพียงเรียกใช้สคริปต์จาก 'เทอร์มินัล'

#!/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")

4

สคริปต์ Python ในคำตอบก่อนหน้านี้มีประโยชน์ แต่ก็ไม่ได้ดูแลเส้นทางที่ AnyConnect เคยใช้เพื่อควบคุมอินเตอร์เฟสอื่น ๆ บนอุปกรณ์ (เช่นอินเตอร์เฟส VMware) นอกจากนี้ยังไม่สามารถจัดการเครือข่าย VPN หลายเครือข่ายได้

นี่คือสคริปต์ที่ฉันใช้:

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

สิ่งนี้ใช้ได้กับ cisco anyconnect 3.1.0 หรือไม่ ฉันไม่คิดว่าจะเป็น ... คุณมีสคริปต์ที่อัปเดตสำหรับ 3.1.0 หรือไม่ ขอบคุณ!
costa

2

มากกว่าผู้ดูแลระบบของคุณควรตั้งค่าการเชื่อมต่อ VPN เพื่อใช้การกำหนดเส้นทางท้องถิ่นสำหรับเครือข่ายย่อย 10.121. * และ 10.122. * และให้เส้นทางระยะไกล (เครื่องที่บ้านของคุณ) กำหนดเส้นทางคำขอทั้งหมดที่เหลือ (มันช่วยประหยัดแบนด์วิดธ์และความรับผิด)

คุณกำลังใช้ "ไคลเอนต์ VPN" ของ Cisco หรือไม่ ระบบปฏิบัติการ OS X?

หากคุณใช้ VPN ของ OS X (ตั้งค่าผ่านบานหน้าต่างการตั้งค่าเครือข่าย) คุณควรจะสามารถคลิก "ขั้นสูง" และเลือกแท็บ "VPN on Demand" จากนั้นจัดหาซับเน็ตที่จำเป็นเพื่อให้ VPN ใช้


4
ไคลเอนต์ OS X vpn มีตัวเลือก "Cisco" แยกต่างหาก (แยกจาก PPTP และ L2TP) ที่ไม่มีตัวเลือก "VPN on Demand"
Mark E. Haase

2

ผมอยาก 'app' พื้นเมืองที่ฉันสามารถเรียกใช้ในการเข้าสู่ระบบ (และยังคงทำงาน / ซ่อนไว้) เพื่อเปิดใช้งานสปลิตอุโมงค์เส้นทางที่คล้ายกับการทำงานของLocamatic บางทีฉันอาจจะแยก Locamatic ในบางจุดและเล่นกับมัน ฉันอาจอัปโหลด AppleScript นี้ไปยัง Github ฉันไม่ต้องการยุ่งกับภูตเพราะคำตอบนี้แนะนำ

สคริปต์นี้จะถือว่า VPN มีค่าเริ่มต้นVPN (Cisco IPSec)ชื่อและเส้นทาง VPN เป็น>10.10.10.1/22 10.10.20.10สิ่งเหล่านี้จะต้องมีการเปลี่ยนแปลง / เพิ่มเส้นทางเพิ่มเติม เรียกใช้เทอร์มินัล> netstat -rnเมื่อเชื่อมต่อ VPN (ก่อนเปิดใช้งานสคริปต์นี้) เพื่อดูเส้นทางที่เพิ่มด้วย VPN

สคริปต์นี้ยังสร้างการแจ้งเตือนแบบคำรามในศูนย์การแจ้งเตือนด้วย :)

ป้อนคำอธิบายรูปภาพที่นี่

ฉันวิ่งเข้าไปในบางประเด็นที่มีมาร์คอีฮา 's คำตอบเป็นปรับเปลี่ยน Cisco VPN ของฉันเกตเวย์ที่มีอยู่จากUCScไปUGScI(en0 อินเตอร์เฟซที่เฉพาะเจาะจง) เส้นทางและเพิ่ม VPN เกตเวย์เป็นUCSเส้นทางทั้งนี้การลบสองเกตเวย์เริ่มต้นและบวกกลับUGScเกตเวย์เริ่มต้นดั้งเดิม

ขอบคุณพระเจ้าสำหรับ StackExchange / google นี่เป็น AppleScript เครื่องแรกของฉันและฉันจะไม่สามารถรวมเข้าด้วยกันได้โดยไม่ต้องใช้เวลาสองสามชั่วโมง

ข้อเสนอแนะ / การแก้ไข / การเพิ่มประสิทธิภาพยินดีต้อนรับ!

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

บันทึกเป็นแอพ:

แอพ Split Tunnel บันทึกการตั้งค่า

คลิกขวา> แสดงเนื้อหาแพคเกจเพิ่มสิ่งต่อไปนี้ใน info.plist (นี่จะซ่อนไอคอนแอพจาก Dock ซึ่งจำเป็นต้องใช้การตรวจสอบกิจกรรมหรือเทอร์มินัล> pkill -f 'Split Tunnel'เพื่อออกจากแอปข้ามหากคุณต้องการไอคอนท่าเรือ:

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

สร้างrouteNOPASSWDไฟล์หนึ่งบรรทัดใหม่ (ไม่มีส่วนขยาย) โดยใช้รหัสต่อไปนี้อย่างแน่นอน (ซึ่งสามารถป้องกันการเข้าถึง sudo หากทำไม่ถูกต้อง google visudoสำหรับข้อมูลเพิ่มเติม - ซึ่งอนุญาตให้คำสั่ง sudo ใน AppleScript ทำงานโดยไม่ต้องแจ้งรหัสผ่านให้ข้ามหากคุณต้องการ พร้อมท์รหัสผ่านเมื่อตารางเส้นทางต้องเปลี่ยน):

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

คัดลอกไฟล์นี้ไปที่ /etc/sudoers.d

เรียกใช้คำสั่งต่อไปนี้ในเทอร์มินัล (คำสั่งที่สองจะถามรหัสผ่าน - อนุญาตให้ใช้sudo routeคำสั่งใน AppleScript โดยไม่ต้องแจ้งให้ใส่รหัสผ่านละเว้นหากต้องการพรอมต์รหัสผ่านเมื่อสคริปต์กำลังเปลี่ยนตารางเส้นทาง)

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

ในที่สุดก็เพิ่มแอพในการตั้งค่าระบบ> ผู้ใช้และกลุ่ม> รายการเข้าสู่ระบบ

แยกรายการเข้าสู่ระบบอุโมงค์


1

คุณควรถามผู้ดูแลระบบของเราเตอร์ที่คุณเชื่อมต่ออยู่เพื่อตั้งค่า "กลุ่ม" แยกที่แยกช่องสัญญาณอุโมงค์และให้ไฟล์ PCF ที่มีชื่อกลุ่มและรหัสผ่านกลุ่มสำหรับกลุ่มนั้น


2
จะไม่เกิดขึ้น :) พวกเขาหวาดระแวง

1

ฉันมีปัญหาเดียวกันและได้ทำงานนี้ขอบคุณ @mehaase

หลังจากสร้างคำ~/vpn.shตอบตามที่ @mehaase คุณสามารถใส่สิ่งนี้ลงในสคริปต์ automator ของแอปพลิเคชันที่รันได้โดยใช้ขั้นตอนเหล่านี้:

  1. การใช้ Automator สร้างแอปพลิเคชันใหม่
  2. เพิ่ม "Run a AppleScript" ใน Library> Utilities
  3. Enter: do shell script "sudo ~/vpn.sh" with administrator privileges
  4. บันทึก

คุณอาจต้องเรียกใช้chmod 700 ~/vpn.shจาก Terminal เพื่อให้สิทธิ์ในการเรียกใช้สคริปต์

หลังจากเชื่อมต่อกับ VPN คุณก็สามารถเรียกใช้สคริปต์แอปพลิเคชันนี้ได้ ป้อนรหัสผ่านผู้ดูแลระบบของคุณแล้วคลิกตกลง - เสร็จสิ้น :)

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.