# r-lanlib
A Rust library crate for performing network scanning operations on any local
area network (LAN). This is the Rust version of the
[go-lanscan package](https://github.com/robgonnella/go-lanscan).
## Features
- **ARP Scanning**: Discover devices on your network using Address Resolution Protocol
- **SYN Scanning**: Detect open ports on discovered devices using TCP SYN packets
- **Full Scanning**: Combined ARP and SYN scanning in a single operation
- **Vendor Detection**: Identify device manufacturers using MAC address lookup
- **Hostname Resolution**: Resolve hostnames for discovered devices
- **Async Communication**: Channel-based communication for real-time scan results
- **Flexible Targeting**: Support for CIDR blocks, IP ranges, and port ranges
## Requirements
- **Root privileges required**: This library performs raw packet operations that
require elevated permissions
- **Rust 1.89.0+** with 2024 edition support
## Installation
```bash
cargo add r-lanlib
```
## Quick Start
### Basic ARP Scanning
```rust
use std::{sync::mpsc, time::Duration};
use r_lanlib::{
network, packet,
scanners::{
arp_scanner::{ARPScanner, ARPScannerArgs},
Device, ScanMessage, Scanner,
},
targets::ips::IPTargets,
};
// Get default network interface
let interface = network::get_default_interface()
.expect("Cannot find network interface");
// Create packet wire (reader/sender)
let wire = packet::wire::default(&interface)
.expect("Failed to create packet wire");
// Define IP targets (scan entire subnet)
let ip_targets = IPTargets::new(vec![interface.cidr.clone()]);
// Create communication channel
let (tx, rx) = mpsc::channel::<ScanMessage>();
// Configure scanner
let scanner = ARPScanner::new(ARPScannerArgs {
interface: &interface,
packet_reader: wire.0,
packet_sender: wire.1,
targets: ip_targets,
source_port: 54321,
include_vendor: true,
include_host_names: true,
idle_timeout: Duration::from_millis(10000),
notifier: tx,
});
// Start scanning (runs in background thread)
let handle = scanner.scan();
// Process results in real-time
let mut devices = Vec::new();
loop {
match rx.recv().expect("Failed to receive message") {
ScanMessage::Done => break,
ScanMessage::ARPScanDevice(device) => {
println!("Found device: {} ({})", device.ip, device.hostname);
devices.push(device);
}
ScanMessage::Info(scanning) => {
println!("Scanning: {}", scanning.ip);
}
}
}
handle.join().expect("Scanner thread failed");
println!("Discovered {} devices", devices.len());
```
### SYN Port Scanning
```rust
use r_lanlib::{
scanners::{
syn_scanner::{SYNScanner, SYNScannerArgs},
Device, PortSet, Scanner,
},
targets::ports::PortTargets,
};
// Define target devices (from previous ARP scan or manual)
let devices = vec![
Device {
hostname: "router".to_string(),
ip: Ipv4Addr::new(192, 168, 1, 1),
mac: MacAddr::new(0xaa, 0xbb, 0xcc, 0xdd, 0xee, 0xff),
vendor: "".to_string(),
is_current_host: false,
open_ports: PortSet::new(),
}
];
// Define port targets
let port_targets = PortTargets::new(vec![
"22".to_string(), // SSH
"80".to_string(), // HTTP
"443".to_string(), // HTTPS
"8000-9000".to_string(), // Port range
]);
let scanner = SYNScanner::new(SYNScannerArgs {
interface: &interface,
packet_reader: wire.0,
packet_sender: wire.1,
targets: devices,
ports: port_targets,
source_port: 54321,
idle_timeout: Duration::from_millis(10000),
notifier: tx,
});
// Process SYN scan results
let mut results = Vec::new();
let handle = scanner.scan();
loop {
match rx.recv().expect("Failed to receive message") {
ScanMessage::Done => break,
ScanMessage::SYNScanDevice(device) => {
for port in device.open_ports.to_sorted_vec() {
println!("Open port {} on {}", port.id, device.ip);
}
results.push(device);
}
_ => {}
}
}
```
### Full Scanning (ARP + SYN)
```rust
use r_lanlib::scanners::{
full_scanner::{FullScanner, FullScannerArgs},
Scanner,
};
let scanner = FullScanner::new(FullScannerArgs {
interface: &interface,
packet_reader: wire.0,
packet_sender: wire.1,
targets: ip_targets,
ports: port_targets,
include_vendor: true,
include_host_names: true,
idle_timeout: Duration::from_millis(10000),
notifier: tx,
source_port: 54321,
});
// This will perform ARP discovery first, then SYN scan on found devices
let handle = scanner.scan();
```
## API Reference
### Core Modules
#### `network`
Provides helpers for selecting network interfaces:
- `get_default_interface()` - Get the default network interface
- `get_interface(name)` - Get a specific interface by name
- `get_available_port()` - Find an available port for scanning
#### `packet`
Low-level packet creation and transmission:
- `wire::default(interface)` - Create default packet reader/sender pair
- Various packet builders for ARP, SYN, RST packets
#### `scanners`
Main scanning implementations:
- `ARPScanner` - Discover devices using ARP
- `SYNScanner` - Scan ports on known devices
- `FullScanner` - Combined ARP + SYN scanning
#### `targets`
Target specification utilities:
- `ips::IPTargets` - Define IP ranges and CIDR blocks
- `ports::PortTargets` - Define port ranges and individual ports
### Data Structures
#### `Device`
Represents a discovered network device:
```rust
pub struct Device {
pub hostname: String,
pub ip: Ipv4Addr,
pub mac: MacAddr,
pub vendor: String,
pub is_current_host: bool,
pub open_ports: PortSet,
}
```
#### `Port`
Represents a network port:
```rust
pub struct Port {
pub id: u16,
pub service: String,
}
```
#### `PortSet`
Wrapper around `HashSet<Port>` with convenience methods:
```rust
pub struct PortSet(pub HashSet<Port>);
impl PortSet {
pub fn new() -> Self;
pub fn to_sorted_vec(&self) -> Vec<Port>;
}
```
#### `ScanMessage`
Messages sent over the notification channel:
```rust
pub enum ScanMessage {
Done, // Scanning complete
Info(Scanning), // Status update
ARPScanDevice(Device), // ARP discovery result
SYNScanDevice(Device), // SYN scan result (Device with open_ports populated)
}
```
### Target Specification
#### IP Targets
```rust
// CIDR blocks
IPTargets::new(vec!["192.168.1.0/24".to_string()]);
// IP ranges
IPTargets::new(vec!["192.168.1.1-192.168.1.100".to_string()]);
// Individual IPs
IPTargets::new(vec!["192.168.1.1".to_string(), "10.0.0.1".to_string()]);
```
#### Port Targets
```rust
// Port ranges
PortTargets::new(vec!["1-1000".to_string()]);
// Individual ports
PortTargets::new(vec!["22".to_string(), "80".to_string(), "443".to_string()]);
// Mixed specification
PortTargets::new(vec![
"22".to_string(),
"80".to_string(),
"8000-9000".to_string()
]);
```
## Examples
The library includes several complete examples in the `examples/` directory:
- **`arp-scanner.rs`** - Basic ARP device discovery
- **`syn-scanner.rs`** - Port scanning on known devices
- **`full-scanner.rs`** - Complete network reconnaissance
Run examples from the workspace root with:
```bash
sudo -E cargo run --example arp-scanner -p r-lanlib
sudo -E cargo run --example syn-scanner -p r-lanlib
sudo -E cargo run --example full-scanner -p r-lanlib
```
## Configuration Options
### Scanner Timeouts
- `idle_timeout` - How long to wait for responses before concluding scan
- Default: 10 seconds (10,000ms)
- Recommended: 5-30 seconds depending on network size and latency
### Scanner Features
- `include_vendor` - Perform MAC address vendor lookup using IEEE OUI database
- `include_host_names` - Resolve hostnames via reverse DNS lookup
- `source_port` - Source port for scan packets (auto-selected if not specified)
### Performance Tuning
- **Concurrent scanning**: Multiple threads handle packet I/O for optimal throughput
- **Memory efficiency**: Zero-copy packet processing where possible
- **Network-aware**: Automatic rate limiting to prevent network congestion
- **Timeout optimization**: Adaptive timeouts based on network response times
## Security Considerations
- **Requires root privileges** for raw socket access on Unix-like systems
- **Network scanning may be restricted** by network policies and firewalls
- **Built-in rate limiting** prevents network congestion and reduces detection risk
- **Minimal network footprint**: Optimized packet sizes and timing
- **Memory safety**: Rust's ownership system prevents buffer overflows and memory corruption
- **Use responsibly** and only on networks you own or have permission to scan
- **Logging**: All scan activities can be logged for audit purposes
### Ethical Usage Guidelines
- Always obtain proper authorization before scanning
- Respect network resources and avoid aggressive scanning
- Be aware that scanning activities may be logged by network security systems
- Consider the impact on network performance during large-scale scans
## Error Handling
The library uses `RLanLibError` for comprehensive error reporting:
## License
This project is dual-licensed under either of
- Apache License, Version 2.0 ([LICENSE-APACHE](../LICENSE-APACHE) or http://www.apache.org/licenses/LICENSE-2.0)
- MIT License ([LICENSE-MIT](../LICENSE-MIT) or http://opensource.org/licenses/MIT)
at your option.
## Related Projects
- [go-lanscan](https://github.com/robgonnella/go-lanscan) - Original Go implementation
- [r-lancli](../cli/README.md) - Command-line interface using this library
- [r-lanterm](../term/README.md) - Terminal UI application using this library