网络不通的版本
parent
84790df859
commit
a7188b94ff
@ -1,24 +1,37 @@
|
||||
WORKSPACE := /root/rocker
|
||||
WORKSPACE := /home/rocker
|
||||
USER_NAME := rocker
|
||||
PASSWORD = asd123
|
||||
|
||||
build:
|
||||
cargo build --release
|
||||
|
||||
# 创建WORKSPACE 对应的文件夹
|
||||
install: build
|
||||
mkdir -p $(WORKSPACE)
|
||||
install:
|
||||
@# 创建一个普通用户
|
||||
-@echo "Creating user $(USER_NAME)"
|
||||
-@sudo useradd -m -s /bin/bash $(USER_NAME)
|
||||
@# 设置密码
|
||||
-@echo "Setting password for $(USER_NAME)"
|
||||
-@echo "$(USER_NAME):$(PASSWORD)" | sudo chpasswd
|
||||
@# 授权sudo
|
||||
-@echo "Authorizing $(USER_NAME) to use sudo"
|
||||
-@sudo sh -c "echo '$(USER_NAME) ALL=(ALL) ALL' >> /etc/sudoers"
|
||||
|
||||
mkdir -p $(WORKSPACE)/images
|
||||
mkdir -p $(WORKSPACE)/volumes
|
||||
mkdir -p $(WORKSPACE)/containers
|
||||
chmod -R 777 $(WORKSPACE)
|
||||
cp images/* $(WORKSPACE)/images/
|
||||
chown -R rocker:rocker $(WORKSPACE)
|
||||
|
||||
cp images/* /root/rocker/images/
|
||||
cp target/release/rocker /usr/bin/rocker
|
||||
|
||||
# 创建一个普通用户
|
||||
-useradd -g rocker rocker
|
||||
-groupadd rocker
|
||||
|
||||
-sysctl net.ipv4.conf.all.forwarding=1
|
||||
-iptables -t filter -P FORWARD ACCEPT
|
||||
clean:
|
||||
-rocker --rm all
|
||||
-rm -rf $(WORKSPACE)
|
||||
-rm -rf $(WORKSPACE)/*
|
||||
-rm -rf /usr/bin/rocker
|
||||
|
||||
-@echo "Cleaning up"
|
||||
-@sudo userdel -r $(USER_NAME)
|
||||
-@sudo sed -i "/^$(USER_NAME)/d" /etc/sudoers
|
||||
|
||||
|
@ -1,33 +1,306 @@
|
||||
use std::{fs::OpenOptions, io::Read, os::unix::net};
|
||||
use rand::Rng;
|
||||
|
||||
fn get_gateway_addr(addr: &str) -> String {
|
||||
let prefix = &addr[..addr.len() - 1];
|
||||
format!("{}0", prefix)
|
||||
}
|
||||
fn create_bridge_dev(bridge_name: &str) {
|
||||
// brctl addbr br0
|
||||
let args = ["addbr", bridge_name];
|
||||
println!("create_bridge_dev: {args:?}");
|
||||
let out = std::process::Command::new("brctl")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
panic!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_bridge_ip(bridge_name: &str, addr: &str){
|
||||
// 设置容器内从ip: ip addr add 192.168.124.1/24 dev bridge_name
|
||||
let args = ["addr", "add", &format!("{addr}/24"), "dev", bridge_name];
|
||||
println!("set_bridge_ip: {args:?}");
|
||||
let out = std::process::Command::new("ip")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
panic!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
fn main(){
|
||||
fn set_slave_ip(slave_veth_name: &str, addr: &str, pid: &str) {
|
||||
// nsenter -t 10050 -n -- ip addr add <ip_address>/<subnet_mask> dev veth1
|
||||
let args = ["-t", pid, "-n", "--", "ip", "addr", "add", &format!("{addr}/24"), "dev", slave_veth_name];
|
||||
println!("set_slave_ip: {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"];
|
||||
println!("set_up: {args:?}");
|
||||
let out = std::process::Command::new("ip")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
panic!("{:?}", out);
|
||||
}
|
||||
|
||||
// sudo ip link set master_veth_name up
|
||||
let args = ["link", "set", master_veth_name, "up"];
|
||||
println!("set_up: {args:?}");
|
||||
let out = std::process::Command::new("ip")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
println!("{:?}", out);
|
||||
}
|
||||
|
||||
// nsenter -t 1970 -n -- ip link set dev slave_veth_name up
|
||||
let args = ["-t", pid, "-n", "--", "ip", "link", "set", "dev", slave_veth_name, "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) {
|
||||
// sudo ip link set bridge_name up
|
||||
let args = ["link", "set", dev_name, "up"];
|
||||
println!("set_up: {args:?}");
|
||||
let out = std::process::Command::new("ip")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
println!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_route(bridge_name: &str, addr: &str) {
|
||||
// ip route add 192.168.100.0/24 via 192.168.100.1 dev bridge_name
|
||||
// sudo ip netns exec ns1 ip route add default via 172.18.0.1 dev veth0
|
||||
// 把addr最后的1位替换为0
|
||||
let gateway_addr = get_gateway_addr(addr);
|
||||
|
||||
// 删掉系统自动添加的 ip route del 172.18.0.0/24 dev br0
|
||||
let args = ["route", "del", &format!("{gateway_addr}/24"), "dev", bridge_name];
|
||||
println!("set_route: {args:?}");
|
||||
let out = std::process::Command::new("ip")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
println!("{:?}", out);
|
||||
}
|
||||
|
||||
let args = ["route", "add", &format!("{gateway_addr}/24"), "via", addr, "dev", bridge_name];
|
||||
println!("set_route: {args:?}");
|
||||
let out = std::process::Command::new("ip")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
println!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
fn set_net(bridge_name: &str, addr: &str){
|
||||
// sudo iptables -t nat -A POSTROUTING -s 172.18.0.0/24 ! -o bridge_name -j MASQUERADE
|
||||
let gateway_addr = get_gateway_addr(addr);
|
||||
let args = ["-t", "nat", "-A", "POSTROUTING", "-s", &format!("{gateway_addr}/24"), "!", "-o", bridge_name, "-j", "MASQUERADE"];
|
||||
println!("set_net: {args:?}");
|
||||
let out = std::process::Command::new("iptables")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
println!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
fn del_bridge(bridge_name: &str) {
|
||||
// sudo brctl delbr br0
|
||||
let args = ["delbr", bridge_name];
|
||||
println!("del_bridge: {args:?}");
|
||||
let out = std::process::Command::new("brctl")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
println!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
fn create_veth_pair(master_veth_name: &str, slave_veth_name: &str) {
|
||||
// sudo ip link add veth0 type veth peer name veth1
|
||||
|
||||
let args = ["link", "add", master_veth_name, "type", "veth", "peer", "name", slave_veth_name];
|
||||
println!("create_veth_pair: {args:?}");
|
||||
let out = std::process::Command::new("ip")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
panic!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#[derive(Debug)]
|
||||
struct NetWrok {
|
||||
gateway_addr: String, // 192.168.124.0
|
||||
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, 插在容器中
|
||||
}
|
||||
|
||||
fn get_all_network() -> Vec<NetWrok> {
|
||||
// 打开 /home/rocker/network 所有已经配置的信息, 如果没有则创建
|
||||
let mut f = OpenOptions::new()
|
||||
.write(true)
|
||||
.create(true)
|
||||
.read(true)
|
||||
.open("/home/rocker/network")
|
||||
.unwrap();
|
||||
let mut text = String::new();
|
||||
f.read_to_string(&mut text).unwrap();
|
||||
vec![]
|
||||
}
|
||||
|
||||
fn master_join_bridge(bridge_name: &str, master_veth_name: &str) {
|
||||
// 将主端链接到桥
|
||||
//sudo brctl addif bridge_name master_veth_name
|
||||
let args = ["addif", bridge_name, master_veth_name];
|
||||
println!("master_join_bridge: {args:?}");
|
||||
let out = std::process::Command::new("brctl")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
if !out.status.success() {
|
||||
panic!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
fn slave_join_bridge(slave_veth_name: &str, pid: &str) {
|
||||
// 将从端 链接到容器
|
||||
// sudo ip link set slave_veth_name netns 1234
|
||||
let args = ["link", "set", slave_veth_name, "netns", pid];
|
||||
println!("slave_join_bridge: {args:?}");
|
||||
|
||||
#[test]
|
||||
fn test_network() {
|
||||
let bridge_name = "test_rocker";
|
||||
// ip link add xxxx
|
||||
// ip link add name br0 type bridge
|
||||
let out = std::process::Command::new("ip")
|
||||
.arg("link")
|
||||
.arg("add")
|
||||
.arg("name")
|
||||
.arg(bridge_name)
|
||||
.arg("type")
|
||||
.arg("bridge")
|
||||
.args(args)
|
||||
.output()
|
||||
.unwrap();
|
||||
out.status.success();
|
||||
println!("{:?}", out);
|
||||
if !out.status.success() {
|
||||
panic!("{:?}", out);
|
||||
}
|
||||
}
|
||||
|
||||
fn create_network(uuid_name: &str, pid: i32) {
|
||||
// 创建一个随机地址段的 没分配过的ip
|
||||
let all_network = get_all_network();
|
||||
let mut rg = rand::thread_rng();
|
||||
|
||||
let network = loop {
|
||||
// 生成一个随机桥ip
|
||||
let base_addr = format!("{}.{}.{}", rg.gen_range(200..240), rg.gen_range(200..240), rg.gen_range(200..240));
|
||||
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 net_work = NetWrok {
|
||||
gateway_addr,
|
||||
bridge_addr,
|
||||
slave_addr,
|
||||
bridge_name,
|
||||
master_veth_name,
|
||||
slave_veth_name,
|
||||
};
|
||||
break net_work;
|
||||
}
|
||||
};
|
||||
|
||||
let line = format!("{},{},{},{},{},{}", network.gateway_addr, network.bridge_addr, network.slave_addr, network.bridge_name, network.master_veth_name, network.slave_veth_name);
|
||||
println!("{line:?}");
|
||||
|
||||
// 系统中创建桥
|
||||
create_bridge_dev(&network.bridge_name);
|
||||
// 给桥分配ip
|
||||
set_bridge_ip(&network.bridge_name, &network.bridge_addr);
|
||||
// 创建veth pair
|
||||
create_veth_pair(&network.master_veth_name, &network.slave_veth_name);
|
||||
// 宿主机 主pair 连接桥
|
||||
master_join_bridge(&network.bridge_name, &network.master_veth_name);
|
||||
// 把从 pair 添加到容器内
|
||||
slave_join_bridge(&network.slave_veth_name, pid.to_string().as_str());
|
||||
// 给容器内 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);
|
||||
// 配置路由
|
||||
|
||||
|
||||
println!("123");
|
||||
|
||||
// let mut f = OpenOptions::new()
|
||||
// .write(true)
|
||||
// .create(true)
|
||||
// .read(true)
|
||||
// .open("/home/rocker/network")
|
||||
// .unwrap();
|
||||
|
||||
}
|
||||
|
||||
fn main(){
|
||||
// get_all_network();
|
||||
|
||||
let container_id = uuid::Uuid::new_v4().to_string()[0..3].to_string();
|
||||
create_network(&container_id, 28930);
|
||||
return;
|
||||
|
||||
let addr = "192.168.124.1";
|
||||
let bridge_name = &format!("rocker_{}", addr[8..].replace(".", "_"));
|
||||
|
||||
println!("{bridge_name}");
|
||||
println!("{addr}");
|
||||
|
||||
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 的网络接口上
|
||||
// set_route(bridge_name, addr);
|
||||
set_net(bridge_name, addr);
|
||||
|
||||
let veth_name = "yanguang";
|
||||
// connect(bridge_name, veth_name);
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
Loading…
Reference in New Issue