web-dev-qa-db-ja.com

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

それはまだ単なるルーティングの問題かもしれませんが、ルートを追加または削除しようとする試みは失敗します。

どのレベルでCisco VPNクライアントドライバがネットワークスタック内でどのような処理を実行すると、ローカル管理者のマシン管理機能が無効になりますか。

Cisco VPNクライアントは魔法を使うことができません。私のコンピュータではまだソフトウェアが動作しています。私のマシンのネットワークに干渉するためにそれはどんなメカニズムを使っていますか? IP/ICMPパケットがネットワークに到着するとどうなりますか?パケットはネットワーキングスタックのどこで食べられていますか?

また見なさい


編集:まだ試していないこと:

>route delete 10.0.*

更新:CiscoはAnyConnect(HTTP SSLベースのVPN)を支持して古いクライアントを放棄したため、この問題は未解決で歴史の遺物として残すことができます。

今後、 彼らの新しいクライアントと同じ問題を解決しようとすることができます

80
Ian Boyd

Anyconnectの問題点は、ルーティングテーブルを最初に変更し、次にそれをベビーシットし、手動で変更した場合はそれを修正することです。これに対する回避策を見つけました。バージョン3.1.00495、3.1.05152、3.1.05170、およびおそらく3.1ファミリーの他のもので動作します。他のバージョンでも動作する可能性がありますが、少なくともコードが書き直されないことを前提として同様のアイデアが機能します。幸いなことに、シスコはベビーシッターの "baby is awake"コールを共有ライブラリに追加しました。そのため、LD_PRELOADを介したvpnagentdによるアクションを防止するという考えです。

  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. 次に、vpnagentdが呼び出される場所にLD_PRELOAD=/opt/Cisco/anyconnect/lib/libhack.soを追加して/etc/init.d/vpnagentdを修正します。

    LD_PRELOAD=/opt/Cisco/anyconnect/lib/libhack.so /opt/Cisco/anyconnect/bin/vpnagentd
    
  7. 今すぐエージェントを起動します。

    /etc/init.d/vpnagentd start
    
  8. AnyConnectがそれらと混同するため、iptablesを修正します。

    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
    

このハックの以前の、より単純なバージョンは、「return 0;」だけをする関数を与えました。 - そのポスターは、「これまでに観察した唯一の副作用は、vpnagentdがtopで報告されているように100%のCPUを使用していることです。私はそれを強調しました、それはアイドルから両方から素早く戻ってくるときループで2つの選択をしているようですが、決して読み書きしません - 私はLD_PRELOADで切り取った呼び出しが読むことになっていたと思います。それをすることはできますが、これまでのところ私には十分です。誰かがもっと良い解決策を持っている場合は、共有してください。」

些細なハックの問題は、それがシングルCPUコアを常に100%にし、ハードウェアCPUスレッド数を事実上1つ減らすことです - あなたのvpn接続がアクティブだったかどうか。私が気付いたのは、コードが実行していた選択がネットリンクソケットで、ルーティングテーブルが変更されたときにvpnagentdデータを送信するということでした。 vpnagentdは、ネットリンクソケットに新しいメッセージがあることに気付き続け、それを処理するためにrouteCallBackHandlerを呼び出しますが、簡単なハックは新しいメッセージをクリアしないため、何度も何度も呼び出され続けます。上で提供された新しいコードはネットリンクデータをフラッシュするので、100%CPUを引き起こした無限ループは起こりません。

問題が解決しない場合は、接続したらgdb -p $(pidof vpnagentd)を実行してください。

b socket
c
bt

そして、自分がどの通話に参加しているかを確認します。次に、どの通話を切り取りたいかを推測し、それをhack.cに追加して再コンパイルします。

53
Sasha Pachev

これは非常に複雑ですが、VMWare Playerなどを使用して最小限のVMを作成し、その中でCisco AnyConnect VPNクライアントを実行すると、VMWare仮想ネットワークを使用しながらルーティングを設定できる可能性があります。アダプタを使用するか、または単にVMを使用して、Cisco SSL VPNを介して必要なリソースにアクセスし、実際のマシンとの間でファイルをドラッグアンドドロップします。

11
LawrenceC

Shrew Soft VPNソフトウェアも、Ian Boydが示唆しているように、私にとってはうまくいきました。

Cisco VPNクライアントプロファイルをインポートできます。 Cisco VPN Clientバージョン5.0.05.0290を使用しました。ShrewVPN(バージョン2.1.7)をインストールしてCiscoプロファイルをインポートした後、Shrew VPN接続を追加設定することなく企業VPNに接続しながらローカルLANにアクセスできましたソフトウェア)。

7
vstrale

Sasha Pachev さん、上記のNice hackに感謝します。

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を忘れないでください。

上記のroutesメソッドのように、コールバックをインターセプトして解決しようとしていますが、対応するコールバックまたはメソッドがまだ見つかりません。

更新1/2:straceは、vpnagentdinotify APIを使用してリゾルバファイルの変更を監視していることを明らかにしました。そこから先は下り坂でした。これが追加のハックです。

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

エージェントを監視するallファイルが無効になるため、これはやややり過ぎです。しかし、うまくいくようです。

以下のvpnクライアントラッパースクリプトは、すべての機能を統合したものです(この追加のハックを含むように更新されました)。 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
Mauro Lacy

私の会社はまだそのVPNを使用しています。 vpncクライアントは単にiptablesの設定を次のように変更します。

#iptables-save 
#iptables-save v1.4.10 2012年6月17日14時12分20秒
 * filter 
:INPUT DROP [0] :0] 
:前方への受け入れ[0:0] 
:OUTPUT DROP [0:0] 
  -  A入力-s 123.244.255.254/32 -d 192.168.0.14/ 32 -j ACCEPT 
  -  A入力-i tun0 -j ACCEPT 
  - 入力-i lo0 -j ACCEPT 
  -  A入力-j DROP 
  -  A出力-s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT 
  - 出力-o tun0 -j ACCEPT 
  - 出力-o lo0 -j ACCEPT 
 ] -A OUTPUT -j DROP 
 COMMIT 

それはVPNトラフィックを除くすべてをフィルタリングします。

単にiptables-saveを使ってファイルにフィルタを入れ、あなたのニーズに合ったINPUTとOUTPOUTアクセスラインを追加してiptables-restoreを使ってファイルを再適用するだけです。

例えば192.168.0のローカルネットワークにアクセスするため

#iptables-save v1.4.10 at Sun Jun 17 14:12:20 2012 
 * filter 
:INPUT DROP [0:0] 
:転送受け入れ[0:0] 
:出力ドロップ[0:0] 
  - 入力-s 123.244.255.254/32 -d 192.168.0.14/32 -j ACCEPT 
 -A入力-s 192.168.0.0/24 -d 192.168.0.14/32 -j ACCEPT #local 
  - 入力-i tun0 -j ACCEPT 
  - 入力-i lo0 -j ACCEPT 
  -  A入力-j DROP 
  -  A出力-s 192.168.0.14/32 -d 123.244.255.254/32 -j ACCEPT 
  - 出力-s 192.168.0.14/32 -d 192.168.0.0/24 -j ACCEPT #local out 
  -  A出力-o tun0 -j ACCEPT 
  - 出力-o lo0 -j ACCEPT 
  -  A OUTPUT -j DROP 
 COMMIT 
4
banjo

これに関する何かニュース?

どのレベルで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
Marki

正しく理解したかどうかはわかりませんが、まず理解を明確にします。

ローカルLAN(たとえば、10.0.0.0/16、リモートCisco VPN Server(たとえば、64.0.0.0/16)があります。CiscoVPNクライアントを介してVPNサーバに接続するには、まだ必要です。この場合は、10.0.xx/16全体をVPN接続から切り離します。次のルートをMacクライアントに追加する必要があります。

/sbin/route add -net 10.0 -interface en1

en1はLANに接続するときに経由するインタフェースです。私はあなたがWindowsとLinuxにも同じことを追加できることを知っています。

3
Yasser Sobhdel

コメントを追加できないので、ここに投稿します。私はWindows上で走っています。

仮想マシンを使用し、VM内でAnyConnectを実行してから、作業環境と会社のネットワーク間のメディエータとしてVMを使用するソリューションでは、「最愛の」IT部門がルーティングしてもうまくいきません。 .0.0 VPN経由であなたのローカルネットワーク(あなたのローカルPCとVM間のこれも含む)でさえもVPNを通してルーティングされます(sic!)。

私は@Sasha Pachevによって投稿された解決策を適用しようとしましたが、結局私はそれが関数の始めに0を返すように.dllにパッチを当てることになりました。動的ライブラリとの戦いの後、やがて私は自分のニーズに応じてルーティングテーブルを修正することができましたが、どうやらそれだけでは不十分です。

私の規則は分割トンネリングを達成するために正しいように思えますが、私はまだ一般的な失敗に遭遇します。 解決できたのと同じような問題に遭遇しましたか?

  • インターネットへの私のゲートウェイは192.168.163.2です
  • 会社のネットワークへの私のゲートウェイは10.64.202.1です(したがって全体で10。。*サブネット私は "comapny's"として扱います)

これは私のルーティングテーブルが現在どのように見えるかです(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が接続されている(変更されていない)場合のテーブルの外観です。8.8.8.8に対してpingを実行しようとすると、単にタイムアウトになります(企業のファイアウォールではイントラネット外へのトラフィックの通過が許可されないため)。

enter image description here

2
Mike

Cisco AnyConnect SSL VPNを使用しているときにルーティングテーブルの制御を維持したい場合は、 OpenConnect を調べてください。どちらもCisco AnyConnect SSL VPNをサポートしており、ルーティングテーブルエントリの中断や「保護」を試みません。 @Vadzim 上記の コメントでこれをほのめかします

AnyConnect Secure Mobility Clientにパッチを適用すること以外はすべて試した後、Windows上で OpenConnect GUI に置き換えることに成功しました。これにより、ローカルリソースへの接続性を維持する(そしてルーティングテーブルを更新する)ことができました。

私はWindows上でOpenConnectを使っていますが、Linux、BSD、macOS(他のプラットフォームの中でも)をサポートしています プロジェクトページによると .

1
Robert Mooney

ゲートウェイ10.64.202.13でそれらのエントリを削除してみてください。ping 8.8.8.8が機能するかどうかを確認してから、それらを1つずつ追加して、問題の原因となっているエントリを特定してください。

DLLにどのようにパッチを当てましたか。ルーティングテーブルを変更することすらできません。VPNゲートウェイで0.0.0.0を追加し続けているからです。

0
Tony