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:
Joseph Mark
2017-07-29 00:06:39 +07:00
committed by Gav Wood
parent ad30a6899b
commit b5f1524e78
15 changed files with 508 additions and 111 deletions

View File

@@ -148,11 +148,15 @@ Networking Options:
These nodes will always have a reserved slot on top
of the normal maximum peers. (default: {flag_reserved_peers:?})
--reserved-only Connect only to reserved nodes. (default: {flag_reserved_only})
--allow-ips FILTER Filter outbound connections. Must be one of:
--allow-ips FILTER Filter outbound connections. FILTER can be one of:
private - connect to private network IP addresses only;
public - connect to public network IP addresses only;
all - connect to any IP address.
(default: {flag_allow_ips})
all - connect to any IP address;
none - block all (for use with a custom filter as below);
a custom filter list in the format: "private ip_range1 -ip_range2 ...".
Where ip_range1 would be allowed and ip_range2 blocked;
Custom blocks ("-ip_range") override custom allows ("ip_range");
(default: {flag_allow_ips}).
--max-pending-peers NUM Allow up to NUM pending connections. (default: {flag_max_pending_peers})
--no-ancient-blocks Disable downloading old blocks after snapshot restoration
or warp sync. (default: {flag_no_ancient_blocks})

View File

@@ -24,7 +24,7 @@ use cli::{Args, ArgsError};
use util::{Hashable, H256, U256, Bytes, version_data, Address};
use util::journaldb::Algorithm;
use util::Colour;
use ethsync::{NetworkConfiguration, is_valid_node_url, AllowIP};
use ethsync::{NetworkConfiguration, is_valid_node_url};
use ethcore::ethstore::ethkey::{Secret, Public};
use ethcore::client::{VMType};
use ethcore::miner::{MinerOptions, Banning, StratumOptions};
@@ -48,6 +48,7 @@ use blockchain::{BlockchainCmd, ImportBlockchain, ExportBlockchain, KillBlockcha
use presale::ImportWallet;
use account::{AccountCmd, NewAccount, ListAccounts, ImportAccounts, ImportFromGethAccounts};
use snapshot::{self, SnapshotCommand};
use network::{IpFilter};
#[derive(Debug, PartialEq)]
pub enum Cmd {
@@ -461,12 +462,10 @@ impl Configuration {
max(self.min_peers(), peers)
}
fn allow_ips(&self) -> Result<AllowIP, String> {
match self.args.flag_allow_ips.as_str() {
"all" => Ok(AllowIP::All),
"public" => Ok(AllowIP::Public),
"private" => Ok(AllowIP::Private),
_ => Err("Invalid IP filter value".to_owned()),
fn ip_filter(&self) -> Result<IpFilter, String> {
match IpFilter::parse(self.args.flag_allow_ips.as_str()) {
Ok(allow_ip) => Ok(allow_ip),
Err(_) => Err("Invalid IP filter value".to_owned()),
}
}
@@ -712,7 +711,7 @@ impl Configuration {
ret.max_peers = self.max_peers();
ret.min_peers = self.min_peers();
ret.snapshot_peers = self.snapshot_peers();
ret.allow_ips = self.allow_ips()?;
ret.ip_filter = self.ip_filter()?;
ret.max_pending_peers = self.max_pending_peers();
let mut net_path = PathBuf::from(self.directories().base);
net_path.push("network");
@@ -968,7 +967,6 @@ impl Configuration {
}.into()
}
fn ui_interface(&self) -> String {
self.interface(&self.args.flag_ui_interface)
}
@@ -1080,6 +1078,7 @@ impl Configuration {
mod tests {
use std::io::Write;
use std::fs::{File, create_dir};
use std::str::FromStr;
use devtools::{RandomTempPath};
use ethcore::client::{VMType, BlockId};
@@ -1097,6 +1096,11 @@ mod tests {
use rpc::{WsConfiguration, UiConfiguration};
use run::RunCmd;
use network::{AllowIP, IpFilter};
extern crate ipnetwork;
use self::ipnetwork::IpNetwork;
use super::*;
#[derive(Debug, PartialEq)]
@@ -1752,4 +1756,50 @@ mod tests {
assert_eq!(&conf0.ipfs_config().interface, "0.0.0.0");
assert_eq!(conf0.ipfs_config().hosts, None);
}
#[test]
fn allow_ips() {
let all = parse(&["parity", "--allow-ips", "all"]);
let private = parse(&["parity", "--allow-ips", "private"]);
let block_custom = parse(&["parity", "--allow-ips", "-10.0.0.0/8"]);
let combo = parse(&["parity", "--allow-ips", "public 10.0.0.0/8 -1.0.0.0/8"]);
let ipv6_custom_public = parse(&["parity", "--allow-ips", "public fc00::/7"]);
let ipv6_custom_private = parse(&["parity", "--allow-ips", "private -fc00::/7"]);
assert_eq!(all.ip_filter().unwrap(), IpFilter {
predefined: AllowIP::All,
custom_allow: vec![],
custom_block: vec![],
});
assert_eq!(private.ip_filter().unwrap(), IpFilter {
predefined: AllowIP::Private,
custom_allow: vec![],
custom_block: vec![],
});
assert_eq!(block_custom.ip_filter().unwrap(), IpFilter {
predefined: AllowIP::All,
custom_allow: vec![],
custom_block: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()],
});
assert_eq!(combo.ip_filter().unwrap(), IpFilter {
predefined: AllowIP::Public,
custom_allow: vec![IpNetwork::from_str("10.0.0.0/8").unwrap()],
custom_block: vec![IpNetwork::from_str("1.0.0.0/8").unwrap()],
});
assert_eq!(ipv6_custom_public.ip_filter().unwrap(), IpFilter {
predefined: AllowIP::Public,
custom_allow: vec![IpNetwork::from_str("fc00::/7").unwrap()],
custom_block: vec![],
});
assert_eq!(ipv6_custom_private.ip_filter().unwrap(), IpFilter {
predefined: AllowIP::Private,
custom_allow: vec![],
custom_block: vec![IpNetwork::from_str("fc00::/7").unwrap()],
});
}
}

View File

@@ -191,7 +191,8 @@ pub fn to_bootnodes(bootnodes: &Option<String>) -> Result<Vec<String>, String> {
#[cfg(test)]
pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
use ethsync::{NetworkConfiguration, AllowIP};
use ethsync::{NetworkConfiguration};
use super::network::IpFilter;
NetworkConfiguration {
config_path: Some(replace_home(&::dir::default_data_path(), "$BASE/network")),
net_config_path: None,
@@ -206,7 +207,7 @@ pub fn default_network_config() -> ::ethsync::NetworkConfiguration {
min_peers: 25,
snapshot_peers: 0,
max_pending_peers: 64,
allow_ips: AllowIP::All,
ip_filter: IpFilter::default(),
reserved_nodes: Vec::new(),
allow_non_reserved: true,
}

View File

@@ -55,6 +55,7 @@ extern crate ethcore_ipc_nano as nanoipc;
extern crate ethcore_light as light;
extern crate ethcore_logger;
extern crate ethcore_util as util;
extern crate ethcore_network as network;
extern crate ethkey;
extern crate ethsync;
extern crate panic_hook;