📜 ⬆️ ⬇️

Logging VPN Connections on the Cisco ASA

Good day, colleagues. There is a Cisco ASA 5512 with a tuned server for IPSEC tunnels to which users cling to access to the corporate network. A task was received - to display a list of active users in monitoring, as well as to log who, when, from which address and with which profile he clung.

I climbed on the Internet, I didn’t find anything suitable for my task (maybe I was looking bad, of course), and decided to write a script that parses the SNMP output and adds it to the table.

MySQL table structure:

CREATE DATABASE `vpn_log` /*!40100 DEFAULT CHARACTER SET latin1 */; CREATE TABLE `logins` ( `id_l` int(10) unsigned NOT NULL AUTO_INCREMENT, `login` varchar(90) NOT NULL, `id_s` int(10) unsigned DEFAULT NULL, PRIMARY KEY (`id_l`), UNIQUE KEY `id_l_UNIQUE` (`id_l`), UNIQUE KEY `login_UNIQUE` (`login`) ) ENGINE=InnoDB AUTO_INCREMENT=121 DEFAULT CHARSET=latin1; CREATE TABLE `sessions` ( `id_s` int(10) unsigned NOT NULL AUTO_INCREMENT, `id_l` int(10) unsigned NOT NULL, `time_start` timestamp NOT NULL DEFAULT CURRENT_TIMESTAMP, `time_end` timestamp NOT NULL DEFAULT '0000-00-00 00:00:00', `ip_source` varchar(45) NOT NULL, `ip_lan` varchar(45) NOT NULL, `s_index` int(10) unsigned NOT NULL, `profile` varchar(255) NOT NULL, PRIMARY KEY (`id_s`), UNIQUE KEY `id_s_UNIQUE` (`id_s`) ) ENGINE=InnoDB AUTO_INCREMENT=2923 DEFAULT CHARSET=latin1; 

Processing script itself:
')
 #!/usr/bin/php <?php ##Database settings $settings['sql_host']="localhost"; $settings['sql_db']="vpn_log"; $settings['sql_user']="vpn_log"; $settings['sql_password']="vpn_log"; #  # function connectdb(){ global $settings; $dbconn = mysqli_connect( $settings['sql_host'], $settings['sql_user'], $settings['sql_password'], $settings['sql_db'] ) or die('Could not connect: ' . mysqli_connect_errno()); return $dbconn; } #     IPSEC # function get_users(){ $ret = snmp3_real_walk( '10.10.10.10', #IP  Cisco ASA 'snmpuser', #SNMP  'authNoPriv', # 'MD5', # 'authpassword', # '', # '', # '1.3.6.1.4.1.9.9.392.1.3.21' #  OID     ); $result = []; $user = []; foreach ($ret as $oid=>$value){ $re = '/(SNMPv2-SMI::enterprises\.9\.9\.392\.1\.3\.21\.1\.[0-9]{1,2}\.[0-9]{1,2}\.)([\.0-9]*)\.([0-9]{4,10})/'; #  ,        $str = $oid; preg_match_all($re, $str, $matches); $oid = explode(".",$matches[2][0]); $value = explode(": ",$value); $login = ""; foreach ($oid as $chr){ $login.=chr($chr); }; $result[strtolower($login)][$matches[3][0]][] = @str_ireplace("\"","",$value[1]); }; return $result; #       [login][s_index][value] }; $x = get_users(); $connect = connectdb(); foreach ($x as $user=>$sessions){ $user = addslashes($user); foreach ($sessions as $session=>$value ){ if (preg_match("/((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)/",$value[7]) and preg_match("/((25[0-5]|2[0-4]\d|[01]?\d\d?)\.){3}(25[0-5]|2[0-4]\d|[01]?\d\d?)/",$value[5])){ $sql = "SELECT * from logins where login = '$user'"; $result = mysqli_query($connect, $sql); $res = mysqli_fetch_array($result); $time = date("Ymd H:i:s",time()-$value[3]); $id_l = $res['id_l']; if (mysqli_num_rows($result)==0){ $sql_1 = "INSERT INTO logins value ('','".$user."','')"; $result_1 = mysqli_query($connect, $sql_1); $id_l = mysqli_insert_id($connect); $sql_1 = "INSERT INTO sessions (id_l,time_start,ip_source,ip_lan,s_index, profile)value ('$id_l','$time','$value[7]','$value[5]','$session', '$value[0]')"; $result_1 = mysqli_query($connect, $sql_1); $id_s = mysqli_insert_id($connect); } else{ $sql_1 = "SELECT * from sessions where (id_l = (select id_l from logins where login = '$user'))and(s_index = '$session')and(time_end = '0')"; $result_1 = mysqli_query($connect, $sql_1); if (mysqli_num_rows($result_1)==0){ $sql_2 = "INSERT INTO sessions (id_l,time_start,ip_source,ip_lan,s_index, profile)value ('$id_l','$time','$value[7]','$value[5]','$session', '$value[0]')"; $result_2 = mysqli_query($connect, $sql_2); } } } } } $sql = "SELECT l.login,s.s_index FROM logins as l left join sessions as s on l.id_l=s.id_l where (s.time_end=0)"; $rw = mysqli_query($connect,$sql); $result = mysqli_fetch_array($rw); while ($result['s_index']>0){ if (@!$x[strtolower($result['login'])][$result['s_index']][0]){ $sql_1 = "UPDATE sessions SET time_end = '".date("Ymd H:i:s",time())."' where s_index='".$result['s_index']."'"; mysqli_query($connect, $sql_1); }; $result = mysqli_fetch_array($rw); }; mysqli_close($connect); ?> 

Work Logic:

The script runs every 30 seconds via crone and polls the SNMP equipment. Since Cisco does not store user logins in open form, it is necessary to pull out logins from a dynamically configured SNMP OID. Each login character is stored using the ASCII code in the SNMP OID part (this is learned from here ).

After working out the get_user () function, the $ x variable takes the value in the following format:

  [login] => Array ( [s_index] => Array ( [0] => profile_name ............................. [34] => 0 ) ) 

Description of values ​​can be found here .

Next, the script checks if there is a login in the Logins table. If there is no such login, it adds it there, if there is, it receives its id_l. Then, it looks - does this login have open sessions with an unspecified end date. If not, it creates a new record in the sessions table.

Then the script receives from the database a list of users who have incomplete sessions. And checks for logins in the survey. If the login is not in the poll or the session number does not match the one in the database (s_index) - the time of session termination is entered.

Ready for comments / corrections / finalizations / questions.

UPD: added strtolower () in the functions of parsing the login and in checking the existence of the login in active sessions (almost at the end already). Otherwise, if the login contains capital letters, then everything works incorrectly.

Source: https://habr.com/ru/post/320156/


All Articles