mirror of
https://github.com/netbirdio/plugins.git
synced 2026-05-22 18:44:07 -07:00
ARPscanner first release (#271)
This commit is contained in:
committed by
Franco Fichtner
parent
ef82e387a6
commit
aec97c0b17
@@ -0,0 +1,8 @@
|
||||
PLUGIN_NAME= ARP Scan
|
||||
PLUGIN_VERSION= 0.1
|
||||
PLUGIN_COMMENT= Get all peers connected to a LAN
|
||||
PLUGIN_MAINTAINER= giuseppe.demarco@unical.it
|
||||
PLUGIN_DEPENDS= arp-scan
|
||||
PLUGINS_DEVEL= yes
|
||||
|
||||
.include "../../Mk/plugins.mk"
|
||||
@@ -0,0 +1,16 @@
|
||||
ARP Scan sends ARP packets to hosts on the local network and displays
|
||||
any responses that are received.
|
||||
|
||||
The Address Resolution Protocol (ARP) uses a simple message format containing
|
||||
one address resolution request or response (usually IPv4).
|
||||
|
||||
ARP Scan is a simple tool yet very powerful and it represent the only way
|
||||
to find a device using an arp response. Once you’ve found the MAC
|
||||
address, you can find more info about that device by matching that MAC
|
||||
address to it’s vendor.
|
||||
|
||||
Arp scan techniques are very important to understand ARP/MAC responses
|
||||
for penetration tester and diagnosys purpose. It is the first tool for
|
||||
network monitoring, especially against ip collisions, arpspoof and all
|
||||
kind of hijack techniques, like Man-In-The-Middle Attack. It also helps
|
||||
in cases when someone is spoofing IP address and DoS-ing your server.
|
||||
+91
@@ -0,0 +1,91 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*/
|
||||
|
||||
namespace OPNsense\ARPscanner\Api;
|
||||
|
||||
use \OPNsense\Base\ApiControllerBase;
|
||||
use \OPNsense\Core\Backend;
|
||||
|
||||
class ServiceController extends ApiControllerBase
|
||||
{
|
||||
|
||||
public function startAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$ifname = escapeshellarg($_POST['interface']);
|
||||
$networks = escapeshellarg($_POST['networks']);
|
||||
//~ return 'arpscanner start '.$ifname.' '.$networks;
|
||||
$backend = new Backend();
|
||||
$result = json_decode(trim($backend->configdRun('arpscanner start '.$ifname.' '.$networks)), true);
|
||||
return $result;
|
||||
}
|
||||
return array("message" => "unable to run config action");
|
||||
}
|
||||
|
||||
public function statusAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$ifname = escapeshellarg($_POST['interface']);
|
||||
//~ return 'arpscanner start '.$ifname.' '.$networks;
|
||||
$backend = new Backend();
|
||||
$result = json_decode(trim($backend->configdRun('arpscanner status '.$ifname)), true);
|
||||
return $result;
|
||||
}
|
||||
return array("message" => "this action must be called using the POST method");
|
||||
}
|
||||
|
||||
public function stopAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$ifname = escapeshellarg($_POST['interface']);
|
||||
$backend = new Backend();
|
||||
$bckresult = trim($backend->configdRun("arpscanner stop ".$ifname));
|
||||
if ($bckresult !== null) {
|
||||
// only return valid json type responses
|
||||
return $bckresult;
|
||||
}
|
||||
return array("message" => "error");
|
||||
}
|
||||
}
|
||||
|
||||
public function checkAction()
|
||||
{
|
||||
if ($this->request->isPost()) {
|
||||
$ifname = escapeshellarg($_POST['interface']);
|
||||
// test: "configctl arpscanner check em0"
|
||||
$backend = new Backend();
|
||||
$bckresult = json_decode(trim($backend->configdRun("arpscanner check ".$ifname)), true);
|
||||
if ($bckresult !== null) {
|
||||
// only return valid json type responses
|
||||
return $bckresult;
|
||||
}
|
||||
return array("message" => "error");
|
||||
}
|
||||
}
|
||||
|
||||
}
|
||||
+103
@@ -0,0 +1,103 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
**/
|
||||
namespace OPNsense\ARPscanner\Api;
|
||||
|
||||
use \OPNsense\Base\ApiControllerBase;
|
||||
use \OPNsense\ARPscanner\ARPscanner;
|
||||
use \OPNsense\Core\Config;
|
||||
use \OPNsense\Core\Backend;
|
||||
|
||||
class SettingsController extends ApiControllerBase
|
||||
{
|
||||
/* retrieve general settings
|
||||
* @return array general settings
|
||||
*/
|
||||
public function getAction()
|
||||
{
|
||||
// define list of configurable settings
|
||||
$result = array();
|
||||
if ($this->request->isGet()) {
|
||||
$mdl = new ARPscanner();
|
||||
$result['arpscanner'] = $mdl->getNodes();
|
||||
// returns: {"arpscanner":{"general":{"interface":
|
||||
// {"lan":{"value":"lan","selected":1}},"networks":
|
||||
// {"10.0.1.0\/24":{"value":"10.0.1.0\/24","selected":1}}}}}
|
||||
|
||||
$backend = new Backend();
|
||||
$bckresult = trim($backend->configdRun("arpscanner interfaces"));
|
||||
$ifnames = json_decode($bckresult);
|
||||
|
||||
$result['arpscanner']['general']['interface'] = array();
|
||||
|
||||
if (is_array($ifnames) || is_object($ifnames))
|
||||
{
|
||||
foreach ($ifnames as &$arr) {
|
||||
$ifname = $arr[0];
|
||||
$result['arpscanner']['general']['interface'][$ifname] = array();
|
||||
$result['arpscanner']['general']['interface'][$ifname]['value'] = join(", ", array($ifname, " (".$arr[2].")") );
|
||||
}
|
||||
}
|
||||
// $result['arpscanner']['general']['networks'] = '192.168.1.0/24,172.16.45.0/25';
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
/**
|
||||
* update arpscan settings
|
||||
* @return array status
|
||||
*/
|
||||
public function setAction()
|
||||
{
|
||||
$result = array("result"=>"failed");
|
||||
if ($this->request->isPost()) {
|
||||
// load model and update with provided data
|
||||
$mdl = new ARPscanner();
|
||||
$mdl->setNodes($this->request->getPost("arpscanner"));
|
||||
|
||||
// perform validation
|
||||
$valMsgs = $mdl->performValidation();
|
||||
foreach ($valMsgs as $field => $msg) {
|
||||
if (!array_key_exists("validations", $result)) {
|
||||
$result["validations"] = array();
|
||||
}
|
||||
$result["validations"]["general.".$msg->getField()] = $msg->getMessage();
|
||||
}
|
||||
|
||||
// serialize model to config and save
|
||||
if ($valMsgs->count() == 0) {
|
||||
$mdl->serializeToConfig();
|
||||
Config::getInstance()->save();
|
||||
$result["result"] = "saved";
|
||||
}
|
||||
}
|
||||
return $result;
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
@@ -0,0 +1,51 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\ARPscanner;
|
||||
|
||||
/**
|
||||
* Class IndexController
|
||||
* @package OPNsense\ARPscanner
|
||||
*/
|
||||
class IndexController extends \OPNsense\Base\IndexController
|
||||
{
|
||||
/**
|
||||
* ARP scanner index page
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function indexAction()
|
||||
{
|
||||
$this->view->title = gettext('ARP Scan');
|
||||
$this->view->general = $this->getForm("general");
|
||||
$this->view->pick('OPNsense/ARPscanner/index');
|
||||
|
||||
$this->view->generalForm = $this->getForm("general");
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,15 @@
|
||||
<form>
|
||||
<field>
|
||||
<id>arpscanner.general.interface</id>
|
||||
<label>Listen Interface</label>
|
||||
<type>dropdown</type>
|
||||
<help>Interface where to find the networks logically linked to.</help>
|
||||
</field>
|
||||
<field>
|
||||
<id>arpscanner.general.networks</id>
|
||||
<label>Network to probe</label>
|
||||
<type>text</type>
|
||||
<help>Network to scan, default: localnet.
|
||||
</help>
|
||||
</field>
|
||||
</form>
|
||||
@@ -0,0 +1,9 @@
|
||||
<acl>
|
||||
<page-services-arpscanner>
|
||||
<name>Diagnostics: ARP Scan</name>
|
||||
<patterns>
|
||||
<pattern>ui/arpscanner/*</pattern>
|
||||
<pattern>api/arpscanner/*</pattern>
|
||||
</patterns>
|
||||
</page-services-arpscanner>
|
||||
</acl>
|
||||
@@ -0,0 +1,42 @@
|
||||
<?php
|
||||
|
||||
/**
|
||||
* Copyright (C) 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
*
|
||||
* All rights reserved.
|
||||
*
|
||||
* Redistribution and use in source and binary forms, with or without
|
||||
* modification, are permitted provided that the following conditions are met:
|
||||
*
|
||||
* 1. Redistributions of source code must retain the above copyright notice,
|
||||
* this list of conditions and the following disclaimer.
|
||||
*
|
||||
* 2. Redistributions in binary form must reproduce the above copyright
|
||||
* notice, this list of conditions and the following disclaimer in the
|
||||
* documentation and/or other materials provided with the distribution.
|
||||
*
|
||||
* THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
* INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
* AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
* AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
* OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
* SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
* INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
* CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
* ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
* POSSIBILITY OF SUCH DAMAGE.
|
||||
*
|
||||
*/
|
||||
|
||||
namespace OPNsense\ARPscanner;
|
||||
|
||||
use OPNsense\Base\BaseModel;
|
||||
|
||||
class ARPscanner extends BaseModel
|
||||
{
|
||||
public function test(){
|
||||
$command="/sbin/ifconfig -l -u";
|
||||
exec($command, $output);
|
||||
return $output;
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,19 @@
|
||||
<model>
|
||||
<mount>//OPNsense/ARPscanner</mount>
|
||||
<version>1.0.0</version>
|
||||
<description>ARP Scan</description>
|
||||
<items>
|
||||
<general>
|
||||
<interface type="TextField">
|
||||
<default>lan</default>
|
||||
<Required>Y</Required>
|
||||
</interface>
|
||||
<networks type="TextField">
|
||||
<default></default>
|
||||
<Required>N</Required>
|
||||
<ValidationMessage>Scan a different ipv4 network, instead of localnet</ValidationMessage>
|
||||
<mask>/^(\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\/\d{1,2}(,)?)+$/</mask>
|
||||
</networks>
|
||||
</general>
|
||||
</items>
|
||||
</model>
|
||||
@@ -0,0 +1,7 @@
|
||||
<menu>
|
||||
<Interfaces>
|
||||
<Diagnostics>
|
||||
<ARPscanner VisibleName="ARP Scan" cssClass="fa fa-search fa-fw" url="/ui/arpscanner/"/>
|
||||
</Diagnostics>
|
||||
</Interfaces>
|
||||
</menu>
|
||||
@@ -0,0 +1,208 @@
|
||||
{#
|
||||
|
||||
Copyright © 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without modification,
|
||||
are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
this list of conditions and the following disclaimer in the documentation
|
||||
and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
#}
|
||||
|
||||
|
||||
<script type="text/javascript">
|
||||
|
||||
function flush_table(){
|
||||
$('#netTable tr').slice(2).remove()
|
||||
}
|
||||
|
||||
var check_state = 0;
|
||||
function check_scanner_status(ifname){
|
||||
// sets 0 if stopped and 1 if running
|
||||
sendData={'interface': ifname }
|
||||
//~ // action to run after successful save, for example reconfigure service.
|
||||
ajaxCall(url="/api/arpscanner/service/check", sendData, callback=function(data,status) {
|
||||
// action to run after reload
|
||||
if (data.length >= 1){
|
||||
$("#update_stop").hide();
|
||||
$("#update_start").show();
|
||||
check_state = 1;
|
||||
$("#scan_progress").addClass("fa fa-spinner fa-pulse");
|
||||
$("#startScanner").addClass("disabled")
|
||||
setTimeout(function(){
|
||||
get_status(ifname)
|
||||
}, 2000 );
|
||||
} else {
|
||||
$("#update_stop").show();
|
||||
$("#update_start").hide();
|
||||
check_state = 0;
|
||||
$("#scan_progress").removeClass("fa fa-spinner fa-pulse");
|
||||
$("#startScanner").removeClass("disabled")
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function get_status(ifname){
|
||||
flush_table();
|
||||
ajaxCall(url="/api/arpscanner/service/status",
|
||||
sendData={'interface':ifname},
|
||||
callback=function(data,status) {
|
||||
$.each(data['peers'], function(key_x,peer) {
|
||||
//~ console.log(peer);
|
||||
ip = peer[0];
|
||||
mac = peer[1];
|
||||
vendor = peer[2];
|
||||
$('#netTable tr:last').after("<tr><td>"+ip+"</td><td>"+mac+"</td><td>"+vendor+"</td></tr>")
|
||||
})
|
||||
check_scanner_status(ifname)
|
||||
$("#ifname").text(ifname);
|
||||
$("#started").text(data['started']);
|
||||
$("#last").text(data['last']);
|
||||
});
|
||||
}
|
||||
|
||||
$( document ).ready(function() {
|
||||
|
||||
var data_get_map = {'frm_GeneralSettings': "/api/arpscanner/settings/get"};
|
||||
//~ console.log(data_get_map);
|
||||
mapDataToFormUI(data_get_map).done(function(data){
|
||||
// place actions to run after load, for example update form styles.
|
||||
formatTokenizersUI();
|
||||
$('select').selectpicker('refresh');
|
||||
// check if the scanner is already running
|
||||
first_status = $('#arpscanner\\.general\\.interface option:selected')[0].value;
|
||||
check_scanner_status(first_status);
|
||||
});
|
||||
|
||||
// link save button to API set action
|
||||
$("#saveAct").click(function(){
|
||||
saveFormToEndpoint(url="/api/arpscanner/settings/set",formid='frm_GeneralSettings',callback_ok=function(){
|
||||
// action to run after successful save, for example reconfigure service.
|
||||
ajaxCall(url="/api/arpscanner/service/reload", sendData={},callback=function(data,status) {
|
||||
// action to run after reload
|
||||
});
|
||||
|
||||
});
|
||||
});
|
||||
|
||||
$("#statusScanner").click(function(){
|
||||
value = $('#arpscanner\\.general\\.interface option:selected')[0].value;
|
||||
get_status(value);
|
||||
});
|
||||
|
||||
$("#stopScanner").click(function(){
|
||||
// action to run after successful save, for example reconfigure service.
|
||||
value = $('#arpscanner\\.general\\.interface option:selected')[0].value;
|
||||
sendData={'interface': value }
|
||||
ajaxCall(url="/api/arpscanner/service/stop", sendData, callback=function(data,status) {
|
||||
// action to run after reload
|
||||
//~ console.log(data);
|
||||
$("#scan_progress").removeClass("fa fa-spinner fa-pulse");
|
||||
check_scanner_status(value);
|
||||
});
|
||||
});
|
||||
|
||||
// CHECK STATUS
|
||||
// check the status opf the scanner on selected interface
|
||||
$("#arpscanner\\.general\\.interface").change(function(){
|
||||
value = $('#arpscanner\\.general\\.interface option:selected')[0].value;
|
||||
get_status(value);
|
||||
$("#ifname").text(value);
|
||||
$("#started").text('');
|
||||
$("#last").text('');
|
||||
});
|
||||
|
||||
|
||||
$("#startScanner").click(function(){
|
||||
//~ $("#responseMsg").removeClass("hidden");
|
||||
$("#scan_progress").addClass("fa fa-spinner fa-pulse");
|
||||
var ifname = $('#arpscanner\\.general\\.interface option:selected')[0].value;
|
||||
var networks = $('#arpscanner\\.general\\.networks').val();
|
||||
ajaxCall(url="/api/arpscanner/service/start",
|
||||
sendData={'interface':ifname, 'networks': networks},
|
||||
callback=function(data,status) {
|
||||
// action to run after reload
|
||||
//~ console.log(data);
|
||||
$("#ifname").text(data['interface']);
|
||||
$("#started").text(data['started']);
|
||||
$("#last").text(data['last']);
|
||||
flush_table();
|
||||
check_scanner_status(ifname);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
}); // END
|
||||
</script>
|
||||
|
||||
<section class="col-xs-12">
|
||||
<div id="update_stop" class="alert alert-info" role="alert" style="min-height: 65px;">
|
||||
<div class="pull-left updatestatus" style="margin-top: 8px;">{{ lang._('Scan is stopped')}}</div>
|
||||
</div>
|
||||
|
||||
<div id="update_start" class="alert alert-warning" role="alert" style="min-height: 65px; display:none;">
|
||||
<div class="pull-left updatestatus" style="margin-top: 8px;">{{ lang._('Scan is running')}}</div>
|
||||
</div>
|
||||
|
||||
<div class="content-box">
|
||||
{{ partial("layout_partials/base_form",['fields':generalForm,'id':'frm_GeneralSettings'])}}
|
||||
|
||||
<div class="col-md-12" style="padding-bottom: 13px; padding-top: 13px;">
|
||||
<button class='btn btn-default' id="stopScanner" style="margin-right: 8px;">{{ lang._('Stop') }} <i id=""></i></button>
|
||||
<button class='btn btn-default' id="statusScanner" style="margin-right: 8px;">{{ lang._('Refresh') }} <i id=""></i></button>
|
||||
<button class="btn btn-primary pull-center" id="startScanner" type="button"><i id="scan_progress" class=""></i><b>{{ lang._('Start') }}</b></button>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<section class="col-xs-12">
|
||||
<div id="responseMsg" class="content-box" style="padding: 27px;">
|
||||
<div class="table-responsive">
|
||||
<table>
|
||||
<thead>
|
||||
<tr>
|
||||
<th><b>{{ lang._('Interface name') }}</b></th>
|
||||
<th><b>{{ lang._('Started') }}</b></th>
|
||||
<th><b>{{ lang._('Last update') }}</b></th>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<td><p id="ifname"></p></td>
|
||||
<td><p id="started"></p></td>
|
||||
<td><p id="last"></p></td>
|
||||
</tbody>
|
||||
|
||||
</table>
|
||||
<hr>
|
||||
<table id="netTable">
|
||||
<thead>
|
||||
<tr>
|
||||
<td><b>{{ lang._('IP') }}</b></td>
|
||||
<td><b>{{ lang._('MAC') }}</b></td>
|
||||
<td><b>{{ lang._('Vendor') }}</b></td>
|
||||
</tr>
|
||||
</thead>
|
||||
<tbody>
|
||||
<tr><td></td><td></td><td></td></tr>
|
||||
</tbody>
|
||||
</table>
|
||||
</div>
|
||||
</div>
|
||||
<section>
|
||||
@@ -0,0 +1,153 @@
|
||||
#!/usr/bin/env python2.7
|
||||
|
||||
"""
|
||||
Copyright (c) 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
from subprocess import Popen, PIPE
|
||||
import datetime
|
||||
import os
|
||||
import time
|
||||
import json
|
||||
import sys
|
||||
import re
|
||||
|
||||
# imports from custom cls
|
||||
from ProcessIO import ProcessIO
|
||||
from FileIO import FileIO
|
||||
|
||||
class ArpScanner(ProcessIO):
|
||||
os_command_filter = """ps ax | \
|
||||
grep "ARPscanner\|arp-scan -I" | \
|
||||
grep {} | \
|
||||
grep -v "ps ax "| \
|
||||
grep -E '^[ 0-9]+'| \
|
||||
awk -F' ' '{{print $1}}'"""
|
||||
|
||||
def __init__(self, ifname, network):
|
||||
"""
|
||||
netif='eth0'
|
||||
network_list=['192.168.0.0/24', ...]
|
||||
"""
|
||||
self.ifname = ifname
|
||||
self.network = network
|
||||
self.result = {} # filtered output containing only what needed
|
||||
# regexp used to retrieve data from arp-scan system command stdout
|
||||
self.regexp = '([0-9\.]+)[\t]*([\dA-F]{2}(?:[-:][\dA-F]{2}){5})[\t]*([A-Za-z0-9\ \.\-\,\'\(\)]*)'
|
||||
# os_command_filter needs '{}'.format(ifname)
|
||||
self._DEBUG = False
|
||||
|
||||
# FileIO contains all the IO files
|
||||
tmp_fileio_path = '/tmp/ARPscanner'
|
||||
self.tmp = tmp_fileio_path
|
||||
|
||||
self.result['peers'] = []
|
||||
self.result['network'] = network
|
||||
self.result['interface'] = self.ifname
|
||||
self.result['started'] = datetime.datetime.now().isoformat()
|
||||
self.result['last_modify'] = datetime.datetime.now().isoformat()
|
||||
|
||||
def status(self):
|
||||
"""
|
||||
if arp-scan is running: parse .current file
|
||||
else: parse .last file
|
||||
returns json parsing of arp-scan output
|
||||
"""
|
||||
fout = os.path.sep.join((self.tmp, self.ifname))+'.out'
|
||||
if not os.path.exists(fout):
|
||||
return
|
||||
|
||||
self.result['last'] = time.ctime(os.path.getmtime(fout))
|
||||
self.result['started'] = time.ctime(os.path.getctime(fout))
|
||||
|
||||
with open(fout, 'r') as f:
|
||||
fcont = f.read()
|
||||
#~ print(fcont)
|
||||
regexp = re.findall(self.regexp , fcont, re.I)
|
||||
if self._DEBUG: print(regexp)
|
||||
for netfound in regexp:
|
||||
self.result['peers'].append(
|
||||
(netfound[0].replace('\t', ''),
|
||||
netfound[1], netfound[2]))
|
||||
#~ return self.result
|
||||
|
||||
def start(self):
|
||||
"""
|
||||
returns 1 if started
|
||||
returns 0 if already running
|
||||
"""
|
||||
running = self.check_run(self.ifname, self.os_command_filter)
|
||||
if running: return self.status()
|
||||
|
||||
fileio = FileIO(self.ifname, self.tmp)
|
||||
os_command = ["arp-scan", "-I", self.ifname, self.network,
|
||||
"--retry", "5"]
|
||||
# run a child and detach
|
||||
osc = Popen(os_command,
|
||||
stdout=fileio.out,
|
||||
stderr=fileio.err,
|
||||
bufsize=0,
|
||||
shell=False)
|
||||
|
||||
def get_json(self):
|
||||
return json.dumps(self.result)
|
||||
|
||||
if __name__ == '__main__':
|
||||
import argparse
|
||||
parser = argparse.ArgumentParser()
|
||||
parser.add_argument('-i', nargs='?', required=True,
|
||||
help="network interface")
|
||||
parser.add_argument('-net', nargs='?', help="""network to scan""")
|
||||
parser.add_argument('-check', action="store_true", required=False,
|
||||
help="check if arp-san is running on that interface")
|
||||
parser.add_argument('-start', action="store_true", required=False,
|
||||
help="starts arp-scan")
|
||||
parser.add_argument('-stop', action="store_true", required=False,
|
||||
help="Stops scanning on that interfaces")
|
||||
parser.add_argument('-status', action="store_true", required=False,
|
||||
help="Parse arp-scan stdout and return json")
|
||||
|
||||
args = parser.parse_args()
|
||||
|
||||
if not args.net:
|
||||
args.net = '--localnet'
|
||||
|
||||
if args.check:
|
||||
pids = ArpScanner.check_run(args.i, ArpScanner.os_command_filter)
|
||||
print(pids)
|
||||
sys.exit()
|
||||
|
||||
if args.stop:
|
||||
killed = ArpScanner.stop(args.i, ArpScanner.os_command_filter)
|
||||
print(killed)
|
||||
sys.exit()
|
||||
|
||||
ap = ArpScanner(args.i, args.net)
|
||||
|
||||
if args.start:
|
||||
ap.start()
|
||||
|
||||
ap.status()
|
||||
print(ap.get_json())
|
||||
|
||||
@@ -0,0 +1,56 @@
|
||||
#!/usr/bin/env python2.7
|
||||
|
||||
"""
|
||||
Copyright (c) 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
import os
|
||||
|
||||
class FileIO(object):
|
||||
"""
|
||||
This class manages files where data is read
|
||||
.out and .err file, where os_command stdout and stderr is stored
|
||||
"""
|
||||
def __init__(self, name, path):
|
||||
# file names
|
||||
self.nerr = '{}.err'.format(name)
|
||||
self.nout = '{}.out'.format(name)
|
||||
|
||||
# file paths
|
||||
self.epath = os.path.sep.join((path, self.nerr))
|
||||
self.opath = os.path.sep.join((path, self.nout))
|
||||
|
||||
if not os.path.exists(path):
|
||||
os.makedirs(path)
|
||||
|
||||
# file obj, 1 means the buffer size, small as possibile to flush
|
||||
# data soon as possible :)
|
||||
# this feature would be better with python3
|
||||
self.err = open(self.epath, 'w', buffering=0)
|
||||
self.out = open(self.opath, 'w', buffering=0)
|
||||
|
||||
|
||||
def close(self):
|
||||
self.err.close()
|
||||
self.out.close()
|
||||
@@ -0,0 +1,179 @@
|
||||
#!/usr/bin/env python2.7
|
||||
# -*- coding: utf-8 -*-
|
||||
|
||||
#~ Copyright © 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
#~ All rights reserved.
|
||||
#~
|
||||
#~ Redistribution and use in source and binary forms, with or without modification,
|
||||
#~ are permitted provided that the following conditions are met:
|
||||
#~
|
||||
#~ 1. Redistributions of source code must retain the above copyright notice,
|
||||
#~ this list of conditions and the following disclaimer.
|
||||
#~
|
||||
#~ 2. Redistributions in binary form must reproduce the above copyright notice,
|
||||
#~ this list of conditions and the following disclaimer in the documentation
|
||||
#~ and/or other materials provided with the distribution.
|
||||
#~
|
||||
#~ THIS SOFTWARE IS PROVIDED “AS IS” AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
#~ INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
#~ AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
#~ AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
#~ OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
#~ SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
#~ INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
#~ CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
#~ ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
#~ POSSIBILITY OF SUCH DAMAGE.
|
||||
|
||||
import socket
|
||||
import fcntl
|
||||
import struct
|
||||
import array
|
||||
import subprocess
|
||||
|
||||
# get_all_interfaces
|
||||
from collections import namedtuple
|
||||
import re
|
||||
import subprocess
|
||||
import json
|
||||
|
||||
# From linux/sockios.h
|
||||
#~ SIOCGIFCONF = 0x8912
|
||||
#~ SIOCGIFINDEX = 0x8933
|
||||
SIOCGIFFLAGS = 0x8913
|
||||
#~ SIOCSIFFLAGS = 0x8914
|
||||
SIOCGIFHWADDR = 0x8927
|
||||
SIOCSIFHWADDR = 0x8924
|
||||
SIOCGIFADDR = 0x8915
|
||||
#~ SIOCSIFADDR = 0x8916
|
||||
#~ SIOCGIFNETMASK = 0x891B
|
||||
#~ SIOCSIFNETMASK = 0x891C
|
||||
#~ SIOCETHTOOL = 0x8946
|
||||
|
||||
# From linux/if.h
|
||||
IFF_UP = 0x1
|
||||
|
||||
|
||||
# From linux/socket.h
|
||||
AF_UNIX = 1
|
||||
AF_INET = 2
|
||||
|
||||
class IPtools(object):
|
||||
|
||||
@staticmethod
|
||||
def get_ip_address(ifname):
|
||||
# python2 only
|
||||
ifname = str.encode(ifname)
|
||||
#
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
SIOCGIFADDR,
|
||||
struct.pack('256s', ifname[:15])
|
||||
)[20:24])
|
||||
|
||||
@staticmethod
|
||||
def get_netmask(ifname):
|
||||
# python2 only
|
||||
ifname = str.encode(ifname)
|
||||
#
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
return socket.inet_ntoa(fcntl.ioctl(
|
||||
s.fileno(),
|
||||
35099,
|
||||
struct.pack('256s', ifname))[20:24])
|
||||
|
||||
@staticmethod
|
||||
def is_up(ifname):
|
||||
''' Return True if the interface is up, False otherwise. '''
|
||||
# python2 only
|
||||
ifname = str.encode(ifname)
|
||||
#
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
# Get existing device flags
|
||||
ifreq = struct.pack('16sh', ifname, 0)
|
||||
flags = struct.unpack('16sh',
|
||||
fcntl.ioctl(s.fileno(),
|
||||
SIOCGIFFLAGS,
|
||||
ifreq))[1]
|
||||
|
||||
# Set new flags
|
||||
if flags & IFF_UP:
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
@staticmethod
|
||||
def get_mac(ifname):
|
||||
''' Obtain the device's mac address. '''
|
||||
# python2 only
|
||||
ifname = str.encode(ifname)
|
||||
#
|
||||
s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
|
||||
ifreq = struct.pack('16sH14s', ifname, AF_UNIX, b'\x00'*14)
|
||||
res = fcntl.ioctl(s.fileno(), SIOCGIFHWADDR, ifreq)
|
||||
address = struct.unpack('16sH14s', res)[2]
|
||||
mac = struct.unpack('6B8x', address)
|
||||
|
||||
return ":".join(['%02X' % i for i in mac])
|
||||
|
||||
@staticmethod
|
||||
def set_mac(ifname, newmac):
|
||||
''' Set the device's mac address. Device must be down for this to
|
||||
succeed. '''
|
||||
# python2 only
|
||||
ifname = str.encode(ifname)
|
||||
#
|
||||
macbytes = [int(i, 16) for i in newmac.split(':')]
|
||||
ifreq = struct.pack('16sH6B8x', ifname, AF_UNIX, *macbytes)
|
||||
fcntl.ioctl(s.fileno(), SIOCSIFHWADDR, ifreq)
|
||||
|
||||
|
||||
@staticmethod
|
||||
def get_interfaces(json_output=False):
|
||||
"""
|
||||
Get a list of network interfaces on Linux.
|
||||
"""
|
||||
name_pattern = "^(\w+)\s"
|
||||
mac_pattern = ".*?HWaddr[ ]([0-9A-Fa-f:]{17})"
|
||||
ip_pattern = ".*?\n\s+inet[ ]addr:((?:\d+\.){3}\d+)"
|
||||
pattern = re.compile("".join((name_pattern,
|
||||
mac_pattern,
|
||||
ip_pattern,
|
||||
)),
|
||||
flags=re.MULTILINE)
|
||||
|
||||
ifconfig = subprocess.check_output("ifconfig").decode()
|
||||
interfaces = pattern.findall(ifconfig)
|
||||
Interface = namedtuple("Interface", "name {mac} {ip}".format(
|
||||
mac="mac",
|
||||
ip="ip"))
|
||||
res = [Interface(*interface) for interface in interfaces]
|
||||
if json_output: return json.dumps(res)
|
||||
return res
|
||||
|
||||
@staticmethod
|
||||
def get_interfaces_bsd(json_output=False):
|
||||
"""
|
||||
Get a list of network interfaces on BSD.
|
||||
"""
|
||||
name_pattern = "^(\w+).+[\n\t\s]*.*[\n\t\s]*"
|
||||
mac_pattern = ".*?ether[ ]([0-9A-Fa-f:]{17})[\n\t\s]*"
|
||||
ip_pattern = ".*?\n\s+inet[ ]((?:\d+\.){3}\d+)"
|
||||
pattern = re.compile("".join((name_pattern,
|
||||
mac_pattern,
|
||||
ip_pattern,
|
||||
)),
|
||||
flags=re.MULTILINE)
|
||||
|
||||
ifconfig = subprocess.check_output(["ifconfig", "-u"]).decode()
|
||||
interfaces = pattern.findall(ifconfig)
|
||||
Interface = namedtuple("Interface", "name {mac} {ip}".format(
|
||||
mac="mac",
|
||||
ip="ip"))
|
||||
res = [Interface(*interface) for interface in interfaces]
|
||||
if json_output: return json.dumps(res)
|
||||
return res
|
||||
|
||||
if __name__ == '__main__':
|
||||
print(IPtools.get_interfaces_bsd(json_output=True))
|
||||
@@ -0,0 +1,72 @@
|
||||
#!/usr/bin/env python2.7
|
||||
|
||||
"""
|
||||
Copyright (c) 2017 Giuseppe De Marco <giuseppe.demarco@unical.it>
|
||||
All rights reserved.
|
||||
|
||||
Redistribution and use in source and binary forms, with or without
|
||||
modification, are permitted provided that the following conditions are met:
|
||||
|
||||
1. Redistributions of source code must retain the above copyright notice,
|
||||
this list of conditions and the following disclaimer.
|
||||
|
||||
2. Redistributions in binary form must reproduce the above copyright
|
||||
notice, this list of conditions and the following disclaimer in the
|
||||
documentation and/or other materials provided with the distribution.
|
||||
|
||||
THIS SOFTWARE IS PROVIDED ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES,
|
||||
INCLUDING, BUT NOT LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY
|
||||
AND FITNESS FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
|
||||
AUTHOR BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY,
|
||||
OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF
|
||||
SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS
|
||||
INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN
|
||||
CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE)
|
||||
ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
|
||||
POSSIBILITY OF SUCH DAMAGE.
|
||||
"""
|
||||
from subprocess import Popen, PIPE
|
||||
from os import kill, getpid, linesep
|
||||
|
||||
_DEBUG = False
|
||||
|
||||
class ProcessIO(object):
|
||||
@staticmethod
|
||||
def check_run(ifname, os_command_filter):
|
||||
"""
|
||||
returns PID if running on that ifname
|
||||
else return 0
|
||||
"""
|
||||
mypid = getpid()
|
||||
os_command = os_command_filter.format(ifname)
|
||||
osc = Popen(os_command,
|
||||
stdin=PIPE,
|
||||
stdout=PIPE,
|
||||
stderr=PIPE,
|
||||
shell=True)
|
||||
output, err = osc.communicate()
|
||||
if _DEBUG: print(output)
|
||||
if output:
|
||||
pids = []
|
||||
for pid in output.split(linesep):
|
||||
if pid and int(pid) != mypid:
|
||||
pids.append(int(pid))
|
||||
return pids[:]
|
||||
return 0
|
||||
|
||||
@classmethod
|
||||
def stop(cls, ifname, os_command_filter):
|
||||
""" stop scanning on that interface """
|
||||
mypid = getpid()
|
||||
chkrun = cls.check_run(ifname, os_command_filter)
|
||||
if not chkrun: return []
|
||||
pids = [int(i) for i in chkrun]
|
||||
killed = []
|
||||
for pid in pids:
|
||||
if pid == mypid: continue
|
||||
try:
|
||||
kill(pid, 9)
|
||||
killed.append(pid)
|
||||
except Exception as e:
|
||||
pass
|
||||
return killed
|
||||
@@ -0,0 +1,30 @@
|
||||
[start]
|
||||
command:python2.7 -u /usr/local/opnsense/scripts/OPNsense/ARPscanner/ARPscanner.py
|
||||
parameters:-i %s -net %s -start
|
||||
type:script_output
|
||||
message:start arp-scan
|
||||
|
||||
[stop]
|
||||
#~ command:ps ax | grep "ARPscanner\|arp-scan" | grep -E '[ 0-9]+' | awk -F' ' '{print $1}' | xargs | xargs kill -TERM
|
||||
command:python2.7 /usr/local/opnsense/scripts/OPNsense/ARPscanner/ARPscanner.py
|
||||
parameters:-i %s -stop
|
||||
type:script
|
||||
message:stop arp-scan
|
||||
|
||||
[status]
|
||||
command:python2.7 -u /usr/local/opnsense/scripts/OPNsense/ARPscanner/ARPscanner.py
|
||||
parameters:-i %s
|
||||
type:script_output
|
||||
message:status
|
||||
|
||||
[interfaces]
|
||||
command:python2.7 /usr/local/opnsense/scripts/OPNsense/ARPscanner/IPtools.py
|
||||
parameters:
|
||||
type:script_output
|
||||
message:get network interfaces
|
||||
|
||||
[check]
|
||||
command:python2.7 /usr/local/opnsense/scripts/OPNsense/ARPscanner/ARPscanner.py
|
||||
parameters:-i %s -check
|
||||
type:script_output
|
||||
message:check if arp scan is running on %s interface
|
||||
@@ -0,0 +1 @@
|
||||
ARPscanner.conf:/usr/local/etc/ARPscanner/ARPscanner.conf
|
||||
@@ -0,0 +1,3 @@
|
||||
[general]
|
||||
Interface={{ OPNsense.arpscanner.general.Interface|default("") }}
|
||||
Networks={{ OPNsense.arpscanner.general.Networks|default('192.168.1.0/24,172.16.45.0/25') }}
|
||||
Reference in New Issue
Block a user