Last Updated: May 15, 2025
Astra is an open-source network scanning tool written in Python, designed for security researchers and network administrators. It enables users to scan IP ranges, resolve domains to IPs, and identify open ports with high flexibility. Unlike many existing tools, Astra operates locally without third-party API dependencies (e.g., no reliance on services like ipinfo.io for core functionality), prioritizing user control, privacy, and customization.
Astra was developed to address the need for a lightweight, customizable network scanner that:
This documentation is intended for developers and maintainers who wish to understand, maintain, or extend Astra’s functionality.
Astra’s core features are designed to be modular and extensible. Below is an overview of each feature and its implementation:
Domain Resolution:
apple.com
) to multiple IPs using the dnspython
library.astra/api.py
via the get_cidr_ranges_local
function./32
CIDR range for consistent handling with user-provided CIDR ranges.CIDR Scanning:
192.168.1.0/24
) or comma-separated CIDR lists.ipaddress
module.astra/api.py
via the get_cidr_ranges
function.Flexible Port Scanning:
--first-1000
), 300 (--first-300
), or custom ports (--ports 80,443
).socket
and concurrent.futures.ThreadPoolExecutor
for efficiency.astra/network.py
via the scan_network
function.IP Limits:
--max-ips
) caps the total number of IPs scanned across all CIDR ranges.--max-ips-per-cidr
, --first-1-per-cidr
, --first-2-per-cidr
, --first-10-per-cidr
) controls the number of IPs scanned per CIDR range.astra/network.py
via the extract_ips
function.Output Options:
--output
, --output-format
).astra/report.py
via the save_results
function.Verbose Logging:
--verbose
, including CIDR ranges, IP counts, and scan progress.logging
module, configured in astra/cli.py
.Configurability:
~/.astra/config.json
) for default settings (e.g., timeout, default ports).astra/config.py
via the load_config
function.Astra follows a modular design with distinct components for each major functionality. The architecture is structured to ensure separation of concerns, making it easy to modify or extend specific features.
Command-Line Parsing (astra/cli.py
):
argparse
.CIDR Resolution (astra/api.py
):
IP Extraction (astra/network.py
):
Network Scanning (astra/network.py
):
Result Handling (astra/report.py
):
Configuration (astra/config.py
):
astra/
__init__.py
: Package initializer.cli.py
: Command-line interface and main entry point.api.py
: Handles domain resolution and CIDR range processing.network.py
: Manages IP extraction and network scanning.report.py
: Formats and saves scan results.config.py
: Loads configuration settings.astra.py
: Entry script that calls cli.main()
.requirements.txt
: Lists dependencies (e.g., dnspython
).README.md
: User-facing documentation.DEVELOPER.md
: This file.cli.py: main()
get_cidr_ranges
, extract_ips
, scan_network
, and save_results
.api.py: get_cidr_ranges()
--cidr
is provided, validates and returns the CIDR(s).get_cidr_ranges_local
.api.py: get_cidr_ranges_local()
dns.resolver
to fetch A records for a domain./32
CIDR ranges.network.py: extract_ips()
ipaddress.ip_network
.max_ips_per_cidr
) and global (max_ips
) limits.network.py: scan_network()
max_workers
) based on workload.report.py: save_results()
dnspython
: For domain resolution (dns.resolver
).argparse
: Command-line argument parsing.logging
: Verbose logging.socket
: TCP scanning.ipaddress
: CIDR range handling.concurrent.futures
: Concurrent scanning.json
and csv
: Output formatting.Dependencies are listed in requirements.txt
and can be installed with:
pip install -r requirements.txt
Astra’s modular design makes it straightforward to add new features or modify existing ones. Below are common extension scenarios:
astra/cli.py
and locate the parse_args
function.parser.add_argument
. For example, to add a --scan-type
argument:
parser.add_argument("--scan-type", choices=["tcp", "udp"], default="tcp", help="Type of scan to perform (tcp, udp)")
main
. For example:
scan_type = args.scan_type
logging.info(f"Using scan type: {scan_type}")
astra/network.py
.scan_port
to support UDP by adding a scan_type
parameter:
def scan_port(ip: str, port: int, timeout: float, scan_type: str = "tcp") -> bool:
try:
if scan_type == "tcp":
sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
elif scan_type == "udp":
sock = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
sock.settimeout(timeout)
result = sock.connect_ex((ip, port))
sock.close()
return result == 0
except socket.error:
return False
scan_network
to pass the scan_type
parameter to scan_port
.astra/report.py
.save_results
to support the new format (e.g., XML):
if output_format == "xml":
import xml.etree.ElementTree as ET
root = ET.Element("scan_results")
# Add scan data to XML structure
tree = ET.ElementTree(root)
tree.write(output_file)
cli.py
to include the new format in the --output-format
choices:
parser.add_argument("--output-format", choices=["json", "csv", "xml"], help="Output format (json, csv, xml)")
max_workers
in network.py
’s scan_network
function. Be cautious of system resource limits.cli.py
to reduce I/O overhead in non-verbose mode.extract_ips
to process IPs in batches if memory usage becomes an issue with large CIDR ranges.To ensure changes don’t break existing functionality:
Unit Tests:
unittest
or pytest
.Example test for extract_ips
:
import unittest
from astra.network import extract_ips
class TestNetwork(unittest.TestCase):
def test_extract_ips(self):
cidr_ranges = ["192.168.1.0/30"]
ips = extract_ips(cidr_ranges, max_ips=2)
self.assertEqual(len(ips), 2)
self.assertEqual(ips, ["192.168.1.0", "192.168.1.1"])
if __name__ == "__main__":
unittest.main()
Manual Testing:
python3 astra.py apple.com --first-1000 --verbose
python3 astra.py --cidr 192.168.1.0/30 --first-300 --first-2-per-cidr --verbose
python3 astra.py apple.com --output results.json --verbose
Fork and Clone:
git clone https://github.com/bhaweshchaudhary/Astra.git
Create a Feature Branch:
git checkout -b feature/your-feature-name
Code Style:
Commit Messages:
Pull Request:
git push origin feature/your-feature-name
Testing:
max_workers
.api.py
and network.py
to use socket.AF_INET6
.For questions or collaboration, reach out via GitHub issues at https://github.com/bhaweshchaudhary/astra.
Note: Astra is for ethical use only. Developers and maintainers must ensure that any use of the tool complies with legal and ethical standards. Unauthorized network scanning is illegal.