feat: bootstrap awg2 harness rust workspace and docs
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
use std::net::Ipv4Addr;
|
||||
|
||||
use crate::{config, docker::run_capture};
|
||||
|
||||
#[derive(Debug, Clone)]
|
||||
pub struct Peer {
|
||||
pub ipv4: Ipv4Addr,
|
||||
}
|
||||
|
||||
pub fn discover_peers(container: &str, peer_cidr: &str) -> anyhow::Result<Vec<Peer>> {
|
||||
let primary = run_capture(&[
|
||||
"docker",
|
||||
"exec",
|
||||
container,
|
||||
"sh",
|
||||
"-c",
|
||||
"wg show all allowed-ips 2>/dev/null",
|
||||
])
|
||||
.unwrap_or_default();
|
||||
|
||||
let mut peers = parse_allowed_ips(&primary, peer_cidr)?;
|
||||
if peers.is_empty() {
|
||||
let fallback = run_capture(&["docker", "exec", container, "sh", "-c", "wg show 2>/dev/null"])
|
||||
.unwrap_or_default();
|
||||
peers = parse_fallback_wg_show(&fallback, peer_cidr)?;
|
||||
}
|
||||
|
||||
peers.sort_by_key(|p| p.ipv4.to_string());
|
||||
peers.dedup_by_key(|p| p.ipv4);
|
||||
Ok(peers)
|
||||
}
|
||||
|
||||
fn parse_allowed_ips(raw: &str, peer_cidr: &str) -> anyhow::Result<Vec<Peer>> {
|
||||
let mut out = Vec::new();
|
||||
for line in raw.lines() {
|
||||
let cols: Vec<&str> = line.split_whitespace().collect();
|
||||
if cols.len() < 3 {
|
||||
continue;
|
||||
}
|
||||
for tok in cols[2].split(',') {
|
||||
let tok = tok.trim();
|
||||
if let Some((ip, pfx)) = tok.split_once('/') {
|
||||
if pfx != "32" {
|
||||
continue;
|
||||
}
|
||||
if let Ok(v4) = ip.parse::<Ipv4Addr>() {
|
||||
if config::ip_in_cidr(v4, peer_cidr)? {
|
||||
out.push(Peer { ipv4: v4 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
fn parse_fallback_wg_show(raw: &str, peer_cidr: &str) -> anyhow::Result<Vec<Peer>> {
|
||||
let mut out = Vec::new();
|
||||
for line in raw.lines() {
|
||||
let t = line.trim();
|
||||
if !t.starts_with("allowed ips:") {
|
||||
continue;
|
||||
}
|
||||
let rest = t.trim_start_matches("allowed ips:").trim();
|
||||
for tok in rest.split(',') {
|
||||
let tok = tok.trim();
|
||||
if let Some((ip, pfx)) = tok.split_once('/') {
|
||||
if pfx != "32" {
|
||||
continue;
|
||||
}
|
||||
if let Ok(v4) = ip.parse::<Ipv4Addr>() {
|
||||
if config::ip_in_cidr(v4, peer_cidr)? {
|
||||
out.push(Peer { ipv4: v4 });
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(out)
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use super::*;
|
||||
|
||||
#[test]
|
||||
fn parse_primary() {
|
||||
let raw = "wg0 key1 10.8.1.10/32\nwg0 key2 10.8.1.2/32";
|
||||
let peers = parse_allowed_ips(raw, "10.8.1.0/24").expect("parse");
|
||||
assert_eq!(peers.len(), 2);
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user