release: NX9-WG v1.0.0
This commit is contained in:
1 parent
c8a9b7cde6
commit
4dfe42fe68
42 files changed
+4689
-336
No files matched your search
+65
-12
@@ -23,9 +23,11 @@ use nx9_wg_core::validation::{
|
||||
validate_port_spec,
|
||||
};
|
||||
use nx9_wg_db::Store;
|
||||
#[allow(unused_imports)]
|
||||
use nx9_wg_network::{
|
||||
IpForwardingStatus, NativeLinuxNetworkEngine, NetworkEngine, SimulatedNetworkEngine,
|
||||
};
|
||||
#[allow(unused_imports)]
|
||||
use nx9_wireguard::{
|
||||
ClientConfigBuilder, NativeLinuxWireGuardEngine, SimulatedWireGuardEngine, WireGuardEngine,
|
||||
generate_qr_ascii, generate_qr_png_bytes, generate_qr_svg,
|
||||
@@ -509,6 +511,8 @@ enum PeerSubcommands {
|
||||
mtu: Option<u16>,
|
||||
#[arg(long, help = "Explicit client profile ID")]
|
||||
profile: Option<String>,
|
||||
#[arg(long, help = "WireGuard server endpoint host or IP")]
|
||||
endpoint: Option<String>,
|
||||
#[arg(short, long, help = "Write configuration to file")]
|
||||
output: Option<PathBuf>,
|
||||
},
|
||||
@@ -533,6 +537,8 @@ enum PeerSubcommands {
|
||||
mtu: Option<u16>,
|
||||
#[arg(long, help = "Explicit client profile ID")]
|
||||
profile: Option<String>,
|
||||
#[arg(long, help = "WireGuard server endpoint host or IP")]
|
||||
endpoint: Option<String>,
|
||||
#[arg(
|
||||
long = "qr-format",
|
||||
default_value = "terminal",
|
||||
@@ -932,6 +938,28 @@ enum LivePeerSubcommands {
|
||||
Show { id: String },
|
||||
}
|
||||
|
||||
fn create_wireguard_engine() -> Arc<dyn WireGuardEngine> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
Arc::new(NativeLinuxWireGuardEngine::new())
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
Arc::new(SimulatedWireGuardEngine::new())
|
||||
}
|
||||
}
|
||||
|
||||
fn create_network_engine() -> Arc<dyn NetworkEngine> {
|
||||
#[cfg(target_os = "linux")]
|
||||
{
|
||||
Arc::new(NativeLinuxNetworkEngine::new())
|
||||
}
|
||||
#[cfg(not(target_os = "linux"))]
|
||||
{
|
||||
Arc::new(SimulatedNetworkEngine::new())
|
||||
}
|
||||
}
|
||||
|
||||
// ── Output Formatter ────────────────────────────────────────────────────────
|
||||
|
||||
fn print_output<T: Serialize>(
|
||||
@@ -1712,7 +1740,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
println!("Interface '{interface}' disabled.");
|
||||
}
|
||||
InterfaceSubcommands::Status { interface } => {
|
||||
let wg = SimulatedWireGuardEngine::new();
|
||||
let wg = create_wireguard_engine();
|
||||
let stats = wg.get_interface_stats(&interface).await?;
|
||||
match stats {
|
||||
Some(s) => print_output(&s, format)?,
|
||||
@@ -1721,8 +1749,8 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
}
|
||||
InterfaceSubcommands::Reconcile { interface: _ } => {
|
||||
let state = AppState::new(store);
|
||||
let wg = Arc::new(SimulatedWireGuardEngine::new());
|
||||
let net = Arc::new(SimulatedNetworkEngine::new());
|
||||
let wg = create_wireguard_engine();
|
||||
let net = create_network_engine();
|
||||
let reconciler = ReconciliationEngine::new(state, wg, net);
|
||||
let report = reconciler.apply().await?;
|
||||
print_output(&report, format)?;
|
||||
@@ -1988,7 +2016,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
.get_interface(peer.interface_id)
|
||||
.await?
|
||||
.ok_or("Interface not found")?;
|
||||
let wg = SimulatedWireGuardEngine::new();
|
||||
let wg = create_wireguard_engine();
|
||||
let iface_stats = wg.get_interface_stats(&iface.name).await?;
|
||||
let peer_stat = iface_stats.and_then(|s| {
|
||||
s.peers
|
||||
@@ -2008,6 +2036,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
nat,
|
||||
mtu,
|
||||
profile,
|
||||
endpoint,
|
||||
output,
|
||||
} => {
|
||||
let peer_id = Uuid::parse_str(&id)?;
|
||||
@@ -2060,10 +2089,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
None
|
||||
};
|
||||
|
||||
let server_host = if let Some(ref ep) = endpoint {
|
||||
ep.trim().to_string()
|
||||
} else if let Some(s) = store.get_setting("server_endpoint").await? {
|
||||
s.value.trim().to_string()
|
||||
} else if let Some(s) = store.get_setting("public_endpoint").await? {
|
||||
s.value.trim().to_string()
|
||||
} else {
|
||||
return Err("No reachable WireGuard server endpoint is configured. Configure 'server_endpoint' in settings or provide --endpoint.".into());
|
||||
};
|
||||
|
||||
let conf = ClientConfigBuilder::build_with_profile(
|
||||
&peer,
|
||||
&iface,
|
||||
"127.0.0.1",
|
||||
&server_host,
|
||||
resolved_profile.as_ref(),
|
||||
)?;
|
||||
if let Some(out_path) = output {
|
||||
@@ -2081,6 +2120,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
nat,
|
||||
mtu,
|
||||
profile,
|
||||
endpoint,
|
||||
qr_format,
|
||||
} => {
|
||||
let peer_id = Uuid::parse_str(&id)?;
|
||||
@@ -2133,10 +2173,20 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
None
|
||||
};
|
||||
|
||||
let server_host = if let Some(ref ep) = endpoint {
|
||||
ep.trim().to_string()
|
||||
} else if let Some(s) = store.get_setting("server_endpoint").await? {
|
||||
s.value.trim().to_string()
|
||||
} else if let Some(s) = store.get_setting("public_endpoint").await? {
|
||||
s.value.trim().to_string()
|
||||
} else {
|
||||
return Err("No reachable WireGuard server endpoint is configured. Configure 'server_endpoint' in settings or provide --endpoint.".into());
|
||||
};
|
||||
|
||||
let conf = ClientConfigBuilder::build_with_profile(
|
||||
&peer,
|
||||
&iface,
|
||||
"127.0.0.1",
|
||||
&server_host,
|
||||
resolved_profile.as_ref(),
|
||||
)?;
|
||||
match qr_format.to_lowercase().as_str() {
|
||||
@@ -2778,12 +2828,12 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
Commands::Live(args) => match args.subcommand {
|
||||
LiveSubcommands::Interface(i_args) => match i_args.subcommand {
|
||||
LiveInterfaceSubcommands::List => {
|
||||
let wg = SimulatedWireGuardEngine::new();
|
||||
let wg = create_wireguard_engine();
|
||||
let list = wg.list_interfaces().await?;
|
||||
print_output(&list, format)?;
|
||||
}
|
||||
LiveInterfaceSubcommands::Show { name } => {
|
||||
let wg = SimulatedWireGuardEngine::new();
|
||||
let wg = create_wireguard_engine();
|
||||
let stats = wg.get_interface_stats(&name).await?;
|
||||
match stats {
|
||||
Some(s) => print_output(&s, format)?,
|
||||
@@ -2796,13 +2846,13 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
},
|
||||
LiveSubcommands::Peer(p_args) => match p_args.subcommand {
|
||||
LivePeerSubcommands::List { interface } => {
|
||||
let wg = SimulatedWireGuardEngine::new();
|
||||
let wg = create_wireguard_engine();
|
||||
let stats = wg.get_interface_stats(&interface).await?;
|
||||
let peers = stats.map(|s| s.peers).unwrap_or_default();
|
||||
print_output(&peers, format)?;
|
||||
}
|
||||
LivePeerSubcommands::Show { id } => {
|
||||
let wg = SimulatedWireGuardEngine::new();
|
||||
let wg = create_wireguard_engine();
|
||||
let ifaces = wg.list_interfaces().await?;
|
||||
let mut found = None;
|
||||
for iface in ifaces {
|
||||
@@ -2835,7 +2885,7 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
print_output(&status, format)?;
|
||||
}
|
||||
LiveSubcommands::Firewall => {
|
||||
let net = NativeLinuxNetworkEngine::new();
|
||||
let net = create_network_engine();
|
||||
let ruleset = net.get_active_nftables_ruleset().await?;
|
||||
print_output(&ruleset, format)?;
|
||||
}
|
||||
@@ -2844,8 +2894,11 @@ async fn main() -> Result<(), Box<dyn std::error::Error>> {
|
||||
print_output(&status, format)?;
|
||||
}
|
||||
LiveSubcommands::Nat => {
|
||||
let net = create_network_engine();
|
||||
let ruleset = net.get_active_nftables_ruleset().await.unwrap_or_default();
|
||||
let nat_active = ruleset.contains("masquerade");
|
||||
let status = serde_json::json!({
|
||||
"nat_active": true,
|
||||
"nat_masquerade_active": nat_active,
|
||||
"table": "inet nx9_wg",
|
||||
"chain": "postrouting"
|
||||
});
|
||||
|
||||
Reference in new issue
Block a user