wip: PXE setup for ipxe and okd files in progress
Some checks failed
Run Check Script / check (pull_request) Failing after 36s
Some checks failed
Run Check Script / check (pull_request) Failing after 36s
This commit is contained in:
parent
e956772593
commit
da6610c625
1
Cargo.lock
generated
1
Cargo.lock
generated
@ -3596,6 +3596,7 @@ dependencies = [
|
|||||||
"tokio",
|
"tokio",
|
||||||
"tokio-stream",
|
"tokio-stream",
|
||||||
"tokio-util",
|
"tokio-util",
|
||||||
|
"uuid",
|
||||||
]
|
]
|
||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
|
|||||||
@ -125,9 +125,10 @@ async fn main() {
|
|||||||
harmony::modules::okd::load_balancer::OKDLoadBalancerScore::new(&topology);
|
harmony::modules::okd::load_balancer::OKDLoadBalancerScore::new(&topology);
|
||||||
|
|
||||||
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
|
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
|
||||||
let http_score = StaticFilesHttpScore::new(Url::LocalFolder(
|
let http_score = StaticFilesHttpScore {
|
||||||
"./data/watchguard/pxe-http-files".to_string(),
|
folder_to_serve: Some(Url::LocalFolder("./data/watchguard/pxe-http-files".to_string())),
|
||||||
));
|
files: vec![],
|
||||||
|
};
|
||||||
let ipxe_score = IpxeScore::new();
|
let ipxe_score = IpxeScore::new();
|
||||||
|
|
||||||
harmony_tui::run(
|
harmony_tui::run(
|
||||||
|
|||||||
@ -1,7 +1,8 @@
|
|||||||
mod topology;
|
mod topology;
|
||||||
|
|
||||||
use harmony::{
|
use harmony::{
|
||||||
modules::{dhcp::DhcpScore, tftp::TftpScore},
|
data::{FileContent, FilePath},
|
||||||
|
modules::{dhcp::DhcpScore, http::StaticFilesHttpScore, tftp::TftpScore},
|
||||||
score::Score,
|
score::Score,
|
||||||
topology::{HAClusterTopology, Url},
|
topology::{HAClusterTopology, Url},
|
||||||
};
|
};
|
||||||
@ -14,6 +15,7 @@ async fn main() {
|
|||||||
let topology = get_topology().await;
|
let topology = get_topology().await;
|
||||||
let gateway_ip = topology.router.get_gateway();
|
let gateway_ip = topology.router.get_gateway();
|
||||||
|
|
||||||
|
// TODO this should be a single IPXEScore instead of having the user do this step by step
|
||||||
let scores: Vec<Box<dyn Score<HAClusterTopology>>> = vec![
|
let scores: Vec<Box<dyn Score<HAClusterTopology>>> = vec![
|
||||||
Box::new(DhcpScore {
|
Box::new(DhcpScore {
|
||||||
host_binding: vec![],
|
host_binding: vec![],
|
||||||
@ -26,7 +28,23 @@ async fn main() {
|
|||||||
Box::new(TftpScore {
|
Box::new(TftpScore {
|
||||||
files_to_serve: Url::LocalFolder("./data/pxe/okd/tftpboot/".to_string()),
|
files_to_serve: Url::LocalFolder("./data/pxe/okd/tftpboot/".to_string()),
|
||||||
}),
|
}),
|
||||||
|
Box::new(StaticFilesHttpScore {
|
||||||
|
folder_to_serve: None,
|
||||||
|
files: vec![FileContent {
|
||||||
|
path: FilePath::Relative("boot.ipxe".to_string()),
|
||||||
|
content: format!(
|
||||||
|
"#!ipxe
|
||||||
|
|
||||||
|
set base-url http://{gateway_ip}:8080
|
||||||
|
set hostfile ${{base-url}}/byMAC/01-${{mac:hexhyp}}.ipxe
|
||||||
|
|
||||||
|
chain ${{hostfile}} || chain ${{base-url}}/default.ipxe"
|
||||||
|
),
|
||||||
|
}],
|
||||||
|
}),
|
||||||
];
|
];
|
||||||
|
|
||||||
harmony_cli::run(inventory, topology, scores, None).await.unwrap();
|
harmony_cli::run(inventory, topology, scores, None)
|
||||||
|
.await
|
||||||
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|||||||
@ -80,9 +80,12 @@ async fn main() {
|
|||||||
let load_balancer_score = OKDLoadBalancerScore::new(&topology);
|
let load_balancer_score = OKDLoadBalancerScore::new(&topology);
|
||||||
|
|
||||||
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
|
let tftp_score = TftpScore::new(Url::LocalFolder("./data/watchguard/tftpboot".to_string()));
|
||||||
let http_score = StaticFilesHttpScore::new(Url::LocalFolder(
|
let http_score = StaticFilesHttpScore {
|
||||||
"./data/watchguard/pxe-http-files".to_string(),
|
folder_to_serve: Some(Url::LocalFolder(
|
||||||
));
|
"./data/watchguard/pxe-http-files".to_string(),
|
||||||
|
)),
|
||||||
|
files: vec![],
|
||||||
|
};
|
||||||
|
|
||||||
harmony_tui::run(
|
harmony_tui::run(
|
||||||
inventory,
|
inventory,
|
||||||
|
|||||||
22
harmony/src/domain/data/file.rs
Normal file
22
harmony/src/domain/data/file.rs
Normal file
@ -0,0 +1,22 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub struct FileContent {
|
||||||
|
pub path: FilePath,
|
||||||
|
pub content: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
#[derive(Debug, Clone, Serialize, Deserialize)]
|
||||||
|
pub enum FilePath {
|
||||||
|
Relative(String),
|
||||||
|
Absolute(String),
|
||||||
|
}
|
||||||
|
|
||||||
|
impl std::fmt::Display for FilePath {
|
||||||
|
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||||
|
match self {
|
||||||
|
FilePath::Relative(path) => f.write_fmt(format_args!("./{path}")),
|
||||||
|
FilePath::Absolute(path) => f.write_fmt(format_args!("/{path}")),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
@ -1,4 +1,6 @@
|
|||||||
mod id;
|
mod id;
|
||||||
mod version;
|
mod version;
|
||||||
|
mod file;
|
||||||
pub use id::*;
|
pub use id::*;
|
||||||
pub use version::*;
|
pub use version::*;
|
||||||
|
pub use file::*;
|
||||||
|
|||||||
@ -4,7 +4,9 @@ use harmony_types::net::MacAddress;
|
|||||||
use log::debug;
|
use log::debug;
|
||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
|
use crate::data::FileContent;
|
||||||
use crate::executors::ExecutorError;
|
use crate::executors::ExecutorError;
|
||||||
|
use crate::topology::PxeOptions;
|
||||||
|
|
||||||
use super::DHCPStaticEntry;
|
use super::DHCPStaticEntry;
|
||||||
use super::DhcpServer;
|
use super::DhcpServer;
|
||||||
@ -155,12 +157,10 @@ impl DhcpServer for HAClusterTopology {
|
|||||||
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)> {
|
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)> {
|
||||||
self.dhcp_server.list_static_mappings().await
|
self.dhcp_server.list_static_mappings().await
|
||||||
}
|
}
|
||||||
async fn set_next_server(&self, ip: IpAddress) -> Result<(), ExecutorError> {
|
async fn set_pxe_options(&self, options: PxeOptions) -> Result<(), ExecutorError> {
|
||||||
self.dhcp_server.set_next_server(ip).await
|
self.dhcp_server.set_pxe_options(options).await
|
||||||
}
|
|
||||||
async fn set_boot_filename(&self, boot_filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
self.dhcp_server.set_boot_filename(boot_filename).await
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn get_ip(&self) -> IpAddress {
|
fn get_ip(&self) -> IpAddress {
|
||||||
self.dhcp_server.get_ip()
|
self.dhcp_server.get_ip()
|
||||||
}
|
}
|
||||||
@ -170,16 +170,6 @@ impl DhcpServer for HAClusterTopology {
|
|||||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||||
self.dhcp_server.commit_config().await
|
self.dhcp_server.commit_config().await
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
self.dhcp_server.set_filename(filename).await
|
|
||||||
}
|
|
||||||
async fn set_filename64(&self, filename64: &str) -> Result<(), ExecutorError> {
|
|
||||||
self.dhcp_server.set_filename64(filename64).await
|
|
||||||
}
|
|
||||||
async fn set_filenameipxe(&self, filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
||||||
self.dhcp_server.set_filenameipxe(filenameipxe).await
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
@ -223,17 +213,21 @@ impl HttpServer for HAClusterTopology {
|
|||||||
self.http_server.serve_files(url).await
|
self.http_server.serve_files(url).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn serve_file_content(&self, file: &FileContent) -> Result<(), ExecutorError> {
|
||||||
|
self.http_server.serve_file_content(file).await
|
||||||
|
}
|
||||||
|
|
||||||
fn get_ip(&self) -> IpAddress {
|
fn get_ip(&self) -> IpAddress {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
self.http_server.get_ip()
|
||||||
}
|
}
|
||||||
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
async fn ensure_initialized(&self) -> Result<(), ExecutorError> {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
self.http_server.ensure_initialized().await
|
||||||
}
|
}
|
||||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
self.http_server.commit_config().await
|
||||||
}
|
}
|
||||||
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
async fn reload_restart(&self) -> Result<(), ExecutorError> {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
self.http_server.reload_restart().await
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -301,19 +295,7 @@ impl DhcpServer for DummyInfra {
|
|||||||
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)> {
|
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)> {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||||
}
|
}
|
||||||
async fn set_next_server(&self, _ip: IpAddress) -> Result<(), ExecutorError> {
|
async fn set_pxe_options(&self, _options: PxeOptions) -> Result<(), ExecutorError> {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
async fn set_boot_filename(&self, _boot_filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
async fn set_filename(&self, _filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
async fn set_filename64(&self, _filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
|
||||||
}
|
|
||||||
async fn set_filenameipxe(&self, _filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||||
}
|
}
|
||||||
fn get_ip(&self) -> IpAddress {
|
fn get_ip(&self) -> IpAddress {
|
||||||
@ -383,6 +365,9 @@ impl HttpServer for DummyInfra {
|
|||||||
async fn serve_files(&self, _url: &Url) -> Result<(), ExecutorError> {
|
async fn serve_files(&self, _url: &Url) -> Result<(), ExecutorError> {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||||
}
|
}
|
||||||
|
async fn serve_file_content(&self, _file: &FileContent) -> Result<(), ExecutorError> {
|
||||||
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||||
|
}
|
||||||
fn get_ip(&self) -> IpAddress {
|
fn get_ip(&self) -> IpAddress {
|
||||||
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
unimplemented!("{}", UNIMPLEMENTED_DUMMY_INFRA)
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use crate::executors::ExecutorError;
|
use crate::{data::FileContent, executors::ExecutorError};
|
||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
|
|
||||||
use super::{IpAddress, Url};
|
use super::{IpAddress, Url};
|
||||||
@ -6,6 +6,7 @@ use super::{IpAddress, Url};
|
|||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait HttpServer: Send + Sync {
|
pub trait HttpServer: Send + Sync {
|
||||||
async fn serve_files(&self, url: &Url) -> Result<(), ExecutorError>;
|
async fn serve_files(&self, url: &Url) -> Result<(), ExecutorError>;
|
||||||
|
async fn serve_file_content(&self, file: &FileContent) -> Result<(), ExecutorError>;
|
||||||
fn get_ip(&self) -> IpAddress;
|
fn get_ip(&self) -> IpAddress;
|
||||||
|
|
||||||
// async fn set_ip(&self, ip: IpAddress) -> Result<(), ExecutorError>;
|
// async fn set_ip(&self, ip: IpAddress) -> Result<(), ExecutorError>;
|
||||||
|
|||||||
@ -46,16 +46,19 @@ pub trait K8sclient: Send + Sync {
|
|||||||
async fn k8s_client(&self) -> Result<Arc<K8sClient>, String>;
|
async fn k8s_client(&self) -> Result<Arc<K8sClient>, String>;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub struct PxeOptions {
|
||||||
|
pub ipxe_filename: String,
|
||||||
|
pub bios_filename: String,
|
||||||
|
pub efi_filename: String,
|
||||||
|
pub tftp_ip: Option<IpAddress>,
|
||||||
|
}
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
pub trait DhcpServer: Send + Sync + std::fmt::Debug {
|
pub trait DhcpServer: Send + Sync + std::fmt::Debug {
|
||||||
async fn add_static_mapping(&self, entry: &DHCPStaticEntry) -> Result<(), ExecutorError>;
|
async fn add_static_mapping(&self, entry: &DHCPStaticEntry) -> Result<(), ExecutorError>;
|
||||||
async fn remove_static_mapping(&self, mac: &MacAddress) -> Result<(), ExecutorError>;
|
async fn remove_static_mapping(&self, mac: &MacAddress) -> Result<(), ExecutorError>;
|
||||||
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)>;
|
async fn list_static_mappings(&self) -> Vec<(MacAddress, IpAddress)>;
|
||||||
async fn set_next_server(&self, ip: IpAddress) -> Result<(), ExecutorError>;
|
async fn set_pxe_options(&self, pxe_options: PxeOptions) -> Result<(), ExecutorError>;
|
||||||
async fn set_boot_filename(&self, boot_filename: &str) -> Result<(), ExecutorError>;
|
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError>;
|
|
||||||
async fn set_filename64(&self, filename64: &str) -> Result<(), ExecutorError>;
|
|
||||||
async fn set_filenameipxe(&self, filenameipxe: &str) -> Result<(), ExecutorError>;
|
|
||||||
fn get_ip(&self) -> IpAddress;
|
fn get_ip(&self) -> IpAddress;
|
||||||
fn get_host(&self) -> LogicalHost;
|
fn get_host(&self) -> LogicalHost;
|
||||||
async fn commit_config(&self) -> Result<(), ExecutorError>;
|
async fn commit_config(&self) -> Result<(), ExecutorError>;
|
||||||
|
|||||||
@ -1,10 +1,10 @@
|
|||||||
use async_trait::async_trait;
|
use async_trait::async_trait;
|
||||||
use harmony_types::net::MacAddress;
|
use harmony_types::net::MacAddress;
|
||||||
use log::debug;
|
use log::{debug, info};
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
executors::ExecutorError,
|
executors::ExecutorError,
|
||||||
topology::{DHCPStaticEntry, DhcpServer, IpAddress, LogicalHost},
|
topology::{DHCPStaticEntry, DhcpServer, IpAddress, LogicalHost, PxeOptions},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::OPNSenseFirewall;
|
use super::OPNSenseFirewall;
|
||||||
@ -26,7 +26,7 @@ impl DhcpServer for OPNSenseFirewall {
|
|||||||
.unwrap();
|
.unwrap();
|
||||||
}
|
}
|
||||||
|
|
||||||
debug!("Registered {:?}", entry);
|
info!("Registered {:?}", entry);
|
||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -46,57 +46,25 @@ impl DhcpServer for OPNSenseFirewall {
|
|||||||
self.host.clone()
|
self.host.clone()
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_next_server(&self, ip: IpAddress) -> Result<(), ExecutorError> {
|
async fn set_pxe_options(&self, options: PxeOptions) -> Result<(), ExecutorError> {
|
||||||
let ipv4 = match ip {
|
let mut writable_opnsense = self.opnsense_config.write().await;
|
||||||
std::net::IpAddr::V4(ipv4_addr) => ipv4_addr,
|
let PxeOptions {
|
||||||
std::net::IpAddr::V6(_) => todo!("ipv6 not supported yet"),
|
ipxe_filename,
|
||||||
};
|
bios_filename,
|
||||||
{
|
efi_filename,
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
tftp_ip,
|
||||||
writable_opnsense.dhcp().set_next_server(ipv4);
|
} = options;
|
||||||
debug!("OPNsense dhcp server set next server {ipv4}");
|
writable_opnsense
|
||||||
}
|
.dhcp()
|
||||||
|
.set_pxe_options(
|
||||||
Ok(())
|
tftp_ip.map(|i| i.to_string()),
|
||||||
}
|
bios_filename,
|
||||||
|
efi_filename,
|
||||||
async fn set_boot_filename(&self, boot_filename: &str) -> Result<(), ExecutorError> {
|
ipxe_filename,
|
||||||
{
|
)
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
.await
|
||||||
writable_opnsense.dhcp().set_boot_filename(boot_filename);
|
.map_err(|dhcp_error| {
|
||||||
debug!("OPNsense dhcp server set boot filename {boot_filename}");
|
ExecutorError::UnexpectedError(format!("Failed to set_pxe_options : {dhcp_error}"))
|
||||||
}
|
})
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_filename(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
{
|
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
|
||||||
writable_opnsense.dhcp().set_filename(filename);
|
|
||||||
debug!("OPNsense dhcp server set filename {filename}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_filename64(&self, filename: &str) -> Result<(), ExecutorError> {
|
|
||||||
{
|
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
|
||||||
writable_opnsense.dhcp().set_filename64(filename);
|
|
||||||
debug!("OPNsense dhcp server set filename {filename}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
|
||||||
|
|
||||||
async fn set_filenameipxe(&self, filenameipxe: &str) -> Result<(), ExecutorError> {
|
|
||||||
{
|
|
||||||
let mut writable_opnsense = self.opnsense_config.write().await;
|
|
||||||
writable_opnsense.dhcp().set_filenameipxe(filenameipxe);
|
|
||||||
debug!("OPNsense dhcp server set filenameipxe {filenameipxe}");
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(())
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -2,23 +2,23 @@ use async_trait::async_trait;
|
|||||||
use log::info;
|
use log::info;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
|
data::FileContent,
|
||||||
executors::ExecutorError,
|
executors::ExecutorError,
|
||||||
topology::{HttpServer, IpAddress, Url},
|
topology::{HttpServer, IpAddress, Url},
|
||||||
};
|
};
|
||||||
|
|
||||||
use super::OPNSenseFirewall;
|
use super::OPNSenseFirewall;
|
||||||
|
const OPNSENSE_HTTP_ROOT_PATH: &str = "/usr/local/http";
|
||||||
|
|
||||||
#[async_trait]
|
#[async_trait]
|
||||||
impl HttpServer for OPNSenseFirewall {
|
impl HttpServer for OPNSenseFirewall {
|
||||||
async fn serve_files(&self, url: &Url) -> Result<(), ExecutorError> {
|
async fn serve_files(&self, url: &Url) -> Result<(), ExecutorError> {
|
||||||
let http_root_path = "/usr/local/http";
|
|
||||||
|
|
||||||
let config = self.opnsense_config.read().await;
|
let config = self.opnsense_config.read().await;
|
||||||
info!("Uploading files from url {url} to {http_root_path}");
|
info!("Uploading files from url {url} to {OPNSENSE_HTTP_ROOT_PATH}");
|
||||||
match url {
|
match url {
|
||||||
Url::LocalFolder(path) => {
|
Url::LocalFolder(path) => {
|
||||||
config
|
config
|
||||||
.upload_files(path, http_root_path)
|
.upload_files(path, OPNSENSE_HTTP_ROOT_PATH)
|
||||||
.await
|
.await
|
||||||
.map_err(|e| ExecutorError::UnexpectedError(e.to_string()))?;
|
.map_err(|e| ExecutorError::UnexpectedError(e.to_string()))?;
|
||||||
}
|
}
|
||||||
@ -27,8 +27,29 @@ impl HttpServer for OPNSenseFirewall {
|
|||||||
Ok(())
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn serve_file_content(&self, file: &FileContent) -> Result<(), ExecutorError> {
|
||||||
|
let path = match &file.path {
|
||||||
|
crate::data::FilePath::Relative(path) => {
|
||||||
|
format!("{OPNSENSE_HTTP_ROOT_PATH}/{}", path.to_string())
|
||||||
|
}
|
||||||
|
crate::data::FilePath::Absolute(path) => {
|
||||||
|
return Err(ExecutorError::ConfigurationError(format!(
|
||||||
|
"Cannot serve file from http server with absolute path : {path}"
|
||||||
|
)));
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
let config = self.opnsense_config.read().await;
|
||||||
|
info!("Uploading file content to {}", path);
|
||||||
|
config
|
||||||
|
.upload_file_content(&path, &file.content)
|
||||||
|
.await
|
||||||
|
.map_err(|e| ExecutorError::UnexpectedError(e.to_string()))?;
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
fn get_ip(&self) -> IpAddress {
|
fn get_ip(&self) -> IpAddress {
|
||||||
todo!();
|
OPNSenseFirewall::get_ip(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
async fn commit_config(&self) -> Result<(), ExecutorError> {
|
||||||
|
|||||||
@ -28,7 +28,7 @@ impl TftpServer for OPNSenseFirewall {
|
|||||||
}
|
}
|
||||||
|
|
||||||
fn get_ip(&self) -> IpAddress {
|
fn get_ip(&self) -> IpAddress {
|
||||||
todo!()
|
OPNSenseFirewall::get_ip(self)
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn set_ip(&self, ip: IpAddress) -> Result<(), ExecutorError> {
|
async fn set_ip(&self, ip: IpAddress) -> Result<(), ExecutorError> {
|
||||||
|
|||||||
@ -7,7 +7,7 @@ use crate::{
|
|||||||
domain::{data::Version, interpret::InterpretStatus},
|
domain::{data::Version, interpret::InterpretStatus},
|
||||||
interpret::{Interpret, InterpretError, InterpretName, Outcome},
|
interpret::{Interpret, InterpretError, InterpretName, Outcome},
|
||||||
inventory::Inventory,
|
inventory::Inventory,
|
||||||
topology::{DHCPStaticEntry, DhcpServer, HostBinding, IpAddress, Topology},
|
topology::{DHCPStaticEntry, DhcpServer, HostBinding, IpAddress, PxeOptions, Topology},
|
||||||
};
|
};
|
||||||
|
|
||||||
use crate::domain::score::Score;
|
use crate::domain::score::Score;
|
||||||
@ -98,69 +98,14 @@ impl DhcpInterpret {
|
|||||||
_inventory: &Inventory,
|
_inventory: &Inventory,
|
||||||
dhcp_server: &D,
|
dhcp_server: &D,
|
||||||
) -> Result<Outcome, InterpretError> {
|
) -> Result<Outcome, InterpretError> {
|
||||||
let next_server_outcome = match self.score.next_server {
|
let pxe_options = PxeOptions {
|
||||||
Some(next_server) => {
|
ipxe_filename: self.score.filenameipxe.clone().unwrap_or_default(),
|
||||||
dhcp_server.set_next_server(next_server).await?;
|
bios_filename: self.score.filename.clone().unwrap_or_default(),
|
||||||
Outcome::new(
|
efi_filename: self.score.filename64.clone().unwrap_or_default(),
|
||||||
InterpretStatus::SUCCESS,
|
tftp_ip: self.score.next_server,
|
||||||
format!("Dhcp Interpret Set next boot to {next_server}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
};
|
||||||
|
|
||||||
let boot_filename_outcome = match &self.score.boot_filename {
|
dhcp_server.set_pxe_options(pxe_options).await?;
|
||||||
Some(boot_filename) => {
|
|
||||||
dhcp_server.set_boot_filename(boot_filename).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set boot filename to {boot_filename}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let filename_outcome = match &self.score.filename {
|
|
||||||
Some(filename) => {
|
|
||||||
dhcp_server.set_filename(filename).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set filename to {filename}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let filename64_outcome = match &self.score.filename64 {
|
|
||||||
Some(filename64) => {
|
|
||||||
dhcp_server.set_filename64(filename64).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set filename64 to {filename64}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
let filenameipxe_outcome = match &self.score.filenameipxe {
|
|
||||||
Some(filenameipxe) => {
|
|
||||||
dhcp_server.set_filenameipxe(filenameipxe).await?;
|
|
||||||
Outcome::new(
|
|
||||||
InterpretStatus::SUCCESS,
|
|
||||||
format!("Dhcp Interpret Set filenameipxe to {filenameipxe}"),
|
|
||||||
)
|
|
||||||
}
|
|
||||||
None => Outcome::noop(),
|
|
||||||
};
|
|
||||||
|
|
||||||
if next_server_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& boot_filename_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& filename_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& filename64_outcome.status == InterpretStatus::NOOP
|
|
||||||
&& filenameipxe_outcome.status == InterpretStatus::NOOP
|
|
||||||
{
|
|
||||||
return Ok(Outcome::noop());
|
|
||||||
}
|
|
||||||
|
|
||||||
Ok(Outcome::new(
|
Ok(Outcome::new(
|
||||||
InterpretStatus::SUCCESS,
|
InterpretStatus::SUCCESS,
|
||||||
|
|||||||
@ -3,7 +3,7 @@ use derive_new::new;
|
|||||||
use serde::Serialize;
|
use serde::Serialize;
|
||||||
|
|
||||||
use crate::{
|
use crate::{
|
||||||
data::{Id, Version},
|
data::{FileContent, Id, Version},
|
||||||
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
interpret::{Interpret, InterpretError, InterpretName, InterpretStatus, Outcome},
|
||||||
inventory::Inventory,
|
inventory::Inventory,
|
||||||
score::Score,
|
score::Score,
|
||||||
@ -23,7 +23,8 @@ use crate::{
|
|||||||
/// ```
|
/// ```
|
||||||
#[derive(Debug, new, Clone, Serialize)]
|
#[derive(Debug, new, Clone, Serialize)]
|
||||||
pub struct StaticFilesHttpScore {
|
pub struct StaticFilesHttpScore {
|
||||||
files_to_serve: Url,
|
pub folder_to_serve: Option<Url>,
|
||||||
|
pub files: Vec<FileContent>,
|
||||||
}
|
}
|
||||||
|
|
||||||
impl<T: Topology + HttpServer> Score<T> for StaticFilesHttpScore {
|
impl<T: Topology + HttpServer> Score<T> for StaticFilesHttpScore {
|
||||||
@ -50,12 +51,20 @@ impl<T: Topology + HttpServer> Interpret<T> for StaticFilesHttpInterpret {
|
|||||||
) -> Result<Outcome, InterpretError> {
|
) -> Result<Outcome, InterpretError> {
|
||||||
http_server.ensure_initialized().await?;
|
http_server.ensure_initialized().await?;
|
||||||
// http_server.set_ip(topology.router.get_gateway()).await?;
|
// http_server.set_ip(topology.router.get_gateway()).await?;
|
||||||
http_server.serve_files(&self.score.files_to_serve).await?;
|
if let Some(folder) = self.score.folder_to_serve.as_ref() {
|
||||||
|
http_server.serve_files(folder).await?;
|
||||||
|
}
|
||||||
|
|
||||||
|
for f in self.score.files.iter() {
|
||||||
|
http_server.serve_file_content(&f).await?
|
||||||
|
}
|
||||||
|
|
||||||
http_server.commit_config().await?;
|
http_server.commit_config().await?;
|
||||||
http_server.reload_restart().await?;
|
http_server.reload_restart().await?;
|
||||||
Ok(Outcome::success(format!(
|
Ok(Outcome::success(format!(
|
||||||
"Http Server running and serving files from {}",
|
"Http Server running and serving files from folder {:?} and content for {}",
|
||||||
self.score.files_to_serve
|
self.score.folder_to_serve,
|
||||||
|
self.score.files.iter().map(|f| f.path.to_string()).collect::<Vec<String>>().join(",")
|
||||||
)))
|
)))
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@ -30,15 +30,15 @@ pub struct CaddyGeneral {
|
|||||||
#[yaserde(rename = "TlsDnsApiKey")]
|
#[yaserde(rename = "TlsDnsApiKey")]
|
||||||
pub tls_dns_api_key: MaybeString,
|
pub tls_dns_api_key: MaybeString,
|
||||||
#[yaserde(rename = "TlsDnsSecretApiKey")]
|
#[yaserde(rename = "TlsDnsSecretApiKey")]
|
||||||
pub tls_dns_secret_api_key: MaybeString,
|
pub tls_dns_secret_api_key: Option<MaybeString>,
|
||||||
#[yaserde(rename = "TlsDnsOptionalField1")]
|
#[yaserde(rename = "TlsDnsOptionalField1")]
|
||||||
pub tls_dns_optional_field1: MaybeString,
|
pub tls_dns_optional_field1: Option<MaybeString>,
|
||||||
#[yaserde(rename = "TlsDnsOptionalField2")]
|
#[yaserde(rename = "TlsDnsOptionalField2")]
|
||||||
pub tls_dns_optional_field2: MaybeString,
|
pub tls_dns_optional_field2: Option<MaybeString>,
|
||||||
#[yaserde(rename = "TlsDnsOptionalField3")]
|
#[yaserde(rename = "TlsDnsOptionalField3")]
|
||||||
pub tls_dns_optional_field3: MaybeString,
|
pub tls_dns_optional_field3: Option<MaybeString>,
|
||||||
#[yaserde(rename = "TlsDnsOptionalField4")]
|
#[yaserde(rename = "TlsDnsOptionalField4")]
|
||||||
pub tls_dns_optional_field4: MaybeString,
|
pub tls_dns_optional_field4: Option<MaybeString>,
|
||||||
#[yaserde(rename = "TlsDnsPropagationTimeout")]
|
#[yaserde(rename = "TlsDnsPropagationTimeout")]
|
||||||
pub tls_dns_propagation_timeout: Option<MaybeString>,
|
pub tls_dns_propagation_timeout: Option<MaybeString>,
|
||||||
#[yaserde(rename = "TlsDnsPropagationTimeoutPeriod")]
|
#[yaserde(rename = "TlsDnsPropagationTimeoutPeriod")]
|
||||||
@ -47,6 +47,8 @@ pub struct CaddyGeneral {
|
|||||||
pub tls_dns_propagation_delay: Option<MaybeString>,
|
pub tls_dns_propagation_delay: Option<MaybeString>,
|
||||||
#[yaserde(rename = "TlsDnsPropagationResolvers")]
|
#[yaserde(rename = "TlsDnsPropagationResolvers")]
|
||||||
pub tls_dns_propagation_resolvers: MaybeString,
|
pub tls_dns_propagation_resolvers: MaybeString,
|
||||||
|
#[yaserde(rename = "TlsDnsEchDomain")]
|
||||||
|
pub tls_dns_ech_domain: MaybeString,
|
||||||
pub accesslist: MaybeString,
|
pub accesslist: MaybeString,
|
||||||
#[yaserde(rename = "DisableSuperuser")]
|
#[yaserde(rename = "DisableSuperuser")]
|
||||||
pub disable_superuser: Option<i32>,
|
pub disable_superuser: Option<i32>,
|
||||||
@ -56,6 +58,10 @@ pub struct CaddyGeneral {
|
|||||||
pub http_version: Option<MaybeString>,
|
pub http_version: Option<MaybeString>,
|
||||||
#[yaserde(rename = "HttpVersions")]
|
#[yaserde(rename = "HttpVersions")]
|
||||||
pub http_versions: Option<MaybeString>,
|
pub http_versions: Option<MaybeString>,
|
||||||
|
pub timeout_read_body: Option<MaybeString>,
|
||||||
|
pub timeout_read_header: Option<MaybeString>,
|
||||||
|
pub timeout_write: Option<MaybeString>,
|
||||||
|
pub timeout_idle: Option<MaybeString>,
|
||||||
#[yaserde(rename = "LogCredentials")]
|
#[yaserde(rename = "LogCredentials")]
|
||||||
pub log_credentials: MaybeString,
|
pub log_credentials: MaybeString,
|
||||||
#[yaserde(rename = "LogAccessPlain")]
|
#[yaserde(rename = "LogAccessPlain")]
|
||||||
|
|||||||
@ -1,4 +1,4 @@
|
|||||||
use yaserde::MaybeString;
|
use yaserde::{MaybeString, RawXml};
|
||||||
use yaserde_derive::{YaDeserialize, YaSerialize};
|
use yaserde_derive::{YaDeserialize, YaSerialize};
|
||||||
|
|
||||||
// This is the top-level struct that represents the entire <dnsmasq> element.
|
// This is the top-level struct that represents the entire <dnsmasq> element.
|
||||||
@ -35,6 +35,7 @@ pub struct DnsMasq {
|
|||||||
pub dhcp_ranges: Vec<DhcpRange>,
|
pub dhcp_ranges: Vec<DhcpRange>,
|
||||||
pub dhcp_options: Vec<DhcpOptions>,
|
pub dhcp_options: Vec<DhcpOptions>,
|
||||||
pub dhcp_boot: Vec<DhcpBoot>,
|
pub dhcp_boot: Vec<DhcpBoot>,
|
||||||
|
pub dhcp_tags: Vec<RawXml>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents the <dhcp> element and its nested fields.
|
// Represents the <dhcp> element and its nested fields.
|
||||||
@ -44,6 +45,7 @@ pub struct Dhcp {
|
|||||||
pub no_interface: MaybeString,
|
pub no_interface: MaybeString,
|
||||||
pub fqdn: u8,
|
pub fqdn: u8,
|
||||||
pub domain: MaybeString,
|
pub domain: MaybeString,
|
||||||
|
pub local: Option<MaybeString>,
|
||||||
pub lease_max: MaybeString,
|
pub lease_max: MaybeString,
|
||||||
pub authoritative: u8,
|
pub authoritative: u8,
|
||||||
pub default_fw_rules: u8,
|
pub default_fw_rules: u8,
|
||||||
@ -86,10 +88,10 @@ pub struct DhcpBoot {
|
|||||||
pub uuid: String,
|
pub uuid: String,
|
||||||
pub interface: MaybeString,
|
pub interface: MaybeString,
|
||||||
pub tag: MaybeString,
|
pub tag: MaybeString,
|
||||||
pub filename: String,
|
pub filename: Option<String>,
|
||||||
pub servername: String,
|
pub servername: String,
|
||||||
pub address: String,
|
pub address: String,
|
||||||
pub description: String,
|
pub description: Option<String>,
|
||||||
}
|
}
|
||||||
|
|
||||||
// Represents a single <dhcp_options> element.
|
// Represents a single <dhcp_options> element.
|
||||||
|
|||||||
@ -1509,7 +1509,7 @@ pub struct Vlans {
|
|||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
pub struct Bridges {
|
pub struct Bridges {
|
||||||
pub bridged: MaybeString,
|
pub bridged: Option<MaybeString>,
|
||||||
}
|
}
|
||||||
|
|
||||||
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
#[derive(Default, PartialEq, Debug, YaSerialize, YaDeserialize)]
|
||||||
|
|||||||
@ -20,6 +20,7 @@ russh-sftp = "2.0.6"
|
|||||||
serde_json = "1.0.133"
|
serde_json = "1.0.133"
|
||||||
tokio-util = { version = "0.7.13", features = ["codec"] }
|
tokio-util = { version = "0.7.13", features = ["codec"] }
|
||||||
tokio-stream = "0.1.17"
|
tokio-stream = "0.1.17"
|
||||||
|
uuid.workspace = true
|
||||||
|
|
||||||
[dev-dependencies]
|
[dev-dependencies]
|
||||||
pretty_assertions.workspace = true
|
pretty_assertions.workspace = true
|
||||||
|
|||||||
@ -70,6 +70,10 @@ impl Config {
|
|||||||
self.shell.upload_folder(source, destination).await
|
self.shell.upload_folder(source, destination).await
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub async fn upload_file_content(&self, path: &str, content: &str) -> Result<String, Error> {
|
||||||
|
self.shell.write_content_to_file(content, path).await
|
||||||
|
}
|
||||||
|
|
||||||
/// Checks in config file if system.firmware.plugins csv field contains the specified package
|
/// Checks in config file if system.firmware.plugins csv field contains the specified package
|
||||||
/// name.
|
/// name.
|
||||||
///
|
///
|
||||||
|
|||||||
@ -9,6 +9,7 @@ use crate::Error;
|
|||||||
pub trait OPNsenseShell: std::fmt::Debug + Send + Sync {
|
pub trait OPNsenseShell: std::fmt::Debug + Send + Sync {
|
||||||
async fn exec(&self, command: &str) -> Result<String, Error>;
|
async fn exec(&self, command: &str) -> Result<String, Error>;
|
||||||
async fn write_content_to_temp_file(&self, content: &str) -> Result<String, Error>;
|
async fn write_content_to_temp_file(&self, content: &str) -> Result<String, Error>;
|
||||||
|
async fn write_content_to_file(&self, content: &str, filename: &str) -> Result<String, Error>;
|
||||||
async fn upload_folder(&self, source: &str, destination: &str) -> Result<String, Error>;
|
async fn upload_folder(&self, source: &str, destination: &str) -> Result<String, Error>;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -25,6 +26,14 @@ impl OPNsenseShell for DummyOPNSenseShell {
|
|||||||
async fn write_content_to_temp_file(&self, _content: &str) -> Result<String, Error> {
|
async fn write_content_to_temp_file(&self, _content: &str) -> Result<String, Error> {
|
||||||
unimplemented!("This is a dummy implementation");
|
unimplemented!("This is a dummy implementation");
|
||||||
}
|
}
|
||||||
|
|
||||||
|
async fn write_content_to_file(
|
||||||
|
&self,
|
||||||
|
_content: &str,
|
||||||
|
_filename: &str,
|
||||||
|
) -> Result<String, Error> {
|
||||||
|
unimplemented!("This is a dummy implementation");
|
||||||
|
}
|
||||||
async fn upload_folder(&self, _source: &str, _destination: &str) -> Result<String, Error> {
|
async fn upload_folder(&self, _source: &str, _destination: &str) -> Result<String, Error> {
|
||||||
unimplemented!("This is a dummy implementation");
|
unimplemented!("This is a dummy implementation");
|
||||||
}
|
}
|
||||||
|
|||||||
@ -44,6 +44,11 @@ impl OPNsenseShell for SshOPNSenseShell {
|
|||||||
.unwrap()
|
.unwrap()
|
||||||
.as_millis()
|
.as_millis()
|
||||||
);
|
);
|
||||||
|
self.write_content_to_file(content, &temp_filename).await
|
||||||
|
}
|
||||||
|
|
||||||
|
async fn write_content_to_file(&self, content: &str, filename: &str) -> Result<String, Error> {
|
||||||
|
// TODO fix this to create the directory before uploading the file
|
||||||
let channel = self.get_ssh_channel().await?;
|
let channel = self.get_ssh_channel().await?;
|
||||||
channel
|
channel
|
||||||
.request_subsystem(true, "sftp")
|
.request_subsystem(true, "sftp")
|
||||||
@ -53,10 +58,10 @@ impl OPNsenseShell for SshOPNSenseShell {
|
|||||||
.await
|
.await
|
||||||
.expect("Should acquire sftp subsystem");
|
.expect("Should acquire sftp subsystem");
|
||||||
|
|
||||||
let mut file = sftp.create(&temp_filename).await.unwrap();
|
let mut file = sftp.create(filename).await.unwrap();
|
||||||
file.write_all(content.as_bytes()).await?;
|
file.write_all(content.as_bytes()).await?;
|
||||||
|
|
||||||
Ok(temp_filename)
|
Ok(filename.to_string())
|
||||||
}
|
}
|
||||||
|
|
||||||
async fn upload_folder(&self, source: &str, destination: &str) -> Result<String, Error> {
|
async fn upload_folder(&self, source: &str, destination: &str) -> Result<String, Error> {
|
||||||
|
|||||||
@ -5,6 +5,7 @@ pub enum DhcpError {
|
|||||||
IpAddressAlreadyMapped(String),
|
IpAddressAlreadyMapped(String),
|
||||||
MacAddressAlreadyMapped(String),
|
MacAddressAlreadyMapped(String),
|
||||||
IpAddressOutOfRange(String),
|
IpAddressOutOfRange(String),
|
||||||
|
Configuration(String),
|
||||||
}
|
}
|
||||||
|
|
||||||
impl std::fmt::Display for DhcpError {
|
impl std::fmt::Display for DhcpError {
|
||||||
@ -21,6 +22,7 @@ impl std::fmt::Display for DhcpError {
|
|||||||
DhcpError::IpAddressOutOfRange(ip) => {
|
DhcpError::IpAddressOutOfRange(ip) => {
|
||||||
write!(f, "IP address {} is out of interface range", ip)
|
write!(f, "IP address {} is out of interface range", ip)
|
||||||
}
|
}
|
||||||
|
DhcpError::Configuration(msg) => f.write_str(&msg),
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -1,9 +1,11 @@
|
|||||||
|
// dnsmasq.rs
|
||||||
use crate::modules::dhcp::DhcpError;
|
use crate::modules::dhcp::DhcpError;
|
||||||
use log::info;
|
use log::{debug, info};
|
||||||
use opnsense_config_xml::MaybeString;
|
use opnsense_config_xml::dnsmasq::{DhcpBoot, DhcpOptions, DnsMasq};
|
||||||
use opnsense_config_xml::StaticMap;
|
use opnsense_config_xml::{MaybeString, StaticMap};
|
||||||
use std::net::Ipv4Addr;
|
use std::net::Ipv4Addr;
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
use uuid::Uuid;
|
||||||
|
|
||||||
use opnsense_config_xml::OPNsense;
|
use opnsense_config_xml::OPNsense;
|
||||||
|
|
||||||
@ -15,6 +17,8 @@ pub struct DhcpConfigDnsMasq<'a> {
|
|||||||
opnsense_shell: Arc<dyn OPNsenseShell>,
|
opnsense_shell: Arc<dyn OPNsenseShell>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const DNS_MASQ_PXE_CONFIG_FILE: &str = "/usr/local/etc/dnsmasq.conf.d/pxe.conf";
|
||||||
|
|
||||||
impl<'a> DhcpConfigDnsMasq<'a> {
|
impl<'a> DhcpConfigDnsMasq<'a> {
|
||||||
pub fn new(opnsense: &'a mut OPNsense, opnsense_shell: Arc<dyn OPNsenseShell>) -> Self {
|
pub fn new(opnsense: &'a mut OPNsense, opnsense_shell: Arc<dyn OPNsenseShell>) -> Self {
|
||||||
Self {
|
Self {
|
||||||
@ -23,47 +27,172 @@ impl<'a> DhcpConfigDnsMasq<'a> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Removes a static mapping by its MAC address.
|
||||||
|
/// Static mappings are stored in the <dhcpd> section of the config, shared with the ISC module.
|
||||||
pub fn remove_static_mapping(&mut self, mac: &str) {
|
pub fn remove_static_mapping(&mut self, mac: &str) {
|
||||||
todo!()
|
let lan_dhcpd = self.get_lan_dhcpd();
|
||||||
|
lan_dhcpd
|
||||||
|
.staticmaps
|
||||||
|
.retain(|static_entry| static_entry.mac != mac);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Retrieves a mutable reference to the LAN interface's DHCP configuration.
|
||||||
|
/// This is located in the shared <dhcpd> section of the config.
|
||||||
fn get_lan_dhcpd(&mut self) -> &mut opnsense_config_xml::DhcpInterface {
|
fn get_lan_dhcpd(&mut self) -> &mut opnsense_config_xml::DhcpInterface {
|
||||||
todo!()
|
&mut self
|
||||||
|
.opnsense
|
||||||
|
.dhcpd
|
||||||
|
.elements
|
||||||
|
.iter_mut()
|
||||||
|
.find(|(name, _config)| name == "lan")
|
||||||
|
.expect("Interface lan should have dhcpd activated")
|
||||||
|
.1
|
||||||
}
|
}
|
||||||
|
|
||||||
|
fn dnsmasq(&mut self) -> &mut DnsMasq {
|
||||||
|
self.opnsense
|
||||||
|
.dnsmasq
|
||||||
|
.as_mut()
|
||||||
|
.expect("Dnsmasq config should exist. Maybe it is not installed yet")
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Adds a new static DHCP mapping.
|
||||||
|
/// Validates the MAC address and checks for existing mappings to prevent conflicts.
|
||||||
pub fn add_static_mapping(
|
pub fn add_static_mapping(
|
||||||
&mut self,
|
&mut self,
|
||||||
mac: &str,
|
mac: &str,
|
||||||
ipaddr: Ipv4Addr,
|
ipaddr: Ipv4Addr,
|
||||||
hostname: &str,
|
hostname: &str,
|
||||||
) -> Result<(), DhcpError> {
|
) -> Result<(), DhcpError> {
|
||||||
todo!()
|
let mac = mac.to_string();
|
||||||
|
let hostname = hostname.to_string();
|
||||||
|
let lan_dhcpd = self.get_lan_dhcpd();
|
||||||
|
let existing_mappings: &mut Vec<StaticMap> = &mut lan_dhcpd.staticmaps;
|
||||||
|
|
||||||
|
if !Self::is_valid_mac(&mac) {
|
||||||
|
return Err(DhcpError::InvalidMacAddress(mac));
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: Validate that the IP address is within a configured DHCP range.
|
||||||
|
|
||||||
|
if existing_mappings
|
||||||
|
.iter()
|
||||||
|
.any(|m| m.ipaddr == ipaddr.to_string() && m.mac == mac)
|
||||||
|
{
|
||||||
|
info!("Mapping already exists for {} [{}], skipping", ipaddr, mac);
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing_mappings
|
||||||
|
.iter()
|
||||||
|
.any(|m| m.ipaddr == ipaddr.to_string())
|
||||||
|
{
|
||||||
|
return Err(DhcpError::IpAddressAlreadyMapped(ipaddr.to_string()));
|
||||||
|
}
|
||||||
|
|
||||||
|
if existing_mappings.iter().any(|m| m.mac == mac) {
|
||||||
|
return Err(DhcpError::MacAddressAlreadyMapped(mac));
|
||||||
|
}
|
||||||
|
|
||||||
|
let static_map = StaticMap {
|
||||||
|
mac,
|
||||||
|
ipaddr: ipaddr.to_string(),
|
||||||
|
hostname: hostname,
|
||||||
|
..Default::default()
|
||||||
|
};
|
||||||
|
|
||||||
|
existing_mappings.push(static_map);
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/// Helper function to validate a MAC address format.
|
||||||
|
fn is_valid_mac(mac: &str) -> bool {
|
||||||
|
let parts: Vec<&str> = mac.split(':').collect();
|
||||||
|
if parts.len() != 6 {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
parts
|
||||||
|
.iter()
|
||||||
|
.all(|part| part.len() <= 2 && part.chars().all(|c| c.is_ascii_hexdigit()))
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Retrieves the list of current static mappings by shelling out to `configctl`.
|
||||||
|
/// This provides the real-time state from the running system.
|
||||||
pub async fn get_static_mappings(&self) -> Result<Vec<StaticMap>, Error> {
|
pub async fn get_static_mappings(&self) -> Result<Vec<StaticMap>, Error> {
|
||||||
todo!()
|
let list_static_output = self
|
||||||
}
|
.opnsense_shell
|
||||||
pub fn enable_netboot(&mut self) {
|
.exec("configctl dhcpd list static")
|
||||||
todo!()
|
.await?;
|
||||||
|
|
||||||
|
let value: serde_json::Value = serde_json::from_str(&list_static_output)
|
||||||
|
.unwrap_or_else(|_| panic!("Got invalid json from configctl {list_static_output}"));
|
||||||
|
let static_maps = value["dhcpd"]
|
||||||
|
.as_array()
|
||||||
|
.ok_or(Error::Command(format!(
|
||||||
|
"Invalid DHCP data from configctl command, got {list_static_output}"
|
||||||
|
)))?
|
||||||
|
.iter()
|
||||||
|
.map(|entry| StaticMap {
|
||||||
|
mac: entry["mac"].as_str().unwrap_or_default().to_string(),
|
||||||
|
ipaddr: entry["ipaddr"].as_str().unwrap_or_default().to_string(),
|
||||||
|
hostname: entry["hostname"].as_str().unwrap_or_default().to_string(),
|
||||||
|
descr: entry["descr"].as_str().map(MaybeString::from),
|
||||||
|
..Default::default()
|
||||||
|
})
|
||||||
|
.collect();
|
||||||
|
|
||||||
|
Ok(static_maps)
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn set_next_server(&mut self, ip: Ipv4Addr) {
|
pub async fn set_pxe_options(
|
||||||
todo!()
|
&self,
|
||||||
}
|
tftp_ip: Option<String>,
|
||||||
|
bios_filename: String,
|
||||||
|
efi_filename: String,
|
||||||
|
ipxe_filename: String,
|
||||||
|
) -> Result<(), DhcpError> {
|
||||||
|
// As of writing this opnsense does not support negative tags, and the dnsmasq config is a
|
||||||
|
// bit complicated anyways. So we are writing directly a dnsmasq config file to
|
||||||
|
// /usr/local/etc/dnsmasq.conf.d
|
||||||
|
let tftp_str = tftp_ip.map_or(String::new(), |i| format!(",{i},{i}"));
|
||||||
|
|
||||||
pub fn set_boot_filename(&mut self, boot_filename: &str) {
|
let config = format!(
|
||||||
todo!()
|
"
|
||||||
}
|
# Add tag ipxe to dhcp requests with user class (77) = iPXE
|
||||||
|
dhcp-match=set:ipxe,77,iPXE
|
||||||
|
# Add tag bios to dhcp requests with arch (93) = 0
|
||||||
|
dhcp-match=set:bios,93,0
|
||||||
|
# Add tag efi to dhcp requests with arch (93) = 7
|
||||||
|
dhcp-match=set:efi,93,7
|
||||||
|
|
||||||
pub fn set_filename(&mut self, filename: &str) {
|
# Provide ipxe efi file to uefi but NOT ipxe clients
|
||||||
todo!()
|
dhcp-boot=tag:efi,tag:!ipxe,{efi_filename}{tftp_str}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_filename64(&mut self, filename64: &str) {
|
# Provide ipxe boot script to ipxe clients
|
||||||
todo!()
|
dhcp-boot=tag:ipxe,{ipxe_filename}{tftp_str}
|
||||||
}
|
|
||||||
|
|
||||||
pub fn set_filenameipxe(&mut self, filenameipxe: &str) {
|
# Provide undionly to legacy bios clients
|
||||||
todo!()
|
dhcp-boot=tag:bios,{bios_filename}{tftp_str}
|
||||||
|
"
|
||||||
|
);
|
||||||
|
info!("Writing configuration file to {DNS_MASQ_PXE_CONFIG_FILE}");
|
||||||
|
debug!("Content:\n{config}");
|
||||||
|
self.opnsense_shell
|
||||||
|
.write_content_to_file(&config, DNS_MASQ_PXE_CONFIG_FILE)
|
||||||
|
.await
|
||||||
|
.map_err(|e| {
|
||||||
|
DhcpError::Configuration(format!(
|
||||||
|
"Could not configure pxe for dhcp because of : {e}"
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
|
||||||
|
info!("Restarting dnsmasq to apply changes");
|
||||||
|
self.opnsense_shell.exec("configctl dnsmasq restart").await
|
||||||
|
.map_err(|e| {
|
||||||
|
DhcpError::Configuration(format!(
|
||||||
|
"Restarting dnsmasq failed : {e}"
|
||||||
|
))
|
||||||
|
})?;
|
||||||
|
Ok(())
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@ -0,0 +1,896 @@
|
|||||||
|
<?xml version="1.0"?>
|
||||||
|
<opnsense>
|
||||||
|
<theme>opnsense</theme>
|
||||||
|
<sysctl>
|
||||||
|
<item/>
|
||||||
|
</sysctl>
|
||||||
|
<system>
|
||||||
|
<serialspeed>115200</serialspeed>
|
||||||
|
<primaryconsole>serial</primaryconsole>
|
||||||
|
<optimization>normal</optimization>
|
||||||
|
<hostname>OPNsense</hostname>
|
||||||
|
<domain>testpxe.harmony.mcd</domain>
|
||||||
|
<group>
|
||||||
|
<name>admins</name>
|
||||||
|
<description>System Administrators</description>
|
||||||
|
<scope>system</scope>
|
||||||
|
<gid>1999</gid>
|
||||||
|
<member>0</member>
|
||||||
|
<priv>page-all</priv>
|
||||||
|
<source_networks/>
|
||||||
|
</group>
|
||||||
|
<user>
|
||||||
|
<name>root</name>
|
||||||
|
<descr>System Administrator</descr>
|
||||||
|
<scope>system</scope>
|
||||||
|
<password>$2y$10$YRVoF4SgskIsrXOvOQjGieB9XqHPRra9R7d80B3BZdbY/j21TwBfS</password>
|
||||||
|
<pwd_changed_at/>
|
||||||
|
<uid>0</uid>
|
||||||
|
<disabled>0</disabled>
|
||||||
|
<landing_page/>
|
||||||
|
<comment/>
|
||||||
|
<email/>
|
||||||
|
<apikeys/>
|
||||||
|
<priv/>
|
||||||
|
<language/>
|
||||||
|
<expires/>
|
||||||
|
<authorizedkeys/>
|
||||||
|
<dashboard/>
|
||||||
|
<otp_seed/>
|
||||||
|
<shell/>
|
||||||
|
</user>
|
||||||
|
<timezone>Etc/UTC</timezone>
|
||||||
|
<timeservers>0.opnsense.pool.ntp.org 1.opnsense.pool.ntp.org 2.opnsense.pool.ntp.org 3.opnsense.pool.ntp.org</timeservers>
|
||||||
|
<webgui>
|
||||||
|
<protocol>https</protocol>
|
||||||
|
<ssl-certref>68a72b6f7f776</ssl-certref>
|
||||||
|
<port/>
|
||||||
|
<ssl-ciphers/>
|
||||||
|
<interfaces/>
|
||||||
|
<compression/>
|
||||||
|
</webgui>
|
||||||
|
<usevirtualterminal>1</usevirtualterminal>
|
||||||
|
<disablenatreflection>yes</disablenatreflection>
|
||||||
|
<disableconsolemenu>1</disableconsolemenu>
|
||||||
|
<disablevlanhwfilter>1</disablevlanhwfilter>
|
||||||
|
<disablechecksumoffloading>1</disablechecksumoffloading>
|
||||||
|
<disablesegmentationoffloading>1</disablesegmentationoffloading>
|
||||||
|
<disablelargereceiveoffloading>1</disablelargereceiveoffloading>
|
||||||
|
<ipv6allow>1</ipv6allow>
|
||||||
|
<powerd_ac_mode>hadp</powerd_ac_mode>
|
||||||
|
<powerd_battery_mode>hadp</powerd_battery_mode>
|
||||||
|
<powerd_normal_mode>hadp</powerd_normal_mode>
|
||||||
|
<bogons>
|
||||||
|
<interval>monthly</interval>
|
||||||
|
</bogons>
|
||||||
|
<pf_share_forward>1</pf_share_forward>
|
||||||
|
<lb_use_sticky>1</lb_use_sticky>
|
||||||
|
<ssh>
|
||||||
|
<group>admins</group>
|
||||||
|
<noauto>1</noauto>
|
||||||
|
<interfaces/>
|
||||||
|
<kex/>
|
||||||
|
<ciphers/>
|
||||||
|
<macs/>
|
||||||
|
<keys/>
|
||||||
|
<enabled>enabled</enabled>
|
||||||
|
<passwordauth>1</passwordauth>
|
||||||
|
<keysig/>
|
||||||
|
<permitrootlogin>1</permitrootlogin>
|
||||||
|
<rekeylimit/>
|
||||||
|
</ssh>
|
||||||
|
<rrdbackup>-1</rrdbackup>
|
||||||
|
<netflowbackup>-1</netflowbackup>
|
||||||
|
<firmware version="1.0.1">
|
||||||
|
<mirror/>
|
||||||
|
<flavour/>
|
||||||
|
<plugins>os-tftp</plugins>
|
||||||
|
<type/>
|
||||||
|
<subscription/>
|
||||||
|
<reboot>0</reboot>
|
||||||
|
</firmware>
|
||||||
|
<language>en_US</language>
|
||||||
|
<dnsserver/>
|
||||||
|
<dnsallowoverride>1</dnsallowoverride>
|
||||||
|
<dnsallowoverride_exclude/>
|
||||||
|
</system>
|
||||||
|
<interfaces>
|
||||||
|
<wan>
|
||||||
|
<if>vtnet0</if>
|
||||||
|
<mtu/>
|
||||||
|
<enable>1</enable>
|
||||||
|
<spoofmac/>
|
||||||
|
<mss/>
|
||||||
|
<ipaddr>dhcp</ipaddr>
|
||||||
|
<dhcphostname/>
|
||||||
|
<blockpriv>0</blockpriv>
|
||||||
|
<blockbogons>1</blockbogons>
|
||||||
|
<subnet/>
|
||||||
|
<ipaddrv6>dhcp6</ipaddrv6>
|
||||||
|
<dhcp6-ia-pd-len>0</dhcp6-ia-pd-len>
|
||||||
|
<gateway/>
|
||||||
|
<media/>
|
||||||
|
<mediaopt/>
|
||||||
|
</wan>
|
||||||
|
<lan>
|
||||||
|
<if>vtnet1</if>
|
||||||
|
<enable>1</enable>
|
||||||
|
<ipaddr>192.168.1.1</ipaddr>
|
||||||
|
<subnet>24</subnet>
|
||||||
|
<ipaddrv6>track6</ipaddrv6>
|
||||||
|
<subnetv6>64</subnetv6>
|
||||||
|
<media/>
|
||||||
|
<mediaopt/>
|
||||||
|
<track6-interface>wan</track6-interface>
|
||||||
|
<track6-prefix-id>0</track6-prefix-id>
|
||||||
|
</lan>
|
||||||
|
<lo0>
|
||||||
|
<internal_dynamic>1</internal_dynamic>
|
||||||
|
<if>lo0</if>
|
||||||
|
<descr>Loopback</descr>
|
||||||
|
<enable>1</enable>
|
||||||
|
<ipaddr>127.0.0.1</ipaddr>
|
||||||
|
<type>none</type>
|
||||||
|
<virtual>1</virtual>
|
||||||
|
<subnet>8</subnet>
|
||||||
|
<ipaddrv6>::1</ipaddrv6>
|
||||||
|
<subnetv6>128</subnetv6>
|
||||||
|
</lo0>
|
||||||
|
</interfaces>
|
||||||
|
<dhcpd/>
|
||||||
|
<snmpd>
|
||||||
|
<syslocation/>
|
||||||
|
<syscontact/>
|
||||||
|
<rocommunity>public</rocommunity>
|
||||||
|
</snmpd>
|
||||||
|
<syslog/>
|
||||||
|
<nat>
|
||||||
|
<outbound>
|
||||||
|
<mode>automatic</mode>
|
||||||
|
</outbound>
|
||||||
|
</nat>
|
||||||
|
<filter>
|
||||||
|
<rule>
|
||||||
|
<type>pass</type>
|
||||||
|
<interface>lan</interface>
|
||||||
|
<ipprotocol>inet</ipprotocol>
|
||||||
|
<descr>Default allow LAN to any rule</descr>
|
||||||
|
<source>
|
||||||
|
<network>lan</network>
|
||||||
|
</source>
|
||||||
|
<destination>
|
||||||
|
<any/>
|
||||||
|
</destination>
|
||||||
|
</rule>
|
||||||
|
<rule>
|
||||||
|
<type>pass</type>
|
||||||
|
<interface>lan</interface>
|
||||||
|
<ipprotocol>inet6</ipprotocol>
|
||||||
|
<descr>Default allow LAN IPv6 to any rule</descr>
|
||||||
|
<source>
|
||||||
|
<network>lan</network>
|
||||||
|
</source>
|
||||||
|
<destination>
|
||||||
|
<any/>
|
||||||
|
</destination>
|
||||||
|
</rule>
|
||||||
|
</filter>
|
||||||
|
<rrd>
|
||||||
|
<enable/>
|
||||||
|
</rrd>
|
||||||
|
<ntpd>
|
||||||
|
<prefer>0.opnsense.pool.ntp.org</prefer>
|
||||||
|
</ntpd>
|
||||||
|
<revision>
|
||||||
|
<username>root@192.168.1.5</username>
|
||||||
|
<description>/api/dnsmasq/settings/set made changes</description>
|
||||||
|
<time>1755800176.40</time>
|
||||||
|
</revision>
|
||||||
|
<OPNsense>
|
||||||
|
<captiveportal version="1.0.4">
|
||||||
|
<zones/>
|
||||||
|
<templates/>
|
||||||
|
</captiveportal>
|
||||||
|
<cron version="1.0.4">
|
||||||
|
<jobs/>
|
||||||
|
</cron>
|
||||||
|
<Netflow version="1.0.1">
|
||||||
|
<capture>
|
||||||
|
<interfaces/>
|
||||||
|
<egress_only/>
|
||||||
|
<version>v9</version>
|
||||||
|
<targets/>
|
||||||
|
</capture>
|
||||||
|
<collect>
|
||||||
|
<enable>0</enable>
|
||||||
|
</collect>
|
||||||
|
<activeTimeout>1800</activeTimeout>
|
||||||
|
<inactiveTimeout>15</inactiveTimeout>
|
||||||
|
</Netflow>
|
||||||
|
<Firewall>
|
||||||
|
<Lvtemplate version="0.0.1">
|
||||||
|
<templates/>
|
||||||
|
</Lvtemplate>
|
||||||
|
<Category version="1.0.0">
|
||||||
|
<categories/>
|
||||||
|
</Category>
|
||||||
|
<Filter version="1.0.4">
|
||||||
|
<rules/>
|
||||||
|
<snatrules/>
|
||||||
|
<npt/>
|
||||||
|
<onetoone/>
|
||||||
|
</Filter>
|
||||||
|
<Alias version="1.0.1">
|
||||||
|
<geoip>
|
||||||
|
<url/>
|
||||||
|
</geoip>
|
||||||
|
<aliases/>
|
||||||
|
</Alias>
|
||||||
|
</Firewall>
|
||||||
|
<IDS version="1.1.0">
|
||||||
|
<rules/>
|
||||||
|
<policies/>
|
||||||
|
<userDefinedRules/>
|
||||||
|
<files/>
|
||||||
|
<fileTags/>
|
||||||
|
<general>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<ips>0</ips>
|
||||||
|
<promisc>0</promisc>
|
||||||
|
<interfaces>wan</interfaces>
|
||||||
|
<homenet>192.168.0.0/16,10.0.0.0/8,172.16.0.0/12</homenet>
|
||||||
|
<defaultPacketSize/>
|
||||||
|
<UpdateCron/>
|
||||||
|
<AlertLogrotate>W0D23</AlertLogrotate>
|
||||||
|
<AlertSaveLogs>4</AlertSaveLogs>
|
||||||
|
<MPMAlgo/>
|
||||||
|
<detect>
|
||||||
|
<Profile/>
|
||||||
|
<toclient_groups/>
|
||||||
|
<toserver_groups/>
|
||||||
|
</detect>
|
||||||
|
<syslog>0</syslog>
|
||||||
|
<syslog_eve>0</syslog_eve>
|
||||||
|
<LogPayload>0</LogPayload>
|
||||||
|
<verbosity/>
|
||||||
|
<eveLog>
|
||||||
|
<http>
|
||||||
|
<enable>0</enable>
|
||||||
|
<extended>0</extended>
|
||||||
|
<dumpAllHeaders/>
|
||||||
|
</http>
|
||||||
|
<tls>
|
||||||
|
<enable>0</enable>
|
||||||
|
<extended>0</extended>
|
||||||
|
<sessionResumption>0</sessionResumption>
|
||||||
|
<custom/>
|
||||||
|
</tls>
|
||||||
|
</eveLog>
|
||||||
|
</general>
|
||||||
|
</IDS>
|
||||||
|
<IPsec version="1.0.4">
|
||||||
|
<general>
|
||||||
|
<enabled/>
|
||||||
|
<preferred_oldsa>0</preferred_oldsa>
|
||||||
|
<disablevpnrules>0</disablevpnrules>
|
||||||
|
<passthrough_networks/>
|
||||||
|
<user_source/>
|
||||||
|
<local_group/>
|
||||||
|
</general>
|
||||||
|
<keyPairs/>
|
||||||
|
<preSharedKeys/>
|
||||||
|
<charon>
|
||||||
|
<max_ikev1_exchanges/>
|
||||||
|
<threads>16</threads>
|
||||||
|
<ikesa_table_size>32</ikesa_table_size>
|
||||||
|
<ikesa_table_segments>4</ikesa_table_segments>
|
||||||
|
<init_limit_half_open>1000</init_limit_half_open>
|
||||||
|
<ignore_acquire_ts>1</ignore_acquire_ts>
|
||||||
|
<install_routes>0</install_routes>
|
||||||
|
<cisco_unity>0</cisco_unity>
|
||||||
|
<make_before_break>0</make_before_break>
|
||||||
|
<retransmit_tries/>
|
||||||
|
<retransmit_timeout/>
|
||||||
|
<retransmit_base/>
|
||||||
|
<retransmit_jitter/>
|
||||||
|
<retransmit_limit/>
|
||||||
|
<syslog>
|
||||||
|
<daemon>
|
||||||
|
<ike_name>1</ike_name>
|
||||||
|
<log_level>0</log_level>
|
||||||
|
<app>1</app>
|
||||||
|
<asn>1</asn>
|
||||||
|
<cfg>1</cfg>
|
||||||
|
<chd>1</chd>
|
||||||
|
<dmn>1</dmn>
|
||||||
|
<enc>1</enc>
|
||||||
|
<esp>1</esp>
|
||||||
|
<ike>1</ike>
|
||||||
|
<imc>1</imc>
|
||||||
|
<imv>1</imv>
|
||||||
|
<job>1</job>
|
||||||
|
<knl>1</knl>
|
||||||
|
<lib>1</lib>
|
||||||
|
<mgr>1</mgr>
|
||||||
|
<net>1</net>
|
||||||
|
<pts>1</pts>
|
||||||
|
<tls>1</tls>
|
||||||
|
<tnc>1</tnc>
|
||||||
|
</daemon>
|
||||||
|
</syslog>
|
||||||
|
<plugins>
|
||||||
|
<attr>
|
||||||
|
<subnet/>
|
||||||
|
<split-include/>
|
||||||
|
<x_28674/>
|
||||||
|
<x_28675/>
|
||||||
|
<x_28672/>
|
||||||
|
<x_28673>0</x_28673>
|
||||||
|
<x_28679/>
|
||||||
|
<dns/>
|
||||||
|
<nbns/>
|
||||||
|
</attr>
|
||||||
|
<eap-radius>
|
||||||
|
<servers/>
|
||||||
|
<accounting>0</accounting>
|
||||||
|
<class_group>0</class_group>
|
||||||
|
</eap-radius>
|
||||||
|
<xauth-pam>
|
||||||
|
<pam_service>ipsec</pam_service>
|
||||||
|
<session>0</session>
|
||||||
|
<trim_email>1</trim_email>
|
||||||
|
</xauth-pam>
|
||||||
|
</plugins>
|
||||||
|
</charon>
|
||||||
|
</IPsec>
|
||||||
|
<Interfaces>
|
||||||
|
<vxlans version="1.0.2"/>
|
||||||
|
<loopbacks version="1.0.0"/>
|
||||||
|
<neighbors version="1.0.0"/>
|
||||||
|
</Interfaces>
|
||||||
|
<Kea>
|
||||||
|
<dhcp4 version="1.0.4" persisted_at="1755786069.95">
|
||||||
|
<general>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<manual_config>0</manual_config>
|
||||||
|
<interfaces/>
|
||||||
|
<valid_lifetime>4000</valid_lifetime>
|
||||||
|
<fwrules>1</fwrules>
|
||||||
|
<dhcp_socket_type>raw</dhcp_socket_type>
|
||||||
|
</general>
|
||||||
|
<ha>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<this_server_name/>
|
||||||
|
<max_unacked_clients>2</max_unacked_clients>
|
||||||
|
</ha>
|
||||||
|
<subnets/>
|
||||||
|
<reservations/>
|
||||||
|
<ha_peers/>
|
||||||
|
</dhcp4>
|
||||||
|
<ctrl_agent version="0.0.1" persisted_at="1755786069.95">
|
||||||
|
<general>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<http_host>127.0.0.1</http_host>
|
||||||
|
<http_port>8000</http_port>
|
||||||
|
</general>
|
||||||
|
</ctrl_agent>
|
||||||
|
<dhcp6 version="1.0.0" persisted_at="1755786069.95">
|
||||||
|
<general>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<manual_config>0</manual_config>
|
||||||
|
<interfaces/>
|
||||||
|
<valid_lifetime>4000</valid_lifetime>
|
||||||
|
<fwrules>1</fwrules>
|
||||||
|
</general>
|
||||||
|
<ha>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<this_server_name/>
|
||||||
|
<max_unacked_clients>2</max_unacked_clients>
|
||||||
|
</ha>
|
||||||
|
<subnets/>
|
||||||
|
<reservations/>
|
||||||
|
<pd_pools/>
|
||||||
|
<ha_peers/>
|
||||||
|
</dhcp6>
|
||||||
|
</Kea>
|
||||||
|
<monit version="1.0.13">
|
||||||
|
<general>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<interval>120</interval>
|
||||||
|
<startdelay>120</startdelay>
|
||||||
|
<mailserver>127.0.0.1</mailserver>
|
||||||
|
<port>25</port>
|
||||||
|
<username/>
|
||||||
|
<password/>
|
||||||
|
<ssl>0</ssl>
|
||||||
|
<sslversion>auto</sslversion>
|
||||||
|
<sslverify>1</sslverify>
|
||||||
|
<logfile/>
|
||||||
|
<statefile/>
|
||||||
|
<eventqueuePath/>
|
||||||
|
<eventqueueSlots/>
|
||||||
|
<httpdEnabled>0</httpdEnabled>
|
||||||
|
<httpdUsername>root</httpdUsername>
|
||||||
|
<httpdPassword/>
|
||||||
|
<httpdPort>2812</httpdPort>
|
||||||
|
<httpdAllow/>
|
||||||
|
<mmonitUrl/>
|
||||||
|
<mmonitTimeout>5</mmonitTimeout>
|
||||||
|
<mmonitRegisterCredentials>1</mmonitRegisterCredentials>
|
||||||
|
</general>
|
||||||
|
<alert uuid="ce8ca7d9-66ab-41d5-acea-598f4803e8ba">
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<recipient>root@localhost.local</recipient>
|
||||||
|
<noton>0</noton>
|
||||||
|
<events/>
|
||||||
|
<format/>
|
||||||
|
<reminder/>
|
||||||
|
<description/>
|
||||||
|
</alert>
|
||||||
|
<service uuid="dc3b9298-4a56-4c45-bd61-be2fdb103383">
|
||||||
|
<enabled>1</enabled>
|
||||||
|
<name>$HOST</name>
|
||||||
|
<description/>
|
||||||
|
<type>system</type>
|
||||||
|
<pidfile/>
|
||||||
|
<match/>
|
||||||
|
<path/>
|
||||||
|
<timeout>300</timeout>
|
||||||
|
<starttimeout>30</starttimeout>
|
||||||
|
<address/>
|
||||||
|
<interface/>
|
||||||
|
<start/>
|
||||||
|
<stop/>
|
||||||
|
<tests>cfed35dc-f74b-417d-9ed9-682c5de96495,f961277a-07f1-49a4-90ee-bb15738d9ebb,30b2cce2-f650-4e44-a3e2-ee53886cda3f,3c86136f-35a4-4126-865b-82732c6542d9</tests>
|
||||||
|
<depends/>
|
||||||
|
<polltime/>
|
||||||
|
</service>
|
||||||
|
<service uuid="b4d5bdb4-206d-4afe-8d86-377ffbbdb2ec">
|
||||||
|
<enabled>1</enabled>
|
||||||
|
<name>RootFs</name>
|
||||||
|
<description/>
|
||||||
|
<type>filesystem</type>
|
||||||
|
<pidfile/>
|
||||||
|
<match/>
|
||||||
|
<path>/</path>
|
||||||
|
<timeout>300</timeout>
|
||||||
|
<starttimeout>30</starttimeout>
|
||||||
|
<address/>
|
||||||
|
<interface/>
|
||||||
|
<start/>
|
||||||
|
<stop/>
|
||||||
|
<tests>fbb8dfe2-b9ad-4730-a0f3-41d7ecda6289</tests>
|
||||||
|
<depends/>
|
||||||
|
<polltime/>
|
||||||
|
</service>
|
||||||
|
<service uuid="f96e3cbb-6c98-4d20-8337-bab717d4ab54">
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<name>carp_status_change</name>
|
||||||
|
<description/>
|
||||||
|
<type>custom</type>
|
||||||
|
<pidfile/>
|
||||||
|
<match/>
|
||||||
|
<path>/usr/local/opnsense/scripts/OPNsense/Monit/carp_status</path>
|
||||||
|
<timeout>300</timeout>
|
||||||
|
<starttimeout>30</starttimeout>
|
||||||
|
<address/>
|
||||||
|
<interface/>
|
||||||
|
<start/>
|
||||||
|
<stop/>
|
||||||
|
<tests>11ceca8a-dff8-45e0-9dc5-ed80dc4b3947</tests>
|
||||||
|
<depends/>
|
||||||
|
<polltime/>
|
||||||
|
</service>
|
||||||
|
<service uuid="69bbd4d5-3a50-42a7-ab64-050450504038">
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<name>gateway_alert</name>
|
||||||
|
<description/>
|
||||||
|
<type>custom</type>
|
||||||
|
<pidfile/>
|
||||||
|
<match/>
|
||||||
|
<path>/usr/local/opnsense/scripts/OPNsense/Monit/gateway_alert</path>
|
||||||
|
<timeout>300</timeout>
|
||||||
|
<starttimeout>30</starttimeout>
|
||||||
|
<address/>
|
||||||
|
<interface/>
|
||||||
|
<start/>
|
||||||
|
<stop/>
|
||||||
|
<tests>fad1f465-4a92-4b93-be66-59d7059b8779</tests>
|
||||||
|
<depends/>
|
||||||
|
<polltime/>
|
||||||
|
</service>
|
||||||
|
<test uuid="2bd5d8c0-6a4a-430b-b953-34214a107ccf">
|
||||||
|
<name>Ping</name>
|
||||||
|
<type>NetworkPing</type>
|
||||||
|
<condition>failed ping</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="0f06ffff-9bfa-463d-b75e-f7195cd8dcab">
|
||||||
|
<name>NetworkLink</name>
|
||||||
|
<type>NetworkInterface</type>
|
||||||
|
<condition>failed link</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="79b119ce-10e0-4a6a-bd1a-b0be371d0fd7">
|
||||||
|
<name>NetworkSaturation</name>
|
||||||
|
<type>NetworkInterface</type>
|
||||||
|
<condition>saturation is greater than 75%</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="cfed35dc-f74b-417d-9ed9-682c5de96495">
|
||||||
|
<name>MemoryUsage</name>
|
||||||
|
<type>SystemResource</type>
|
||||||
|
<condition>memory usage is greater than 75%</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="f961277a-07f1-49a4-90ee-bb15738d9ebb">
|
||||||
|
<name>CPUUsage</name>
|
||||||
|
<type>SystemResource</type>
|
||||||
|
<condition>cpu usage is greater than 75%</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="30b2cce2-f650-4e44-a3e2-ee53886cda3f">
|
||||||
|
<name>LoadAvg1</name>
|
||||||
|
<type>SystemResource</type>
|
||||||
|
<condition>loadavg (1min) is greater than 4</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="3c86136f-35a4-4126-865b-82732c6542d9">
|
||||||
|
<name>LoadAvg5</name>
|
||||||
|
<type>SystemResource</type>
|
||||||
|
<condition>loadavg (5min) is greater than 3</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="27e91c6f-3e8e-4570-bb3a-27f46dd301a7">
|
||||||
|
<name>LoadAvg15</name>
|
||||||
|
<type>SystemResource</type>
|
||||||
|
<condition>loadavg (15min) is greater than 2</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="fbb8dfe2-b9ad-4730-a0f3-41d7ecda6289">
|
||||||
|
<name>SpaceUsage</name>
|
||||||
|
<type>SpaceUsage</type>
|
||||||
|
<condition>space usage is greater than 75%</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="11ceca8a-dff8-45e0-9dc5-ed80dc4b3947">
|
||||||
|
<name>ChangedStatus</name>
|
||||||
|
<type>ProgramStatus</type>
|
||||||
|
<condition>changed status</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
<test uuid="fad1f465-4a92-4b93-be66-59d7059b8779">
|
||||||
|
<name>NonZeroStatus</name>
|
||||||
|
<type>ProgramStatus</type>
|
||||||
|
<condition>status != 0</condition>
|
||||||
|
<action>alert</action>
|
||||||
|
<path/>
|
||||||
|
</test>
|
||||||
|
</monit>
|
||||||
|
<OpenVPNExport version="0.0.1">
|
||||||
|
<servers/>
|
||||||
|
</OpenVPNExport>
|
||||||
|
<Syslog version="1.0.2">
|
||||||
|
<general>
|
||||||
|
<enabled>1</enabled>
|
||||||
|
<loglocal>1</loglocal>
|
||||||
|
<maxpreserve>31</maxpreserve>
|
||||||
|
<maxfilesize/>
|
||||||
|
</general>
|
||||||
|
<destinations/>
|
||||||
|
</Syslog>
|
||||||
|
<TrafficShaper version="1.0.3" persisted_at="1755786069.77">
|
||||||
|
<pipes/>
|
||||||
|
<queues/>
|
||||||
|
<rules/>
|
||||||
|
</TrafficShaper>
|
||||||
|
<unboundplus version="1.0.12">
|
||||||
|
<general>
|
||||||
|
<enabled>1</enabled>
|
||||||
|
<port>53</port>
|
||||||
|
<stats>0</stats>
|
||||||
|
<active_interface/>
|
||||||
|
<dnssec>0</dnssec>
|
||||||
|
<dns64>0</dns64>
|
||||||
|
<dns64prefix/>
|
||||||
|
<noarecords>0</noarecords>
|
||||||
|
<regdhcp>0</regdhcp>
|
||||||
|
<regdhcpdomain/>
|
||||||
|
<regdhcpstatic>0</regdhcpstatic>
|
||||||
|
<noreglladdr6>0</noreglladdr6>
|
||||||
|
<noregrecords>0</noregrecords>
|
||||||
|
<txtsupport>0</txtsupport>
|
||||||
|
<cacheflush>0</cacheflush>
|
||||||
|
<local_zone_type>transparent</local_zone_type>
|
||||||
|
<outgoing_interface/>
|
||||||
|
<enable_wpad>0</enable_wpad>
|
||||||
|
</general>
|
||||||
|
<advanced>
|
||||||
|
<hideidentity>0</hideidentity>
|
||||||
|
<hideversion>0</hideversion>
|
||||||
|
<prefetch>0</prefetch>
|
||||||
|
<prefetchkey>0</prefetchkey>
|
||||||
|
<dnssecstripped>0</dnssecstripped>
|
||||||
|
<aggressivensec>1</aggressivensec>
|
||||||
|
<serveexpired>0</serveexpired>
|
||||||
|
<serveexpiredreplyttl/>
|
||||||
|
<serveexpiredttl/>
|
||||||
|
<serveexpiredttlreset>0</serveexpiredttlreset>
|
||||||
|
<serveexpiredclienttimeout/>
|
||||||
|
<qnameminstrict>0</qnameminstrict>
|
||||||
|
<extendedstatistics>0</extendedstatistics>
|
||||||
|
<logqueries>0</logqueries>
|
||||||
|
<logreplies>0</logreplies>
|
||||||
|
<logtagqueryreply>0</logtagqueryreply>
|
||||||
|
<logservfail>0</logservfail>
|
||||||
|
<loglocalactions>0</loglocalactions>
|
||||||
|
<logverbosity>1</logverbosity>
|
||||||
|
<valloglevel>0</valloglevel>
|
||||||
|
<privatedomain/>
|
||||||
|
<privateaddress>0.0.0.0/8,10.0.0.0/8,100.64.0.0/10,169.254.0.0/16,172.16.0.0/12,192.0.2.0/24,192.168.0.0/16,198.18.0.0/15,198.51.100.0/24,203.0.113.0/24,233.252.0.0/24,::1/128,2001:db8::/32,fc00::/8,fd00::/8,fe80::/10</privateaddress>
|
||||||
|
<insecuredomain/>
|
||||||
|
<msgcachesize/>
|
||||||
|
<rrsetcachesize/>
|
||||||
|
<outgoingnumtcp/>
|
||||||
|
<incomingnumtcp/>
|
||||||
|
<numqueriesperthread/>
|
||||||
|
<outgoingrange/>
|
||||||
|
<jostletimeout/>
|
||||||
|
<discardtimeout/>
|
||||||
|
<cachemaxttl/>
|
||||||
|
<cachemaxnegativettl/>
|
||||||
|
<cacheminttl/>
|
||||||
|
<infrahostttl/>
|
||||||
|
<infrakeepprobing>0</infrakeepprobing>
|
||||||
|
<infracachenumhosts/>
|
||||||
|
<unwantedreplythreshold/>
|
||||||
|
</advanced>
|
||||||
|
<acls>
|
||||||
|
<default_action>allow</default_action>
|
||||||
|
</acls>
|
||||||
|
<dnsbl>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
<safesearch>0</safesearch>
|
||||||
|
<type/>
|
||||||
|
<lists/>
|
||||||
|
<whitelists/>
|
||||||
|
<blocklists/>
|
||||||
|
<wildcards/>
|
||||||
|
<address/>
|
||||||
|
<nxdomain>0</nxdomain>
|
||||||
|
</dnsbl>
|
||||||
|
<forwarding>
|
||||||
|
<enabled>0</enabled>
|
||||||
|
</forwarding>
|
||||||
|
<dots/>
|
||||||
|
<hosts/>
|
||||||
|
<aliases/>
|
||||||
|
</unboundplus>
|
||||||
|
<DHCRelay version="1.0.1" persisted_at="1755786069.97"/>
|
||||||
|
<trust>
|
||||||
|
<general version="1.0.1" persisted_at="1755786070.08">
|
||||||
|
<store_intermediate_certs>0</store_intermediate_certs>
|
||||||
|
<install_crls>0</install_crls>
|
||||||
|
<fetch_crls>0</fetch_crls>
|
||||||
|
<enable_legacy_sect>1</enable_legacy_sect>
|
||||||
|
<enable_config_constraints>0</enable_config_constraints>
|
||||||
|
<CipherString/>
|
||||||
|
<Ciphersuites/>
|
||||||
|
<SignatureAlgorithms/>
|
||||||
|
<groups/>
|
||||||
|
<MinProtocol/>
|
||||||
|
<MinProtocol_DTLS/>
|
||||||
|
</general>
|
||||||
|
</trust>
|
||||||
|
<tftp>
|
||||||
|
<general version="0.0.1">
|
||||||
|
<enabled>1</enabled>
|
||||||
|
<listen>192.168.1.1</listen>
|
||||||
|
</general>
|
||||||
|
</tftp>
|
||||||
|
<wireguard>
|
||||||
|
<general version="0.0.1">
|
||||||
|
<enabled>0</enabled>
|
||||||
|
</general>
|
||||||
|
<server version="1.0.0">
|
||||||
|
<servers/>
|
||||||
|
</server>
|
||||||
|
<client version="1.0.0">
|
||||||
|
<clients/>
|
||||||
|
</client>
|
||||||
|
</wireguard>
|
||||||
|
<Swanctl version="1.0.0">
|
||||||
|
<Connections/>
|
||||||
|
<locals/>
|
||||||
|
<remotes/>
|
||||||
|
<children/>
|
||||||
|
<Pools/>
|
||||||
|
<VTIs/>
|
||||||
|
<SPDs/>
|
||||||
|
</Swanctl>
|
||||||
|
<OpenVPN version="1.0.1">
|
||||||
|
<Overwrites/>
|
||||||
|
<Instances/>
|
||||||
|
<StaticKeys/>
|
||||||
|
</OpenVPN>
|
||||||
|
<Gateways version="1.0.0" persisted_at="1755786217.76"/>
|
||||||
|
</OPNsense>
|
||||||
|
<staticroutes version="1.0.0"/>
|
||||||
|
<ca/>
|
||||||
|
<cert>
|
||||||
|
<refid>68a72b6f7f776</refid>
|
||||||
|
<descr>Web GUI TLS certificate</descr>
|
||||||
|
<crt>LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tCk1JSUhFakNDQlBxZ0F3SUJBZ0lVUkZqWUQ0Z1U0bzRNZGdiN2pIc29KNU9GVGFnd0RRWUpLb1pJaHZjTkFRRUwKQlFBd2dZWXhHakFZQmdOVkJBTU1FVTlRVG5ObGJuTmxMbWx1ZEdWeWJtRnNNUXN3Q1FZRFZRUUdFd0pPVERFVgpNQk1HQTFVRUNBd01XblZwWkMxSWIyeHNZVzVrTVJVd0V3WURWUVFIREF4TmFXUmtaV3hvWVhKdWFYTXhMVEFyCkJnTlZCQW9NSkU5UVRuTmxibk5sSUhObGJHWXRjMmxuYm1Wa0lIZGxZaUJqWlhKMGFXWnBZMkYwWlRBZUZ3MHkKTlRBNE1qRXhOREl4TXpaYUZ3MHlOakE1TWpJeE5ESXhNelphTUlHR01Sb3dHQVlEVlFRRERCRlBVRTV6Wlc1egpaUzVwYm5SbGNtNWhiREVMTUFrR0ExVUVCaE1DVGt3eEZUQVRCZ05WQkFnTURGcDFhV1F0U0c5c2JHRnVaREVWCk1CTUdBMVVFQnd3TVRXbGtaR1ZzYUdGeWJtbHpNUzB3S3dZRFZRUUtEQ1JQVUU1elpXNXpaU0J6Wld4bUxYTnAKWjI1bFpDQjNaV0lnWTJWeWRHbG1hV05oZEdVd2dnSWlNQTBHQ1NxR1NJYjNEUUVCQVFVQUE0SUNEd0F3Z2dJSwpBb0lDQVFDbENkeFJ3ZWJQQkxvYlVORnYvL2t3TEdKWExweDl6OFFHV2lyWTNpamVDeUxDQ0FwczBLaE1adTNRClhkczMranppbDRnSE96L0hvUEo5Z0xxMy9FYnR4cE9ENWkvQzZwbXc3SGM1M2tTQ3JCK2tlWUFnVWZ1aDU3MzAKZyt3cGc5RDQzaHFBNzF1L3F0ZC95eitnTVJnTWdZMndEK3ZWQWRrdGxVSWlmN2piTmR1RDRGMmdkL0gwbzljWApEUm5zMzNNQVptTkZwajN4QWFwQi9RWnhKV1JMZ1J5K1A5MWcyZEZFNzhNaWY4ZTRNSCtrU29ndzIwVG1JbmpzCitKdEVTc0xQZmx2eUZUa0lkTVdFbURWOG1HUk5hNXVoYXlEbVNEUU9xV0NUTlZHV3ZVWjZTRnJRZ1Q1MDBEdXgKWnRtYlhGdEVqRzlIaGd5SW5QT0dKbWYzTWVzS3dYclVNMW1BenVCRVBFR0lwOTc3UTY2SitpTDYzWTUvTTB3aAphMGVVNGppNTVRQnJOQjlaWjJsa080bGU2TXdmZm50c29JakMrVDh5RW5tbW5nQTlTdWNPRW9CcFFhd3cvRGhOCmtSNGk4TUptR1JNdmpLazlHVzZ3Z2VNVThJVDhKZDRjTmJOVzdFSGpzV08xN1luTVhIMEUxOVZqa2d1R3dIODAKZ3ZROGtzTmV4WVA3WWo0b0VycnRKbWVhWU8wbFVkV0tGektNdS8va0UvNG5HK0h4emlRUnA5QmdyTURNYks4ZgpkM29mY2tqZFZTTW9Vc1FJaWlmdTFMK1I4V1Y3K3hsTzdTWS80dGk3Y28zcjNXRTYyVlE4Vk9QMVphcStWRFpvClNIMVRCa0lTSU5paVJFRzhZSDQvRHJwNWZ2dHBPcERBRGN1TGdDNDJHcExmS1pwVEtRSURBUUFCbzRJQmREQ0MKQVhBd0NRWURWUjBUQkFJd0FEQVJCZ2xnaGtnQmh2aENBUUVFQkFNQ0JrQXdOQVlKWUlaSUFZYjRRZ0VOQkNjVwpKVTlRVG5ObGJuTmxJRWRsYm1WeVlYUmxaQ0JUWlhKMlpYSWdRMlZ5ZEdsbWFXTmhkR1V3SFFZRFZSME9CQllFCkZIdUVQK05yYlorZWdMdWZVSUFKaUo2M1c4SDFNSUd3QmdOVkhTTUVnYWd3Z2FXaGdZeWtnWWt3Z1lZeEdqQVkKQmdOVkJBTU1FVTlRVG5ObGJuTmxMbWx1ZEdWeWJtRnNNUXN3Q1FZRFZRUUdFd0pPVERFVk1CTUdBMVVFQ0F3TQpXblZwWkMxSWIyeHNZVzVrTVJVd0V3WURWUVFIREF4TmFXUmtaV3hvWVhKdWFYTXhMVEFyQmdOVkJBb01KRTlRClRuTmxibk5sSUhObGJHWXRjMmxuYm1Wa0lIZGxZaUJqWlhKMGFXWnBZMkYwWllJVVJGallENGdVNG80TWRnYjcKakhzb0o1T0ZUYWd3SFFZRFZSMGxCQll3RkFZSUt3WUJCUVVIQXdFR0NDc0dBUVVGQ0FJQ01Bc0dBMVVkRHdRRQpBd0lGb0RBY0JnTlZIUkVFRlRBVGdoRlBVRTV6Wlc1elpTNXBiblJsY201aGJEQU5CZ2txaGtpRzl3MEJBUXNGCkFBT0NBZ0VBV2JzM2MwSXYwcEd3Y0wvUmRlbnBiZVJHQ3FsODY0V1ZITEtMZzJIR3BkKytJdmRFcHJEZkZ3SCsKdHdOd2VrZTlXUEtYa20vUkZDWE5DQmVLNjkxeURVWCtCNUJOMjMvSks5N1lzRVdtMURIV3FvSDE1WmdqelZ0QQp2d2JmbnRQdlhCWU1wV2ZQY0Zua0hjN3pxUjI3RzBEZHFUeGg2TjhFenV1S3JRWXFtaWhJUXFkNU9HRVhteW9ZCmdPVjdoZ0lWSUR6a1Z0QkRiS3dFV3VFN2pKYzViMXR4Mk1FUFRsVklEZGo0Zm5vdURWemdkczA2RER4aFM4eXAKbXJOSXhxb045ekEzYXVtTnRNZ2haSHVZRHdjbm5GSnBNZHlJSEdHZ1dlNnZZNHFtdEFSVDd3a0x6MTZnUG9LMAo5bFhVU0RmV3YwUDJGUXFHZTJjaXQ3VVE2ZGtsUWsrVGVtUEFwNnhEV09HR3oxRkdmUUoxN040b3AvOGtlOUo2Cm96RVp3QTh1aDVYTUl2N3loM2dobjV1d1R6RDUyZ1BBZFdaekEyaHVWV3p5cVM0WVc0N3ZkaGV6TTFTUndabVEKUmYzNDk0UVFydWd0bzdycWdMUlRTSXN4WEtkU21MaHZjT0hsSlhISW1XNTRzeFlXNm9NUStpRExFT29ZVVdpcgp1aUJvT1RsNEJaOG5Xcm9pV0JtWlFLaVRPYlFRczVWTkIwYnVybmRISTJVdmtIRTE3QTM0bFYySjY5Q0dNNzJ2CjQ5aE9TN3B2Tzg4cEVKZm90d01YYlRhdkR2WTBHazZxbERFMVBud1U2Wm8ySEprcFdUTUxOSzh1alZ1RkhlMGkKR2JvZi9va08vZW4rUi9PUXNyd1JYbzFwVTRiWnlyWGVQeUdqSSsrdFYzemhjd0IwWjNJPQotLS0tLUVORCBDRVJUSUZJQ0FURS0tLS0tCg==</crt>
|
||||||
|
<prv>LS0tLS1CRUdJTiBQUklWQVRFIEtFWS0tLS0tCk1JSUpRUUlCQURBTkJna3Foa2lHOXcwQkFRRUZBQVNDQ1Nzd2dna25BZ0VBQW9JQ0FRQ2xDZHhSd2ViUEJMb2IKVU5Gdi8va3dMR0pYTHB4OXo4UUdXaXJZM2lqZUN5TENDQXBzMEtoTVp1M1FYZHMzK2p6aWw0Z0hPei9Ib1BKOQpnTHEzL0VidHhwT0Q1aS9DNnBtdzdIYzUza1NDckIra2VZQWdVZnVoNTczMGcrd3BnOUQ0M2hxQTcxdS9xdGQvCnl6K2dNUmdNZ1kyd0QrdlZBZGt0bFVJaWY3amJOZHVENEYyZ2QvSDBvOWNYRFJuczMzTUFabU5GcGozeEFhcEIKL1FaeEpXUkxnUnkrUDkxZzJkRkU3OE1pZjhlNE1IK2tTb2d3MjBUbUluanMrSnRFU3NMUGZsdnlGVGtJZE1XRQptRFY4bUdSTmE1dWhheURtU0RRT3FXQ1ROVkdXdlVaNlNGclFnVDUwMER1eFp0bWJYRnRFakc5SGhneUluUE9HCkptZjNNZXNLd1hyVU0xbUF6dUJFUEVHSXA5NzdRNjZKK2lMNjNZNS9NMHdoYTBlVTRqaTU1UUJyTkI5WloybGsKTzRsZTZNd2ZmbnRzb0lqQytUOHlFbm1tbmdBOVN1Y09Fb0JwUWF3dy9EaE5rUjRpOE1KbUdSTXZqS2s5R1c2dwpnZU1VOElUOEpkNGNOYk5XN0VIanNXTzE3WW5NWEgwRTE5VmprZ3VHd0g4MGd2UThrc05leFlQN1lqNG9FcnJ0CkptZWFZTzBsVWRXS0Z6S011Ly9rRS80bkcrSHh6aVFScDlCZ3JNRE1iSzhmZDNvZmNramRWU01vVXNRSWlpZnUKMUwrUjhXVjcreGxPN1NZLzR0aTdjbzNyM1dFNjJWUThWT1AxWmFxK1ZEWm9TSDFUQmtJU0lOaWlSRUc4WUg0LwpEcnA1ZnZ0cE9wREFEY3VMZ0M0MkdwTGZLWnBUS1FJREFRQUJBb0lDQUFTSHc4Tit4aDR5ckFVcDc4WGFTZlhYCmtnK0FtUTBmRWV0MnVDeGgxTTlia09Xd29OQ2gzYXpUT24zNHhaYkF5TUVUbGNsVkNBZ3IwOXc4RjJRTGljcm4KSTQrQVZ4bExwVkprKzFUY1ZCY2VNSFFzWGFjRmVSblZxYkkzbU5qKzVGS2dqaXV4NWx2WmpiYlZWbmJJUWplOQpxcTBGa3R5ekEwb3NDYmUydDlWVW9pVDVtTGhaOG90Ym9BRGkvQzR6YUEyL3djUGNyMkNaUWhvem51U21PUjJWCmVydUNOMHA4VURGTFA1a0gxdXlvY0NpTFh6ZXdIVEVRQ3krK0YwMEZuRmxqeDVSYW5za3JvMnhqWFR5QlZtZUYKcDYwRHF0Q0hkTjVlS2VlQWxDL0dIRlFvL2swdzd3ejMxbHVsVGgza3FDQzJsaXRwYzVpZ2JsTGxaUDgxSUpXTQp0bkhlczNsTXk1RGNDWUx3L3huZFdmVDZFMTB4WlhFNWI0QTdxYjF4Yjhsd1FoNHFJckhDZ2p1NDVPYXNCMERJClBYZ3E2eWkwL2FKWXV6SU5kcjRTeFRibExGUkp6MXlQaGZTZDVGbjdWQVBYU1JNTDlDbzJrL0M1SDlwdG1HMjYKZHBLQVNib1ZMcStrbXg3anVKYXc0a1JNNHZmYndHZGNMZEhqMXByZ08xNkd1ckpQOVRRQ0x5YzhaR0xOekcvaApIMzBpU2FlclJOUmtDRlhmeTEzWWJJZTZHTE12KzVmODlYSENGNmZrZ1JkZjVrbTA3cEc3SCtMZytmZFdtd2lZCm0waExNSFVZeHJ3WkFma2tvZjhlSllscEVQVmQ3ZytCVjd2eTZhYW0yQituUTdHYk84WUprSnlJME04amlSaDEKeGdjRmFZaGZlT21RZGtVbi9BcUJBb0lCQVFEU1JZbDl0SnJyQk5UOXlZN0twWTJiOGVURFJqdDByU1NQRUJvNgppeWoyVWR5S1ZSbHFFdzRma2IrejV3WWt2bnBpMW1uS3NjNFlLZmoyaDVSdXVDbzVzTUNLbmpDUXBpbll4bWRFCk45Z3l6SWRYMmlzRUh6dXNSZkZiajBVSWU1dHc0TE9pL3cyVzFYWGJUc3liOFdhTmhkbVQ4TGxDNjQ5WkNNUWQKeDZkeTdOWS9uYnVWVVQ0KzM3WmV0VlR1eDg1ekl5OTdnMWp4dFZhaXZrd2hQVWtLcWpXWDYzaUZidjFuY1FVdgpiQURrWkFoOXRWYWV2UGZ2NURDeDZITldiVFlObjVRZWd3OTRyVndoSjhYb1V5ZDRqWFB0VmdXU2VkN0tWd2U5CmNkNW9CZWFBOVhDdnJxdkNIRjI4QXg2OUI2YWQrQlk1S0dVcGU2LythQnlKdlQwUkFvSUJBUURJN2c3c0dMc3AKVWJ4dGhJQm9yRzF5MDRKWWlnaE5VMlF4YjdzSkxocnRTc2NtRkxSZU5DYy8zOTBCV3ZrbVFIazFnZkpxV3hDLwp2R0VMT0Iwd3U5VFBBRWFsS25IZ2RhNkFTMURuM3NTWTltcFBRRjYvbEY2cm00cDlNUU1TTFo1V3ZsL0ZNRklHCjUvaXVSVjJaOVdkeTV4QVFWNG5uZmdMOWJDNzhPa2k3VnFPTDJDZk0vcEJEMHdzRUZmOGZiejFSZXo4dEFRZ2QKVXY4cEpFTWdDTCtQeEdkdG5DYUcxYm5obXhEUUxiWmQ4TTFOQkpKOWZLZFgzVWtLcTlDdmFJVXBIZlduSFBWVAprVWNwMUVTYnEzOFVhTzFSS1NBNUtQd1ZiNkVPVGJBSGtlaEN4ZVhpN2F3YkZwYXlTelpIaWl4Y05QQjk1YUtSCkpJQ0J5ekFwQTVTWkFvSUJBRlZKYXlrWGxqWjVNVUwyKy9ucUNIUVdPeW1SVlJCUUlpSDg4QWFLNTBSeGs3aHcKSit6RWFkZ1lMOTl5ZHlWME5RUGQzKzhkQzNEMXBVdXBWbVZLUWFaQXNQZ0lqYjQrQjM4cmlqczdRMi9uVVlZcQpzWVBzZnpHeTlPQ2tUZVhRN1ExdHRxOElNS1RiVkFCdUI4UEF1RTN5Mm51TkNqZkFmOVluSGhUT0pIY1M1UnZNCmlJZForcHRaOWdpWUdDajUxaDBSU25NWXBYejBobjFnSGxUbEhMazhySnhBSUJSUEhtMVVoRHZsM0w3R2JFTkEKeUM5K2lqbzlIaHNySTQwTW92NEhtZlorUmtvMlZzWUQ4ZHYzem15eFF6SWkwQVBIZHJ3dmJLNUVmMmRGN1dhbApKdDI3UldOb1NnUzJaME5ZMVJZQnlGSEt0cTJLdzZtMjVNeGhlMkVDZ2dFQVhSNFdSRXhoMEpCVXB0eVZOZTFTCis3Z1IzRDU4QW5uM0lRSUt5QUpaOEVhTGJKYUQwSFNUREFNUFJTV0grYlkvZGhDMjY1c3djK3MxZmlHUFJacUcKMFRmcmhYZmFOby9UUXhta2NSRElRNnRQTVZNL2xjR0k3amF6UTdtSEZ0R1ZZOVh1UkZCVWMyYmwxTDNJMXlUbgp3RlJkR1hXNEwxUXl4b2R3YnV3RDhPNEI5VGxEbUxrUTJwM2ZxUkVZbnRUS3NneFFCdWRIZjIrTFdPRzVTZ3RECjI3akZ4Z0pyeUdrY0wvWFJJT2xPYnRLK0VrZGdMRStzcmdlYlpocWlKK2hrYmQyNGpxM1k4OVdNQ1ZLYVNScDkKVmxRYVIxYXIzRkdtSWJrT0JyYnlNVS9wTjZqSEZSZllmdVZGQ1hQWnYrWEZFU1pubmJEaVdpbDBkTEpacTJoQgpZUUtDQVFBOVlTcE1wS3dhVGwrTmhTZlovMXU0NjZiMkpZcmJPYlRJM2VCZUowMnFwNXdQTjZYUHJ5aVZaZ1FXClh5cG04a3M5MEJIblBPNUczNFJnKzhLRFlONU1Ed1hBclJubDdSeTEySG5oV3lSaHNKYmdZOEh1c2d4SEROMU8KMEcwSFBpVWtIbTYydlRNYll6bkhPeE5sS1hFdFhBcTlZM3dQYkFjb01rRXZ0MzEwdEdLSUNtdTdEWkpXRlVvTAp1Y3RVS3Boc0V5VWdHbHIwRjJKekVoQWdMRXplczB0S1JpRWdlaFdnbXdlMEhlTEhCdW5oRFBTMmFJY2lCME1pCjY2SGc3cVZyMDlneXpFeGxrY3RLRzhsSm9WbU8vdlhucWQrWDB5M21YTUVZbkFIWHpIeG1Pd2JCNnF3Y3VWTlEKZytqRXliUWF3d3A2OC9id0JncFREQUhORGxrRQotLS0tLUVORCBQUklWQVRFIEtFWS0tLS0tCg==</prv>
|
||||||
|
</cert>
|
||||||
|
<dhcpdv6/>
|
||||||
|
<virtualip version="1.0.1">
|
||||||
|
<vip/>
|
||||||
|
</virtualip>
|
||||||
|
<openvpn/>
|
||||||
|
<ppps>
|
||||||
|
<ppp/>
|
||||||
|
</ppps>
|
||||||
|
<vlans version="1.0.0">
|
||||||
|
<vlan/>
|
||||||
|
</vlans>
|
||||||
|
<bridges>
|
||||||
|
<bridged/>
|
||||||
|
</bridges>
|
||||||
|
<gifs version="1.0.0">
|
||||||
|
<gif/>
|
||||||
|
</gifs>
|
||||||
|
<gres version="1.0.0">
|
||||||
|
<gre/>
|
||||||
|
</gres>
|
||||||
|
<laggs version="1.0.0">
|
||||||
|
<lagg/>
|
||||||
|
</laggs>
|
||||||
|
<wireless>
|
||||||
|
<clone/>
|
||||||
|
</wireless>
|
||||||
|
<hasync version="1.0.2">
|
||||||
|
<pfsyncinterface/>
|
||||||
|
<synchronizetoip/>
|
||||||
|
<verifypeer>0</verifypeer>
|
||||||
|
<username/>
|
||||||
|
<password/>
|
||||||
|
<disablepreempt>0</disablepreempt>
|
||||||
|
<disconnectppps>0</disconnectppps>
|
||||||
|
<pfsyncpeerip/>
|
||||||
|
<pfsyncversion>1400</pfsyncversion>
|
||||||
|
<syncitems/>
|
||||||
|
</hasync>
|
||||||
|
<ifgroups version="1.0.0"/>
|
||||||
|
<dnsmasq version="1.0.7" persisted_at="1755800176.40">
|
||||||
|
<enable>1</enable>
|
||||||
|
<regdhcp>0</regdhcp>
|
||||||
|
<regdhcpstatic>0</regdhcpstatic>
|
||||||
|
<dhcpfirst>0</dhcpfirst>
|
||||||
|
<strict_order>0</strict_order>
|
||||||
|
<domain_needed>0</domain_needed>
|
||||||
|
<no_private_reverse>0</no_private_reverse>
|
||||||
|
<no_resolv>0</no_resolv>
|
||||||
|
<log_queries>0</log_queries>
|
||||||
|
<no_hosts>0</no_hosts>
|
||||||
|
<strictbind>0</strictbind>
|
||||||
|
<dnssec>0</dnssec>
|
||||||
|
<regdhcpdomain/>
|
||||||
|
<interface>lan</interface>
|
||||||
|
<port>0</port>
|
||||||
|
<dns_forward_max/>
|
||||||
|
<cache_size/>
|
||||||
|
<local_ttl/>
|
||||||
|
<add_mac/>
|
||||||
|
<add_subnet>0</add_subnet>
|
||||||
|
<strip_subnet>0</strip_subnet>
|
||||||
|
<dhcp>
|
||||||
|
<no_interface/>
|
||||||
|
<fqdn>1</fqdn>
|
||||||
|
<domain/>
|
||||||
|
<lease_max/>
|
||||||
|
<authoritative>0</authoritative>
|
||||||
|
<default_fw_rules>1</default_fw_rules>
|
||||||
|
<reply_delay/>
|
||||||
|
<enable_ra>0</enable_ra>
|
||||||
|
<nosync>0</nosync>
|
||||||
|
</dhcp>
|
||||||
|
<no_ident>1</no_ident>
|
||||||
|
<dhcp_tags uuid="8d190cf3-8d2d-47db-ab9b-fa21016b533e">
|
||||||
|
<tag>ipxe</tag>
|
||||||
|
</dhcp_tags>
|
||||||
|
<dhcp_tags uuid="0b2982da-198c-4ca4-9a3e-95813667047c">
|
||||||
|
<tag>pxeEfi</tag>
|
||||||
|
</dhcp_tags>
|
||||||
|
<dhcp_tags uuid="993e079f-09b9-4a0f-a70f-8898872b9983">
|
||||||
|
<tag>pxeBios</tag>
|
||||||
|
</dhcp_tags>
|
||||||
|
<dhcp_ranges uuid="843574fc-4c3f-4f81-9e86-56be45f4ba49">
|
||||||
|
<interface>lan</interface>
|
||||||
|
<set_tag/>
|
||||||
|
<start_addr>192.168.1.41</start_addr>
|
||||||
|
<end_addr>192.168.1.245</end_addr>
|
||||||
|
<subnet_mask/>
|
||||||
|
<constructor/>
|
||||||
|
<mode/>
|
||||||
|
<prefix_len/>
|
||||||
|
<lease_time/>
|
||||||
|
<domain_type>range</domain_type>
|
||||||
|
<domain/>
|
||||||
|
<nosync>0</nosync>
|
||||||
|
<ra_mode/>
|
||||||
|
<ra_priority/>
|
||||||
|
<ra_mtu/>
|
||||||
|
<ra_interval/>
|
||||||
|
<ra_router_lifetime/>
|
||||||
|
<description/>
|
||||||
|
</dhcp_ranges>
|
||||||
|
<dhcp_options uuid="1e8d6f0f-7c2c-4873-8960-95a5c9447318">
|
||||||
|
<type>match</type>
|
||||||
|
<option>77</option>
|
||||||
|
<option6/>
|
||||||
|
<interface/>
|
||||||
|
<tag/>
|
||||||
|
<set_tag>8d190cf3-8d2d-47db-ab9b-fa21016b533e</set_tag>
|
||||||
|
<value>iPXE</value>
|
||||||
|
<force/>
|
||||||
|
<description/>
|
||||||
|
</dhcp_options>
|
||||||
|
<dhcp_options uuid="9b54181b-aa68-4fd6-9d59-10a77c291fcb">
|
||||||
|
<type>match</type>
|
||||||
|
<option>93</option>
|
||||||
|
<option6/>
|
||||||
|
<interface/>
|
||||||
|
<tag/>
|
||||||
|
<set_tag>993e079f-09b9-4a0f-a70f-8898872b9983</set_tag>
|
||||||
|
<value>0</value>
|
||||||
|
<force/>
|
||||||
|
<description/>
|
||||||
|
</dhcp_options>
|
||||||
|
<dhcp_options uuid="26402b93-91bb-48a9-92da-b567a91ed4d8">
|
||||||
|
<type>match</type>
|
||||||
|
<option>93</option>
|
||||||
|
<option6/>
|
||||||
|
<interface/>
|
||||||
|
<tag/>
|
||||||
|
<set_tag>0b2982da-198c-4ca4-9a3e-95813667047c</set_tag>
|
||||||
|
<value>7</value>
|
||||||
|
<force/>
|
||||||
|
<description/>
|
||||||
|
</dhcp_options>
|
||||||
|
<dhcp_boot uuid="57436655-6f95-4590-bcdc-dfe542347560">
|
||||||
|
<interface/>
|
||||||
|
<tag>0b2982da-198c-4ca4-9a3e-95813667047c</tag>
|
||||||
|
<filename>ipxe.efi</filename>
|
||||||
|
<servername>192.168.1.1</servername>
|
||||||
|
<address>192.168.1.1</address>
|
||||||
|
<description/>
|
||||||
|
</dhcp_boot>
|
||||||
|
<dhcp_boot uuid="dcc00bf2-5148-40ef-9f79-1f17bf572f6c">
|
||||||
|
<interface/>
|
||||||
|
<tag>8d190cf3-8d2d-47db-ab9b-fa21016b533e</tag>
|
||||||
|
<filename>http://192.168.1.1:8080/boot.ipxe</filename>
|
||||||
|
<servername>192.168.1.1</servername>
|
||||||
|
<address>192.168.1.1</address>
|
||||||
|
<description/>
|
||||||
|
</dhcp_boot>
|
||||||
|
<dhcp_boot uuid="8b9263a4-d242-4c41-8ff2-6f1af5001c41">
|
||||||
|
<interface/>
|
||||||
|
<tag>993e079f-09b9-4a0f-a70f-8898872b9983</tag>
|
||||||
|
<filename>undionly.kpxe</filename>
|
||||||
|
<servername>192.168.1.1</servername>
|
||||||
|
<address>192.168.1.1</address>
|
||||||
|
<description/>
|
||||||
|
</dhcp_boot>
|
||||||
|
</dnsmasq>
|
||||||
|
</opnsense>
|
||||||
Loading…
Reference in New Issue
Block a user