Parse NW filters XML structure
This commit is contained in:
parent
b4f765d486
commit
3849b0d51d
@ -1,5 +1,7 @@
|
||||
use crate::app_config::AppConfig;
|
||||
use crate::libvirt_lib_structures::{DomainState, DomainXML, NetworkXML, XMLUuid};
|
||||
use crate::libvirt_lib_structures::{
|
||||
DomainState, DomainXML, NetworkFilterXML, NetworkXML, XMLUuid,
|
||||
};
|
||||
use crate::libvirt_rest_structures::*;
|
||||
use actix::{Actor, Context, Handler, Message};
|
||||
use image::ImageOutputFormat;
|
||||
@ -7,6 +9,7 @@ use std::io::Cursor;
|
||||
use virt::connect::Connect;
|
||||
use virt::domain::Domain;
|
||||
use virt::network::Network;
|
||||
use virt::nwfilter::NWFilter;
|
||||
use virt::stream::Stream;
|
||||
use virt::sys;
|
||||
use virt::sys::VIR_DOMAIN_XML_SECURE;
|
||||
@ -549,3 +552,39 @@ impl Handler<StopNetwork> for LibVirtActor {
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "anyhow::Result<Vec<XMLUuid>>")]
|
||||
pub struct GetNWFiltersListReq;
|
||||
|
||||
impl Handler<GetNWFiltersListReq> for LibVirtActor {
|
||||
type Result = anyhow::Result<Vec<XMLUuid>>;
|
||||
|
||||
fn handle(&mut self, _msg: GetNWFiltersListReq, _ctx: &mut Self::Context) -> Self::Result {
|
||||
log::debug!("Get full list of network filters");
|
||||
let networks = self.m.list_all_nw_filters(0)?;
|
||||
let mut ids = Vec::with_capacity(networks.len());
|
||||
|
||||
for d in networks {
|
||||
ids.push(XMLUuid::parse_from_str(&d.get_uuid_string()?)?);
|
||||
}
|
||||
|
||||
Ok(ids)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Message)]
|
||||
#[rtype(result = "anyhow::Result<NetworkFilterXML>")]
|
||||
pub struct GetNWFilterXMLReq(pub XMLUuid);
|
||||
|
||||
impl Handler<GetNWFilterXMLReq> for LibVirtActor {
|
||||
type Result = anyhow::Result<NetworkFilterXML>;
|
||||
|
||||
fn handle(&mut self, msg: GetNWFilterXMLReq, _ctx: &mut Self::Context) -> Self::Result {
|
||||
log::debug!("Get network filter XML:\n{}", msg.0.as_string());
|
||||
let filter = NWFilter::lookup_by_uuid_string(&self.m, &msg.0.as_string())?;
|
||||
let xml = filter.get_xml_desc(0)?;
|
||||
log::debug!("XML = {}", xml);
|
||||
NetworkFilterXML::parse_xml(xml)
|
||||
}
|
||||
}
|
||||
|
@ -46,3 +46,31 @@ pub const DISK_SIZE_MAX: usize = 1000 * 1000 * 2;
|
||||
|
||||
/// Network mac address default prefix
|
||||
pub const NET_MAC_ADDR_PREFIX: &str = "52:54:00";
|
||||
|
||||
/// Built-in network filter rules
|
||||
pub const BUILTIN_NETWORK_FILTER_RULES: [&str; 24] = [
|
||||
"allow-arp",
|
||||
"allow-dhcp",
|
||||
"allow-dhcp-server",
|
||||
"allow-dhcpv6",
|
||||
"allow-dhcpv6-server",
|
||||
"allow-incoming-ipv4",
|
||||
"allow-incoming-ipv6",
|
||||
"allow-ipv4",
|
||||
"allow-ipv6",
|
||||
"clean-traffic",
|
||||
"clean-traffic-gateway",
|
||||
"no-arp-ip-spoofing",
|
||||
"no-arp-mac-spoofing",
|
||||
"no-arp-spoofing",
|
||||
"no-ip-multicast",
|
||||
"no-ip-spoofing",
|
||||
"no-ipv6-multicast",
|
||||
"no-ipv6-spoofing",
|
||||
"no-mac-broadcast",
|
||||
"no-mac-spoofing",
|
||||
"no-other-l2-traffic",
|
||||
"no-other-rarp-traffic",
|
||||
"qemu-announce-self",
|
||||
"qemu-announce-self-rarp",
|
||||
];
|
||||
|
@ -8,6 +8,7 @@ use std::io::ErrorKind;
|
||||
pub mod auth_controller;
|
||||
pub mod iso_controller;
|
||||
pub mod network_controller;
|
||||
pub mod nwfilter_controller;
|
||||
pub mod server_controller;
|
||||
pub mod static_controller;
|
||||
pub mod vm_controller;
|
||||
|
36
virtweb_backend/src/controllers/nwfilter_controller.rs
Normal file
36
virtweb_backend/src/controllers/nwfilter_controller.rs
Normal file
@ -0,0 +1,36 @@
|
||||
use crate::controllers::{HttpResult, LibVirtReq};
|
||||
use crate::libvirt_lib_structures::XMLUuid;
|
||||
use actix_web::{web, HttpResponse};
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize)]
|
||||
pub struct NetworkFilterID {
|
||||
uid: XMLUuid,
|
||||
}
|
||||
|
||||
/// Get the list of network filters
|
||||
pub async fn list(client: LibVirtReq) -> HttpResult {
|
||||
let networks = match client.get_full_network_filters_list().await {
|
||||
Err(e) => {
|
||||
log::error!("Failed to get the list of network filters! {e}");
|
||||
return Ok(HttpResponse::InternalServerError()
|
||||
.json(format!("Failed to get the list of networks! {e}")));
|
||||
}
|
||||
Ok(l) => l,
|
||||
};
|
||||
|
||||
/*let networks = networks
|
||||
.into_iter()
|
||||
.map(|n| NetworkInfo::from_xml(n).unwrap())
|
||||
.collect::<Vec<_>>();*/
|
||||
// TODO : turn into lib structure
|
||||
println!("{:#?}", networks);
|
||||
|
||||
Ok(HttpResponse::Ok().body(format!("{:#?}", networks)))
|
||||
}
|
||||
|
||||
/// Get the information about a single network filter
|
||||
pub async fn get_single(client: LibVirtReq, req: web::Path<NetworkFilterID>) -> HttpResult {
|
||||
let nwfilter = client.get_single_network_filter(req.uid).await?;
|
||||
// TODO : turn into lib structure
|
||||
Ok(HttpResponse::Ok().body(format!("{:#?}", nwfilter)))
|
||||
}
|
@ -16,6 +16,7 @@ struct StaticConfig {
|
||||
iso_mimetypes: &'static [&'static str],
|
||||
net_mac_prefix: &'static str,
|
||||
constraints: ServerConstraints,
|
||||
builtin_network_rules: &'static [&'static str],
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize)]
|
||||
@ -45,6 +46,7 @@ pub async fn static_config(local_auth: LocalAuthEnabled) -> impl Responder {
|
||||
oidc_auth_enabled: !AppConfig::get().disable_oidc,
|
||||
iso_mimetypes: &constants::ALLOWED_ISO_MIME_TYPES,
|
||||
net_mac_prefix: constants::NET_MAC_ADDR_PREFIX,
|
||||
builtin_network_rules: &constants::BUILTIN_NETWORK_FILTER_RULES,
|
||||
constraints: ServerConstraints {
|
||||
iso_max_size: constants::ISO_MAX_SIZE,
|
||||
|
||||
|
@ -1,6 +1,8 @@
|
||||
use crate::actors::libvirt_actor;
|
||||
use crate::actors::libvirt_actor::LibVirtActor;
|
||||
use crate::libvirt_lib_structures::{DomainState, DomainXML, NetworkXML, XMLUuid};
|
||||
use crate::libvirt_lib_structures::{
|
||||
DomainState, DomainXML, NetworkFilterXML, NetworkXML, XMLUuid,
|
||||
};
|
||||
use crate::libvirt_rest_structures::{HypervisorInfo, NetworkInfo, VMInfo};
|
||||
use actix::Addr;
|
||||
|
||||
@ -165,4 +167,19 @@ impl LibVirtClient {
|
||||
pub async fn stop_network(&self, id: XMLUuid) -> anyhow::Result<()> {
|
||||
self.0.send(libvirt_actor::StopNetwork(id)).await?
|
||||
}
|
||||
|
||||
/// Get the full list of network filters
|
||||
pub async fn get_full_network_filters_list(&self) -> anyhow::Result<Vec<NetworkFilterXML>> {
|
||||
let ids = self.0.send(libvirt_actor::GetNWFiltersListReq).await??;
|
||||
let mut info = Vec::with_capacity(ids.len());
|
||||
for id in ids {
|
||||
info.push(self.get_single_network_filter(id).await?)
|
||||
}
|
||||
Ok(info)
|
||||
}
|
||||
|
||||
/// Get the information about a single domain
|
||||
pub async fn get_single_network_filter(&self, id: XMLUuid) -> anyhow::Result<NetworkFilterXML> {
|
||||
self.0.send(libvirt_actor::GetNWFilterXMLReq(id)).await?
|
||||
}
|
||||
}
|
||||
|
@ -1,3 +1,4 @@
|
||||
use std::fmt::Display;
|
||||
use std::net::{IpAddr, Ipv4Addr};
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Clone, Copy, Debug)]
|
||||
@ -548,3 +549,316 @@ impl NetworkXML {
|
||||
Ok(network_xml)
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "filterref")]
|
||||
pub struct NetworkFilterRefXML {
|
||||
#[serde(rename(serialize = "@filter"))]
|
||||
pub filter: String,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "all")]
|
||||
pub struct NetworkFilterRuleProtocolAll {}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "mac")]
|
||||
pub struct NetworkFilterRuleProtocolMac {
|
||||
#[serde(
|
||||
rename(serialize = "@srcmacaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcmacaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcmacmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcmacmask: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstmacaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstmacaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstmacmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstmacmask: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@comment"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
comment: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "arp")]
|
||||
pub struct NetworkFilterRuleProtocolArp {
|
||||
#[serde(
|
||||
rename(serialize = "@srcmacaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcmacaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcmacmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcmacmask: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstmacaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstmacaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstmacmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstmacmask: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@arpsrcipaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
arpsrcipaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@arpsrcipmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
arpsrcipmask: Option<u8>,
|
||||
#[serde(
|
||||
rename(serialize = "@arpdstipaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
arpdstipaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@arpdstipmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
arpdstipmask: Option<u8>,
|
||||
|
||||
#[serde(
|
||||
rename(serialize = "@comment"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
comment: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "ipvx")]
|
||||
pub struct NetworkFilterRuleProtocolIpvx {
|
||||
#[serde(
|
||||
rename(serialize = "@srcmacaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcmacaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcmacmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcmacmask: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstmacaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstmacaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstmacmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstmacmask: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcipaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcipaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcipmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcipmask: Option<u8>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstipaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstipaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstipmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstipmask: Option<u8>,
|
||||
|
||||
#[serde(
|
||||
rename(serialize = "@comment"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
comment: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "layer4")]
|
||||
pub struct NetworkFilterRuleProtocolLayer4 {
|
||||
#[serde(
|
||||
rename(serialize = "@srcmacaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcmacaddr: Option<String>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcipaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcipaddr: Option<IpAddr>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcipmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcipmask: Option<u8>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstipaddr"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstipaddr: Option<IpAddr>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstipmask"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstipmask: Option<u8>,
|
||||
/// Start of range of source IP address
|
||||
#[serde(
|
||||
rename(serialize = "@srcipfrom"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcipfrom: Option<IpAddr>,
|
||||
/// End of range of source IP address
|
||||
#[serde(
|
||||
rename(serialize = "@srcipto"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcipto: Option<IpAddr>,
|
||||
/// Start of range of destination IP address
|
||||
#[serde(
|
||||
rename(serialize = "@dstipfrom"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstipfrom: Option<IpAddr>,
|
||||
/// End of range of destination IP address
|
||||
#[serde(
|
||||
rename(serialize = "@dstipto"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstipto: Option<IpAddr>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcportstart"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcportstart: Option<u16>,
|
||||
#[serde(
|
||||
rename(serialize = "@srcportend"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
srcportend: Option<u16>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstportstart"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstportstart: Option<u16>,
|
||||
#[serde(
|
||||
rename(serialize = "@dstportend"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
dstportend: Option<u16>,
|
||||
#[serde(rename(serialize = "@state"), skip_serializing_if = "Option::is_none")]
|
||||
state: Option<String>,
|
||||
|
||||
#[serde(
|
||||
rename(serialize = "@comment"),
|
||||
skip_serializing_if = "Option::is_none"
|
||||
)]
|
||||
comment: Option<String>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "rule")]
|
||||
pub struct NetworkFilterRuleXML {
|
||||
#[serde(rename(serialize = "@action"))]
|
||||
pub action: String,
|
||||
#[serde(rename(serialize = "@direction"))]
|
||||
pub direction: String,
|
||||
#[serde(rename(serialize = "@priority"))]
|
||||
pub priority: Option<i32>,
|
||||
|
||||
/// Match all protocols
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub all: Option<NetworkFilterRuleProtocolAll>,
|
||||
|
||||
/// Match mac protocol
|
||||
#[serde(default, rename = "mac", skip_serializing_if = "Vec::is_empty")]
|
||||
pub mac_rules: Vec<NetworkFilterRuleProtocolMac>,
|
||||
|
||||
/// Match arp protocol
|
||||
#[serde(default, rename = "arp", skip_serializing_if = "Vec::is_empty")]
|
||||
pub arp_rules: Vec<NetworkFilterRuleProtocolArp>,
|
||||
|
||||
/// Match IPv4 protocol
|
||||
#[serde(default, rename = "ip", skip_serializing_if = "Vec::is_empty")]
|
||||
pub ipv4_rules: Vec<NetworkFilterRuleProtocolIpvx>,
|
||||
|
||||
/// Match IPv6 protocol
|
||||
#[serde(default, rename = "ipv6", skip_serializing_if = "Vec::is_empty")]
|
||||
pub ipv6_rules: Vec<NetworkFilterRuleProtocolIpvx>,
|
||||
|
||||
/// Match TCP protocol
|
||||
#[serde(default, rename = "tcp", skip_serializing_if = "Vec::is_empty")]
|
||||
pub tcp_rules: Vec<NetworkFilterRuleProtocolLayer4>,
|
||||
|
||||
/// Match UDP protocol
|
||||
#[serde(default, rename = "udp", skip_serializing_if = "Vec::is_empty")]
|
||||
pub udp_rules: Vec<NetworkFilterRuleProtocolLayer4>,
|
||||
|
||||
/// Match SCTP protocol
|
||||
#[serde(default, rename = "sctp", skip_serializing_if = "Vec::is_empty")]
|
||||
pub sctp_rules: Vec<NetworkFilterRuleProtocolLayer4>,
|
||||
}
|
||||
|
||||
#[derive(serde::Serialize, serde::Deserialize, Debug)]
|
||||
#[serde(rename = "filter")]
|
||||
pub struct NetworkFilterXML {
|
||||
#[serde(rename(serialize = "@name"))]
|
||||
pub name: String,
|
||||
#[serde(rename(serialize = "@chain"), default)]
|
||||
pub chain: String,
|
||||
#[serde(
|
||||
skip_serializing_if = "Option::is_none",
|
||||
rename(serialize = "@priority"),
|
||||
default
|
||||
)]
|
||||
pub priority: Option<i32>,
|
||||
#[serde(skip_serializing_if = "Option::is_none")]
|
||||
pub uuid: Option<XMLUuid>,
|
||||
#[serde(default, rename = "filterref", skip_serializing_if = "Vec::is_empty")]
|
||||
pub filterrefs: Vec<NetworkFilterRefXML>,
|
||||
#[serde(default, rename = "rule", skip_serializing_if = "Vec::is_empty")]
|
||||
pub rules: Vec<NetworkFilterRuleXML>,
|
||||
}
|
||||
|
||||
impl NetworkFilterXML {
|
||||
pub fn parse_xml<D: Display>(xml: D) -> anyhow::Result<Self> {
|
||||
let xml = xml.to_string();
|
||||
|
||||
// We need to put all filter refs at the same location
|
||||
let mut filter_refs = Vec::new();
|
||||
let xml = lazy_regex::regex_replace_all!(r#"<filterref.*/>"#, &xml, |r: &str| {
|
||||
filter_refs.push(r.to_string());
|
||||
|
||||
if r.contains('\n') {
|
||||
log::warn!("A filterref contain a new line. This is a symptom of a new unsupported child attribute of <filterref /> object!");
|
||||
}
|
||||
|
||||
""
|
||||
});
|
||||
|
||||
let filter_refs = filter_refs.join("\n");
|
||||
let xml = xml.replace("</filter>", &format!("{filter_refs}</filter>"));
|
||||
log::debug!("Effective NW filter rule parsed: {xml}");
|
||||
|
||||
Ok(serde_xml_rs::from_str(&xml)?)
|
||||
}
|
||||
}
|
||||
|
@ -700,6 +700,144 @@ impl NetworkInfo {
|
||||
}
|
||||
}
|
||||
|
||||
pub enum NetworkFilterChain {
|
||||
Root,
|
||||
Mac,
|
||||
STP,
|
||||
VLAN,
|
||||
ARP,
|
||||
RARP,
|
||||
IPv4,
|
||||
IPv6,
|
||||
}
|
||||
|
||||
/// Network filter definition
|
||||
pub struct NetworkFilter {
|
||||
name: String,
|
||||
chain: Option<NetworkFilterChain>,
|
||||
priority: Option<i32>,
|
||||
uuid: Option<XMLUuid>,
|
||||
/// Referenced filters rules
|
||||
join_rules: Vec<String>,
|
||||
rules: Vec<NetworkFilterRule>,
|
||||
}
|
||||
|
||||
pub enum NetworkFilterAction {
|
||||
/// matching the rule silently discards the packet with no further analysis
|
||||
Drop,
|
||||
/// matching the rule generates an ICMP reject message with no further analysis
|
||||
Reject,
|
||||
/// matching the rule accepts the packet with no further analysis
|
||||
Accept,
|
||||
/// matching the rule passes this filter, but returns control to the calling filter for further
|
||||
/// analysis
|
||||
Return,
|
||||
/// matching the rule goes on to the next rule for further analysis
|
||||
Continue,
|
||||
}
|
||||
|
||||
pub enum NetworkFilterDirection {
|
||||
In,
|
||||
Out,
|
||||
InOut,
|
||||
}
|
||||
|
||||
pub enum Layer4State {
|
||||
NEW,
|
||||
ESTABLISHED,
|
||||
RELATED,
|
||||
INVALID,
|
||||
NONE,
|
||||
}
|
||||
|
||||
pub enum Layer4Type {
|
||||
TCP,
|
||||
UDP,
|
||||
SCTP,
|
||||
ICMP,
|
||||
TCPipv6,
|
||||
UDPipv6,
|
||||
SCTPipv6,
|
||||
ICMPipv6,
|
||||
}
|
||||
|
||||
pub enum NetworkFilterSelector {
|
||||
All,
|
||||
Mac {
|
||||
src_mac_addr: Option<String>,
|
||||
src_mac_mask: Option<String>,
|
||||
dst_mac_addr: Option<String>,
|
||||
dst_mac_mask: Option<String>,
|
||||
comment: Option<String>,
|
||||
},
|
||||
Arp {
|
||||
srcmacaddr: Option<String>,
|
||||
srcmacmask: Option<String>,
|
||||
dstmacaddr: Option<String>,
|
||||
dstmacmask: Option<String>,
|
||||
arpsrcipaddr: Option<IpAddr>,
|
||||
arpsrcipmask: Option<u8>,
|
||||
arpdstipaddr: Option<IpAddr>,
|
||||
arpdstipmask: Option<u8>,
|
||||
comment: Option<String>,
|
||||
},
|
||||
IPv4 {
|
||||
srcmacaddr: Option<String>,
|
||||
srcmacmask: Option<String>,
|
||||
dstmacaddr: Option<String>,
|
||||
dstmacmask: Option<String>,
|
||||
srcipaddr: Option<Ipv4Addr>,
|
||||
srcipmask: Option<u8>,
|
||||
dstipaddr: Option<Ipv4Addr>,
|
||||
dstipmask: Option<u8>,
|
||||
comment: Option<String>,
|
||||
},
|
||||
IPv6 {
|
||||
srcmacaddr: Option<String>,
|
||||
srcmacmask: Option<String>,
|
||||
dstmacaddr: Option<String>,
|
||||
dstmacmask: Option<String>,
|
||||
srcipaddr: Option<Ipv6Addr>,
|
||||
srcipmask: Option<u8>,
|
||||
dstipaddr: Option<Ipv6Addr>,
|
||||
dstipmask: Option<u8>,
|
||||
comment: Option<String>,
|
||||
},
|
||||
Layer4 {
|
||||
r#type: Layer4Type,
|
||||
srcmacaddr: Option<String>,
|
||||
srcipaddr: Option<IpAddr>,
|
||||
srcipmask: Option<u8>,
|
||||
dstipaddr: Option<IpAddr>,
|
||||
dstipmask: Option<u8>,
|
||||
/// Start of range of source IP address
|
||||
srcipfrom: Option<IpAddr>,
|
||||
/// End of range of source IP address
|
||||
srcipto: Option<IpAddr>,
|
||||
/// Start of range of destination IP address
|
||||
dstipfrom: Option<IpAddr>,
|
||||
/// End of range of destination IP address
|
||||
dstipto: Option<IpAddr>,
|
||||
srcportstart: Option<u16>,
|
||||
srcportend: Option<u16>,
|
||||
dstportstart: Option<u16>,
|
||||
dstportend: Option<u16>,
|
||||
state: Option<Layer4State>,
|
||||
comment: Option<String>,
|
||||
},
|
||||
}
|
||||
|
||||
pub struct NetworkFilterRule {
|
||||
action: NetworkFilterAction,
|
||||
direction: NetworkFilterDirection,
|
||||
/// optional; the priority of the rule controls the order in which the rule will be instantiated
|
||||
/// relative to other rules
|
||||
///
|
||||
/// Valid values are in the range of -1000 to 1000.
|
||||
priority: Option<i32>,
|
||||
selectors: Vec<NetworkFilterSelector>,
|
||||
}
|
||||
|
||||
fn extract_ipv4(ip: IpAddr) -> Ipv4Addr {
|
||||
match ip {
|
||||
IpAddr::V4(i) => i,
|
||||
|
@ -22,8 +22,8 @@ use virtweb_backend::constants::{
|
||||
MAX_INACTIVITY_DURATION, MAX_SESSION_DURATION, SESSION_COOKIE_NAME,
|
||||
};
|
||||
use virtweb_backend::controllers::{
|
||||
auth_controller, iso_controller, network_controller, server_controller, static_controller,
|
||||
vm_controller,
|
||||
auth_controller, iso_controller, network_controller, nwfilter_controller, server_controller,
|
||||
static_controller, vm_controller,
|
||||
};
|
||||
use virtweb_backend::libvirt_client::LibVirtClient;
|
||||
use virtweb_backend::middlewares::auth_middleware::AuthChecker;
|
||||
@ -239,6 +239,15 @@ async fn main() -> std::io::Result<()> {
|
||||
"/api/network/{uid}/stop",
|
||||
web::get().to(network_controller::stop),
|
||||
)
|
||||
// Network filters controller
|
||||
.route(
|
||||
"/api/nwfilter/list",
|
||||
web::get().to(nwfilter_controller::list),
|
||||
)
|
||||
.route(
|
||||
"/api/nwfilter/{uid}",
|
||||
web::get().to(nwfilter_controller::get_single),
|
||||
)
|
||||
// Static assets
|
||||
.route("/", web::get().to(static_controller::root_index))
|
||||
.route(
|
||||
|
Loading…
Reference in New Issue
Block a user