1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
use crate::packet::Packet;
use std::net::SocketAddr;
use std::sync::atomic::Ordering;
mod cache;
mod config;
use crate::discv5::PERMIT_BAN_LIST;
use crate::metrics::METRICS;
use cache::ReceivedPacketCache;
pub use config::{FilterConfig, FilterConfigBuilder};
use log::debug;
use std::collections::HashMap;
pub(crate) struct Filter {
config: FilterConfig,
raw_packets_received: ReceivedPacketCache<SocketAddr>,
_packets_received: ReceivedPacketCache<(SocketAddr, Packet)>,
}
impl Filter {
pub fn new(config: &FilterConfig) -> Filter {
Filter {
config: config.clone(),
raw_packets_received: ReceivedPacketCache::new(
config.max_requests_per_second,
METRICS.moving_window,
),
_packets_received: ReceivedPacketCache::new(
config.max_requests_per_second,
METRICS.moving_window,
),
}
}
pub fn initial_pass(&mut self, src: &SocketAddr) -> bool {
if PERMIT_BAN_LIST.read().permit_ips.get(&src.ip()).is_some() {
return true;
}
if PERMIT_BAN_LIST.read().ban_ips.get(&src.ip()).is_some() {
debug!("Dropped unsolicited packet from banned src: {:?}", src);
return false;
}
let result = self.raw_packets_received.insert_reset(*src);
METRICS
.unsolicited_requests_per_window
.store(self.raw_packets_received.len(), Ordering::Relaxed);
let hashmap = {
let mut hashmap = HashMap::with_capacity(10);
for ip in self
.raw_packets_received
.iter()
.map(|packet| packet.content.ip())
{
*hashmap.entry(ip).or_default() += 1.0 / (METRICS.moving_window as f64);
}
hashmap
};
*METRICS.requests_per_ip_per_second.write() = hashmap;
if self.config.enabled {
if let Some(max_requests_per_ip_per_second) = self.config.max_requests_per_ip_per_second
{
if let Some(requests) = METRICS.requests_per_ip_per_second.read().get(&src.ip()) {
if requests >= &max_requests_per_ip_per_second {
debug!(
"Dropped unsolicited packet from IP rate limit: {:?}",
src.ip()
);
return false;
}
}
}
result
} else {
true
}
}
pub fn final_pass(&mut self, _src: &SocketAddr, _packet: &Packet) -> bool {
true
}
}