Adding Socket Statistic Application Support (#15307)

This commit is contained in:
bnerickson 2023-10-13 20:45:03 -07:00 committed by GitHub
parent 1d361c9447
commit 78a4bfb9d9
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
25 changed files with 1752 additions and 0 deletions

View File

@ -79,6 +79,7 @@ class StringHelpers
'rrdcached' => 'RRDCached',
'sdfsinfo' => 'SDFS info',
'smart' => 'SMART',
'ss' => 'Socket Statistics',
'ups-apcups' => 'UPS apcups',
'ups-nut' => 'UPS nut',
'zfs' => 'ZFS',

View File

@ -2908,6 +2908,135 @@ setup. If the default does not work, check the docs for it at
sagan_stat_check](https://metacpan.org/dist/Sagan-Monitoring/view/bin/sagan_stat_check)
## Socket Statistics (ss)
The Socket Statistics application polls ss and scrapes socket statuses. Individual sockets and address families may be filtered out within the script's optional configuration JSON file.
a. The following socket types are polled directly. Filtering a socket will disable direct polling as-well-as indirect polling via any address families that list the socket as their child:
```
dccp (also exists within AF inet,inet6)
mptcp (also exists within AF inet,inet6)
raw (also exists within AF inet,inet6)
sctp (also exists within AF inet,inet6)
tcp (also exists within AF inet,inet6)
udp (also exists within AF inet,inet6)
xdp
```
b. The following socket types are polled within an address family only:
```
inet6 (within AF inet6)
p_dgr (within AF link)
p_raw (within AF link)
ti_dg (within AF tipc)
ti_rd (within AF tipc)
ti_sq (within AF tipc)
ti_st (within AF tipc)
v_dgr (within AF vsock)
v_str (within AF vsock)
unknown (within AF inet,inet6,link,tipc,vsock)
```
c. The following address families are polled directly, however, they also have socket types within their address family "umbrella". Filtering a socket will filter it from the address family. Filtering an address family will filter out all of its child sockets UNLESS those child sockets are polled directly; see (a) above:
```
inet
dccp
mptcp
raw
sctp
tcp
udp
unknown
inet6
dccp
icmp6
mptcp
raw
sctp
tcp
udp
unknown
link
p_dgr
p_raw
unknown
netlink
tipc
ti_dg
ti_rd
ti_sq
ti_st
unknown
unix
u_dgr
u_seq
u_str
vsock
v_dgr
v_str
unknown
```
### SNMP Extend
1. Copy the python script, ss.py, to the desired host
```
wget https://github.com/librenms/librenms-agent/raw/master/snmp/ss.py -O /etc/snmp/ss.py
```
2. Make the script executable
```
chmod +x /etc/snmp/ss.py
```
3. Edit your snmpd.conf file and add:
```
extend ss /etc/snmp/ss.py
```
4. (Optional) Create a /etc/snmp/ss.json file and specify:
a.) "ss_cmd" - String path to the ss binary: ["/sbin/ss"]
b.) "socket_types" - A comma-delimited list of socket types to include. The following socket types are valid: dccp, icmp6, mptcp, p_dgr, p_raw, raw, sctp, tcp, ti_dg, ti_rd, ti_sq, ti_st, u_dgr, u_seq, u_str, udp, unknown, v_dgr, v_dgr, xdp. Please note that the "unknown" socket type is represented in ss output with the netid "???". Please also note that the p_dgr and p_raw socket types are specific to the "link" address family; the ti_dg, ti_rd, ti_sq, and ti_st socket types are specific to the "tipc" address family; the u_dgr, u_seq, and u_str socket types are specific to the "unix" address family; and the v_dgr and v_str socket types are specific to the "vsock" address family. Filtering out the parent address families for the aforementioned will also filter out their specific socket types. Specifying "all" includes all of the socket types. For example: to include only tcp, udp, icmp6 sockets, you would specify "tcp,udp,icmp6": ["all"]
c.) "addr_families" - A comma-delimited list of address families to include. The following families are valid: inet, inet6, link, netlink, tipc, unix, vsock. As mentioned above under (b), filtering out the link, tipc, unix, or vsock address families will also filter out their respective socket types. Specifying "all" includes all of the families. For example: to include only inet and inet6 families, you would specify "inet,inet6": ["all"]
```
{
"ss_cmd": "/sbin/ss",
"socket_types": "all"
"addr_families": "all"
}
```
In order to filter out usually unused socket types, it is recommended to go with the following JSON:
```
{
"ss_cmd": "/sbin/ss",
"socket_types": "icmp6,p_dgr,p_raw,raw,tcp,u_dgr,u_seq,u_str,udp",
"addr_families": "inet,inet6,link,netlink,unix"
}
```
5. (Optional) If you have SELinux in Enforcing mode, you must add a module so the script can access socket state:
```
cat << EOF > snmpd_ss.te
module snmp_ss 1.0;
require {
type snmpd_t;
class netlink_tcpdiag_socket { bind create getattr nlmsg_read read setopt write };
}
#============= snmpd_t ==============
allow snmpd_t self:netlink_tcpdiag_socket { bind create getattr nlmsg_read read setopt write };
EOF
checkmodule -M -m -o snmpd_ss.mod snmpd_ss.te
semodule_package -o snmpd_ss.pp -m snmpd_ss.mod
semodule -i snmpd_ss.pp
```
6. Restart snmpd.
## Suricata
### SNMP Extend

View File

@ -0,0 +1,35 @@
<?php
$name = 'ss';
$colours = 'psychedelic';
$scale_min = 0;
$polling_type = 'app';
$unit_text = 'Status';
$unitlen = 7;
$bigdescrlen = 20;
$smalldescrlen = 20;
$rrd_list = [];
foreach (array_keys($rrdArray) as $socket_type) {
$rrd_filename = Rrd::name($device['hostname'], [
$polling_type,
$name,
$app->app_id,
$socket_type,
]);
if (Rrd::checkRrdExists($rrd_filename)) {
$i = 0;
foreach ($rrdArray[$socket_type] as $socket_status => $socket_status_desc) {
$rrd_list[$i]['filename'] = $rrd_filename;
$rrd_list[$i]['descr'] = $socket_status_desc['descr'];
$rrd_list[$i]['ds'] = $socket_status;
$i++;
}
} else {
d_echo('RRD ' . $rrd_filename . ' not found');
}
}
require 'includes/html/graphs/generic_multi_line_exact_numbers.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$socket_type = 'dccp';
$rrdArray = [];
if (array_key_exists($socket_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$socket_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,24 @@
<?php
require_once 'includes/ss-shared.inc.php';
$addr_family = 'inet';
$rrdArray = [];
$netid = $vars['netid'];
$socket_type = $addr_family . '_' . $netid;
if (array_key_exists($netid, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$netid];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = [
'descr' => $socket_state_clean_name,
];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,24 @@
<?php
require_once 'includes/ss-shared.inc.php';
$addr_family = 'inet6';
$rrdArray = [];
$netid = $vars['netid'];
$socket_type = $addr_family . '_' . $netid;
if (array_key_exists($netid, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$netid];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = [
'descr' => $socket_state_clean_name,
];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,24 @@
<?php
require_once 'includes/ss-shared.inc.php';
$addr_family = 'link';
$rrdArray = [];
$netid = $vars['netid'];
$socket_type = $addr_family . '_' . $netid;
if (array_key_exists($netid, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$netid];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = [
'descr' => $socket_state_clean_name,
];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$socket_type = 'mptcp';
$rrdArray = [];
if (array_key_exists($socket_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$socket_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$addr_family = 'netlink';
$rrdArray = [];
if (array_key_exists($addr_family, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$addr_family];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$addr_family][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$socket_type = 'raw';
$rrdArray = [];
if (array_key_exists($socket_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$socket_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$socket_type = 'sctp';
$rrdArray = [];
if (array_key_exists($socket_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$socket_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,52 @@
<?php
require_once 'includes/ss-shared.inc.php';
$allowed_sockets = $app->data['allowed_sockets'] ?? [];
$allowed_afs = $app->data['allowed_afs'] ?? [];
$rrdArray = [];
foreach ($ss_section_list as $gen_type) {
// Don't display data for filtered sockets and address families.
if (! in_array($gen_type, $allowed_sockets) && ! in_array($gen_type, $allowed_afs)) {
continue;
}
// Display graphs for address families with netids.
if (array_key_exists($gen_type, $ss_netid_mapper)) {
foreach ($ss_netid_mapper[$gen_type] as $netid) {
// Don't display data for filtered sockets.
if (! in_array($netid, $allowed_sockets)) {
continue;
}
$socket_type = $gen_type . '_' . $netid;
// Map the socket type to its available statues.
if (array_key_exists($gen_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$gen_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = [
'descr' => $socket_type . '_' . $socket_state_clean_name,
];
}
}
} else {
// Map the socket type to its available statues.
if (array_key_exists($gen_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$gen_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$gen_type][$socket_state_clean_name] = ['descr' => $gen_type . '_' . $socket_state_clean_name];
}
}
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$socket_type = 'tcp';
$rrdArray = [];
if (array_key_exists($socket_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$socket_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,24 @@
<?php
require_once 'includes/ss-shared.inc.php';
$addr_family = 'tipc';
$rrdArray = [];
$netid = $vars['netid'];
$socket_type = $addr_family . '_' . $netid;
if (array_key_exists($netid, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$netid];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = [
'descr' => $socket_state_clean_name,
];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$socket_type = 'udp';
$rrdArray = [];
if (array_key_exists($socket_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$socket_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,24 @@
<?php
require_once 'includes/ss-shared.inc.php';
$addr_family = 'unix';
$rrdArray = [];
$netid = $vars['netid'];
$socket_type = $addr_family . '_' . $netid;
if (array_key_exists($netid, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$netid];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = [
'descr' => $socket_state_clean_name,
];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,24 @@
<?php
require_once 'includes/ss-shared.inc.php';
$addr_family = 'vsock';
$rrdArray = [];
$netid = $vars['netid'];
$socket_type = $addr_family . '_' . $netid;
if (array_key_exists($netid, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$netid];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = [
'descr' => $socket_state_clean_name,
];
}
require 'ss-common.inc.php';

View File

@ -0,0 +1,18 @@
<?php
require_once 'includes/ss-shared.inc.php';
$socket_type = 'xdp';
$rrdArray = [];
if (array_key_exists($socket_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$socket_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$rrdArray[$socket_type][$socket_state_clean_name] = ['descr' => $socket_state_clean_name];
}
require 'ss-common.inc.php';

View File

@ -521,6 +521,9 @@ $graphs['privoxy'] = [
'resp_xxx',
'ver',
];
$graphs['ss'] = [
'sockets',
];
echo '<div class="panel panel-default">';
echo '<div class="panel-heading">';

View File

@ -0,0 +1,134 @@
<?php
require_once 'includes/ss-shared.inc.php';
$allowed_sockets = $app->data['allowed_sockets'] ?? [];
$allowed_afs = $app->data['allowed_afs'] ?? [];
/**
* Builds the graphs variable
*
* @param string $gen_type
* @param associative-array $ss_netid_mapper
* @param array $graphs
* @return $graphs
*/
function ss_graph_builder($gen_type, $ss_netid_mapper, $allowed_sockets, $graphs)
{
$graph_name = 'ss_' . $gen_type;
$graphs[$graph_name]['type'] = $gen_type;
// Build graphs for socket types and the netlink address family.
if (! array_key_exists($gen_type, $ss_netid_mapper)) {
$graph_descr = strtoupper($gen_type) . ' Sockets\' Statuses';
$graphs[$graph_name]['desc'] = $graph_descr;
} else {
// Build graphs for address family's netids.
foreach ($ss_netid_mapper[$gen_type] as $netid) {
// Don't build graphs for socket types (netids)
// that have been filtered out.
if (! in_array($netid, $allowed_sockets)) {
continue;
}
$graph_descr = strtoupper($gen_type) . ' ' . strtoupper($netid) . ' Sockets\' Statuses';
$graphs[$graph_name]['netid_statuses'][$netid]['desc'] = $graph_descr;
}
}
return $graphs;
}
/**
* Builds a graph array and outputs the graph.
*
* @param string $gen_type
* @param string $app_id
* @param null|string $netid
* @param string $graph_desc
*/
function ss_graph_printer($gen_type, $app_id, $netid, $graph_desc)
{
$graph_type = $gen_type;
$graph_array['height'] = '100';
$graph_array['width'] = '215';
$graph_array['to'] = time();
$graph_array['id'] = $app_id;
$graph_array['type'] = 'application_' . $gen_type;
if (! is_null($netid)) {
$graph_array['netid'] = $netid;
}
echo '<div class="panel panel-default">
<div class="panel-heading">
<h3 class="panel-title">' .
$graph_desc .
'</h3>
</div>
<div class="panel-body">
<div class="row">';
include 'includes/html/print-graphrow.inc.php';
echo '</div>';
echo '</div>';
echo '</div>';
}
$link_array = [
'page' => 'device',
'device' => $device['device_id'],
'tab' => 'apps',
'app' => 'ss',
];
print_optionbar_start();
echo generate_link('All Socket Types\' Statuses', $link_array) . ' | ';
$first_section_listed = false;
foreach ($ss_section_list as $gen_type) {
// Don't generate links for socket types or address
// families that have been filtered out.
if (! in_array($gen_type, $allowed_sockets) && ! in_array($gen_type, $allowed_afs)) {
continue;
}
if (! $first_section_listed) {
$first_section_listed = true;
} else {
echo ', ';
}
echo generate_link(strtoupper($gen_type), $link_array, ['section' => $gen_type]);
$i++;
}
print_optionbar_end();
$graphs = [];
// Build graphs variable
if (isset($vars['section'])) {
// Build graphs for the individual socket type sections.
$graphs = ss_graph_builder($vars['section'], $ss_netid_mapper, $allowed_sockets, $graphs);
} else {
// Build graphs for the combined socket statuses section.
foreach ($ss_section_list as $gen_type) {
// Don't generate links for socket types or address
// families that have been filtered out.
if (! in_array($gen_type, $allowed_sockets) && ! in_array($gen_type, $allowed_afs)) {
continue;
}
$graphs = ss_graph_builder($gen_type, $ss_netid_mapper, $allowed_sockets, $graphs);
}
}
// Display the built graphs
foreach ($graphs as $gen_type => $gen_values) {
// Print graphs for address families with netids.
if (array_key_exists($gen_values['type'], $ss_netid_mapper)) {
foreach ($gen_values['netid_statuses'] as $netid => $text) {
ss_graph_printer($gen_type, $app['app_id'], $netid, $text['desc']);
}
} else {
// Print graphs for socket types and the netlink address family.
ss_graph_printer($gen_type, $app['app_id'], null, $gen_values['desc']);
}
}

View File

@ -0,0 +1,209 @@
<?php
require_once 'includes/ss-shared.inc.php';
use LibreNMS\Exceptions\JsonAppException;
use LibreNMS\Exceptions\JsonAppMissingKeysException;
use LibreNMS\RRD\RrdDefinition;
$name = 'ss';
$output_success = 'OK';
$polling_type = 'app';
$metrics = [];
/**
* Performs a data update and returns the updated metrics.
*
* @param string $app_id
* @param class $device
* @param array $fields
* @param array $metrics
* @param string $name
* @param string $polling_type
* @param class $rrd_def
* @param string $gen_type
* @return $metrics
*/
function ss_data_update_helper($app_id, $fields, $metrics, $name, $polling_type, $rrd_def, $gen_type)
{
global $device;
$rrd_name = [$polling_type, $name, $app_id, $gen_type];
$metrics[$gen_type] = $fields;
$tags = [
'name' => $name,
'app_id' => $app_id,
'type' => $gen_type,
'rrd_def' => $rrd_def,
'rrd_name' => $rrd_name,
];
data_update($device, $polling_type, $tags, $fields);
return $metrics;
}
try {
$polling_data = json_app_get($device, $name, 1)['data'];
} catch (JsonAppMissingKeysException $e) {
$polling_data = $e->getParsedJson();
} catch (JsonAppException $e) {
echo PHP_EOL . $name . ':' . $e->getCode() . ':' . $e->getMessage() . PHP_EOL;
update_application($app, $e->getCode() . ':' . $e->getMessage(), []);
return;
}
// List to track which sockets we should graph. If the end-user
// filtered out the socket on the host system, it will not be
// added to the list.
$allowed_sockets = [];
// List to track which address families we should graph. If the
// end-user filtered out the socket on the host system, it will
// not be added to the list.
$allowed_afs = [];
// Use the mapping variable in ss-shared.inc.php to parse
// the json data received from the ss.py script.
foreach ($ss_section_list as $gen_type) {
// If a socket type does not exist in the results, then it
// was filtered out, so skip populating RRD for this type.
if (! array_key_exists($gen_type, $polling_data)) {
continue;
}
// Add the key of the data to either the allowed sockets list
// or the allowed address families list.
if (in_array($gen_type, $ss_socket_list)) {
array_push($allowed_sockets, $gen_type);
} elseif (in_array($gen_type, $ss_af_list)) {
array_push($allowed_afs, $gen_type);
} else {
$fgen_type = is_string($gen_type) ? filter_var($gen_type, FILTER_SANITIZE_STRING) : null;
$log_message = 'Socket Statistics Invalid Socket or AF Returned by Script: ' . $fgen_type;
log_event($log_message, $device, 'application');
continue;
}
// Process sockets that do not have netids. With the exception of "netlink",
// these are socket types.
if (! array_key_exists($gen_type, $ss_netid_mapper)) {
$rrd_def = RrdDefinition::make();
$fields = [];
// Grab a list of socket states for the socket type we are working with.
if (array_key_exists($gen_type, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$gen_type];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
// Iterate through socket statuses.
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$field_name = $socket_state_clean_name;
$field_value = $polling_data[$gen_type][$socket_state] ?? 0;
// Verify data passed by application script is valid.
// Update fields and rrd definition.
if (is_int($field_value)) {
$fields[$field_name] = $field_value;
} else {
$log_message = 'Secure Sockets Polling Warning: Invalid data returned by ';
$log_message .= 'application for socket ' . 'type ' . $gen_type . ' with socket ';
$log_message .= 'state' . $socket_state . '.';
log_event($log_message, $device, 'application');
continue;
}
$rrd_def->addDataset($field_name, 'GAUGE', 0);
}
$metrics = ss_data_update_helper($app->app_id, $fields, $metrics, $name, $polling_type, $rrd_def, $gen_type);
} else {
// Process sockets that have netids. These are all address families.
// Iterate through netids.
foreach ($ss_netid_mapper[$gen_type] as $netid) {
// If a socket type does not exist in the results, then it
// was filtered out, so skip populating RRD for this type.
if (! array_key_exists($netid, $polling_data[$gen_type])) {
continue;
}
// Add the key of the data to the allowed sockets list.
if (in_array($netid, $ss_socket_list)) {
array_push($allowed_sockets, $netid);
} else {
$fgen_type = is_string($gen_type) ? filter_var($gen_type, FILTER_SANITIZE_STRING) : null;
$log_message = 'Socket Statistics Invalid Socket Returned by Script: ' . $fgen_type;
log_event($log_message, $device, 'application');
continue;
}
$rrd_def = RrdDefinition::make();
$fields = [];
// Grab a list of socket states for the socket type we are working with.
if (array_key_exists($netid, $ss_socket_states_mapper)) {
$local_ss_socket_states_mapper = $ss_socket_states_mapper[$netid];
} else {
$local_ss_socket_states_mapper = $ss_socket_states_mapper['default'];
}
// Iterate through socket statuses.
foreach ($local_ss_socket_states_mapper as $socket_state => $socket_state_clean_name) {
$field_name = $socket_state_clean_name;
$field_value = $polling_data[$gen_type][$netid][$socket_state] ?? 0;
// Verify data passed by application script is valid.
// Update fields and rrd definition.
if (is_int($field_value)) {
$fields[$field_name] = $field_value;
} else {
$log_message = 'Secure Sockets Polling Warning: Invalid data returned by ';
$log_message .= 'application for socket ' . 'type ' . $gen_type . ' with ';
$log_message .= 'netid ' . $netid . ' and socket state' . $socket_state . '.';
log_event($log_message, $device, 'application');
continue;
}
$rrd_def->addDataset($field_name, 'GAUGE', 0);
}
$flat_type = $gen_type . '_' . $netid;
$metrics = ss_data_update_helper($app->app_id, $fields, $metrics, $name, $polling_type, $rrd_def, $flat_type);
}
}
}
// Get old allowed sockets list.
$old_allowed_sockets = $app->data['allowed_sockets'] ?? [];
// Get old allowed address families list.
$old_allowed_afs = $app->data['allowed_afs'] ?? [];
$updated_app_data = [
'allowed_afs' => $allowed_afs,
'allowed_sockets' => $allowed_sockets,
];
// Check for socket type changes.
$added_sockets = array_diff($allowed_sockets, $old_allowed_sockets);
$removed_sockets = array_diff($old_allowed_sockets, $allowed_sockets);
if (count($added_sockets) > 0 || count($removed_sockets) > 0) {
$log_message = 'Socket Statistics Allowed Sockets Change:';
$log_message .= count($added_sockets) > 0 ? ' Added ' . implode(',', $added_sockets) : '';
$log_message .= count($removed_sockets) > 0 ? ' Removed ' . implode(',', $removed_sockets) : '';
log_event($log_message, $device, 'application');
}
// Check for address family changes.
$added_afs = array_diff($allowed_afs, $old_allowed_afs);
$removed_afs = array_diff($old_allowed_afs, $allowed_afs);
if (count($added_afs) > 0 || count($removed_afs) > 0) {
$log_message = 'Socket Statistics Allowed Address Families Change:';
$log_message .= count($added_afs) > 0 ? ' Added ' . implode(',', $added_afs) : '';
$log_message .= count($removed_afs) > 0 ? ' Removed ' . implode(',', $removed_afs) : '';
log_event($log_message, $device, 'application');
}
$app->data = $updated_app_data;
update_application($app, $output_success, $metrics);

112
includes/ss-shared.inc.php Normal file
View File

@ -0,0 +1,112 @@
<?php
// Global variable used by the ss application to
// build graphs, rrd names and descriptions, and
// parse the ss.py script results.
// List of main sections.
$ss_section_list = ['dccp', 'inet', 'inet6', 'link', 'mptcp', 'netlink', 'raw', 'sctp', 'tcp', 'tipc', 'udp', 'unix', 'vsock', 'xdp'];
// List of all socket types.
$ss_socket_list = ['dccp', 'icmp6', 'mptcp', 'p_dgr', 'p_raw', 'raw', 'sctp', 'tcp', 'ti_dg', 'ti_rd', 'ti_sq', 'ti_st', 'u_dgr', 'u_seq', 'u_str', 'udp', 'v_dgr', 'v_str', 'xdp', 'unknown'];
// List of all address families.
$ss_af_list = ['inet', 'inet6', 'link', 'netlink', 'tipc', 'unix', 'vsock'];
// List all socket states mapped to all socket types.
$ss_socket_states_mapper = [
'default' => [
'ESTAB' => 'established',
'LISTEN' => 'listening',
'TOTAL' => 'total',
'UNCONN' => 'unconnected',
'UNKNOWN' => 'unknown',
],
'mptcp' => [
'CLOSE-WAIT' => 'close-wait',
'CLOSING' => 'closing',
'ESTAB' => 'established',
'FIN-WAIT-1' => 'fin-wait-1',
'FIN-WAIT-2' => 'fin-wait-2',
'LAST-ACK' => 'last-ack',
'LISTEN' => 'listening',
'SYN-SENT' => 'syn-sent',
'SYN-RECV' => 'syn-recv',
'TIME-WAIT' => 'time-wait',
'TOTAL' => 'total',
'UNCONN' => 'unconnected',
'UNKNOWN' => 'unknown',
],
'sctp' => [
'ACK_SENT' => 'ack-sent',
'CLOSED' => 'closed',
'COOKIE_ECHOED' => 'cookie-echoed',
'COOKIE_WAIT' => 'cookie-wait',
'ESTAB' => 'established',
'SHUTDOWN_PENDING' => 'shutdown-pending',
'SHUTDOWN_RECEIVED' => 'shutdown-received',
'SHUTDOWN_SENT' => 'shutdown-sent',
'TOTAL' => 'total',
],
'tcp' => [
'CLOSE-WAIT' => 'close-wait',
'CLOSING' => 'closing',
'ESTAB' => 'established',
'FIN-WAIT-1' => 'fin-wait-1',
'FIN-WAIT-2' => 'fin-wait-2',
'LAST-ACK' => 'last-ack',
'LISTEN' => 'listening',
'SYN-SENT' => 'syn-sent',
'SYN-RECV' => 'syn-recv',
'TIME-WAIT' => 'time-wait',
'TOTAL' => 'total',
'UNCONN' => 'unconnected',
'UNKNOWN' => 'unknown',
],
];
// Mapping of address families w/netids. Note that
// "unknown" is output as "???" by the ss.py application.
$ss_netid_mapper = [
'inet' => [
'dccp',
'mptcp',
'raw',
'sctp',
'tcp',
'udp',
'unknown',
],
'inet6' => [
'dccp',
'icmp6',
'mptcp',
'raw',
'sctp',
'tcp',
'udp',
'unknown',
],
'link' => [
'p_dgr',
'p_raw',
'unknown',
],
'tipc' => [
'ti_dg',
'ti_rd',
'ti_sq',
'ti_st',
'unknown',
],
'unix' => [
'u_dgr',
'u_seq',
'u_str',
],
'vsock' => [
'v_dgr',
'v_str',
'unknown',
],
];

View File

@ -753,6 +753,16 @@
"name": "SMART: one or more disk could not be polled",
"severity": "critical"
},
{
"rule": "applications.app_type = \"ss\" && application_metrics.metric = \"tcp_time-wait\" && application_metrics.value > \"100\"",
"name": "SS TCP TIME-WAIT Sessions > 100",
"severity": "warning"
},
{
"rule": "applications.app_type = \"ss\" && application_metrics.metric = \"inet6_tcp_established\" && application_metrics.value < \"10\"",
"name": "SS IPv6 TCP ESTABLISHED Sessions < 10",
"severity": "critical"
},
{
"rule": "applications.app_type = \"suricata_extract\" && application_metrics.metric = \"errors\" && application_metrics.value > \"0\"",
"name": "Suricata Extract Submit errors found > 0",

769
tests/data/linux_ss-v1.json Normal file
View File

@ -0,0 +1,769 @@
{
"os": {
"discovery": {
"devices": [
{
"sysName": "<private>",
"sysObjectID": ".1.3.6.1.4.1.8072.3.2.10",
"sysDescr": "Linux server 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64",
"sysContact": "<private>",
"version": "3.10.0-693.5.2.el7.x86_64",
"hardware": "Generic x86 64-bit",
"features": null,
"location": "<private>",
"os": "linux",
"type": "server",
"serial": null,
"icon": "linux.svg"
}
]
},
"poller": "matches discovery"
},
"applications": {
"discovery": {
"applications": [
{
"app_type": "ss",
"app_state": "UNKNOWN",
"discovered": 1,
"app_state_prev": null,
"app_status": "",
"app_instance": "",
"data": null,
"deleted_at": null
}
]
},
"poller": {
"applications": [
{
"app_type": "ss",
"app_state": "OK",
"discovered": 1,
"app_state_prev": "UNKNOWN",
"app_status": "",
"app_instance": "",
"data": "{\"allowed_afs\":[\"inet\",\"inet6\",\"link\",\"netlink\",\"unix\"],\"allowed_sockets\":[\"raw\",\"tcp\",\"udp\",\"unknown\",\"icmp6\",\"raw\",\"tcp\",\"udp\",\"unknown\",\"p_dgr\",\"p_raw\",\"unknown\",\"raw\",\"tcp\",\"udp\",\"u_dgr\",\"u_seq\",\"u_str\"]}",
"deleted_at": null
}
],
"application_metrics": [
{
"metric": "inet_raw_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_raw_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_raw_total",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_raw_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_raw_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_close-wait",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_closing",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_established",
"value": 1,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_fin-wait-1",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_fin-wait-2",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_last-ack",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_listening",
"value": 5,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_syn-recv",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_syn-sent",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_time-wait",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_total",
"value": 6,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_tcp_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_udp_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_udp_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_udp_total",
"value": 9,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_udp_unconnected",
"value": 9,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_udp_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_unknown_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_unknown_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_unknown_total",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_unknown_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet_unknown_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_icmp6_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_icmp6_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_icmp6_total",
"value": 1,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_icmp6_unconnected",
"value": 1,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_icmp6_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_raw_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_raw_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_raw_total",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_raw_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_raw_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_close-wait",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_closing",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_established",
"value": 3,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_fin-wait-1",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_fin-wait-2",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_last-ack",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_listening",
"value": 8,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_syn-recv",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_syn-sent",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_time-wait",
"value": 6,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_total",
"value": 17,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_tcp_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_udp_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_udp_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_udp_total",
"value": 7,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_udp_unconnected",
"value": 7,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_udp_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_unknown_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_unknown_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_unknown_total",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_unknown_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "inet6_unknown_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_dgr_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_dgr_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_dgr_total",
"value": 1,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_dgr_unconnected",
"value": 1,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_dgr_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_raw_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_raw_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_raw_total",
"value": 2,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_raw_unconnected",
"value": 2,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_p_raw_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_unknown_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_unknown_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_unknown_total",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_unknown_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "link_unknown_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "netlink_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "netlink_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "netlink_total",
"value": 49,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "netlink_unconnected",
"value": 49,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "netlink_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "raw_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "raw_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "raw_total",
"value": 1,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "raw_unconnected",
"value": 1,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "raw_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_close-wait",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_closing",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_established",
"value": 4,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_fin-wait-1",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_fin-wait-2",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_last-ack",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_listening",
"value": 13,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_syn-recv",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_syn-sent",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_time-wait",
"value": 6,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_total",
"value": 23,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "tcp_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "udp_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "udp_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "udp_total",
"value": 16,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "udp_unconnected",
"value": 16,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "udp_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_dgr_established",
"value": 43,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_dgr_listening",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_dgr_total",
"value": 61,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_dgr_unconnected",
"value": 18,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_dgr_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_seq_established",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_seq_listening",
"value": 2,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_seq_total",
"value": 2,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_seq_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_seq_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_str_established",
"value": 236,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_str_listening",
"value": 56,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_str_total",
"value": 292,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_str_unconnected",
"value": 0,
"value_prev": null,
"app_type": "ss"
},
{
"metric": "unix_u_str_unknown",
"value": 0,
"value_prev": null,
"app_type": "ss"
}
]
}
}
}

View File

@ -0,0 +1,10 @@
1.3.6.1.2.1.1.1.0|4|Linux server 3.10.0-693.5.2.el7.x86_64 #1 SMP Fri Oct 20 20:32:50 UTC 2017 x86_64
1.3.6.1.2.1.1.2.0|6|1.3.6.1.4.1.8072.3.2.10
1.3.6.1.2.1.1.3.0|67|77550514
1.3.6.1.2.1.1.4.0|4|<private>
1.3.6.1.2.1.1.5.0|4|<private>
1.3.6.1.2.1.1.6.0|4|<private>
1.3.6.1.2.1.25.1.1.0|67|77552962
1.3.6.1.4.1.8072.1.3.2.2.1.21.6.100.105.115.116.114.111|2|1
1.3.6.1.4.1.8072.1.3.2.2.1.21.2.115.115|2|1
1.3.6.1.4.1.8072.1.3.2.3.1.2.2.115.115|4x|7b226572726f72537472696e67223a2022222c20226572726f72223a20302c202276657273696f6e223a20312c202264617461223a207b22696e6574223a207b22726177223a207b7d2c2022746370223a207b224c495354454e223a20352c2022544f54414c223a20362c20224553544142223a20317d2c2022756470223a207b22554e434f4e4e223a20392c2022544f54414c223a20397d2c2022756e6b6e6f776e223a207b7d7d2c2022696e657436223a207b2269636d7036223a207b22554e434f4e4e223a20312c2022544f54414c223a20317d2c2022726177223a207b7d2c2022746370223a207b224c495354454e223a20382c2022544f54414c223a2031372c20224553544142223a20332c202254494d452d57414954223a20367d2c2022756470223a207b22554e434f4e4e223a20372c2022544f54414c223a20377d2c2022756e6b6e6f776e223a207b7d7d2c20226c696e6b223a207b22705f646772223a207b22554e434f4e4e223a20312c2022544f54414c223a20317d2c2022705f726177223a207b22554e434f4e4e223a20322c2022544f54414c223a20327d2c2022756e6b6e6f776e223a207b7d7d2c20226e65746c696e6b223a207b22554e434f4e4e223a2034392c2022544f54414c223a2034397d2c2022726177223a207b22554e434f4e4e223a20312c2022544f54414c223a20317d2c2022746370223a207b224c495354454e223a2031332c2022544f54414c223a2032332c20224553544142223a20342c202254494d452d57414954223a20367d2c2022756470223a207b22554e434f4e4e223a2031362c2022544f54414c223a2031367d2c2022756e6978223a207b22755f646772223a207b22554e434f4e4e223a2031382c2022544f54414c223a2036312c20224553544142223a2034337d2c2022755f736571223a207b224c495354454e223a20322c2022544f54414c223a20327d2c2022755f737472223a207b224c495354454e223a2035362c2022544f54414c223a203239322c20224553544142223a203233367d7d7d7d0a