# 自动为多网卡Linux云服务器配置IPv4策略路由（Ubuntu）
#### 操作场景
本文档指导用户使用自动化脚本为双网卡Linux云服务器配置策略路由，**自动化脚本支持的操作系统为Ubuntu 22.04版本。**
关于云服务器双网卡的背景知识及组网说明，请参见[方案概述](https://support.huaweicloud.com/usermanual-vpc/vpc_nic_0014.html#vpc_nic_0014)。
#### Linux IPv4操作步骤
1. 收集配置策略路由需要的云服务器IPv4网卡地址等信息。 具体操作请参见[收集云服务器网络信息](https://support.huaweicloud.com/usermanual-vpc/vpc_nic_0015.html#vpc_nic_0015)。
   本示例中，云服务器的网络信息如[表1]所示。
    表1Linux IPv4信息说明 
   | 类型   | 主网卡                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                | 扩展网卡                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                     |
   |:---|:---|:---|
   | 源端  | - 网卡IPv4地址：10.0.0.115  - 子网IPv4网段：10.0.0.0/24  - 子网IPv4网关：10.0.0.1   | - 网卡IPv4地址：10.0.1.183  - 子网IPv4网段：10.0.1.0/24  - 子网IPv4网关：10.0.1.1   |
   | 目的端 | 网卡IPv4地址：10.0.2.12                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                 | 不涉及                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                                       |
      
   
2. 登录源端云服务器。 ECS有多种登录方法，具体请参见[登录弹性云服务器](https://support.huaweicloud.com/ecs_faq/ecs_faq_0632.html)。
   
3. 执行以下命令，检查源端云服务器主网卡和目的端云服务器IPv4网络通信情况。 **配置多网卡策略路由前，请务必确保源端主网卡和目的端通信正常。**
   **ping -I** *源端云服务器主网卡IPv4地址* *目的端云服务器网卡IPv4地址*
   命令示例：
   ping -I 10.0.0.115 10.0.2.12
   回显类似如下信息，表示可以正常通信。
   ```
   root@ecs-resource:~# ping -I 10.0.0.115 10.0.2.12
   PING 10.0.2.12 (10.0.2.12) from 10.0.0.115 : 56(84) bytes of data.
   64 bytes from 10.0.2.12: icmp_seq=1 ttl=64 time=0.262 ms
   64 bytes from 10.0.2.12: icmp_seq=2 ttl=64 time=0.193 ms
   64 bytes from 10.0.2.12: icmp_seq=3 ttl=64 time=0.086 ms
   ^C
   --- 10.0.2.12 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2045ms
   rtt min/avg/max/mdev = 0.086/0.180/0.262/0.072 ms
   ```
   
4. 执行以下命令，查看云服务器网卡名称。 ifconfig
   回显类似如下信息，通过网卡地址查找对应的网卡名称，本示例中：
   - 10.0.0.115为主网卡IPv4地址，对应的名称为eth0。
   
   - 10.0.1.183为扩展网卡IPv4地址，对应的名称为eth1。
    
   ```
   root@ecs-resource:~# ifconfig
   eth0: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
           inet 10.0.0.115  netmask 255.255.255.0  broadcast 10.0.0.255
           inet6 fe80::f816:3eff:fe72:72e5  prefixlen 64  scopeid 0x20<link>
           ether fa:16:3e:72:72:e5  txqueuelen 1000  (Ethernet)
           RX packets 139035  bytes 201093027 (201.0 MB)
           RX errors 0  dropped 0  overruns 0  frame 0
           TX packets 18669  bytes 1744334 (1.7 MB)
           TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
   eth1: flags=4163<UP,BROADCAST,RUNNING,MULTICAST>  mtu 1500
           inet 10.0.1.183  netmask 255.255.255.0  broadcast 10.0.1.255
           inet6 fe80::f816:3eff:fe72:7329  prefixlen 64  scopeid 0x20<link>
           ether fa:16:3e:72:73:29  txqueuelen 1000  (Ethernet)
           RX packets 2  bytes 738 (738.0 B)
           RX errors 0  dropped 0  overruns 0  frame 0
           TX packets 35  bytes 2466 (2.4 KB)
           TX errors 0  dropped 0 overruns 0  carrier 0  collisions 0
   ```
   
5. 执行以下步骤，创建自动化脚本配置IPv4路由。
   1. 执行以下命令，创建自动化配置脚本文件**15-policy-route.sh** 。
      **vi /etc/NetworkManager/dispatcher.d/15-policy-route.sh**
      
   
   2. 按i进入编辑模式。
   
   3. 在文件中添加自动化脚本配置文件。
      ```
      #!/bin/bash
      if [ "$2" != "up" ]; then
          exit 0
      fi
      interface=$1
      check_route_table() {
          local route_table_id=$1
          local ip_version=$2
          local max_attempts=100
          local attempts=0
          while [ $attempts -lt $max_attempts ]; do
              output=$(ip -$ip_version route show table $route_table_id &>/dev/null)
              if [ $? -ne 0 ] || [ -z "$output" ]; then
                  break
              else
                  route_table_id=$((route_table_id + 1))
                  attempts=$((attempts + 1))
              fi
          done
          echo $route_table_id
      }
      add_ipv4_route_table() {
          local DEFAULT_IPV4_ROUTE_TABLE_ID=1000
          v4_route_table_id=$(ip route show table all | grep -F "default via $gateway dev $interface table" | awk '{print $NF}')
          if [ -z $v4_route_table_id ]; then
              interface_number=$(echo $interface | grep -o '[0-9]*$')
              if [ -z "$interface_number" ]; then
                  v4_route_table_id="$DEFAULT_IPV4_ROUTE_TABLE_ID"
              else
                  v4_route_table_id=$((DEFAULT_IPV4_ROUTE_TABLE_ID + interface_number))
              fi
              v4_route_table_id=$(check_route_table $v4_route_table_id 4)
              echo "add policy route for dev: $interface table: $v4_route_table_id subnet: $subnet gateway: $gateway"
              ip route add default via $gateway dev $interface table $v4_route_table_id
              ip route add $subnet dev $interface table $v4_route_table_id
          fi
      }
      get_gateway_by_subnet() {
        subnet=$1
        IFS='/' read -r ip mask <<< "$subnet"
        IFS='.' read -r ip1 ip2 ip3 ip4 <<< "$ip"
        gateway="$ip1.$ip2.$ip3.$((ip4+1))"
        echo $gateway
      }
      generate_ipv4_policy_route() {
          subnet=$(nmcli device show $interface | grep -F 'IP4.ROUTE' | grep -F 'nh = 0.0.0.0' | cut -d'=' -f2 | cut -d',' -f1 | tr -d ' ' | head -n 1)
          gateway=$(get_gateway_by_subnet $subnet)
          add_ipv4_route_table
          nmcli device show $interface | grep -F 'IP4.ADDRESS' | while read -r line; do
              IP=$(echo $line | awk '{print $2}' | cut -d'/' -f1)
              if ip rule list | grep -F "$v4_route_table_id" | grep -q "$IP"; then
                  echo "ip rule already exists for $IP with table $v4_route_table_id"
                  continue
              fi
              echo "Adding rule for $IP on $interface with table $v4_route_table_id"
              ip rule add from $IP table $v4_route_table_id
          done
      }
      generate_ipv4_policy_route
      ```
      
   
   4. 按ESC退出，并输入:wq!保存配置。
   
   5. 执行以下命令，查看自动化配置脚本文件**15-policy-route.sh** 的权限。
      **ll /etc/NetworkManager/dispatcher.d/**
      回显类似如下信息，**15-policy-route.sh** 权限为**-rw-r--r--** ，和其他系统文件（比如**01-ifupdown\*** ）的权限（**-rwxr-xr-x** ）不一样。
      ```
      root@ecs-resource:~# ll /etc/NetworkManager/dispatcher.d/
      total 32
      drwxr-xr-x 5 root root 4096 Nov  7 12:21 ./
      drwxr-xr-x 7 root root 4096 Apr 22  2025 ../
      -rwxr-xr-x 1 root root 2293 Dec 11  2024 01-ifupdown*
      -rw-r--r-- 1 root root 2317 Nov  7 12:21 15-policy-route.sh
      -rwxrwxr-x 1 root root  719 May 10  2019 hook-network-manager*
      drwxr-xr-x 2 root root 4096 Dec 11  2024 no-wait.d/
      drwxr-xr-x 2 root root 4096 Dec 11  2024 pre-down.d/
      drwxr-xr-x 2 root root 4096 Dec 11  2024 pre-up.d/
      ```
      
   
   6. 执行以下命令，为自动化配置脚本文件**15-policy-route.sh** 添加权限。
      **sudo chown root:root /etc/NetworkManager/dispatcher.d/15-policy-route.sh**
      **sudo chmod 755 /etc/NetworkManager/dispatcher.d/15-policy-route.sh**
      
   
   7. 执行以下命令，再次查看自动化配置脚本文件**15-policy-route.sh** 的权限。
      **ll /etc/NetworkManager/dispatcher.d/**
      回显类似如下信息，**15-policy-route.sh** 权限为**-rwxr-xr-x。**
      ```
      root@ecs-resource:~# ll /etc/NetworkManager/dispatcher.d/
      total 32
      drwxr-xr-x 5 root root 4096 Nov  7 12:21 ./
      drwxr-xr-x 7 root root 4096 Apr 22  2025 ../
      -rwxr-xr-x 1 root root 2293 Dec 11  2024 01-ifupdown*
      -rwxr-xr-x 1 root root 2317 Nov  7 12:21 15-policy-route.sh*
      -rwxrwxr-x 1 root root  719 May 10  2019 hook-network-manager*
      drwxr-xr-x 2 root root 4096 Dec 11  2024 no-wait.d/
      drwxr-xr-x 2 root root 4096 Dec 11  2024 pre-down.d/
      drwxr-xr-x 2 root root 4096 Dec 11  2024 pre-up.d/
      ```
      
   
   8. 执行以下命令，重启网络服务以触发脚本**15-policy-route.sh** 运行。
      **systemctl restart NetworkManager**
      ![](https://support.huaweicloud.com/usermanual-vpc/public_sys-resources/caution_3.0-zh-cn.png)
      重启网络服务时，此处请确保不影响业务再重启。
      
    
6. 依次执行以下命令，确认网卡IPv4策略路由是否添加成功。 **ip rule**
   **ip route show table 1000**
   **ip route show table** **1001**
   其中，**table** **1000** 为主网卡的路由表名称，**table** **1001**为扩展网卡的路由表名称。
   回显类似如下信息，表示IPv4策略路由添加成功。
   ```
   root@ecs-resource:~# ip rule
   0:      from all lookup local
   32764:  from 10.0.1.183 lookup 1001
   32765:  from 10.0.0.115 lookup 1000
   32766:  from all lookup main
   32767:  from all lookup default
   root@ecs-resource:~# ip route show table 1000
   default via 10.0.0.1 dev eth0 
   10.0.0.0/24 dev eth0 scope link 
   root@ecs-resource:~# ip route show table 1001
   default via 10.0.1.1 dev eth1 
   10.0.1.0/24 dev eth1 scope link
   ```
   
7. 执行以下命令，验证源端云服务器和目的端云服务器是否可以通过IPv4地址正常通信。 **ping -I** *源端云服务器主网卡IPv4地址 目的端云服务器网卡IPv4地址*
   **ping -I** *源端云服务器扩展网卡IPv4地址 目的端云服务器网卡IPv4地址*
   命令示例：
   **ping -I 10.0.0.115 10.0.2.12**
   **ping -I 10.0.1.183 10.0.2.12**
   回显类似如下信息，源端两个IPv4地址均可以和目的端正常通信，表示IPv4策略路由配置成功。
   ```
   root@ecs-resource:~# ping -I 10.0.0.115 10.0.2.12
   PING 10.0.2.12 (10.0.2.12) from 10.0.0.115 : 56(84) bytes of data.
   64 bytes from 10.0.2.12: icmp_seq=1 ttl=64 time=0.233 ms
   64 bytes from 10.0.2.12: icmp_seq=2 ttl=64 time=0.177 ms
   64 bytes from 10.0.2.12: icmp_seq=3 ttl=64 time=0.089 ms
   ^C
   --- 10.0.2.12 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2029ms
   rtt min/avg/max/mdev = 0.089/0.166/0.233/0.059 ms
   root@ecs-resource:~# ping -I 10.0.1.183 10.0.2.12
   PING 10.0.2.12 (10.0.2.12) from 10.0.1.183 : 56(84) bytes of data.
   64 bytes from 10.0.2.12: icmp_seq=1 ttl=64 time=0.300 ms
   64 bytes from 10.0.2.12: icmp_seq=2 ttl=64 time=0.194 ms
   64 bytes from 10.0.2.12: icmp_seq=3 ttl=64 time=0.100 ms
   ^C
   --- 10.0.2.12 ping statistics ---
   3 packets transmitted, 3 received, 0% packet loss, time 2025ms
   rtt min/avg/max/mdev = 0.100/0.198/0.300/0.081 ms
   ```
   
 
