mirror of
https://github.com/EasyTier/EasyTier.git
synced 2026-05-07 10:14:35 +00:00
Implement ACL (#1140)
1. get acl stats
```
./easytier-cli acl stats
AclStats:
Global:
CacheHits: 4
CacheMaxSize: 10000
CacheSize: 5
DefaultAllows: 3
InboundPacketsAllowed: 2
InboundPacketsTotal: 2
OutboundPacketsAllowed: 7
OutboundPacketsTotal: 7
PacketsAllowed: 9
PacketsTotal: 9
RuleMatches: 2
ConnTrack:
[src: 10.14.11.1:57444, dst: 10.14.11.2:1000, proto: Tcp, state: New, pkts: 1, bytes: 60, created: 2025-07-24 10:13:39 +08:00, last_seen: 2025-07-24 10:13:39 +08:00]
Rules:
[name: 'tcp_whitelist', prio: 1000, action: Allow, enabled: true, proto: Tcp, ports: ["1000"], src_ports: [], src_ips: [], dst_ips: [], stateful: true, rate: 0, burst: 0] [pkts: 2, bytes: 120]
```
2. use tcp/udp whitelist to block unexpected traffic.
`sudo ./easytier-core -d --tcp-whitelist 1000`
3. use complete acl ability with config file:
```
[[acl.acl_v1.chains]]
name = "inbound_whitelist"
chain_type = 1
description = "Auto-generated inbound whitelist from CLI"
enabled = true
default_action = 2
[[acl.acl_v1.chains.rules]]
name = "tcp_whitelist"
description = "Auto-generated TCP whitelist rule"
priority = 1000
enabled = true
protocol = 1
ports = ["1000"]
source_ips = []
destination_ips = []
source_ports = []
action = 1
rate_limit = 0
burst_limit = 0
stateful = true
```
This commit is contained in:
@@ -0,0 +1,95 @@
|
||||
use std::fmt::Display;
|
||||
|
||||
include!(concat!(env!("OUT_DIR"), "/acl.rs"));
|
||||
|
||||
impl Display for ConnTrackEntry {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
let src = self
|
||||
.src_addr
|
||||
.as_ref()
|
||||
.map(|a| a.to_string())
|
||||
.unwrap_or_else(|| "-".to_string());
|
||||
let dst = self
|
||||
.dst_addr
|
||||
.as_ref()
|
||||
.map(|a| a.to_string())
|
||||
.unwrap_or_else(|| "-".to_string());
|
||||
let last_seen = chrono::DateTime::<chrono::Utc>::from_timestamp(self.last_seen as i64, 0)
|
||||
.unwrap()
|
||||
.with_timezone(&chrono::Local);
|
||||
let created_at = chrono::DateTime::<chrono::Utc>::from_timestamp(self.created_at as i64, 0)
|
||||
.unwrap()
|
||||
.with_timezone(&chrono::Local);
|
||||
write!(
|
||||
f,
|
||||
"[src: {}, dst: {}, proto: {:?}, state: {:?}, pkts: {}, bytes: {}, created: {}, last_seen: {}]",
|
||||
src,
|
||||
dst,
|
||||
Protocol::try_from(self.protocol).unwrap_or(Protocol::Unspecified),
|
||||
ConnState::try_from(self.state).unwrap_or(ConnState::Invalid),
|
||||
self.packet_count,
|
||||
self.byte_count,
|
||||
created_at,
|
||||
last_seen
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for Rule {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"[name: '{}', prio: {}, action: {:?}, enabled: {}, proto: {:?}, ports: {:?}, src_ports: {:?}, src_ips: {:?}, dst_ips: {:?}, stateful: {}, rate: {}, burst: {}]",
|
||||
self.name,
|
||||
self.priority,
|
||||
Action::try_from(self.action).unwrap_or(Action::Noop),
|
||||
self.enabled,
|
||||
Protocol::try_from(self.protocol).unwrap_or(Protocol::Unspecified),
|
||||
self.ports,
|
||||
self.source_ports,
|
||||
self.source_ips,
|
||||
self.destination_ips,
|
||||
self.stateful,
|
||||
self.rate_limit,
|
||||
self.burst_limit
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for StatItem {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
write!(
|
||||
f,
|
||||
"[pkts: {}, bytes: {}]",
|
||||
self.packet_count, self.byte_count
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
impl Display for AclStats {
|
||||
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
|
||||
writeln!(f, "AclStats:")?;
|
||||
writeln!(f, " Global:")?;
|
||||
for (k, v) in &self.global {
|
||||
writeln!(f, " {}: {}", k, v)?;
|
||||
}
|
||||
writeln!(f, " ConnTrack:")?;
|
||||
for entry in &self.conn_track {
|
||||
writeln!(f, " {}", entry)?;
|
||||
}
|
||||
writeln!(f, " Rules:")?;
|
||||
for rule_stat in &self.rules {
|
||||
if let Some(rule) = &rule_stat.rule {
|
||||
write!(f, " {} ", rule)?;
|
||||
} else {
|
||||
write!(f, " <default/none> ")?;
|
||||
}
|
||||
if let Some(stat) = &rule_stat.stat {
|
||||
writeln!(f, "{}", stat)?;
|
||||
} else {
|
||||
writeln!(f)?;
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user