我们在使用Cisco ASA防火墙和其它网络建立IPsec VPN通道后,可能需要监控这些VPN通道的状态,本文将分享一套便捷的方式给你,使VPN的连接状态清晰的展示在你的面前。

数据采集:Python、SNMP

数据库:InfluxDB

展示平台:Grafana

Cisco ASA防火墙的SNMP MIB中提供了很多关于IPsec VPN的OID,我们这里只使用两个相对有用的,一个是cikeTunStatus,对应OID:1.3.6.1.4.1.9.9.171.1.2.3.1.35,另外一个是 cikeTunRemoteValue,对应OID:1.3.6.1.4.1.9.9.171.1.2.3.1.7。 cikeTunStatus这个OID会列出当前存在的VPN状态,同时会列出已经存在VPN所对应的SNMP序列,如下:

Grafana监控ASA防火墙VPN状态-成长便签

cikeTunRemoteValue需要结合VPN序列使用,会列出IPsec Peer的IP,如下:

Grafana监控ASA防火墙VPN状态-成长便签

以上两个OID结合使用,我们便可以拿到防火墙上已经建立的IPSec VPN的对端IP,剩下就是如何数据获取、保存及展示的问题。

关于数据获取,我们可以Python编写脚本对指定防火墙IP进行两次SNMP Get操作。第一次使用cikeTunStatus获取所有VPN会话的序列,第二次遍历拿到的序列数据,组成第二次Get查询语句并循环执行所有组合语句。以上操作我们可以用以下代码完成:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
import os

#SNMP OID
linkoid = '1.3.6.1.4.1.9.9.171.1.2.3.1.35'
ipoid = '1.3.6.1.4.1.9.9.171.1.2.3.1.7'

def GetPeerIP(host,community):
    links = os.popen('snmpwalk -t 0.4 -v 2c -c '+ community + ' ' + host + ' ' + linkoid).read().split('\n')[:-1]
    ips = []
    if len(links):
        for link in links:
            linkid = link.replace('=','.').split('.')[-2].rstrip()
            peerip = os.popen('snmpwalk -O v -t 0.5 -v 2c -c '+ community + ' ' + host + ' ' + ipoid + '.' +linkid).read().split('\n')[:-1]
            if len(peerip):
                peerip[0] = peerip[0].replace('"','').split(': ')[-1]
                ips.append(peerip[0])
    return ips

接着是数据保存,为了能够展示VPN会话的历史连接信息,我们使用InfluxDB基于时序的方式保存数据,数据库的结构也比较简单,使用防火墙的IP作为表名,使用获取到的Peer IP作为以后的关键查询条件,最后增加一个“State”表段作为判断条件。创建数据库相关代码如下:

1
2
3
4
CREATE DATABASE "vpnmonitor"
CREATE RETENTION POLICY "vpnmonitor_retention" ON "vpnmonitor" DURATION 2160h0m0s REPLICATION 1
CREATE USER test WITH PASSWORD 'test2019'
GRANT ALL ON vpnmonitor to test

Python脚本中写入数据库代码如下:

1
2
3
4
5
6
7
8
9
#Database info

dbname = 'vpnmonitor'
dbuser = 'test'
dbpass = 'test2019'

def SaveData(data):
    databaseurl = 'http://127.0.0.1:8086/write?db=' + dbname +'&u=' + dbuser + '&p=' + dbpass
    response = requests.post(databaseurl,data = data)

然后我们再创建一个调用函数,执行数据查询和保存操作,代码如下:

1
2
3
4
5
6
7
8
9
def doVPNMonitor(host,community):
    ips = GetPeerIP(host,community)
    if len(ips):
        for peerip in ips:
            data = host + ",PeerIP=" + peerip + " State=1"
            SaveData(data)

#执行操作,替换自己防火墙的IP和SNMP Community
doVPNMonitor("192.168.100.1","public")

最后我们使用Grafana添加创建的InfluxDB数据库,然后创建Dashboard,在Dashboard中添加Graph图形,在Graph图形中配置如下查询语句:

Grafana监控ASA防火墙VPN状态-成长便签

一个Graph中可以添加多条语句对应不同的VPN会话,以下是是最终的展示效果:

Grafana监控ASA防火墙VPN状态-成长便签

阴影部分表示某条VPN会话曾经中断过,如果觉得Graph图形不够醒目,可以为每个VPN会话创建一个Status Panel,剩下的就自己探索吧。