云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置

1.需求说明

部分云业务需要跟物联网卡进行互联,通常物联卡都是通过GRE隧道进行访问,由于业务成本控制,没办法新增除云主机以外的产品,如云下一代防火墙来配置GRE隧道,所以需要通过在云主机上配置GRE隧道。

针对上诉业务需求,对业务配置中所遇到的问题和场景进行记录,以下配置基于centos7的操作环境进行配置,操作系统使用network进行网卡管理,非NetworkManager进行网卡管理,如果NetworkManager管理可能导致开机无法启动gre接口,需要禁用该服务,或者采用nmcli进行gre接口创建

2. 问题说明

问题1:安全组入方向策略没有放行导致GRE建立失败

GRE数据包大致的封装过程为,原始的请求数据包进入gre接口会在数据包前封装GRE头,再交由IP协议进行传输到对端(GRE外层地址),对端地址收到数据包后,发现为GRE数据,会进行拆包,解析出里面的请求信息再进行处理。

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

对于场景1 点对点的GRE隧道情况下,主机A与主机B数据传输的时候,原始报文通过封装后,交由传输协议来进行传输,主机B收到的请求包都会主机A的公网地址传输过来,再经过解包后才会看到实际的源和IP。主机B回复请求,该数据包最终封装 传输到主机A 一样的原理,所以A和B的安全组都需要放行源IP为对端公网IP的数据包

下图为主机B收到的主机A发送过来的数据包

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte
云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte


针对场景2和场景3的情况,主机B和主机C充当GRE的数据转发网关,当主机A的数据包转发到主机B或主机C后,主机B或C会对其进行解包,解包后根据原始数据包的情况路由转发到主机C或者D,这个时候传输的是原始数据包,所以对于主机C或者主机D来看 源IP为主机A的gre接口IP(内层地址)

下图为场景2,主机C收到的数据包,数据包为已经解包后数据,无GRE封装了

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

问题2:GRE数据转发失败情况

在场景2和场景3的情况下,因为数据包经过封装和转发,转发出去的源IP可能跟网卡IP不一致,所以需要对转发的接口网卡,关闭源目的地址检查这个功能(部分大云节点无该项)

换句话来说,如果把云主机当网关或者路由的情况下 都需要关闭该功能,不然数据包会被拦截丢弃

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

除了上诉功能以外,对于需要转发数据包的主机(场景2和场景3中的主机B和主机C),都需要在操作系统层面配置IP转发功能。

3. 云主机GRE隧道配置

3.1 场景1:主机与对端建立GRE隧道与对端业务进行互访

3.1.1 环境与需求说明

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

主机A:单网卡
eth0:192.168.9.230
弹性公网IP:36.213.74.239
GRE接口:192.168.250.1

主机B:单网卡
eth0:10.99.4.151
弹性公网IP:112.47.53.4
GRE接口:192.168.250.2

需求: 192.168.9.230与10.99.4.151互访

3.1.2 配置步骤

3.1.2.1 查看模块加载情况

主机A和主机B

#查看是否有加载GRE模块
lsmod | grep gre
#查看gre模块信息,如果有的话 创建并启动 GRE接口时,系统会自动加载所需的模块
modinfo  ip_gre
#手动加载GRE模块 (可选)
modprobe  ip_gre

3.1.2.2 创建和启动GRE接口

在 vi /etc/sysconfig/network-scripts/文件夹下创建接口配置文件ifcfg-gre1

注意,MY_OUTER_IPADDR=192.168.9.230为可选项,不一定非要添加,如果要添加需要填云主机的网卡地址,公有云云主机网卡均为内网,绑定弹性公网IP相当于在云侧出口做1对1 NAT

主机A

#接口名称
DEVICE=gre1
BOOTPROTO=none
ONBOOT=yes
TYPE=GRE
#对端GRE外层地址
PEER_OUTER_IPADDR=112.47.53.4
#对端GRE内层地址
PEER_INNER_IPADDR=192.168.250.2
#本地GRE内层地址
MY_INNER_IPADDR=192.168.250.1
#本地 外部IP(可选),
# MY_OUTER_IPADDR=192.168.9.230

启动GRE接口

ifup gre1 

主机B

DEVICE=gre1
BOOTPROTO=none
ONBOOT=yes
TYPE=GRE
#对端外部IP地址
PEER_OUTER_IPADDR=36.213.74.239
#对端内部IP地址
PEER_INNER_IPADDR=192.168.250.1
#本地内部IP地址
MY_INNER_IPADDR=192.168.250.2
#本地 外部IP--(可选)
# MY_OUTER_IPADDR=172.20.235.121
ifup gre1 

注意,该接口配置只适合用network管理 如果是用NetworkManager管理 可能开机后不能自动up gre1口,可以systemctl disable NetworkManager服务 或者手动ifup gre1

3.1.2.3 添加路由

主机A

编辑vi /etc/sysconfig/network-scripts/route-gre1 添加如下路由

10.99.4.0/24 via 192.168.250.2 dev gre1

主机B

192.168.9.0/24 via 192.168.250.1 dev gre1

3.1.2.4 安全组添加入方向策略

主机A

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

主机B

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

3.2 场景2:主机B通过主机A的GRE隧道访问对端业务

3.2.1 环境与需求说明

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

主机A:单网卡
eth0:192.168.9.230
弹性公网IP:36.213.74.239
GRE接口:192.168.250.1

主机B:双网卡
eth0:10.99.4.151
eth1:10.99.3.112
弹性公网IP:112.47.53.4
GRE接口:192.168.250.2

主机C:单网卡
eth0:10.99.3.66

需求: 主机A 192.168.9.230与主机C10.99.3.66互访

3.2.2 配置步骤

3.2.2.1 查看模块,创建与编辑GRE接口

主机A和主机B 参考3.1.2.1-3.1.2.2

3.2.2.2 主机B 开启IP转发

IP 转发功能,可以将一台具有多个网络接口的系统作为路由器或网关,实现不同网络之间的通信,该场景中需要将主机B当作网关,用于转发主机C与主机A的流量,所以主机B需要开机IP转发

echo  "net.ipv4.ip_forward=1" >>/etc/sysctl.conf
sysctl -p

3.2.2.2 添加路由

#主机A
echo  "10.99.3.0/24 via 192.168.250.2 dev gre1" >>  /etc/sysconfig/network-scripts/route-gre1

#主机B
echo  "192.168.9.0/24 via 192.168.250.1 dev gre1" >>  /etc/sysconfig/network-scripts/route-gre1
#主机C  注意路由添加的目的地址应该为主机A的GRE接口
echo  "192.168.250.0/24 via 10.99.3.112 dev eth0" >>  /etc/sysconfig/network-scripts/route-eth0

3.2.2.3 安全组放行

主机A和主机B参考3.1.2.4

主机C需要添加 入放行规则 源IP为 192.168.250.1

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

3.2.2.4 关闭源和目标检测

主机B和主机C的 10.99.3.0/24 网卡需要关闭源/目的检查

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

3.3 场景3:云主机GRE主备

3.3.1 环境与需求说明

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

主机A:单网卡
eth0:192.168.9.230
弹性公网IP:36.213.74.239
GRE01接口:192.168.250.1
GRE02接口:192.168.250.5

主机B:双网卡
eth0:10.99.4.151
eth0绑定弹性公网IP:112.47.53.4
GRE接口:192.168.250.2
eth1:10.99.3.112

主机C:双网卡
eth0:10.99.4.139
eth0绑定弹性公网IP:112.47.53.73
GRE接口:192.168.250.6
eth1:10.99.3.226

主机D:单网卡
eth0:10.99.3.66

需求: 主机A 192.168.9.230与主机D 10.99.3.66互访 同时GRE01和GRE02 中断一条 不影响业务使用

3.3.2 配置步骤

3.3.2.1 创建和启动GRE接口

参考3.1.2.2 创建主机A和主机B的gre1 接口

新增主机A gre2 接口

DEVICE=gre2
BOOTPROTO=none
ONBOOT=yes
TYPE=GRE
PEER_OUTER_IPADDR=112.47.53.73
PEER_INNER_IPADDR=192.168.250.6
MY_INNER_IPADDR=192.168.250.5
ifup gre2 

主机C 配置启动gre1接口

DEVICE=gre1
BOOTPROTO=none
ONBOOT=yes
TYPE=GRE
PEER_OUTER_IPADDR=36.213.74.239
PEER_INNER_IPADDR=192.168.250.5
MY_INNER_IPADDR=192.168.250.6
ifup  gre1 

3.3.2.2 主机B和主机C 开启IP转发

参考:3.2.2.2 主机B 开启IP转发

3.3.2.3 创建和绑定虚拟IP

主机B和主机C 10.99.3.0/24 子网创建一个虚拟IP,并绑定到主机B和C的10.99.3.0/24对应网卡

云主机上基于Centos7创建GRE隧道以及GRE隧道主备配置-一字节.OneByte

3.3.2.4 添加路由

主机A

echo  "10.99.3.0/24 via 192.168.250.2 dev gre1 metric 10" >>  /etc/sysconfig/network-scripts/route-gre1

echo  "10.99.3.0/24 via 192.168.250.6 dev gre2 metric 20" >>  /etc/sysconfig/network-scripts/route-gre2

主机B

echo  "192.168.9.0/24 via 192.168.250.1 dev gre1" >>  /etc/sysconfig/network-scripts/route-gre1

主机C

echo  "192.168.9.0/24 via 192.168.250.5 dev gre1" >>  /etc/sysconfig/network-scripts/route-gre1

主机D

10.99.3.125为虚拟IP

echo  "192.168.250.0/24 via 10.99.3.112 dev eth0" >>  /etc/sysconfig/network-scripts/route-eth0

**3.3.2.5 主机B和主机C 安装并配置keepalived

安装keepalived

yum install -y epel-release
yum install -y keepalived

主机B和主机C 修改keepalived配置文件 /etc/keepalived/keepalived.conf

主机B

vrrp_instance VI_1 {
    state BACKUP
    interface eth1  # 替换为实际网卡名
    virtual_router_id 51
    priority 50       # 较低的优先级
    advert_int 1      # 健康检查频率
    authentication {
        auth_type PASS
        auth_pass 123123  # 保持与主节点一致的密码
    }
    virtual_ipaddress {
        10.99.3.125  # 保持与主节点一致的VIP地址
    }
}

主机C

vrrp_instance VI_1 {
    state MASTER
    interface eth1  
    virtual_router_id 51
    priority 100      
    advert_int 1     
    authentication {
        auth_type PASS
        auth_pass 123123  
    }
    virtual_ipaddress {
        10.99.3.125 
    }
}

启动并配置开机启动 keepalived

systemctl start keepalived
systemctl enable keepalived  

主机A部署检测脚本 gre_check.sh

脚本每5秒检测一次gre1对端内层地址,如果ping不通后会自动修改路由的权重,优先级最高切换到gre2

#!/bin/bash

while true; do
    # 检查 gre1 是否可达
    ping -c 1 -w 2 192.168.250.2 >/dev/null 2>&1

    if [ $? -ne 0 ]; then
        # 如果 gre1 不可达,调整路由优先级
        ip route change 10.99.3.0/24 via 192.168.250.6 dev gre2 metric 10
        ip route change 10.99.3.0/24 via 192.168.250.2 dev gre1 metric 20
    else
        # 如果 gre1 可达,恢复默认优先级
        ip route change 10.99.3.0/24 via 192.168.250.2 dev gre1 metric 10
        ip route change 10.99.3.0/24 via 192.168.250.6 dev gre2 metric 20
    fi

    # 等待 5 秒
    sleep 5
done

配置开机运行脚本

chmod o+x gre_check.sh
echo "/root/gre_check.sh"  >> /etc/rc.d/rc.local
chmod +x /etc/rc.d/rc.local

参考资料

https://www.jb51.net/server/309938tvh.htm
https://blog.csdn.net/omaidb/article/details/120824823
https://support.huawei.com/enterprise/zh/doc/EDOC1100174722/246ecee3