深入理解 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 工程师都至关重要。

相关推荐
maosheng11462 小时前
RHCSA的第一次作业
linux·运维·服务器
wifi chicken2 小时前
Linux 端口扫描及拓展
linux·端口扫描·网络攻击
旺仔.2913 小时前
Linux 信号详解
linux·运维·网络
放飞梦想C3 小时前
CPU Cache
linux·cache
Hoshino.413 小时前
基于Linux中的数据库操作——下载与安装(1)
linux·运维·数据库
播播资源5 小时前
CentOS系统 + 宝塔面板 部署 OpenClaw源码开发版完整教程
linux·运维·centos
源远流长jerry5 小时前
在 Ubuntu 22.04 上配置 Soft-RoCE 并运行 RDMA 测试程序
linux·服务器·网络·tcp/ip·ubuntu·架构·ip
lay_liu6 小时前
Linux安装redis
linux·运维·redis
寂柒7 小时前
序列化与反序列化
linux·网络
lay_liu7 小时前
ubuntu 安装 Redis
linux·redis·ubuntu