Refactor --allow-ips to handle custom ip-ranges (#6144)
* Add checks for additional reserved ip addresses 100.64.0.0/10 and 240.0.0.0/4 are both reserved but not currently filtered. * Add check for special purpose addresses 192.0.0.0/24 - Used for the IANA IPv4 Special Purpose Address Registry * Refactor ip_utils (#5872) * Add checks for all ipv4 special use addresses * Add comprehensive ipv4 test cases * Refactor Ipv6 address checks (#5872) * Refactor AllowIP (#5872) * Add IpFilter struct to wrap predefined filter (AllowIP) with custom allow/block filters. * Refactor parsing of --allow-ips to handle custom filters. * Move AllowIP/IpFilter from ethsync to ethcore-network where they are used. * Revert Cargo.lock * Tests for custom ip filters (#5872) * Add "none" as a valid argument for --allow-ips to allow narrow custom ranges, eg.: --allow-ips="none 10.0.0.0/8" * Add tests for parsing filter arguments and node endpoints. * Add ipnetwork crate to dev dependencies for testing. * Add ipv6 filter tests (#5872) * Revert parity-ui-precompiled to master * Fix minor detail in usage.txt (#5872) * Spaces to tabs * Rename IpFilter::new() to ::default() * Small readability improvements * Test (#5872) * Revert "Test (#5872)" This reverts commit 7a8906430a6dad633fe29df3dca57f1630851fa9.
This commit is contained in:
@@ -30,7 +30,7 @@ use util::UtilError;
|
||||
use rlp::*;
|
||||
use time::Tm;
|
||||
use error::NetworkError;
|
||||
use AllowIP;
|
||||
use {AllowIP, IpFilter};
|
||||
use discovery::{TableUpdates, NodeEntry};
|
||||
use ip_utils::*;
|
||||
pub use rustc_serialize::json::Json;
|
||||
@@ -55,11 +55,21 @@ impl NodeEndpoint {
|
||||
}
|
||||
}
|
||||
|
||||
pub fn is_allowed(&self, filter: AllowIP) -> bool {
|
||||
pub fn is_allowed(&self, filter: &IpFilter) -> bool {
|
||||
(self.is_allowed_by_predefined(&filter.predefined) || filter.custom_allow.iter().any(|ipnet| {
|
||||
self.address.ip().is_within(ipnet)
|
||||
}))
|
||||
&& !filter.custom_block.iter().any(|ipnet| {
|
||||
self.address.ip().is_within(ipnet)
|
||||
})
|
||||
}
|
||||
|
||||
pub fn is_allowed_by_predefined(&self, filter: &AllowIP) -> bool {
|
||||
match filter {
|
||||
AllowIP::All => true,
|
||||
AllowIP::Private => !self.address.ip().is_global_s(),
|
||||
AllowIP::Public => self.address.ip().is_global_s(),
|
||||
&AllowIP::All => true,
|
||||
&AllowIP::Private => self.address.ip().is_usable_private(),
|
||||
&AllowIP::Public => self.address.ip().is_usable_public(),
|
||||
&AllowIP::None => false,
|
||||
}
|
||||
}
|
||||
|
||||
@@ -101,8 +111,8 @@ impl NodeEndpoint {
|
||||
pub fn is_valid(&self) -> bool {
|
||||
self.udp_port != 0 && self.address.port() != 0 &&
|
||||
match self.address {
|
||||
SocketAddr::V4(a) => !a.ip().is_unspecified_s(),
|
||||
SocketAddr::V6(a) => !a.ip().is_unspecified_s()
|
||||
SocketAddr::V4(a) => !a.ip().is_unspecified(),
|
||||
SocketAddr::V6(a) => !a.ip().is_unspecified()
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -219,8 +229,8 @@ impl NodeTable {
|
||||
}
|
||||
|
||||
/// Returns node ids sorted by number of failures
|
||||
pub fn nodes(&self, filter: AllowIP) -> Vec<NodeId> {
|
||||
let mut refs: Vec<&Node> = self.nodes.values().filter(|n| !self.useless_nodes.contains(&n.id) && n.endpoint.is_allowed(filter)).collect();
|
||||
pub fn nodes(&self, filter: IpFilter) -> Vec<NodeId> {
|
||||
let mut refs: Vec<&Node> = self.nodes.values().filter(|n| !self.useless_nodes.contains(&n.id) && n.endpoint.is_allowed(&filter)).collect();
|
||||
refs.sort_by(|a, b| a.failures.cmp(&b.failures));
|
||||
refs.iter().map(|n| n.id.clone()).collect()
|
||||
}
|
||||
@@ -283,7 +293,7 @@ impl NodeTable {
|
||||
let mut json = String::new();
|
||||
json.push_str("{\n");
|
||||
json.push_str("\"nodes\": [\n");
|
||||
let node_ids = self.nodes(AllowIP::All);
|
||||
let node_ids = self.nodes(IpFilter::default());
|
||||
for i in 0 .. node_ids.len() {
|
||||
let node = self.nodes.get(&node_ids[i]).expect("self.nodes() only returns node IDs from self.nodes");
|
||||
json.push_str(&format!("\t{{ \"url\": \"{}\", \"failures\": {} }}{}\n", node, node.failures, if i == node_ids.len() - 1 {""} else {","}))
|
||||
@@ -366,7 +376,7 @@ mod tests {
|
||||
use util::H512;
|
||||
use std::str::FromStr;
|
||||
use devtools::*;
|
||||
use AllowIP;
|
||||
use ipnetwork::IpNetwork;
|
||||
|
||||
#[test]
|
||||
fn endpoint_parse() {
|
||||
@@ -412,7 +422,7 @@ mod tests {
|
||||
table.note_failure(&id1);
|
||||
table.note_failure(&id2);
|
||||
|
||||
let r = table.nodes(AllowIP::All);
|
||||
let r = table.nodes(IpFilter::default());
|
||||
assert_eq!(r[0][..], id3[..]);
|
||||
assert_eq!(r[1][..], id2[..]);
|
||||
assert_eq!(r[2][..], id1[..]);
|
||||
@@ -434,9 +444,55 @@ mod tests {
|
||||
|
||||
{
|
||||
let table = NodeTable::new(Some(temp_path.as_path().to_str().unwrap().to_owned()));
|
||||
let r = table.nodes(AllowIP::All);
|
||||
let r = table.nodes(IpFilter::default());
|
||||
assert_eq!(r[0][..], id1[..]);
|
||||
assert_eq!(r[1][..], id2[..]);
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_allow() {
|
||||
let filter = IpFilter {
|
||||
predefined: AllowIP::None,
|
||||
custom_allow: vec![IpNetwork::from_str(&"10.0.0.0/8").unwrap(), IpNetwork::from_str(&"1.0.0.0/8").unwrap()],
|
||||
custom_block: vec![],
|
||||
};
|
||||
assert!(!NodeEndpoint::from_str("123.99.55.44:7770").unwrap().is_allowed(&filter));
|
||||
assert!(NodeEndpoint::from_str("10.0.0.1:7770").unwrap().is_allowed(&filter));
|
||||
assert!(NodeEndpoint::from_str("1.0.0.55:5550").unwrap().is_allowed(&filter));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_block() {
|
||||
let filter = IpFilter {
|
||||
predefined: AllowIP::All,
|
||||
custom_allow: vec![],
|
||||
custom_block: vec![IpNetwork::from_str(&"10.0.0.0/8").unwrap(), IpNetwork::from_str(&"1.0.0.0/8").unwrap()],
|
||||
};
|
||||
assert!(NodeEndpoint::from_str("123.99.55.44:7770").unwrap().is_allowed(&filter));
|
||||
assert!(!NodeEndpoint::from_str("10.0.0.1:7770").unwrap().is_allowed(&filter));
|
||||
assert!(!NodeEndpoint::from_str("1.0.0.55:5550").unwrap().is_allowed(&filter));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_allow_ipv6() {
|
||||
let filter = IpFilter {
|
||||
predefined: AllowIP::None,
|
||||
custom_allow: vec![IpNetwork::from_str(&"fc00::/8").unwrap()],
|
||||
custom_block: vec![],
|
||||
};
|
||||
assert!(NodeEndpoint::from_str("[fc00::]:5550").unwrap().is_allowed(&filter));
|
||||
assert!(!NodeEndpoint::from_str("[fd00::]:5550").unwrap().is_allowed(&filter));
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn custom_block_ipv6() {
|
||||
let filter = IpFilter {
|
||||
predefined: AllowIP::All,
|
||||
custom_allow: vec![],
|
||||
custom_block: vec![IpNetwork::from_str(&"fc00::/8").unwrap()],
|
||||
};
|
||||
assert!(!NodeEndpoint::from_str("[fc00::]:5550").unwrap().is_allowed(&filter));
|
||||
assert!(NodeEndpoint::from_str("[fd00::]:5550").unwrap().is_allowed(&filter));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user