aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRichard Qin <richard.qin.x@gmail.com>2026-10-29 02:57:51 +0800
committerRichard Qin <richard.qin.x@gmail.com>2026-10-29 02:57:51 +0800
commitaeb1ab2c3e960c6eb38ee2c9b18519b9b3bd8fa4 (patch)
tree4404733e7bce7e41058ee227c8ce1c8fbf9d57a3
parentb25c21a3272416d52e805b5253cc46f59587d4c2 (diff)
downloadrutils-aeb1ab2c3e960c6eb38ee2c9b18519b9b3bd8fa4.tar.gz
rutils-aeb1ab2c3e960c6eb38ee2c9b18519b9b3bd8fa4.tar.xz
Add NAT networking with bridge, veth, DNS, routing, and firewall configuration for containers.
Signed-off-by: Richard Qin <richard.qin.x@gmail.com>
-rw-r--r--debian-container/README9
-rw-r--r--debian-container/lib/common.sh7
-rw-r--r--debian-container/lib/container.sh12
-rw-r--r--debian-container/lib/network.sh82
4 files changed, 107 insertions, 3 deletions
diff --git a/debian-container/README b/debian-container/README
index c0ef344..0328def 100644
--- a/debian-container/README
+++ b/debian-container/README
@@ -46,6 +46,7 @@ sudo ./debian-container.sh resize test-3 --size 12G
sudo ./debian-container.sh enter test-1
sudo ./debian-container.sh enter test-1 --network host
+sudo ./debian-container.sh enter test-1 --network nat
sudo ./debian-container.sh enter test-1 --mount /home/richard/project:/workspace:rw
sudo ./debian-container.sh enter test-1 --mount /home/richard/data:/data:ro
@@ -53,6 +54,7 @@ sudo ./debian-container.sh enter test-1 --mount /home/richard/data:/data:ro
sudo ./debian-container.sh exec test-1 -- uname -a
sudo ./debian-container.sh exec test-1 --network host -- apt-get update
+sudo ./debian-container.sh exec test-1 --network nat -- apt-get update
sudo ./debian-container.sh exec test-1 --mount /home/richard/project:/workspace:rw -- make -C /workspace
列出和查看容器:
@@ -95,7 +97,12 @@ DEBIAN_ARCH 目标架构
DEBIAN_MIRROR Debian 镜像地址
DEBIAN_INCLUDE 额外软件包,使用逗号分隔
DEBIAN_EXCLUDE 要排除的软件包,使用逗号分隔
-DEBIAN_NETWORK 默认网络模式,none 或 host
+DEBIAN_NETWORK 默认网络模式,none、host 或 nat
+DEBIAN_NAT_BRIDGE NAT 网桥名称,默认 rutils0
+DEBIAN_NAT_NETWORK NAT 子网,默认 10.88.0.0/24
+DEBIAN_NAT_GATEWAY NAT 网关地址,默认 10.88.0.1
+DEBIAN_NAT_ADDRESS NAT 容器地址,默认 10.88.0.2
+DEBIAN_NAT_DNS NAT 模式 DNS,默认 1.1.1.1
挂载参数格式:
diff --git a/debian-container/lib/common.sh b/debian-container/lib/common.sh
index 6177482..075cd15 100644
--- a/debian-container/lib/common.sh
+++ b/debian-container/lib/common.sh
@@ -77,7 +77,7 @@ base-create 选项:
--exclude PACKAGES 要排除的软件包,使用逗号分隔
网络选项:
- --network MODE 网络模式:none(默认)或 host
+ --network MODE 网络模式:none(默认)、host 或 nat
挂载选项:
--mount SPEC 目录挂载:HOST:CONTAINER[:ro|rw]
@@ -97,6 +97,11 @@ profile 配置项:
DEBIAN_INCLUDE 额外软件包,使用逗号分隔
DEBIAN_EXCLUDE 要排除的软件包,使用逗号分隔
DEBIAN_NETWORK 默认网络模式(默认:none)
+ DEBIAN_NAT_BRIDGE NAT 网桥名称(默认:rutils0)
+ DEBIAN_NAT_NETWORK NAT 子网(默认:10.88.0.0/24)
+ DEBIAN_NAT_GATEWAY NAT 网关地址(默认:10.88.0.1)
+ DEBIAN_NAT_ADDRESS 容器地址(默认:10.88.0.2)
+ DEBIAN_NAT_DNS NAT 模式 DNS(默认:1.1.1.1)
EOF
}
diff --git a/debian-container/lib/container.sh b/debian-container/lib/container.sh
index b3d8c9b..62ab0b3 100644
--- a/debian-container/lib/container.sh
+++ b/debian-container/lib/container.sh
@@ -247,6 +247,11 @@ dc_enter() {
bind_args+=(--mount "$spec")
done
+ if [[ "$network_mode" == nat ]]; then
+ dc_network_nat_run _enter "${bind_args[@]}"
+ return
+ fi
+
unshare --mount --uts --ipc --pid --fork --propagation private \
"${DC_NETWORK_UNSHARE_ARGS[@]}" -- bash "$DC_SCRIPT" _enter "$DC_INSTANCE" "${bind_args[@]}"
}
@@ -255,6 +260,7 @@ dc_enter_rootfs() {
dc_bind_load_options "$@"
dc_mount_root
trap dc_cleanup_mounts EXIT
+ dc_network_configure_rootfs
dc_mount_virtual_filesystems
dc_bind_mount_all
hostname debian-container
@@ -306,6 +312,11 @@ dc_exec() {
bind_args+=(--mount "$spec")
done
+ if [[ "$network_mode" == nat ]]; then
+ dc_network_nat_run _exec "${bind_args[@]}" -- "$@"
+ return
+ fi
+
unshare --mount --uts --ipc --pid --fork --propagation private \
"${DC_NETWORK_UNSHARE_ARGS[@]}" -- \
bash "$DC_SCRIPT" _exec "$DC_INSTANCE" "${bind_args[@]}" -- "$@"
@@ -335,6 +346,7 @@ dc_exec_rootfs() {
(($# > 0)) || dc_die 'exec 需要一个命令。'
dc_mount_root
trap dc_cleanup_mounts EXIT
+ dc_network_configure_rootfs
dc_mount_virtual_filesystems
dc_bind_mount_all
hostname debian-container
diff --git a/debian-container/lib/network.sh b/debian-container/lib/network.sh
index 333869f..a5a31dd 100644
--- a/debian-container/lib/network.sh
+++ b/debian-container/lib/network.sh
@@ -4,6 +4,12 @@
DC_NETWORK_MODE=${DEBIAN_NETWORK:-none}
DC_NETWORK_UNSHARE_ARGS=()
+DC_NAT_BRIDGE=${DEBIAN_NAT_BRIDGE:-rutils0}
+DC_NAT_NETWORK=${DEBIAN_NAT_NETWORK:-10.88.0.0/24}
+DC_NAT_PREFIX=${DC_NAT_NETWORK#*/}
+DC_NAT_GATEWAY=${DEBIAN_NAT_GATEWAY:-10.88.0.1}
+DC_NAT_ADDRESS=${DEBIAN_NAT_ADDRESS:-10.88.0.2}
+DC_NAT_DNS=${DEBIAN_NAT_DNS:-1.1.1.1}
dc_network_prepare() {
local mode=${1:-$DC_NETWORK_MODE}
@@ -15,8 +21,82 @@ dc_network_prepare() {
host)
DC_NETWORK_UNSHARE_ARGS=()
;;
+ nat)
+ DC_NETWORK_UNSHARE_ARGS=(--net)
+ ;;
*)
- dc_die "网络模式无效:$mode(可选:none、host)"
+ dc_die "网络模式无效:$mode(可选:none、host、nat)"
;;
esac
}
+
+dc_network_configure_rootfs() {
+ [[ "$DC_NETWORK_MODE" == nat ]] || return 0
+ rm -f "$DC_ROOT/etc/resolv.conf"
+ printf 'nameserver %s\n' "$DC_NAT_DNS" > "$DC_ROOT/etc/resolv.conf"
+}
+
+dc_network_nat_setup_firewall() {
+ dc_require_commands grep nft sysctl
+
+ sysctl -w net.ipv4.ip_forward=1 >/dev/null
+ if ! nft list table ip rutils_nat >/dev/null 2>&1; then
+ nft add table ip rutils_nat
+ fi
+ if ! nft list chain ip rutils_nat postrouting >/dev/null 2>&1; then
+ nft 'add chain ip rutils_nat postrouting { type nat hook postrouting priority 100; policy accept; }'
+ fi
+ if ! nft list chain ip rutils_nat postrouting | grep -Fq "ip saddr $DC_NAT_NETWORK"; then
+ nft add rule ip rutils_nat postrouting ip saddr "$DC_NAT_NETWORK" oifname != "$DC_NAT_BRIDGE" masquerade
+ fi
+}
+
+dc_network_nat_setup() {
+ local netns=$1
+ local host_interface=$2
+ local guest_interface=$3
+
+ dc_require_commands grep ip
+ if ! ip link show "$DC_NAT_BRIDGE" >/dev/null 2>&1; then
+ ip link add "$DC_NAT_BRIDGE" type bridge
+ fi
+ ip link set "$DC_NAT_BRIDGE" up
+ if ! ip -4 addr show dev "$DC_NAT_BRIDGE" | grep -Fq "inet $DC_NAT_GATEWAY/"; then
+ ip addr add "$DC_NAT_GATEWAY/$DC_NAT_PREFIX" dev "$DC_NAT_BRIDGE"
+ fi
+
+ ip netns add "$netns"
+ ip link add "$host_interface" type veth peer name "$guest_interface"
+ ip link set "$guest_interface" netns "$netns"
+ ip link set "$host_interface" master "$DC_NAT_BRIDGE"
+ ip link set "$host_interface" up
+
+ ip netns exec "$netns" ip link set lo up
+ ip netns exec "$netns" ip link set "$guest_interface" name eth0
+ ip netns exec "$netns" ip addr add "$DC_NAT_ADDRESS/$DC_NAT_PREFIX" dev eth0
+ ip netns exec "$netns" ip link set eth0 up
+ ip netns exec "$netns" ip route add default via "$DC_NAT_GATEWAY"
+ dc_network_nat_setup_firewall
+}
+
+dc_network_nat_cleanup() {
+ local netns=$1
+ local host_interface=$2
+
+ ip link delete "$host_interface" 2>/dev/null || true
+ ip netns delete "$netns" 2>/dev/null || true
+}
+
+dc_network_nat_run() {
+ local child_action=$1
+ local netns="rutils-${DC_INSTANCE}-$$"
+ local host_interface="rvh$$"
+ local guest_interface="rvg$$"
+
+ shift
+ trap "dc_network_nat_cleanup '$netns' '$host_interface'" EXIT
+ dc_network_nat_setup "$netns" "$host_interface" "$guest_interface"
+ env DEBIAN_NETWORK=nat ip netns exec "$netns" \
+ unshare --mount --uts --ipc --pid --fork --propagation private -- \
+ bash "$DC_SCRIPT" "$child_action" "$DC_INSTANCE" "$@"
+}