add network whitelist for public relay node

This commit is contained in:
sijie.sun 2024-08-03 15:12:54 +08:00 committed by Sijie.Sun
parent 02b5b5f3c7
commit 0da09ec605
7 changed files with 75 additions and 3 deletions

7
Cargo.lock generated
View File

@ -1425,6 +1425,7 @@ dependencies = [
"tun-easytier",
"url",
"uuid",
"wildmatch",
"windows-sys 0.52.0",
"winreg 0.11.0",
"zerocopy",
@ -6801,6 +6802,12 @@ dependencies = [
"rustix",
]
[[package]]
name = "wildmatch"
version = "2.3.4"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "3928939971918220fed093266b809d1ee4ec6c1a2d72692ff6876898f3b16c19"
[[package]]
name = "winapi"
version = "0.3.9"

View File

@ -166,6 +166,8 @@ smoltcp = { version = "0.11.0", optional = true, default-features = false, featu
] }
parking_lot = { version = "0.12.0", optional = true }
wildmatch = "2.3.4"
[target.'cfg(windows)'.dependencies]
windows-sys = { version = "0.52", features = [
"Win32_Networking_WinSock",

View File

@ -169,6 +169,8 @@ pub struct Flags {
pub no_tun: bool,
#[derivative(Default(value = "false"))]
pub use_smoltcp: bool,
#[derivative(Default(value = "\"*\".to_string()"))]
pub foreign_network_whitelist: String,
}
#[derive(Debug, Clone, Deserialize, Serialize, PartialEq)]

View File

@ -1007,7 +1007,6 @@ pub mod tests {
use tokio::net::UdpSocket;
use crate::connector::udp_hole_punch::UdpHolePunchListener;
use crate::rpc::{NatType, StunInfo};
use crate::tunnel::common::tests::wait_for_condition;

View File

@ -79,7 +79,10 @@ struct Cli {
#[arg(
short,
long,
help = "automatically determine and set IP address by Easytier, and the IP address starts from 10.0.0.1 by default. Warning, if there is an IP conflict in the network when using DHCP, the IP will be automatically changed."
help = "automatically determine and set IP address by Easytier, and the
IP address starts from 10.0.0.1 by default. Warning, if there is an IP
conflict in the network when using DHCP, the IP will be automatically
changed."
)]
dhcp: bool,
@ -219,10 +222,19 @@ and the vpn client is in network of 10.14.14.0/24"
#[arg(
long,
help = "assign routes cidr manually, will disable subnet proxy and
wireguard routes propogated from peers. e.g.: 192.168.0.0/16",
wireguard routes propogated from peers. e.g.: 192.168.0.0/16",
num_args = 0..
)]
manual_routes: Option<Vec<String>>,
#[arg(
long,
help = "only relay traffic of whitelisted networks, input is a wildcard
string, e.g.: '*' (all networks), 'def*' (network prefixed with def), can specify multiple networks
disable relay if arg is empty. default is allowing all networks",
num_args = 0..,
)]
relay_network_whitelist: Option<Vec<String>>,
}
impl Cli {
@ -455,6 +467,9 @@ impl From<Cli> for TomlConfigLoader {
f.enable_exit_node = cli.enable_exit_node;
f.no_tun = cli.no_tun || cfg!(not(feature = "tun"));
f.use_smoltcp = cli.use_smoltcp;
if let Some(wl) = cli.relay_network_whitelist {
f.foreign_network_whitelist = wl.join(" ");
}
cfg.set_flags(f);
cfg.set_exit_nodes(cli.exit_nodes.clone());

View File

@ -399,6 +399,37 @@ mod tests {
assert_eq!(2, rpc_resp.foreign_networks["net1"].peers.len());
}
async fn foreign_network_whitelist_helper(name: String) {
let pm_center = create_mock_peer_manager_with_mock_stun(crate::rpc::NatType::Unknown).await;
tracing::debug!("pm_center: {:?}", pm_center.my_peer_id());
let mut flag = pm_center.get_global_ctx().get_flags();
flag.foreign_network_whitelist = vec!["net1".to_string(), "net2*".to_string()].join(" ");
pm_center.get_global_ctx().config.set_flags(flag);
let pma_net1 = create_mock_peer_manager_for_foreign_network(name.as_str()).await;
let (a_ring, b_ring) = crate::tunnel::ring::create_ring_tunnel_pair();
let b_mgr_copy = pm_center.clone();
let s_ret = tokio::spawn(async move { b_mgr_copy.add_tunnel_as_server(b_ring).await });
pma_net1.add_client_tunnel(a_ring).await.unwrap();
s_ret.await.unwrap().unwrap();
}
#[tokio::test]
async fn foreign_network_whitelist() {
foreign_network_whitelist_helper("net1".to_string()).await;
foreign_network_whitelist_helper("net2".to_string()).await;
foreign_network_whitelist_helper("net2abc".to_string()).await;
}
#[tokio::test]
#[should_panic]
async fn foreign_network_whitelist_fail() {
foreign_network_whitelist_helper("net3".to_string()).await;
}
#[tokio::test]
async fn test_foreign_network_manager() {
let pm_center = create_mock_peer_manager_with_mock_stun(crate::rpc::NatType::Unknown).await;

View File

@ -309,6 +309,21 @@ impl PeerManager {
self.add_client_tunnel(t).await
}
fn check_network_in_whitelist(&self, network_name: &str) -> Result<(), Error> {
if self
.global_ctx
.get_flags()
.foreign_network_whitelist
.split(" ")
.map(wildmatch::WildMatch::new)
.any(|wl| wl.matches(network_name))
{
Ok(())
} else {
Err(anyhow::anyhow!("network {} not in whitelist", network_name).into())
}
}
#[tracing::instrument]
pub async fn add_tunnel_as_server(&self, tunnel: Box<dyn Tunnel>) -> Result<(), Error> {
tracing::info!("add tunnel as server start");
@ -319,6 +334,7 @@ impl PeerManager {
{
self.add_new_peer_conn(peer).await?;
} else {
self.check_network_in_whitelist(&peer.get_network_identity().network_name)?;
self.foreign_network_manager.add_peer_conn(peer).await?;
}
tracing::info!("add tunnel as server done");