From d388e4e18b4403f061447c83a4e0fc316dba596b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=E9=98=B3=E5=85=89=E5=B0=91=E5=B9=B4?= <849317537@qq.com> Date: Fri, 9 Aug 2024 09:21:52 +0000 Subject: [PATCH] =?UTF-8?q?=E6=B5=8B=E8=AF=95=E9=80=9A=E8=BF=87?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- Makefile | 2 - src/main.rs | 23 ++++++----- src/network.rs | 108 +++++++++++++++++++++++++++++++++++++++++++------ 3 files changed, 108 insertions(+), 25 deletions(-) diff --git a/Makefile b/Makefile index 83f9862..4895b23 100644 --- a/Makefile +++ b/Makefile @@ -24,8 +24,6 @@ install: cp images/* $(WORKSPACE)/images/ chown -R rocker:rocker $(WORKSPACE) - -sysctl net.ipv4.conf.all.forwarding=1 - -iptables -t filter -P FORWARD ACCEPT clean: -rocker --rm all -rm -rf $(WORKSPACE)/* diff --git a/src/main.rs b/src/main.rs index d9143da..866db4f 100644 --- a/src/main.rs +++ b/src/main.rs @@ -194,8 +194,8 @@ fn init_container_env(env: Option<&String>) -> Result<()>{ std::env::remove_var(k); } - if let Some(env) = env { - let env_vec = if env.starts_with("./") || env.starts_with("/") { + let env_vec = if let Some(env) = env { + let mut env_vec = if env.starts_with("./") || env.starts_with("/") { // 读取出路径指定的文件作为env let env_path = Path::new(env); let mut env_file = fs::File::open(env_path)?; @@ -208,14 +208,17 @@ fn init_container_env(env: Option<&String>) -> Result<()>{ } else { env.split(",").map(String::from).collect::>() }; - - for item_env in env_vec.iter() { - let item_env_v = item_env.split("=").collect::>(); - if item_env_v.len() == 2 { - std::env::set_var(item_env_v[0], item_env_v[1]) - } else { - println!("env 格式不正确: {item_env}") - } + env_vec.push(r#"PS1=\u\h\W\$ "#.to_string()); + env_vec + } else { + vec![r#"PS1=\u\h\W\$ "#.to_string()] + }; + for item_env in env_vec.iter() { + let item_env_v = item_env.split("=").collect::>(); + if item_env_v.len() == 2 { + std::env::set_var(item_env_v[0], item_env_v[1]) + } else { + println!("env 格式不正确: {item_env}") } } Ok(()) diff --git a/src/network.rs b/src/network.rs index cfe2c58..cb43a81 100644 --- a/src/network.rs +++ b/src/network.rs @@ -44,6 +44,56 @@ fn set_slave_ip(slave_veth_name: &str, addr: &str, pid: &str) { } } +fn set_snat(gateway_addr: &str, bridge_name: &str) { + // sudo iptables -t nat -A POSTROUTING -s 172.18.0.0/24 ! -o br0 -j MASQUERADE + let args = ["-t", "nat", "-A", "POSTROUTING", "-s", &format!("{gateway_addr}/24"), "!", "-o", bridge_name, "-j", "MASQUERADE"]; + println!("set_snat: {args:?}"); + let out = std::process::Command::new("iptables") + .args(args) + .output() + .unwrap(); + if !out.status.success() { + panic!("{:?}", out); + } +} + +fn set_iptables_forward() { + // sudo sysctl net.ipv4.conf.all.forwarding=1 + let args = ["net.ipv4.conf.all.forwarding=1"]; + println!("set_iptables_forward: {args:?}"); + let out = std::process::Command::new("sysctl") + .args(args) + .output() + .unwrap(); + if !out.status.success() { + panic!("{:?}", out); + } + // sudo iptables -t filter -P FORWARD ACCEPT + let args = ["-t", "filter", "-P", "FORWARD", "ACCEPT"]; + println!("set_iptables_forward: {args:?}"); + let out = std::process::Command::new("iptables") + .args(args) + .output() + .unwrap(); + if !out.status.success() { + panic!("{:?}", out); + } +} + + +fn set_slave_route(slave_veth_name: &str, bridge_addr: &str, pid: &str) { + // sudo nsenter -t 1851 -n -- ip route add default via 172.18.0.1 dev veth3 + let args = ["-t", pid, "-n", "--", "ip", "route", "add", "default", "via", bridge_addr, "dev", slave_veth_name]; + println!("set_slave_route: {args:?}"); + let out = std::process::Command::new("nsenter") + .args(args) + .output() + .unwrap(); + if !out.status.success() { + panic!("{:?}", out); + } +} + fn set_net_up(bridge_name: &str, master_veth_name: &str, pid: &str, slave_veth_name: &str) { // sudo ip link set bridge_name up let args = ["link", "set", bridge_name, "up"]; @@ -77,9 +127,17 @@ fn set_net_up(bridge_name: &str, master_veth_name: &str, pid: &str, slave_veth_n if !out.status.success() { println!("{:?}", out); } - - + // ip link set lo up + let args = ["-t", pid, "-n", "--", "ip", "link", "set", "lo", "up"]; + println!("set_up: {args:?}"); + let out = std::process::Command::new("nsenter") + .args(args) + .output() + .unwrap(); + if !out.status.success() { + println!("{:?}", out); + } } fn set_up(dev_name: &str) { @@ -152,7 +210,7 @@ fn del_bridge(bridge_name: &str) { fn create_veth_pair(master_veth_name: &str, slave_veth_name: &str) { - // sudo ip link add veth0 type veth peer name veth1 + // sudo ip link add master_veth_name type veth peer name slave_veth_name let args = ["link", "add", master_veth_name, "type", "veth", "peer", "name", slave_veth_name]; println!("create_veth_pair: {args:?}"); @@ -172,9 +230,9 @@ struct NetWrok { bridge_addr: String, // 192.168.124.1 slave_addr: String, - bridge_name: String, // uuid[:8]_1 // ip 就是 192.168.124.1 - master_veth_name: String, // uuid[:8]_2 // 不分配ip 直接插到桥 - slave_veth_name: String, // uuid[:8]_3 // ip 就是 192.168.124.3, 插在容器中 + bridge_name: String, // ro_uuid[:8]_1 // ip 就是 192.168.124.1 + master_veth_name: String, // ro_uuid[:8]_2 // 不分配ip 直接插到桥 + slave_veth_name: String, // ro_uuid[:8]_3 // ip 就是 192.168.124.3, 插在容器中 } fn get_all_network() -> Vec { @@ -226,15 +284,15 @@ fn create_network(uuid_name: &str, pid: i32) { let network = loop { // 生成一个随机桥ip - let base_addr = format!("{}.{}.{}", rg.gen_range(200..240), rg.gen_range(200..240), rg.gen_range(200..240)); + let base_addr = format!("{}.{}.{}", rg.gen_range(150..190), rg.gen_range(150..190), rg.gen_range(150..190)); let gateway_addr = format!("{base_addr}.0"); let bridge_addr = format!("{base_addr}.1"); let slave_addr = format!("{base_addr}.3"); if all_network.iter().any(|n|n.bridge_addr == bridge_addr) == false { - let bridge_name = format!("{uuid_name}_1"); - let master_veth_name = format!("{uuid_name}_2"); - let slave_veth_name = format!("{uuid_name}_3"); + let bridge_name = format!("ro_{uuid_name}_1"); + let master_veth_name = format!("ro_{uuid_name}_2"); + let slave_veth_name = format!("ro_{uuid_name}_3"); let net_work = NetWrok { gateway_addr, bridge_addr, @@ -264,7 +322,30 @@ fn create_network(uuid_name: &str, pid: i32) { set_slave_ip(&network.slave_veth_name, &network.slave_addr, pid.to_string().as_str()); // 激活 上线 set_net_up(&network.bridge_name, &network.master_veth_name, pid.to_string().as_str(), &&network.slave_veth_name); + // 访问公网设置 // 配置路由 + set_slave_route(&network.slave_veth_name, &network.bridge_addr, pid.to_string().as_str()); + // 设置转发规则 + set_iptables_forward(); + // 设置snat + set_snat(&network.gateway_addr, &network.bridge_name); + + + // // 创建veth pair + // create_veth_pair(&network.master_veth_name, &network.slave_veth_name); + // // 把从 pair 添加到容器内 + // slave_join_bridge(&network.slave_veth_name, pid.to_string().as_str()); + // // 系统中创建桥 + // create_bridge_dev(&network.bridge_name); + // // 宿主机 主pair 连接桥 + // master_join_bridge(&network.bridge_name, &network.master_veth_name); + // // 给桥分配ip + // set_bridge_ip(&network.bridge_name, &network.bridge_addr); + // // 给容器内 pair 分配ip + // set_slave_ip(&network.slave_veth_name, &network.slave_addr, pid.to_string().as_str()); + // // 激活 上线 + // set_net_up(&network.bridge_name, &network.master_veth_name, pid.to_string().as_str(), &&network.slave_veth_name); + // // 配置路由 @@ -280,8 +361,8 @@ fn create_network(uuid_name: &str, pid: i32) { fn main(){ // get_all_network(); - let container_id = uuid::Uuid::new_v4().to_string()[0..3].to_string(); - create_network(&container_id, 28930); + let container_id = uuid::Uuid::new_v4().to_string()[0..8].to_string(); + create_network(&container_id, 15992); return; let addr = "192.168.124.1"; @@ -293,7 +374,8 @@ fn main(){ create_bridge_dev(&bridge_name); set_bridge_ip(&bridge_name, &addr); set_up(&bridge_name); - // 我们在 set_bridge中补充了网段信息 /24 所以在 set_up的时候, 会自动配置路由表配置路由表 192.168.0.0/24 转发到这 bridge_name 的网络接口上 + // 我们在 ip addr add 172.18.0.1/24 dev br0 的时候补全了网段信息 /24, 所以在 ip link set br0 up的时候, + // 会自动配置路由表配置路由表 192.168.0.0/24 转发到这 bridge_name 的网络接口上 // set_route(bridge_name, addr); set_net(bridge_name, addr);