support mapping subnet proxy (#978)

- **support mapping subproxy network cidr**
- **add command line option for proxy network mapping**
- **fix Instance leak in tests.
This commit is contained in:
Sijie.Sun
2025-06-14 11:42:45 +08:00
committed by GitHub
parent 950cb04534
commit 25dcdc652a
23 changed files with 521 additions and 216 deletions

View File

@@ -188,6 +188,24 @@ pub async fn init_three_node_ex<F: Fn(TomlConfigLoader) -> TomlConfigLoader>(
vec![inst1, inst2, inst3]
}
pub async fn drop_insts(insts: Vec<Instance>) {
let mut set = JoinSet::new();
for mut inst in insts {
set.spawn(async move {
inst.clear_resources().await;
let pm = Arc::downgrade(&inst.get_peer_manager());
drop(inst);
let now = std::time::Instant::now();
while now.elapsed().as_secs() < 5 && pm.strong_count() > 0 {
tokio::time::sleep(std::time::Duration::from_millis(50)).await;
}
debug_assert_eq!(pm.strong_count(), 0, "PeerManager should be dropped");
});
}
while let Some(_) = set.join_next().await {}
}
async fn ping_test(from_netns: &str, target_ip: &str, payload_size: Option<usize>) -> bool {
let _g = NetNS::new(Some(ROOT_NETNS_NAME.to_owned())).guard();
let code = tokio::process::Command::new("ip")
@@ -233,14 +251,17 @@ pub async fn basic_three_node_test(#[values("tcp", "udp", "wg", "ws", "wss")] pr
Duration::from_secs(5000),
)
.await;
drop_insts(insts).await;
}
async fn subnet_proxy_test_udp() {
async fn subnet_proxy_test_udp(target_ip: &str) {
use crate::tunnel::{common::tests::_tunnel_pingpong_netns, udp::UdpTunnelListener};
use rand::Rng;
let udp_listener = UdpTunnelListener::new("udp://10.1.2.4:22233".parse().unwrap());
let udp_connector = UdpTunnelConnector::new("udp://10.1.2.4:22233".parse().unwrap());
let udp_connector =
UdpTunnelConnector::new(format!("udp://{}:22233", target_ip).parse().unwrap());
// NOTE: this should not excced udp tunnel max buffer size
let mut buf = vec![0; 7 * 1024];
@@ -257,7 +278,8 @@ async fn subnet_proxy_test_udp() {
// no fragment
let udp_listener = UdpTunnelListener::new("udp://10.1.2.4:22233".parse().unwrap());
let udp_connector = UdpTunnelConnector::new("udp://10.1.2.4:22233".parse().unwrap());
let udp_connector =
UdpTunnelConnector::new(format!("udp://{}:22233", target_ip).parse().unwrap());
let mut buf = vec![0; 1 * 1024];
rand::thread_rng().fill(&mut buf[..]);
@@ -305,12 +327,13 @@ async fn subnet_proxy_test_udp() {
.await;
}
async fn subnet_proxy_test_tcp() {
async fn subnet_proxy_test_tcp(target_ip: &str) {
use crate::tunnel::{common::tests::_tunnel_pingpong_netns, tcp::TcpTunnelListener};
use rand::Rng;
let tcp_listener = TcpTunnelListener::new("tcp://10.1.2.4:22223".parse().unwrap());
let tcp_connector = TcpTunnelConnector::new("tcp://10.1.2.4:22223".parse().unwrap());
let tcp_connector =
TcpTunnelConnector::new(format!("tcp://{}:22223", target_ip).parse().unwrap());
let mut buf = vec![0; 32];
rand::thread_rng().fill(&mut buf[..]);
@@ -341,15 +364,15 @@ async fn subnet_proxy_test_tcp() {
.await;
}
async fn subnet_proxy_test_icmp() {
async fn subnet_proxy_test_icmp(target_ip: &str) {
wait_for_condition(
|| async { ping_test("net_a", "10.1.2.4", None).await },
|| async { ping_test("net_a", target_ip, None).await },
Duration::from_secs(5),
)
.await;
wait_for_condition(
|| async { ping_test("net_a", "10.1.2.4", Some(5 * 1024)).await },
|| async { ping_test("net_a", target_ip, Some(5 * 1024)).await },
Duration::from_secs(5),
)
.await;
@@ -369,8 +392,8 @@ async fn subnet_proxy_test_icmp() {
}
#[rstest::rstest]
#[tokio::test]
#[serial_test::serial]
#[tokio::test]
pub async fn subnet_proxy_three_node_test(
#[values("tcp", "udp", "wg")] proto: &str,
#[values(true, false)] no_tun: bool,
@@ -378,6 +401,7 @@ pub async fn subnet_proxy_three_node_test(
#[values(true, false)] enable_kcp_proxy: bool,
#[values(true, false)] disable_kcp_input: bool,
#[values(true, false)] dst_enable_kcp_proxy: bool,
#[values(true, false)] test_mapped_cidr: bool,
) {
let insts = init_three_node_ex(
proto,
@@ -388,7 +412,14 @@ pub async fn subnet_proxy_three_node_test(
flags.disable_kcp_input = disable_kcp_input;
flags.enable_kcp_proxy = dst_enable_kcp_proxy;
cfg.set_flags(flags);
cfg.add_proxy_cidr("10.1.2.0/24".parse().unwrap());
cfg.add_proxy_cidr(
"10.1.2.0/24".parse().unwrap(),
if test_mapped_cidr {
Some("10.1.3.0/24".parse().unwrap())
} else {
None
},
);
}
if cfg.get_inst_name() == "inst2" && relay_by_public_server {
@@ -410,19 +441,31 @@ pub async fn subnet_proxy_three_node_test(
)
.await;
assert_eq!(insts[2].get_global_ctx().get_proxy_cidrs().len(), 1);
assert_eq!(insts[2].get_global_ctx().config.get_proxy_cidrs().len(), 1);
wait_proxy_route_appear(
&insts[0].get_peer_manager(),
"10.144.144.3/24",
insts[2].peer_id(),
"10.1.2.0/24",
if test_mapped_cidr {
"10.1.3.0/24"
} else {
"10.1.2.0/24"
},
)
.await;
subnet_proxy_test_icmp().await;
subnet_proxy_test_tcp().await;
subnet_proxy_test_udp().await;
let target_ip = if test_mapped_cidr {
"10.1.3.4"
} else {
"10.1.2.4"
};
subnet_proxy_test_icmp(target_ip).await;
subnet_proxy_test_tcp(target_ip).await;
subnet_proxy_test_udp(target_ip).await;
drop_insts(insts).await;
}
#[rstest::rstest]
@@ -464,6 +507,8 @@ pub async fn data_compress(
Duration::from_secs(5),
)
.await;
drop_insts(_insts).await;
}
#[cfg(feature = "wireguard")]
@@ -577,6 +622,8 @@ pub async fn proxy_three_node_disconnect_test(#[values("tcp", "wg")] proto: &str
set_link_status("net_d", true);
}
drop_insts(insts).await;
});
let (ret,) = tokio::join!(task);
@@ -630,6 +677,8 @@ pub async fn udp_broadcast_test() {
tokio::time::sleep(tokio::time::Duration::from_secs(2)).await;
assert_eq!(counter.load(std::sync::atomic::Ordering::Relaxed), 2);
drop_insts(_insts).await;
}
#[tokio::test]
@@ -678,6 +727,8 @@ pub async fn foreign_network_forward_nic_data() {
Duration::from_secs(5),
)
.await;
drop_insts(vec![center_inst, inst1, inst2]).await;
}
use std::{net::SocketAddr, str::FromStr};
@@ -778,6 +829,8 @@ pub async fn wireguard_vpn_portal() {
Duration::from_secs(5),
)
.await;
drop_insts(insts).await;
}
#[cfg(feature = "wireguard")]
@@ -837,6 +890,8 @@ pub async fn socks5_vpn_portal(#[values("10.144.144.1", "10.144.144.3")] dst_add
drop(conn);
tokio::join!(task).0.unwrap();
drop_insts(_insts).await;
}
#[tokio::test]
@@ -886,6 +941,7 @@ pub async fn foreign_network_functional_cluster() {
let peer_map_inst1 = inst1.get_peer_manager();
println!("inst1 peer map: {:?}", peer_map_inst1.list_routes().await);
drop(peer_map_inst1);
wait_for_condition(
|| async { ping_test("net_c", "10.144.145.2", None).await },
@@ -905,6 +961,8 @@ pub async fn foreign_network_functional_cluster() {
Duration::from_secs(5),
)
.await;
drop_insts(vec![center_inst1, center_inst2, inst1, inst2]).await;
}
#[rstest::rstest]
@@ -974,6 +1032,9 @@ pub async fn manual_reconnector(#[values(true, false)] is_foreign: bool) {
Duration::from_secs(5),
)
.await;
drop(peer_map);
drop_insts(vec![center_inst, inst1, inst2]).await;
}
#[rstest::rstest]
@@ -1017,7 +1078,7 @@ pub async fn port_forward_test(
},
]);
} else if cfg.get_inst_name() == "inst3" {
cfg.add_proxy_cidr("10.1.2.0/24".parse().unwrap());
cfg.add_proxy_cidr("10.1.2.0/24".parse().unwrap(), None);
}
let mut flags = cfg.get_flags();
flags.no_tun = no_tun;
@@ -1093,4 +1154,6 @@ pub async fn port_forward_test(
buf,
)
.await;
drop_insts(_insts).await;
}