題 如何在連接到Cisco VPN時允許本地LAN訪問?


如何在連接到Cisco VPN時保持本地LAN訪問?

使用Cisco VPN連接時,服務器必須能夠指示客戶端阻止本地LAN訪問。

假設無法關閉此服務器端選項,如何在與Cisco VPN客戶端連接時允許本地LAN訪問?


我曾經認為這只是添加路由的問題,捕獲具有更高指標的LAN流量,例如:

  Network 
Destination      Netmask        Gateway       Interface  Metric
   10.0.0.0  255.255.0.0       10.0.0.3        10.0.0.3      20  <--Local LAN
   10.0.0.0  255.255.0.0  192.168.199.1  192.168.199.12       1  <--VPN Link

並試圖刪除 10.0.x.x -> 192.168.199.12 路線沒有任何影響:

>route delete 10.0.0.0
>route delete 10.0.0.0 mask 255.255.0.0
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1 if 192.168.199.12
>route delete 10.0.0.0 mask 255.255.0.0 192.168.199.1 if 0x3

雖然它可能只是一個路由問題,但嘗試添加或刪除路由失敗。

思科VPN客戶端驅動程序在什麼級別上執行網絡堆棧中的操作,以覆蓋本地管理員管理其計算機的能力?

Cisco VPN客戶端不能使用魔術。它仍然是我的電腦上運行的軟件。它用什麼機制干擾我的機器網絡?當IP / ICMP數據包到達網絡時會發生什麼?網絡堆棧中的數據包被吃掉了?

也可以看看


編輯: 我還沒試過的事情:

>route delete 10.0.*

更新: 由於思科已經放棄了他們的舊客戶端,轉而使用AnyConnect(基於HTTP SSL的VPN),這個未解決的問題可以留作歷史遺留物。

展望未來,我們可以嘗試解決 與他們的新客戶相同的問題


75
2018-05-17 14:23


起源


VPN鏈路具有較低的度量標準,因此在您的本地路由之前嘗試。增加本地LAN的指標很可能會禁用本地LAN。如果VPN未配置為隧道所有流量切換,則您的歸屬子網可能是一種解決方案。您需要通過此VPN訪問哪些IP?這是VPN端的整個10.0.0.0嗎? - pberlijn
這聽起來很可能是問題;我認為的衡量標準 更高=更好。 - Ian Boyd
確實, 較低的指標=首選。 - Jonathon Reinhart
Cisco AnyConnect可以替換為OpenConnect替代主要兼容的客戶端 serverfault.com/a/664097/104573 - Vadzim


答案:


Anyconnect的問題在於它首先修改了路由表,然後在你手動修改它的情況下進行保管並修復它。我找到了解決方法。適用於版本3.1.00495,3.1.05152,3.1.05170,以及3.1系列中的任何其他內容。可以使用其他版本,至少類似的想法應該工作假設代碼不會被重寫。對我們來說幸運的是,思科已將保姆“嬰兒醒著”的電話放入共享庫中。所以我們的想法是我們阻止vpnagentd通過LD_PRELOAD採取行動。

  1. 首先我們創建一個文件 hack.c

    #include <sys/socket.h>
    #include <linux/netlink.h>
    
    int _ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv()
    {
      int fd=50;          // max fd to try
      char buf[8192];
      struct sockaddr_nl sa;
      socklen_t len = sizeof(sa);
    
      while (fd) {
         if (!getsockname(fd, (struct sockaddr *)&sa, &len)) {
            if (sa.nl_family == AF_NETLINK) {
               ssize_t n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
            }
         }
         fd--;
      }
      return 0;
    }
    
  2. 然後像這樣編譯它:

    gcc -o libhack.so -shared -fPIC hack.c
    
  3. 安裝 libhack.so 進入思科庫路徑:

    sudo cp libhack.so  /opt/cisco/anyconnect/lib/
    
  4. 降下代理人:

    /etc/init.d/vpnagentd stop
    
  5. 確保它確實失效了

    ps auxw | grep vpnagentd
    

    如果不, kill -9 只是要確定。

  6. 然後通過添加修復/etc/init.d/vpnagentd LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so 調用vpnagentd的位置如下所示:

    LD_PRELOAD=/opt/cisco/anyconnect/lib/libhack.so /opt/cisco/anyconnect/bin/vpnagentd
    
  7. 現在啟動代理:

    /etc/init.d/vpnagentd start
    
  8. 修復iptables,因為AnyConnect與它們混淆:

    iptables-save | grep -v DROP | iptables-restore
    

    您可能希望在此處執行更高級的操作以僅允許訪問某些LAN主機。

  9. 現在可以根據需要修改路線,例如:

    route add -net 192.168.1.0 netmask 255.255.255.0 dev wlan0
    
  10. 檢查它們是否真的存在:

    route -n
    

這個hack的先前更簡單的版本給出了一個只返回“返回0”的函數。 - 那張海報指出“到目前為止,我觀察到的唯一副作用是vpnagentd正在使用top報告的100%的CPU,但整體CPU只有3%的用戶和20%的系統,並且系統完全響應我把它拉了過來,它似乎是在循環中做兩次選擇,當兩次快速返回空閒時,但它從不讀或寫 - 我想我用LD_PRELOAD切出的調用應該是讀的。可能有一種更乾淨的方式要做到這一點,但到目前為止對我來說已經足夠了。如果有人有更好的解決方案,請分享。“

瑣碎的黑客問題是它導致單個cpu核心始終為100%,有效地將您的硬件CPU線程數減少一個 - 無論您的VPN連接是否處於活動狀態。我注意到代碼所做的選擇是在netlink套接字上,當路由表發生變化時,它會發送vpnagentd數據。 vpnagentd一直注意到netlink套接字上有一條新消息,並調用routeCallBackHandler來處理它,但由於瑣碎的hack沒有清除新消息,它只是一次又一次地被調用。上面提供的新代碼刷新了netlink數據,因此導致100%cpu的無限循環不會發生。

如果某些東西不起作用,那就行 gdb -p $(pidof vpnagentd),一旦附加:

b socket
c
bt

看看你在哪個電話。然後猜猜你想要刪除哪一個,將它添加到hack.c並重新編譯。


52
2018-02-05 00:07



這是天才。我試圖讓它在OSX上工作,並有一個問題:你怎麼知道覆蓋的方法被命名 _ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv? - donturner
@donturner試試 nm /opt/cisco/anyconnect/lib/libvpnagentutilities.dylib | grep routeCallbackHandlerEv 然後你會發現 __ZN25CInterfaceRouteMonitorMac20routeCallbackHandlerEv - McKelvin
我通過使用gdb附加到vpnagentd並設置各種斷點來解決這個問題。 - Sasha Pachev
@McKelvin nm /opt/cisco/anyconnect/lib/libvpnagentutilities.so 回報 nm: /opt/cisco/anyconnect/lib/libvpnagentutilities.so: no symbols 在Ubuntu下的AnyConnect上,所以它是在沒有符號表信息的情況下生成的。你怎麼能得到那個? - nephewtom
@SashaPachev如何在沒有符號信息的情況下調試vpnagentd? - nephewtom


這非常複雜,但如果您使用VMWare Player或類似設備創建最小VM,並在其中運行Cisco AnyConnect VPN客戶端,則可以根據需要使用VMWare虛擬網絡適配器設置路由,或者僅使用需要通過Cisco SSL VPN訪問任何資源的VM,並將文件“拖放”到實際機器上。


11
2017-12-24 14:43





潑婦 軟VPN軟件對我來說也是如此 伊恩博伊德 建議。

它可以導入Cisco VPN客戶端配置文件。我使用了思科VPN客戶端版本5.0.05.0290,在安裝了Shrew VPN(版本2.1.7)並導入思科配置文件後,我可以在連接到公司VPN時訪問本地局域網,而無需任何其他配置的Shrew VPN連接(或軟件)。


5
2018-03-05 13:17



如果這可用於Android,那將是驚人的。 - Gabriel Fair


謝謝 Sasha Pachev 對於上面的好黑客。

vpnagentd 通過覆蓋所做的更改,也會與解析器混淆 /etc/resolv.conf。我通過最終贏得比賽來解決它:

#!/bin/bash

dnsfix() {
    [ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
    while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup #>/dev/null
    do
         cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
    done
    chattr +i /etc/resolv.conf
    diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null 
}

while ! dnsfix
do
    echo "Retrying..."
    chattr -i /etc/resolv.conf
done

別忘了 chattr -i /etc/resolv.conf 斷開連接時。

我試圖通過攔截回調來解決它,就像上面的路由方法一樣,但是還不能找到相應的回調或方法。

Update1 / 2:A strace 透露 vpnagentd正在使用 inotify 用於監視解析程序文件更改的API。從那時起它就是下坡了。 這是額外的黑客攻擊:

int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
  return 0;
}

這有點矯枉過正,因為它禁用了 所有 文件正在觀看代理商。但似乎工作正常。

下面的vpn客戶端包裝器腳本集成了所有功能(更新以包含此額外的hack)。 chattr 不再使用/需要。

更新3:修復腳本中的用戶名/密碼設置。它現在使用了 vpn.conf 具有下述格式的文件(以及僅限root權限)。

#!/bin/bash

# Change this as needed
CONF="/etc/vpnc/vpn.conf"
# vpn.conf format
#gateway <IP>
#username <username>
#password <password>
#delete_routes <"route spec"...> eg. "default gw 0.0.0.0 dev cscotun0"
#add_routes <"route spec"...> eg. "-net 192.168.10.0 netmask 255.255.255.0 dev cscotun0" "-host 10.10.10.1 dev cscotun0"

ANYCONNECT="/opt/cisco/anyconnect"

usage() {
    echo "Usage: $0 {connect|disconnect|state|stats|hack}"
    exit 1
}

CMD="$1"
[ -z "$CMD" ] && usage

ID=`id -u`

VPNC="$ANYCONNECT/bin/vpn"

dnsfix() {
    [ -f /etc/resolv.conf.vpnbackup ] || echo "Not connected?" >&2 || return 0 # do nothing in case of failure
    while ! diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null
    do
         cat /etc/resolv.conf.vpnbackup >/etc/resolv.conf
    done
#    chattr +i /etc/resolv.conf
    diff -q /etc/resolv.conf /etc/resolv.conf.vpnbackup >/dev/null 
}

case "$CMD" in
    "connect")
        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        HOST=`grep ^gateway $CONF | awk '{print $2}'`
        USER=`grep ^user $CONF | awk '{print $2}'`
        PASS=`grep ^password $CONF | awk '{print $2}'`
        OLDIFS=$IFS
        IFS='"'
        DEL_ROUTES=(`sed -n '/^delete_routes/{s/delete_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF`)
        ADD_ROUTES=(`sed -n '/^add_routes/{s/add_routes[ \t\"]*//;s/\"[ \t]*\"/\"/g;p}' $CONF`)
        IFS=$OLDIFS

        /usr/bin/expect <<EOF
set vpn_client "$VPNC";
set ip "$HOST";
set user "$USER";
set pass "$PASS";
set timeout 5
spawn \$vpn_client connect \$ip
match_max 100000
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    ">> The VPN client is not connected." { exit 0};
    ">> state: Disconnecting" { exit 0};
    "Connect Anyway?"
}
sleep .1
send -- "y\r"
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    "Username:"
}
sleep .1
send -- "\$user\r"
expect { 
    timeout {
        puts "timeout error\n"
        spawn killall \$vpn_client
        exit 1
    }
    "Password: "
}
send -- "\$pass\r";
expect eof
EOF
        sleep 2
        # iptables
        iptables-save | grep -v DROP | iptables-restore

        # routes
        for ROUTE in "${DEL_ROUTES[@]}"
        do
#            echo route del $ROUTE
            route del $ROUTE
        done
        for ROUTE in "${ADD_ROUTES[@]}"
        do
#            echo route add $ROUTE
            route add $ROUTE
        done

        # dns
        while ! dnsfix
        do
            echo "Try again..."
#            chattr -i /etc/resolv.conf
        done

        echo "done."
        ;;
    "disconnect")
#        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        # dns
#        chattr -i /etc/resolv.conf

        $VPNC disconnect
        ;;
    "state"|"stats")
        $VPNC $CMD
        ;;
    "hack")
        [ $ID -ne 0 ] && echo "Needs root." && exit 1
        /etc/init.d/vpnagentd stop
        sleep 1
        killall -9 vpnagentd 2>/dev/null
        cat - >/tmp/hack.c <<EOF
#include <sys/socket.h>
#include <linux/netlink.h>

int _ZN27CInterfaceRouteMonitorLinux20routeCallbackHandlerEv()
{
  int fd=50;          // max fd to try
  char buf[8192];
  struct sockaddr_nl sa;
  socklen_t len = sizeof(sa);

  while (fd) {
     if (!getsockname(fd, (struct sockaddr *)&sa, &len)) {
        if (sa.nl_family == AF_NETLINK) {
           ssize_t n = recv(fd, buf, sizeof(buf), MSG_DONTWAIT);
        }
     }
     fd--;
  }
  return 0;
}

int _ZN18CFileSystemWatcher11AddNewWatchESsj(void *string, unsigned int integer)
{
  return 0;
}
EOF
        gcc -o /tmp/libhack.so -shared -fPIC /tmp/hack.c
        mv /tmp/libhack.so $ANYCONNECT
        sed -i "s+^\([ \t]*\)$ANYCONNECT/bin/vpnagentd+\1LD_PRELOAD=$ANYCONNECT/lib/libhack.so $ANYCONNECT/bin/vpnagentd+" /etc/init.d/vpnagentd
        rm -f /tmp/hack.c
        /etc/init.d/vpnagentd start
        echo "done."
        ;;
    *)
        usage
        ;;
esac

5
2018-01-28 18:51



您的通知黑客通過我的AnyConnect 3.1.14018安裝解決了我的新發現(2017-02-25)問題,每次打開新的終端窗口或GNU屏幕時都會斷開連接。它出於某種原因正在觀察/ var / run / utmp。好吧,不再了,謝謝! - Martin Dorey
尼斯。有時候“矯枉過正”可能是你的朋友。 :-) - Mauro Lacy


我的公司仍然使用該VPN。 vpnc客戶端只需改變你的iptables設置:

#iptables-save
#在2012年6月17日星期日14:12:20由iptables-save v1.4.10生成
*過濾
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT DROP [0:0]
-A INPUT -s 123.244.255.254/32 -d 192.168.0.14/32 -j ACCEPT
-A INPUT -i tun0 -j ACCEPT
-A INPUT -i lo0 -j ACCEPT
-A INPUT -j DROP
-A OUTPUT -s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT
-A OUTPUT -o tun0 -j ACCEPT
-A OUTPUT -o lo0 -j ACCEPT
-A OUTPUT -j DROP
承諾

它會過濾除vpn流量之外的所有內容。

只需使用iptables-save將過濾器放入文件中,添加符合您需求的INPUT和OUTPOUT訪問行,並使用iptables-restore重新應用該文件。

例如,訪問192.168.0上的本地網絡

#在2012年6月17日星期日14:12:20由iptables-save v1.4.10生成
*過濾
:INPUT DROP [0:0]
:FORWARD ACCEPT [0:0]
:OUTPUT DROP [0:0]
-A INPUT -s 123.244.255.254/32 -d 192.168.0.14/32 -j ACCEPT
-A INPUT -s 192.168.0.0/24 -d 192.168.0.14/32 -j ACCEPT #local in
-A INPUT -i tun0 -j ACCEPT
-A INPUT -i lo0 -j ACCEPT
-A INPUT -j DROP
-A OUTPUT -s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT
-A OUTPUT -s 192.168.0.14/32 -d 192.168.0.0/24 -j ACCEPT #local out
-A OUTPUT -o tun0 -j ACCEPT
-A OUTPUT -o lo0 -j ACCEPT
-A OUTPUT -j DROP
承諾

4
2018-06-17 13:37



它錯了,它不是那麼容易只添加你的路線..我試過,它沒有工作.. VPN客戶端控制內核路由表,這是不讓你修改 - Satish


關於這個的任何消息?

Cisco VPN客戶端驅動程序在什麼級別執行網絡中的操作   覆蓋,覆蓋本地管理員的能力   管理他們的機器?

我完全同意並且想知道同樣的事情。

無論如何,它是一個需要管理員權限才能安裝的應用程序,並且在運行時它可以很好地過濾你所做的...

我在Windows上的嘗試也失敗了:

route change 0.0.0.0 mask 0.0.0.0 192.168.1.1 metric 1
 OK!

IPv4 Route Table
===========================================================================
Active Routes:
Network Destination        Netmask          Gateway       Interface  Metric
          0.0.0.0          0.0.0.0      192.168.1.1    192.168.1.230     21 <-- LAN
          0.0.0.0          0.0.0.0    192.168.120.1    192.168.120.3      2 <-- VPN

哈哈。似乎沒有低於20的指標。


3
2017-07-23 19:49



就linux而言,這(petefreitag.com/item/753.cfm)似乎表明防火牆也參與其中。 - Marki
我找到了ShrewSoft VPN。它可以連接到Cisco IPSec VPN服務器,它忽略了VPN服務器管理員要求我從我自己的網絡斷開連接的要求。 (看到 superuser.com/questions/312947/... 詳細說明)儘管它沒有回答這個問題,但它是一種解決方法。 注意:ShrewSoft VPN僅適用於IPSec;它不適用於SSL VPN(即較新的Cisco AnyConnect VPN客戶端) - Ian Boyd


我不知道我是否理解它,但我首先澄清了我的理解:

你有一個本地局域網(例如,說10.0.0.0/16,和一個遠程思科VPN服務器(例如,64.0.0.0 / 16)。你想通過思科VPN客戶端連接到VPN服務器,但你需要有LAN訪問權限。在這種情況下,您希望將整個10.0.xx / 16與VPN連接分開)。必須在Mac客戶端中添加以下路由:

/sbin/route add -net 10.0 -interface en1

其中en1是連接到LAN的接口。我知道你也可以在Windows和Linux中添加相同的東西。


3
2017-11-06 11:44



適用於Mac客戶端的+1;這不適用於我。雖然此命令可能有效,但思科客戶端可能會在創建後立即將其刪除(思科客戶端似乎阻止任何人更改路由) - Ian Boyd


由於我無法添加評論,我將在此處發布。我在Windows上運行。

使用虛擬機並在VM中運行AnyConnect,然後使用VM作為工作環境和公司網絡之間的中介的解決方案將不起作用,如果您的“心愛的”IT部門通過VPN路由0.0.0.0甚至您的本地網絡(包括此在本地PC和VM之間)通過VPN路由(原文如此!)。

我嘗試應用@Sasha Pachev發布的解決方案,但最終我最終修補.dll以便在函數開頭返回0。 最後在與動態庫進行一些鬥爭後,我能夠根據我的需要修改路由表,但顯然這還不夠!

即使我的規則似乎是正確的實現拆分隧道,我仍然得到一般失敗。 您是否遇到過能夠解決問題的類似問題?

  • 我的互聯網門戶是192.168.163.2
  • 我通往公司網絡的門戶是10.64.202.1(因此整個10。。*子網我視為“comapny的”)

這就是我的路由表現在的樣子(在啟用VPN後進行手動修改)

enter image description here

然而ping的結果如下

C:\Users\Mike>ping -n 1 10.64.10.11
Reply from 10.64.10.11: bytes=32 time=162ms TTL=127

C:\Users\Mike>ping -n 1 8.8.8.8
PING: transmit failed. General failure.

C:\Users\Mike>ping -n 1 192.168.163.2
General failure.

僅供參考,下面是VPN斷開連接時的路由表(未更改)

enter image description here

這就是連接VPN時表格的樣子(未改變) 在那種情況下,當我試圖ping 8.8.8.8 我只是暫停(因為公司的防火牆不允許流量進入內部網)

enter image description here


2
2018-02-28 10:12



我修補DLL有困難,有人可以提供他們的副本或概述更多細節,我需要更改哪些偏移? - Sean C


嘗試使用網關刪除這些條目 10.64.202.13 看看是否ping 8.8.8.8 然後工作然後逐個添加它們並確定哪一個導致了麻煩。

你是如何修補DLL的?我甚至無法修改路由表,因為它不斷添加 0.0.0.0 用VPN網關回來。


0
2018-05-01 03:42



如果您需要澄清問題或有關問題的其他信息,請發表評論,而不是將其包含在您的答案中。謝謝。 - Matthew Williams
不允許我在現有問題上添加評論。 - Tony