Skip to content

Commit

Permalink
add Matlab findssh
Browse files Browse the repository at this point in the history
  • Loading branch information
scivision committed Sep 21, 2018
1 parent 3f7fd82 commit ae58142
Show file tree
Hide file tree
Showing 5 changed files with 55 additions and 19 deletions.
2 changes: 2 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
Expand Up @@ -14,6 +14,8 @@ Scans entire IPv4 subnet in less than 1 second using 100 threads via Python stan

Although speed advantages weren't seen in our testing, `findssh` works with PyPy as well.

Matlab `findssh.m` works similarly.

## Install

Just run `findssh.py` directly.
Expand Down
28 changes: 28 additions & 0 deletions findssh.m
Original file line number Diff line number Diff line change
@@ -0,0 +1,28 @@
function findssh(port, service, timeout, baseip)
%% FINDSSH find SSH or other servers on an IPv4 subnet
%
% must first do one-time install in Python 3.6 from Terminal:
% pip install -e .
%
% example (find all SSH servers on IPv4 subnet on Port 22):
% findssh()

assert(~verLessThan('matlab', '8.4'), 'Matlab >= R2014b required')

if nargin < 1, port=22; end
if nargin < 2, service = ''; end
if nargin < 3, timeout = 0.1; end
if nargin < 4, baseip = ''; end


validateattributes(port, {'numeric'}, {'integer', 'nonnegative'})
validateattributes(service, {'string', 'char'}, {'scalartext'})
validateattributes(timeout, {'numeric'}, {'real', 'nonnegative'})
validateattributes(baseip, {'string', 'char'}, {'scalartext'})

% Matlab R2018b didn't like ThreadPoolExectutor
servers = py.findssh.run(uint16(port), service, timeout, baseip, true);

hosts = cellfun(@char, cell(servers), 'uniformoutput', false);
disp(hosts)
end
38 changes: 21 additions & 17 deletions findssh.py
Original file line number Diff line number Diff line change
Expand Up @@ -18,15 +18,17 @@
import socket
import ipaddress as ip
import concurrent.futures
from itertools import repeat
import itertools

TIMEOUT = 0.3
PORT = 22


def run(port: int=PORT, service: str='', timeout: float=TIMEOUT,
baseip: Union[str, ip.IPv4Address]=None, debug: bool=False):
tic = time()
def run(port: int = PORT,
service: str = '',
timeout: float = TIMEOUT,
baseip: Union[str, ip.IPv4Address] = None,
debug: bool = False) -> List[ip.IPv4Address]:

if not baseip:
ownip = getLANip()
Expand All @@ -38,11 +40,7 @@ def run(port: int=PORT, service: str='', timeout: float=TIMEOUT,

net = netfromaddress(ownip)

servers = scanhosts(net, port, service, timeout, debug)
print('\n*** RESULTS ***')
print('found', len(servers), service, 'servers on port', port,
'in {:.1f} seconds:'.format(time()-tic))
print('\n'.join(map(str, servers)))
return scanhosts(net, port, service, timeout, debug)


# %% (1) get LAN IP of laptop
Expand All @@ -65,8 +63,8 @@ def getLANip() -> Union[ip.IPv4Address, ip.IPv6Address]:

# %% (2) scan subnet for SSH servers
def isportopen(host: ip.IPv4Address, port: int, service: str,
timeout: float=TIMEOUT,
verbose: bool=True) -> bool:
timeout: float = TIMEOUT,
verbose: bool = True) -> bool:
h = host.exploded

with socket.socket(socket.AF_INET, socket.SOCK_STREAM) as s:
Expand Down Expand Up @@ -136,16 +134,15 @@ def scanhosts(net: ip.IPv4Network,

print('searching', net)

hosts = net.hosts()
hosts = list(net.hosts())

if debug:
servers = [h for h in hosts if isportopen(h, port, service, timeout)]
else:
with concurrent.futures.ThreadPoolExecutor(max_workers=100) as exc:
servers = [h for h, s in zip(hosts,
exc.map(isportopen, hosts,
repeat(port),
repeat(service))) if s]
portsopen = exc.map(isportopen, hosts,
itertools.repeat(port), itertools.repeat(service))
servers = list(itertools.compress(hosts, portsopen))

return servers

Expand All @@ -166,7 +163,14 @@ def main():
action='store_true')
P = p.parse_args()

run(P.port, P.service, P.timeout, P.baseip, P.debug)
servers = run(P.port, P.service, P.timeout, P.baseip, P.debug)

tic = time()

print('\n*** RESULTS ***')
print('found', len(servers), P.service, 'servers on port', P.port,
'in {:.1f} seconds:'.format(time()-tic))
print('\n'.join(map(str, servers)))


if __name__ == '__main__':
Expand Down
2 changes: 1 addition & 1 deletion setup.cfg
Original file line number Diff line number Diff line change
@@ -1,6 +1,6 @@
[metadata]
name = findssh
version = 1.0.9
version = 1.1.0
author = Michael Hirsch, Ph.D.
url = https://github.com/scivision/findssh
description = find open servers on your IPv4 subnet, e.g. SSH
Expand Down
4 changes: 3 additions & 1 deletion tests/test_all.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@
import pytest
import subprocess
import findssh
import ipaddress as ip


def test_script():
Expand All @@ -12,7 +13,8 @@ def test_script():


def test_mod():
findssh.run()
servers = findssh.run()
assert isinstance(servers[0], ip.IPv4Address)


if __name__ == '__main__':
Expand Down

0 comments on commit ae58142

Please sign in to comment.