Source code for tech_tools.detective_functions

from tech_tools.utilities import (
    generate_range_from_subnet,
    local_ip,
    tcp_ip_port_scanner,
)

from tech_tools.cli import (
    ping_range_ip,
    parse_local_arp,
    parse_trace_route_local,
)
from tech_tools.resources import mac_lookup


[docs] def local_devices(network=None, ports=None): """Return a DataFrame containing ip, mac, valid tcp ports, and manufacture information obtained from local network :param network: (optional) Interface IP Address, local_ip() by default :type network: str, IPv4Address :param ports: (optional) TCP ports to scan, should be provided as integers, [80, 443] by default :type ports: list :return: host ip addresses, mac addresses, valid tcp ports, manufacturing company :rtype: Pandas.DataFrame Note: If no interface address is provided, the function will attempt to locate devices based on the address returned from the local_ip() function. If multiple interfaces are present, it is recommended to manually select the preferred one. This function requires a valid host ping, as well as a valid entry in the local arp table. Some hosts might not meet these criteria. """ if network is None: network = local_ip() local_network = generate_range_from_subnet(network) print("Attempting to gather information for local devices, please wait...") successful_pings = ping_range_ip(local_network) # Look on supplied tcp ports, using http and https by default if ports is None: ports = [80, 443] successful_tcp_requests = tcp_ip_port_scanner( successful_pings, ports=ports, df=False ) local_arp_table = parse_local_arp() # Subset arp table df with ip addresses that received valid pings local_arp_table = ( local_arp_table[local_arp_table["ip"].isin(successful_pings)] .sort_values(by="ip") .reset_index(drop=True) ) # Map ports to dataframe using tcp dictionary local_arp_table["ports"] = local_arp_table["ip"].map(successful_tcp_requests) local_arp_table["company"] = local_arp_table["mac"].apply(mac_lookup) # All manufacturing company values will be listed as not_found in case a match is not obtained #local_arp_table["company"] = "not_found" """for device in local_arp_table["mac"].to_list(): # Locate the mac prefix within the manufacturer table found = [mac for mac in mac_df["mac"].to_list() if device.startswith(mac)] if len(found) == 1: # Use that prefix to identify the manufacturer company = mac_df[mac_df["mac"].isin(found)]["company"].iloc[0] # Write that company name into the local_arp_table in the row where the original mac address was located local_arp_table["company"] = np.where( (local_arp_table["mac"] == device), company, local_arp_table["company"] )""" return local_arp_table
[docs] def semi_local_devices(destination="8.8.8.8", ports=None): """Return a DataFrame of ip and TCP port information for Private networks along a designated trace route path. :param destination: (optional) Remote host, 8.8.8.8 by default :type destination: str, IPv4Address :param ports: (optional) TCP ports to scan, should be provided as integers, [80, 443] by default :type ports: list :return: host ip addresses, valid tcp ports :rtype: Pandas.DataFrame Note: Assumes /24 subnet, though this might not be correct in many cases. Recommended to scan networks individually if subnets of different sizes exist along the trace path. A list of local networks along the trace path can be achieved with parse_trace_route_local(). """ print("Attempting to gather information for semi-local devices, please wait...") # Identify hops with private IP address private_ips = parse_trace_route_local(destination) # Generate a subnet for each hop, list comprehension to expand for all ip address to scan hosts_to_scan = [ ip for host in private_ips for ip in generate_range_from_subnet(host) ] # Look on supplied tcp ports, using http and https by default if ports is None: ports = [80, 443] successful_tcp_requests = tcp_ip_port_scanner(hosts_to_scan, ports=ports) return successful_tcp_requests