深入理解 Linux 网络命名空间:自己动手实现"虚拟网络"

1. 概述

Linux 网络命名空间是 Linux 内核提供的一种网络隔离机制,它允许创建完全独立的网络栈实例。每个网络命名空间都有自己的网络设备、IP 地址、路由表、防火墙规则等网络资源。这项技术是容器化技术(如 Docker)和虚拟化的基础。

2. 环境准备

2.1 系统要求

  • Linux 内核 2.6.24 或更高版本
  • iproute2 工具包
  • root 权限或 sudo 权限

2.2 检查系统支持

创建检查脚本 check_system.sh

bash 复制代码
#!/bin/bash

# 文件名: check_system.sh

echo "=== 系统检查开始 ==="

# 检查内核版本
echo "1. 检查内核版本:"
uname -r

# 检查网络命名空间支持
echo -e "\n2. 检查网络命名空间支持:"
if [ -e /proc/self/ns/net ]; then
    echo "✓ 系统支持网络命名空间"
else
    echo "✗ 系统不支持网络命名空间"
    exit 1
fi

# 检查 iproute2 工具
echo -e "\n3. 检查 iproute2 工具:"
if command -v ip > /dev/null 2>&1; then
    echo "✓ iproute2 已安装"
    ip -Version
else
    echo "✗ iproute2 未安装,请安装: sudo apt-get install iproute2"
    exit 1
fi

# 检查用户权限
echo -e "\n4. 检查用户权限:"
if [ "$EUID" -eq 0 ]; then
    echo "✓ 当前为 root 用户"
else
    echo "⚠ 当前为非 root 用户,部分操作可能需要 sudo"
fi

echo -e "\n=== 系统检查完成 ==="

运行检查脚本:

bash 复制代码
chmod +x check_system.sh
./check_system.sh

3. 基础网络命名空间操作

3.1 创建和删除网络命名空间

创建基础操作脚本 basic_namespace_operations.sh

bash 复制代码
#!/bin/bash

# 文件名: basic_namespace_operations.sh

set -e  # 遇到错误立即退出

# 颜色定义
RED='\033[0;31m'
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
NC='\033[0m' # No Color

# 打印带颜色的消息
print_info() {
    echo -e "${GREEN}[INFO]${NC} $1"
}

print_warning() {
    echo -e "${YELLOW}[WARNING]${NC} $1"
}

print_error() {
    echo -e "${RED}[ERROR]${NC} $1"
}

# 创建网络命名空间
create_namespace() {
    local ns_name=$1
    print_info "创建网络命名空间: $ns_name"
    ip netns add $ns_name
    
    # 验证创建
    if ip netns list | grep -q "$ns_name"; then
        print_info "✓ 命名空间 $ns_name 创建成功"
    else
        print_error "✗ 命名空间 $ns_name 创建失败"
        exit 1
    fi
}

# 在命名空间中执行命令
exec_in_namespace() {
    local ns_name=$1
    local command=$2
    print_info "在命名空间 $ns_name 中执行: $command"
    ip netns exec $ns_name $command
}

# 显示命名空间网络信息
show_namespace_network() {
    local ns_name=$1
    print_info "=== 命名空间 $ns_name 的网络信息 ==="
    
    echo "网络接口:"
    exec_in_namespace $ns_name "ip link show"
    
    echo -e "\nIP 地址:"
    exec_in_namespace $ns_name "ip addr show"
    
    echo -e "\n路由表:"
    exec_in_namespace $ns_name "ip route show"
}

# 删除网络命名空间
delete_namespace() {
    local ns_name=$1
    print_info "删除网络命名空间: $ns_name"
    ip netns delete $ns_name
    
    # 验证删除
    if ! ip netns list | grep -q "$ns_name"; then
        print_info "✓ 命名空间 $ns_name 删除成功"
    else
        print_error "✗ 命名空间 $ns_name 删除失败"
    fi
}

# 主函数
main() {
    print_info "开始基础网络命名空间操作演示"
    
    # 创建两个测试命名空间
    create_namespace "ns1"
    create_namespace "ns2"
    
    echo -e "\n"
    print_info "当前所有网络命名空间:"
    ip netns list
    
    echo -e "\n"
    # 显示默认命名空间信息
    print_info "=== 默认命名空间网络信息 ==="
    ip link show
    echo -e "\n"
    ip addr show
    echo -e "\n"
    ip route show
    
    echo -e "\n"
    # 显示新创建的命名空间信息
    show_namespace_network "ns1"
    echo -e "\n"
    show_namespace_network "ns2"
    
    # 清理
    echo -e "\n"
    delete_namespace "ns1"
    delete_namespace "ns2"
    
    print_info "基础网络命名空间操作演示完成"
}

# 执行主函数
main "$@"

运行基础操作脚本:

bash 复制代码
chmod +x basic_namespace_operations.sh
sudo ./basic_namespace_operations.sh

4. 创建虚拟网络设备

4.1 创建 veth pair

veth(虚拟以太网设备)总是成对出现,用于连接不同的网络命名空间。

创建 veth 配置脚本 create_veth_network.sh

bash 复制代码
#!/bin/bash

# 文件名: create_veth_network.sh

set -e

# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
NC='\033[0m'

print_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_step() { echo -e "${BLUE}[STEP]${NC} $1"; }

# 清理函数
cleanup() {
    print_info "执行清理操作..."
    
    # 删除命名空间(如果存在)
    for ns in ns1 ns2; do
        if ip netns list | grep -q "$ns"; then
            ip netns delete $ns 2>/dev/null || true
        fi
    done
    
    # 删除 veth 设备(如果存在)
    ip link delete veth1 2>/dev/null || true
    ip link delete veth1-br 2>/dev/null || true
    ip link delete veth2 2>/dev/null || true
    ip link delete veth2-br 2>/dev/null || true
    ip link delete br0 2>/dev/null || true
}

# 捕获退出信号
trap cleanup EXIT

main() {
    print_info "开始创建虚拟网络..."
    
    # 步骤1: 创建网络命名空间
    print_step "1. 创建网络命名空间"
    ip netns add ns1
    ip netns add ns2
    print_info "✓ 创建命名空间: ns1, ns2"
    
    # 步骤2: 创建第一对 veth
    print_step "2. 创建 veth pair: veth1 <-> veth1-br"
    ip link add veth1 type veth peer name veth1-br
    print_info "✓ 创建 veth pair: veth1 <-> veth1-br"
    
    # 步骤3: 创建第二对 veth
    print_step "3. 创建 veth pair: veth2 <-> veth2-br"
    ip link add veth2 type veth peer name veth2-br
    print_info "✓ 创建 veth pair: veth2 <-> veth2-br"
    
    # 步骤4: 将 veth 设备移动到对应的命名空间
    print_step "4. 移动 veth 设备到命名空间"
    ip link set veth1 netns ns1
    ip link set veth2 netns ns2
    print_info "✓ veth1 移动到 ns1"
    print_info "✓ veth2 移动到 ns2"
    
    # 步骤5: 在命名空间中配置网络接口
    print_step "5. 配置命名空间中的网络接口"
    
    # 配置 ns1 中的 veth1
    ip netns exec ns1 ip link set lo up
    ip netns exec ns1 ip link set veth1 up
    ip netns exec ns1 ip addr add 10.0.1.10/24 dev veth1
    print_info "✓ ns1: veth1 配置 IP 10.0.1.10/24"
    
    # 配置 ns2 中的 veth2
    ip netns exec ns2 ip link set lo up
    ip netns exec ns2 ip link set veth2 up
    ip netns exec ns2 ip addr add 10.0.1.20/24 dev veth2
    print_info "✓ ns2: veth2 配置 IP 10.0.1.20/24"
    
    # 步骤6: 测试连通性
    print_step "6. 测试直接连通性"
    
    # 由于没有桥接,此时应该无法连通
    print_info "测试 ns1 -> ns2 连通性:"
    if ip netns exec ns1 ping -c 2 -W 1 10.0.1.20 >/dev/null 2>&1; then
        print_info "✓ ns1 可以 ping 通 ns2"
    else
        print_warning "✗ ns1 无法 ping 通 ns2 (正常,因为尚未桥接)"
    fi
    
    # 显示网络配置
    print_step "7. 显示当前网络配置"
    
    echo -e "\n默认命名空间接口:"
    ip link show | grep -E "(veth|br)"
    
    echo -e "\nns1 网络配置:"
    ip netns exec ns1 ip addr show
    
    echo -e "\nns2 网络配置:"
    ip netns exec ns2 ip addr show
    
    print_info "虚拟网络创建完成!"
    print_warning "注意: 由于没有桥接设备,命名空间之间目前无法通信"
}

main "$@"

运行 veth 创建脚本:

bash 复制代码
chmod +x create_veth_network.sh
sudo ./create_veth_network.sh

5. 构建完整虚拟网络

5.1 使用 Linux 网桥连接多个命名空间

创建完整的虚拟网络脚本 create_complete_network.sh

bash 复制代码
#!/bin/bash

# 文件名: create_complete_network.sh

set -e

# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
BLUE='\033[0;34m'
RED='\033[0;31m'
NC='\033[0m'

print_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_step() { echo -e "${BLUE}[STEP]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }

# 网络配置
BRIDGE_NAME="br0"
BRIDGE_IP="10.0.1.1/24"
NS1_IP="10.0.1.10/24"
NS2_IP="10.0.1.20/24"
NS3_IP="10.0.1.30/24"

# 清理函数
cleanup() {
    print_info "执行清理操作..."
    
    # 删除命名空间
    for ns in ns1 ns2 ns3; do
        if ip netns list | grep -q "$ns"; then
            ip netns delete $ns 2>/dev/null || true
        fi
    done
    
    # 删除网络接口
    for iface in veth1 veth1-br veth2 veth2-br veth3 veth3-br $BRIDGE_NAME; do
        if ip link show $iface >/dev/null 2>&1; then
            ip link delete $iface 2>/dev/null || true
        fi
    done
    
    # 清理 iptables 规则
    iptables -t nat -D POSTROUTING -s 10.0.1.0/24 -j MASQUERADE 2>/dev/null || true
}

trap cleanup EXIT

# 测试连通性
test_connectivity() {
    local source_ns=$1
    local target_ip=$2
    local test_name=$3
    
    print_info "测试 $test_name: $source_ns -> $target_ip"
    if ip netns exec $source_ns ping -c 2 -W 1 $target_ip >/dev/null 2>&1; then
        print_info "✓ $test_name 成功"
        return 0
    else
        print_error "✗ $test_name 失败"
        return 1
    fi
}

main() {
    print_info "开始创建完整虚拟网络..."
    
    # 步骤1: 创建网络命名空间
    print_step "1. 创建三个网络命名空间"
    for ns in ns1 ns2 ns3; do
        ip netns add $ns
        print_info "✓ 创建命名空间: $ns"
    done
    
    # 步骤2: 创建 Linux 网桥
    print_step "2. 创建 Linux 网桥: $BRIDGE_NAME"
    ip link add name $BRIDGE_NAME type bridge
    ip link set $BRIDGE_NAME up
    ip addr add $BRIDGE_IP dev $BRIDGE_NAME
    print_info "✓ 网桥 $BRIDGE_NAME 创建并启动,IP: $BRIDGE_IP"
    
    # 步骤3: 创建并配置 veth pair
    print_step "3. 创建和配置 veth pair"
    
    for i in 1 2 3; do
        # 创建 veth pair
        ip link add veth$i type veth peer name veth$i-br
        print_info "✓ 创建 veth pair: veth$i <-> veth$i-br"
        
        # 将 veth 一端移动到命名空间
        ip link set veth$i netns ns$i
        print_info "✓ veth$i 移动到 ns$i"
        
        # 将 veth 另一端连接到网桥
        ip link set veth$i-br master $BRIDGE_NAME
        ip link set veth$i-br up
        print_info "✓ veth$i-br 连接到网桥 $BRIDGE_NAME"
        
        # 配置命名空间中的网络
        ip netns exec ns$i ip link set lo up
        ip netns exec ns$i ip link set veth$i up
        
        # 分配 IP 地址
        case $i in
            1) ip netns exec ns$i ip addr add $NS1_IP dev veth$i ;;
            2) ip netns exec ns$i ip addr add $NS2_IP dev veth$i ;;
            3) ip netns exec ns$i ip addr add $NS3_IP dev veth$i ;;
        esac
        
        print_info "✓ ns$i: veth$i 配置完成"
    done
    
    # 步骤4: 配置默认网关
    print_step "4. 配置默认网关"
    for i in 1 2 3; do
        ip netns exec ns$i ip route add default via 10.0.1.1 dev veth$i
        print_info "✓ ns$i 默认网关: 10.0.1.1"
    done
    
    # 步骤5: 启用 IP 转发和 NAT
    print_step "5. 配置系统网络设置"
    echo 1 > /proc/sys/net/ipv4/ip_forward
    iptables -t nat -A POSTROUTING -s 10.0.1.0/24 -j MASQUERADE
    print_info "✓ 启用 IPv4 转发"
    print_info "✓ 配置 NAT MASQUERADE"
    
    # 步骤6: 测试网络连通性
    print_step "6. 测试网络连通性"
    
    # 测试网桥内部通信
    test_connectivity "ns1" "10.0.1.20" "内部通信 ns1->ns2"
    test_connectivity "ns1" "10.0.1.30" "内部通信 ns1->ns3"
    test_connectivity "ns2" "10.0.1.10" "内部通信 ns2->ns1"
    test_connectivity "ns3" "10.0.1.10" "内部通信 ns3->ns1"
    
    # 测试网关可达性
    test_connectivity "ns1" "10.0.1.1" "网关可达性"
    
    # 步骤7: 显示网络拓扑信息
    print_step "7. 显示网络拓扑信息"
    
    echo -e "\n${BLUE}=== 网络拓扑摘要 ===${NC}"
    echo "网桥: $BRIDGE_NAME (IP: $BRIDGE_IP)"
    echo "命名空间:"
    echo "  ns1: veth1 (IP: $NS1_IP)"
    echo "  ns2: veth2 (IP: $NS2_IP)" 
    echo "  ns3: veth3 (IP: $NS3_IP)"
    
    echo -e "\n${BLUE}=== 网桥信息 ===${NC}"
    brctl show $BRIDGE_NAME
    
    echo -e "\n${BLUE}=== 详细接口信息 ===${NC}"
    for ns in ns1 ns2 ns3; do
        echo -e "\n命名空间 $ns:"
        ip netns exec $ns ip addr show | grep -E "(inet|veth)"
        echo "路由表:"
        ip netns exec $ns ip route show
    done
    
    print_info "完整虚拟网络创建成功!"
    print_warning "输入 'sudo ./cleanup_network.sh' 来清理网络"
}

main "$@"

运行完整网络创建脚本:

bash 复制代码
chmod +x create_complete_network.sh
sudo ./create_complete_network.sh

5.2 网络拓扑可视化

创建网络拓扑图生成脚本 generate_network_diagram.sh

bash 复制代码
#!/bin/bash

# 文件名: generate_network_diagram.sh

cat > network_topology.md << 'EOF'
# 虚拟网络拓扑图

```mermaid
graph TB
    %% 样式定义
    classDef default fill:#1e1e1e,stroke:#666,stroke-width:2px,color:#fff;
    classDef namespace fill:#2d5a78,stroke:#4ca1cf,stroke-width:2px,color:#fff;
    classDef bridge fill:#5d3a6a,stroke:#b57edc,stroke-width:2px,color:#fff;
    classDef veth fill:#356635,stroke:#6bc36b,stroke-width:2px,color:#fff;
    
    %% 网桥
    br0[br0<br/>10.0.1.1/24]:::bridge
    
    %% 命名空间1
    subgraph ns1[网络命名空间 ns1]
        veth1_ns[veth1<br/>10.0.1.10/24]:::veth
    end
    
    %% 命名空间2  
    subgraph ns2[网络命名空间 ns2]
        veth2_ns[veth2<br/>10.0.1.20/24]:::veth
    end
    
    %% 命名空间3
    subgraph ns3[网络命名空间 ns3]
        veth3_ns[veth3<br/>10.0.1.30/24]:::veth
    end
    
    %% 连接关系
    veth1_ns -.->|veth pair| veth1_br
    veth2_ns -.->|veth pair| veth2_br  
    veth3_ns -.->|veth pair| veth3_br
    
    veth1_br --> br0
    veth2_br --> br0
    veth3_br --> br0
    
    %% 隐藏的桥接端
    veth1_br:::veth
    veth2_br:::veth
    veth3_br:::veth
    
    %% 样式应用
    class ns1,ns2,ns3 namespace;

数据流路径

flowchart TD A[外部网络] <--> B[物理接口 eth0] B <--> C[Linux 主机路由] C <--> D{NAT 转换iptables} D <--> E[网桥 br0 10.0.1.1/24] E <--> F[veth1-br] F <-.-> G[veth1 10.0.1.10/24] G <--> H[ns1 应用] E <--> I[veth2-br] I <-.-> J[veth2 10.0.1.20/24] J <--> K[ns2 应用] E <--> L[veth3-br] L <-.-> M[veth3 10.0.1.30/24] M <--> N[ns3 应用]

EOF

echo "网络拓扑图已生成到 network_topology.md" echo "可以使用支持 Mermaid 的 Markdown 查看器查看图表"

运行拓扑图生成脚本:

bash 复制代码
chmod +x generate_network_diagram.sh
./generate_network_diagram.sh

6. 高级网络配置

6.1 VLAN 隔离配置

创建 VLAN 配置脚本 configure_vlan.sh

bash 复制代码
#!/bin/bash

# 文件名: configure_vlan.sh

set -e

# 颜色定义
GREEN='\033[0;32m'
BLUE='\033[0;34m'
NC='\033[0m'

print_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
print_step() { echo -e "${BLUE}[STEP]${NC} $1"; }

cleanup() {
    print_info "清理 VLAN 配置..."
    
    # 删除命名空间
    for ns in vlan10-ns1 vlan10-ns2 vlan20-ns1 vlan20-ns2; do
        if ip netns list | grep -q "$ns"; then
            ip netns delete $ns 2>/dev/null || true
        fi
    done
    
    # 删除 VLAN 接口和网桥
    for br in br-vlan10 br-vlan20; do
        if ip link show $br >/dev/null 2>&1; then
            ip link set $br down
            ip link delete $br 2>/dev/null || true
        fi
    done
    
    # 删除物理接口上的 VLAN
    for vlan in 10 20; do
        if ip link show eth0.$vlan >/dev/null 2>&1; then
            ip link delete eth0.$vlan 2>/dev/null || true
        fi
    done
}

trap cleanup EXIT

main() {
    print_info "开始配置 VLAN 网络..."
    
    # 步骤1: 创建命名空间
    print_step "1. 创建 VLAN 命名空间"
    for ns in vlan10-ns1 vlan10-ns2 vlan20-ns1 vlan20-ns2; do
        ip netns add $ns
        print_info "✓ 创建命名空间: $ns"
    done
    
    # 步骤2: 创建 VLAN 网桥
    print_step "2. 创建 VLAN 网桥"
    ip link add name br-vlan10 type bridge
    ip link add name br-vlan20 type bridge
    ip link set br-vlan10 up
    ip link set br-vlan20 up
    print_info "✓ 创建网桥: br-vlan10, br-vlan20"
    
    # 步骤3: 配置 VLAN 接口 (如果物理接口存在)
    print_step "3. 配置 VLAN 接口"
    PHYSICAL_IFACE=$(ip route | grep default | awk '{print $5}' | head -1)
    
    if [ -n "$PHYSICAL_IFACE" ] && [ "$PHYSICAL_IFACE" != "br0" ]; then
        # 创建 VLAN 子接口
        ip link add link $PHYSICAL_IFACE name $PHYSICAL_IFACE.10 type vlan id 10
        ip link add link $PHYSICAL_IFACE name $PHYSICAL_IFACE.20 type vlan id 20
        
        ip link set $PHYSICAL_IFACE.10 up
        ip link set $PHYSICAL_IFACE.20 up
        
        # 将 VLAN 接口连接到对应的网桥
        ip link set $PHYSICAL_IFACE.10 master br-vlan10
        ip link set $PHYSICAL_IFACE.20 master br-vlan20
        
        print_info "✓ 在 $PHYSICAL_IFACE 上创建 VLAN 10 和 VLAN 20"
    else
        print_info "⚠ 未找到合适的物理接口,仅配置内部 VLAN"
    fi
    
    # 步骤4: 创建并配置 veth pair
    print_step "4. 配置 veth pair 和 VLAN 连接"
    
    # VLAN 10 的命名空间
    for i in 1 2; do
        # 创建 veth pair
        ip link add veth-vlan10-$i type veth peer name veth-vlan10-$i-br
        
        # 配置命名空间端
        ip link set veth-vlan10-$i netns vlan10-ns$i
        ip netns exec vlan10-ns$i ip link set lo up
        ip netns exec vlan10-ns$i ip link set veth-vlan10-$i up
        ip netns exec vlan10-ns$i ip addr add 10.10.10.$i$i/24 dev veth-vlan10-$i
        
        # 配置网桥端
        ip link set veth-vlan10-$i-br master br-vlan10
        ip link set veth-vlan10-$i-br up
        
        print_info "✓ 配置 VLAN10: vlan10-ns$i -> 10.10.10.$i$i"
    done
    
    # VLAN 20 的命名空间  
    for i in 1 2; do
        # 创建 veth pair
        ip link add veth-vlan20-$i type veth peer name veth-vlan20-$i-br
        
        # 配置命名空间端
        ip link set veth-vlan20-$i netns vlan20-ns$i
        ip netns exec vlan20-ns$i ip link set lo up
        ip netns exec vlan20-ns$i ip link set veth-vlan20-$i up
        ip netns exec vlan20-ns$i ip addr add 10.10.20.$i$i/24 dev veth-vlan20-$i
        
        # 配置网桥端
        ip link set veth-vlan20-$i-br master br-vlan20
        ip link set veth-vlan20-$i-br up
        
        print_info "✓ 配置 VLAN20: vlan20-ns$i -> 10.10.20.$i$i"
    done
    
    # 步骤5: 配置网桥 IP
    print_step "5. 配置网桥管理 IP"
    ip addr add 10.10.10.1/24 dev br-vlan10 2>/dev/null || true
    ip addr add 10.10.20.1/24 dev br-vlan20 2>/dev/null || true
    
    # 步骤6: 测试连通性
    print_step "6. 测试 VLAN 连通性"
    
    echo -e "\n测试 VLAN10 内部通信:"
    if ip netns exec vlan10-ns1 ping -c 2 -W 1 10.10.10.22 >/dev/null 2>&1; then
        print_info "✓ VLAN10 内部通信正常"
    else
        print_info "✗ VLAN10 内部通信失败"
    fi
    
    echo -e "\n测试 VLAN20 内部通信:"
    if ip netns exec vlan20-ns1 ping -c 2 -W 1 10.10.20.22 >/dev/null 2>&1; then
        print_info "✓ VLAN20 内部通信正常"
    else
        print_info "✗ VLAN20 内部通信失败"
    fi
    
    echo -e "\n测试 VLAN 间隔离:"
    if ip netns exec vlan10-ns1 ping -c 2 -W 1 10.10.20.11 >/dev/null 2>&1; then
        print_info "✗ VLAN 隔离失败 (异常)"
    else
        print_info "✓ VLAN 隔离正常"
    fi
    
    # 步骤7: 显示配置信息
    print_step "7. 显示 VLAN 配置信息"
    
    echo -e "\n网桥信息:"
    for br in br-vlan10 br-vlan20; do
        echo -e "\n$br:"
        bridge link show dev $br 2>/dev/null || brctl show $br 2>/dev/null || echo "无法获取网桥信息"
    done
    
    echo -e "\nVLAN 接口:"
    ip link show | grep -E "vlan|br-vlan"
    
    print_info "VLAN 配置完成!"
}

main "$@"

运行 VLAN 配置脚本:

bash 复制代码
chmod +x configure_vlan.sh
sudo ./configure_vlan.sh

7. 网络监控和诊断

7.1 网络状态监控脚本

创建网络监控脚本 network_monitor.sh

bash 复制代码
#!/bin/bash

# 文件名: network_monitor.sh

# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
BLUE='\033[0;34m'
NC='\033[0m'

print_header() {
    echo -e "${BLUE}=== $1 ===${NC}"
}

print_success() {
    echo -e "${GREEN}✓ $1${NC}"
}

print_warning() {
    echo -e "${YELLOW}⚠ $1${NC}"
}

print_error() {
    echo -e "${RED}✗ $1${NC}"
}

# 监控函数
monitor_namespaces() {
    print_header "网络命名空间状态"
    
    local namespaces=$(ip netns list)
    if [ -z "$namespaces" ]; then
        print_warning "没有找到网络命名空间"
        return
    fi
    
    echo "$namespaces" | while read ns; do
        echo -e "\n命名空间: $ns"
        echo "接口状态:"
        ip netns exec $ns ip -o link show | awk '{print "  " $2 " " $3 " " $9}'
        echo "IP 地址:"
        ip netns exec $ns ip -o addr show | grep -v "inet6" | awk '{print "  " $2 " " $4}'
        echo "路由表:"
        ip netns exec $ns ip route show | sed 's/^/  /'
    done
}

monitor_bridges() {
    print_header "网桥状态"
    
    # 尝试使用 bridge 命令
    if command -v bridge > /dev/null 2>&1; then
        bridge link show
    else
        # 回退到 brctl
        if command -v brctl > /dev/null 2>&1; then
            brctl show
        else
            print_warning "未找到 bridge-utils 或 iproute2 bridge 工具"
        fi
    fi
}

monitor_connections() {
    print_header "活跃连接测试"
    
    # 测试本地回环
    if ping -c 1 -W 1 127.0.0.1 >/dev/null 2>&1; then
        print_success "本地回环正常"
    else
        print_error "本地回环异常"
    fi
    
    # 测试网关连接(如果有默认网关)
    local gateway=$(ip route | grep default | awk '{print $3}' | head -1)
    if [ -n "$gateway" ]; then
        if ping -c 1 -W 1 $gateway >/dev/null 2>&1; then
            print_success "网关 $gateway 可达"
        else
            print_warning "网关 $gateway 不可达"
        fi
    fi
}

monitor_iptables() {
    print_header "防火墙规则"
    
    for table in filter nat mangle; do
        echo -e "\n表: $table"
        iptables -t $table -L -n 2>/dev/null | head -20
    done
}

monitor_system_stats() {
    print_header "系统网络统计"
    
    echo -e "\n网络接口统计:"
    ip -s link show
    
    echo -e "\n连接统计:"
    ss -s
}

# 持续监控模式
continuous_monitor() {
    local interval=${1:-5}
    
    while true; do
        clear
        print_header "网络监控 - $(date)"
        monitor_namespaces
        monitor_bridges
        monitor_connections
        echo -e "\n${YELLOW}按 Ctrl+C 退出监控...${NC}"
        sleep $interval
    done
}

# 主函数
main() {
    case "${1:-}" in
        "continuous"|"cont"|"c")
            continuous_monitor "${2:-5}"
            ;;
        "help"|"-h"|"--help")
            echo "用法: $0 [mode]"
            echo "模式:"
            echo "  continuous [interval]   持续监控模式,可指定间隔(秒)"
            echo "  help                    显示此帮助信息"
            echo "  无参数                  单次监控快照"
            ;;
        *)
            print_header "网络监控快照 - $(date)"
            monitor_namespaces
            monitor_bridges
            monitor_connections
            monitor_iptables
            monitor_system_stats
            ;;
    esac
}

main "$@"

运行网络监控:

bash 复制代码
chmod +x network_monitor.sh
# 单次监控
sudo ./network_monitor.sh

# 持续监控(每5秒刷新)
sudo ./network_monitor.sh continuous 5

8. 清理脚本

创建网络清理脚本 cleanup_network.sh

bash 复制代码
#!/bin/bash

# 文件名: cleanup_network.sh

set -e

# 颜色定义
GREEN='\033[0;32m'
YELLOW='\033[1;33m'
RED='\033[0;31m'
NC='\033[0m'

print_info() { echo -e "${GREEN}[INFO]${NC} $1"; }
print_warning() { echo -e "${YELLOW}[WARNING]${NC} $1"; }
print_error() { echo -e "${RED}[ERROR]${NC} $1"; }

confirm_cleanup() {
    read -p "确定要清理所有虚拟网络配置吗?(y/N): " -n 1 -r
    echo
    if [[ ! $REPLY =~ ^[Yy]$ ]]; then
        print_info "取消清理操作"
        exit 0
    fi
}

cleanup_namespaces() {
    print_info "清理网络命名空间..."
    
    local namespaces=$(ip netns list | awk '{print $1}')
    if [ -z "$namespaces" ]; then
        print_info "没有找到需要清理的命名空间"
        return
    fi
    
    for ns in $namespaces; do
        print_info "删除命名空间: $ns"
        ip netns delete $ns
    done
}

cleanup_bridges() {
    print_info "清理网桥..."
    
    # 获取所有网桥
    local bridges=$(ip link show type bridge | grep -o "br[^:]*" || true)
    
    for br in $bridges; do
        # 跳过一些系统网桥
        case $br in
            "docker0"|"virbr0")
                print_warning "跳过系统网桥: $br"
                continue
                ;;
        esac
        
        print_info "删除网桥: $br"
        ip link set $br down
        ip link delete $br
    done
}

cleanup_veth_pairs() {
    print_info "清理 veth pair..."
    
    # 查找所有 veth 设备
    local veth_devices=$(ip link show | grep -o "veth[^@]*" | uniq || true)
    
    for dev in $veth_devices; do
        print_info "删除 veth 设备: $dev"
        ip link delete $dev 2>/dev/null || true
    done
}

cleanup_vlan_interfaces() {
    print_info "清理 VLAN 接口..."
    
    # 查找 VLAN 子接口
    local vlan_ifaces=$(ip link show | grep -o "[^ ]*\.[0-9]*@[^:]*" | cut -d'@' -f1 | uniq || true)
    
    for iface in $vlan_ifaces; do
        print_info "删除 VLAN 接口: $iface"
        ip link delete $iface 2>/dev/null || true
    done
}

cleanup_iptables_rules() {
    print_info "清理 iptables 规则..."
    
    # 清理 NAT 规则
    iptables -t nat -F
    iptables -t mangle -F
    iptables -F
    iptables -X
    
    print_info "✓ iptables 规则已清理"
}

reset_network_settings() {
    print_info "重置网络设置..."
    
    # 禁用 IP 转发
    echo 0 > /proc/sys/net/ipv4/ip_forward
    
    # 刷新路由缓存
    ip route flush cache
    
    print_info "✓ 网络设置已重置"
}

show_remaining_objects() {
    print_info "检查剩余网络对象..."
    
    echo -e "\n剩余网络命名空间:"
    ip netns list
    
    echo -e "\n剩余网桥:"
    ip link show type bridge 2>/dev/null || echo "无"
    
    echo -e "\n剩余 veth 设备:"
    ip link show | grep "veth" || echo "无"
}

main() {
    echo "=== 虚拟网络清理工具 ==="
    
    # 请求确认
    confirm_cleanup
    
    # 执行清理操作
    cleanup_namespaces
    cleanup_bridges
    cleanup_veth_pairs
    cleanup_vlan_interfaces
    cleanup_iptables_rules
    reset_network_settings
    
    echo -e "\n"
    show_remaining_objects
    
    print_info "虚拟网络清理完成!"
}

# 检查 root 权限
if [ "$EUID" -ne 0 ]; then
    print_error "请使用 root 权限运行此脚本: sudo $0"
    exit 1
fi

main "$@"

运行清理脚本:

bash 复制代码
chmod +x cleanup_network.sh
sudo ./cleanup_network.sh

9. 总结

通过本教程,我们深入学习了 Linux 网络命名空间的各个方面:

  1. 基础概念:理解了网络命名空间的隔离机制
  2. 实际操作:掌握了创建、配置和管理网络命名空间的技能
  3. 网络构建:学会了使用 veth pair 和网桥构建复杂虚拟网络
  4. 高级特性:了解了 VLAN 配置和网络隔离
  5. 监控诊断:掌握了网络状态监控和故障诊断方法

这些技能为理解容器网络、虚拟化技术和云原生基础设施打下了坚实基础。网络命名空间是现代 Linux 网络虚拟化的核心技术,掌握它对于系统管理员、网络工程师和 DevOps 工程师都至关重要。

相关推荐
powerfulhell3 小时前
11.11作业
linux·运维·centos
板鸭〈小号〉3 小时前
进程间关系(linux)
linux·运维·服务器
liu****3 小时前
18.HTTP协议(一)
linux·网络·网络协议·http·udp·1024程序员节
脏脏a3 小时前
【Linux】冯诺依曼体系结构与操作系统概述
linux·服务器
adnyting4 小时前
【Linux日新月异(三)】CentOS 7软件管理深度指南:从YUM到源码编译
linux·运维·centos
知识分享小能手4 小时前
openEuler入门学习教程,从入门到精通,云计算与 Linux 操作系统概述(1)
linux·云计算·openeuler
励志成为编程高手4 小时前
在ubuntu中创建根文件系统
linux·ubuntu·rootfs
HIT_Weston4 小时前
31、【Ubuntu】【远程开发】内网穿透:反向隧道建立(三)
linux·运维·ubuntu
skywalk81635 小时前
在FreeBSD 14.3上部署轻量级Linux jail环境 仅仅占用10M内存
linux·运维·服务器·虚拟机·轻量化·freebsd·jail