如何在 Mac 上强制拆分隧道路由至 Cisco VPN

如何在 Mac 上强制拆分隧道路由至 Cisco VPN

有人知道如何破解路由表(在 Mac 上)以击败通过 Cisco VPN 强制对所有内容进行 VPN 路由的功能吗?我想要做的就是在 VPN 上只使用 10.121.* 和 10.122.* 地址,其他所有内容直接连接到互联网。

答案1

以下对我有用。连接到 Cisco VPN 后运行这些。(我使用的是 OS X 的内置 Cisco 客户端,而不是 Cisco 品牌的客户端。)

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

将第一个命令替换10为隧道另一端的网络。

替换192.168.0.1为您本地网络的网关。

我将其放入 bash 脚本中,如下所示:

$ 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 Tran 的案件,看起来网络是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— 它位于“默认”目的地的右侧。

答案2

使用来自 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")

答案3

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

答案4

您的管理员很可能希望设置 VPN 连接以使用 10.121.* 和 10.122.* 子网的本地路由,并让远程(您的家用机器)路由所有其余请求。(这为他们节省了带宽和责任)

您使用的是思科的“VPN 客户端”吗?操作系统是 OS X?

如果您使用 OS X 的 VPN(通过网络偏好设置窗格设置),您应该能够单击“高级”并选择“按需 VPN”选项卡。然后提供 VPN 使用的必要子网。

相关内容