ToB企服应用市场:ToB评测及商务社交产业平台

标题: 网络运输层之(3)GRE协议 [打印本页]

作者: 祗疼妳一个    时间: 2024-6-20 14:30
标题: 网络运输层之(3)GRE协议
网络运输层之(3)GRE协议

   
    Author: Once Day Date: 2024年4月8日


   一位热衷于Linux学习和开辟的菜鸟,试图谱写一场冒险之旅,大概终点只是一场白日梦…


    漫漫长路,有人对你微笑过嘛…


   全系列文档可参考专栏:通信网络技术_Once-Day的博客-CSDN博客。


   参考文章:
   
   
  
   
  1. 概述

  1.1 GRE协议先容

  GRE通用路由封装协议(Generic Rrouting Encapsulation)是一种网络协议,重要用于封装差别网络协议的数据包。
  
  比方,如果一个企业需要在使用差别版本互联网协议(如IPv6与IPv4)的两个局域网(LAN)之间建立连接,而连接这两个网的中间网络仅支持IPv4,那么GRE可以将IPv6的数据包封装在IPv4数据包中举行传输。如许,IPv6的数据包就可以“搭乘”IPv4网络,绕过协议不兼容的问题。
  GRE协议的优缺点如下表所示:
  优点缺点基于IP协议,可以在互联网上使用隧道模式下封装开销较大,影响效率支持点对点和点对多点通信不支持组播和广播(GRE支持组播)支持多种承载网络,包罗IP、MPLS等配置较为复杂,对网络管理要求较高采用隧道技术,能够穿越NAT和防火墙缺乏流量控制和拥塞控制机制路由可扩展性好,支持动态路由协议隧道会合终结易形成单点故障和性能瓶颈  1.2 GRE使用场景

  GRE 协议有三种重要的应用场景。
  (1)多协议当地网络通过单一协议骨干网实现互联。
  
  (2)扩大步数受限网络(如 RIP)的范围。
  
  (3)与 IPsec 团结使用,提供安全的 VPN 服务。
  
  GRE协议虽然传输的流量是不加密的,但可以通过团结IPSec技术,先建立GRE隧道对报文举行GRE封装,然后再建立IPSec隧道对报文举行加密,以包管报文传输的完整性和私密性。下面是一种常见的GRE使用拓扑图:
  

  1.3 GRE和VPN/IPsec/L2TP/PPTP之间的关系

  VPN是通过公共网络建立的假造专用通信网络的统称,用于连接远程用户、公司分支机构到公司内部网。重要有以下几种范例:
  
  GRE、L2TP、IPsec、PPTP都是VPN常用的隧道技术,用于在公网上建立点到点的逻辑通道,它们的区别在于:
  
  在典型VPN组网中,GRE/IPsec常用于骨干网的隧道构建,L2TP/PPTP用于接入层用户拨号接入,通过团结使用来构建全面的VPN网络
  比方,GRE和L2TP都是一种隧道协议,但偏重很差别,如下表所示:
  GRE协议L2TP协议协议类别网络协议用户接入协议关注领域只关注网络端的隧道连通除网络连通外还涉及到用户侧的接入报文报文结构比较简单,仅包含GRE头和隧道负载报文结构复杂,隧道模式下需要封装PPP协议,
网络模式下需要封装以太网帧  1.4 GRETAP先容

  GRETAP (Generic Routing Encapsulation Transparent Aggregation Protocol) 是一种网络协议,用于在以太网链路上透明地聚合和转发数据包。
  GRETAP则是GRE的一种变体,专门用于封装以太网帧,重要特点和应用如下:
    GRETAP在某些特定场合下为以太网扩展和互联提供了一种灵活的办理方案,不过随着大二层技术的发展,越来越多的场景开始采用VXLAN等新型隧道协议
  1.5 相关RFC文档

  下面是与GRE协议相关的重要RFC文档列表:
    2. 报文格式

  2.1 GRE报文格式

  GRE报文格式(RFC 2784)如下图所示:
  

  GRE报文分为三个组成部分,每层对应一个协议概念,如下所示:
  
  GRE头部字段解释如下:
  字段长度描述C1 bit校验和验证。
如果该位为1,表示GRE头插入了校验和(Checksum)字段。
如果该位为0,表示GRE头不包含校验和字段。K1 bit关键字。
如果该位为1,表示GRE头插入了关键字(Key)字段。
如果该位为0,表示GRE头不包含关键字字段。Recursion3 bits用来表示GRE报文被封装的层数。
完成一次GRE封装后将该字段加1,如果封装层数大于3,则扬弃该报文。
该字段的作用是防止报文被无限次的封装。Flags5 bits预留字段。当前必须设为0。Version3 bits版本字段,必须置为0。Version为1是使用在RFC2637的PPTP中。Protocol Type16 bits乘客协议的协议范例,好比0x0800表示IPv4,0x86DD表示IPv6。Checksum16 bits对GRE头及其负载的校验和字段。Key31 bits关键字字段,隧道接收端用于对收到的报文举行验证。  2.2 旧GRE报文格式(RFC1701)区别

  RFC2784移除了一些旧GRE协议的字段,如下所示:
  
  RFC 1701规定的GRE头部格式如下:
  

  RFC 1701的GRE头部字段描述如下:
  字段名位数描述C (Checksum Present)1校验和标志位。
1: Checksum和Offset字段存在
0: Checksum和Offset字段不存在R (Routing Present)1路由标志位。
1: Routing字段存在
0: Routing字段不存在K (Key Present)1密钥标志位。
1: Key字段存在
0: Key字段不存在S (Sequence Number Present)1序列号同步标志位。
1: Sequence Number字段存在
0: Sequence Number字段不存在s (Strict Source Route)1严格源路由标志位。
1: 严格源路由
0: 宽松源路由Recur (Recursion Control)3控制GRE递归封装的最大层数,0-7。通常为0。Flags5保留,必须为0。Ver (Version)3GRE版本,当前必须为0。Protocol Type16封装在GRE中的协议范例,如0x0800表示IPv4。Checksum (可选)16GRE头部及payload的校验和。Offset (可选)16GRE头部后附加字段的偏移量。Key (可选)32用于身份验证的密钥。Sequence Number (可选)32序列号,用于报文重组和去重。Routing (可选)变长源路由列表,支持严格/宽松源路由。  相比RFC 2784 ,RFC 1701的GRE提供了更多特性,如:
  
  这些附加特性也增加了GRE的复杂度和开销,以是在后续的RFC 2784中简化并移除了一些不常用的特性
  2.3 GRE隧道对MTU和MSS的影响

  MTU和MSS都是用来限制通过网络传输的数据包最大长度的度量单元:
  
  GRE隧道协议会在数据包原有巨细基础上增加几个字节,在数据包的MSS和MTU设置中必须思量这个因素。
     如果MTU设为1500 字节,MSS设为1460 字节,则增加GRE 12字节头部后将导致数据包超过MTU限值:
   1460 字节 [有效负载] + 20 字节 [TCP 标头] + 20 字节 [IP 标头] + 12 字节 [GRE 标头+ IP 标头] = 1512字节
    因此,数据包将被分段,减慢数据包通报,并增加算力开销,由于超出 MTU 的数据包必须分解然后重新组合。
  通过淘汰 MSS 长度以包含 GRE 标头,可以制止这种环境。
     如果将MSS设置为1448而不是1460,那么加上GRE 12字节头部后的数据包不会超过MTU 值 1500:
   1448 字节 [有效负载] + 20 字节 [TCP 标头] + 20 字节 [IP 标头] + 12 字节 [GRE 标头+ IP 标头] = 1500 字节
    只管制止了分段,但效果却是有效载荷变小,这意味着需要额外的数据包来通报数据,并增加毫秒级的数据传输耽误。不过,使用 GRE 比不使用 GRE 可以使这些数据包选择更快的网络路径,进而可以弥补丧失的时间。
  3. 工作流程

  3.1 报文封装和解封装流程

  GRE报文传输流程示意图如下:
  

  上述流程以一个Ping Request报文为例子,先容了如何从10.10.4.0/24网络里通过Gre0和Gre1这对GRE隧道到达10.10.6.0/24网络。
    整个过程可以概括为:原始IP报文被添加上GRE头部、新的IP头部,形成GRE over IP的封装报文,通过隧道传输。隧道出口解封装,得到原始IP报文,再转发给目标主机
  需要注意,Gre接口需要配置路由条目才气将流量导入到接口中,路由的下一跳地址为Gre接口的私网地址,而不是local/remote等公网地址
  3.2 GRE隧道keepalive检测

  通用路由封装(GRE)的Keepalive功能是一种网络协议机制,旨在确保网络连接的连续性和可靠性。在GRE隧道中,Keepalive机制通过定期发送探测消息来检测和维持隧道两头的运动状态。
  
  GRE的keepalive探测包构成如下:
  
  隧道对端接收到keepalive包后,会解封装,检查内层GRE头的PT字段。若为0,则辨以为keepalive包,并扬弃它,同时重置keepalive计数器
  4. Linux Ubuntu配置GRE接口

  4.1 Linux内核支持GRE选项配置

  Linux 内核支持GRE接口需要启用以下相关配置。
  功能配置宏描述GRE 隧道支持CONFIG_NET_IPGRE启用通用 GRE 隧道支持,是使用 GRE 的基础。GRE 隧道设备支持CONFIG_NET_IPGRE_DEMUX启用此选项可以支持多个 GRE 隧道设备,每个设备可以单独配置。GRE 广播和组播支持(可选)CONFIG_NET_IPGRE_BROADCAST启用 GRE 隧道的广播和组播支持,答应 GRE 隧道传输广播和组播数据包。Netfilter 连接跟踪支持(可选)CONFIG_NF_CT_PROTO_GRE如果需要对 GRE 数据包举行连接跟踪和状态检查(如防火墙规则),则需要启用此选项。GRE IPv6报文支持CONFIG_IPV6_GRE启用GRE over IPv6支持。IP 隧道驱动步伐(可选)CONFIG_NET_IPIP虽然此选项重要用于 IPIP 隧道,但某些 GRE 实现大概也依靠于它。  在 Linux 内核的 make menuconfig 配置界面中,这些选项通常位于以下位置:
  1. Networking support  --->
  2.   Networking options  --->
  3.     [*] IP: GRE demultiplexer
  4.     [*]   IP: broadcast GRE over IP
  5.     -*- The IPv6 protocol  --->
  6.       [*]   IPv6: GRE demultiplexer
  7.       [*]     IPv6: broadcast GRE over IPv6
  8. Device Drivers  --->
  9.   [*] Network device support  --->
  10.     <*>   IP: GRE over IP
  11.     <*>   IPv6: GRE over IPv6
  12.     <*>   IP: IPIP tunnel
  13. Netfilter Configuration  --->
  14.   [*] IP virtual reassembly in netfilter
  15.   [M]   "conntrack" connection tracking match support
  16.   [M]     "conntrack" connection tracking match support for GRE
复制代码
在实际运行的ubuntu服务器上,可以检查/boot目录下配置文件,如下:
  1. onceday@ubuntu1:~$ cat /boot/config-5.15.0-100-generic |grep GRE
  2. CONFIG_NET_IPGRE_DEMUX=m
  3. CONFIG_NET_IPGRE=m
  4. CONFIG_NET_IPGRE_BROADCAST=y
  5. CONFIG_IPV6_GRE=m
  6. CONFIG_NF_CT_PROTO_GRE=y
  7. CONFIG_OPENVSWITCH_GRE=m
复制代码
在这台ubuntu设备上,可以看到相关的GRE功能Linux内核都已经支持了。
  4.2 Linux上配置GRE接口

  测试和验证GRE功能需要两台Linux服务器,这里使用VirtualBox的假造机来搭建环境(3.1节报文封装和解封装流程所示拓扑)。
  (1) 在服务器ubuntu1和ubuntu2上配置物理接口enp0s9(或者其他接口)的地址,两者之间要能Ping通(内部网络或者网卡桥接)。
  1. # ubuntu1配置6.6.6.6/24地址
  2. onceday@ubuntu1:~$ ip link set enp0s9 up
  3. onceday@ubuntu1:~$ ip addr add 6.6.6.6/24 dev enp0s9
  4. # ubuntu2配置6.6.6.7/24地址
  5. onceday@ubuntu1:~$ ip link set enp0s9 up
  6. onceday@ubuntu2:~$ ip addr add 6.6.6.7/24 dev enp0s9
  7. # 两者之间可以Ping通
  8. onceday@ubuntu1:~$ ping 6.6.6.7
  9. PING 6.6.6.7 (6.6.6.7) 56(84) bytes of data.
  10. 64 bytes from 6.6.6.7: icmp_seq=1 ttl=64 time=0.807 ms
复制代码
(2) 在两个服务器上分别配置GRE假造子接口,local和remote就是enp0s9接口的IP地址。
    服务器ubuntu1配置操作输出信息如下:
  1. onceday@ubuntu1:~$ ip tunnel add gre1 mode gre remote 6.6.6.7 local 6.6.6.6 ttl 255
  2. onceday@ubuntu1:~$ ip addr add 10.10.5.1/30 dev gre1
  3. onceday@ubuntu1:~$ ip link set gre1 up
  4. onceday@ubuntu1:~$ ip route add 10.10.0.0/16 dev gre1
  5. onceday@ubuntu1:~$ ip addr 4: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000     link/ether 08:00:27:93:6f:37 brd ff:ff:ff:ff:ff:ff     inet 6.6.6.6/24 scope global enp0s9        valid_lft forever preferred_lft forever     inet6 fe80::a00:27ff:fe93:6f37/64 scope link         valid_lft forever preferred_lft forever 8: gre1@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1476 qdisc noqueue state UNKNOWN group default qlen 1000     link/gre 6.6.6.6 peer 6.6.6.7     inet 10.10.5.1/30 scope global gre1        valid_lft forever preferred_lft forever     inet6 fe80::606:606/64 scope link         valid_lft forever preferred_lft forever
复制代码
最终可以看到gre1接口上面有接口IP(10.10.5.1),这个IP用于流量引流的下一跳地址。
  同理完成ubuntu2的配置操作:
  1. onceday@ubuntu2:~$ ip tunnel add gre1 mode gre remote 6.6.6.6 local 6.6.6.7 ttl 255 onceday@ubuntu2:~$ ip addr add 10.10.5.2/30 dev gre1 onceday@ubuntu2:~$ ip link set gre1 up
  2. onceday@ubuntu2:~$ ip route add 10.10.0.0/16 dev gre1
  3. onceday@ubuntu2:~$ ip addr 3: enp0s9: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc fq_codel state UP group default qlen 1000     link/ether 08:00:27:56:7b:06 brd ff:ff:ff:ff:ff:ff     inet 6.6.6.7/24 scope global enp0s9        valid_lft forever preferred_lft forever     inet6 fe80::a00:27ff:fe56:7b06/64 scope link         valid_lft forever preferred_lft forever 7: gre1@NONE: <POINTOPOINT,NOARP,UP,LOWER_UP> mtu 1476 qdisc noqueue state UNKNOWN group default qlen 1000     link/gre 6.6.6.7 peer 6.6.6.6     inet 10.10.5.2/30 scope global gre1        valid_lft forever preferred_lft forever     inet6 fe80::606:607/64 scope link         valid_lft forever preferred_lft forever
复制代码
完成以上配置之后,可以尝试举行ping操作,并且用TCP抓包看看GRE隧道报文。
  1. onceday@ubuntu1:~$ ping 10.10.5.2
  2. PING 10.10.5.2 (10.10.5.2) 56(84) bytes of data.
  3. 64 bytes from 10.10.5.2: icmp_seq=1 ttl=64 time=0.810 ms
  4. 64 bytes from 10.10.5.2: icmp_seq=2 ttl=64 time=0.991 ms
  5. ......
复制代码
下面是对enp0s9接口抓包,可以看到外层报文和内层报文交互环境:
  1. onceday@ubuntu1:~$ sudo tcpdump -vv  -i enp0s9
  2. tcpdump: listening on enp0s9, link-type EN10MB (Ethernet), snapshot length 262144 bytes
  3. 17:19:29.285962 IP (tos 0x0, ttl 255, id 4763, offset 0, flags [DF], proto GRE (47), length 108)
  4.     6.6.6.6 > 6.6.6.7: GREv0, Flags [none], length 88
  5.         IP (tos 0x0, ttl 64, id 1897, offset 0, flags [DF], proto ICMP (1), length 84)
  6.     ubuntu1 > 10.10.5.2: ICMP echo request, id 7, seq 1, length 64
  7. 17:19:29.286757 IP (tos 0x0, ttl 255, id 10776, offset 0, flags [DF], proto GRE (47), length 108)
  8.     6.6.6.7 > 6.6.6.6: GREv0, Flags [none], length 88
  9.         IP (tos 0x0, ttl 64, id 65215, offset 0, flags [none], proto ICMP (1), length 84)
  10.     10.10.5.2 > ubuntu1: ICMP echo reply, id 7, seq 1, length 64
复制代码
到此,GRE隧道接口测试就完成了,操作很简单,重点是理解GRE报文的传输流程。
  5. 总结

  GRE协议比较简单,但是具体的报文传输流程和路由寻路就比较难以理解。对于终端,需要设置一个GRE接口,同时配置Local IP和remote IP,这两个IP用于封装GRE报文的外层IP头。
  此外,GRE接口本身还需要一个接口IP,注意这个接口IP不能直接作为外部设备的下一跳(NextHop),由于这是一个三层虚接口,没有MAC等链路层地址,所有是无法作为邻人表项存在的。
  在终端上,需要对应的物理接口IP完成外部路由过程,而GRE接口IP,重要用于将物理接口的入流量(即准备举行封装的报文)导入到GRE接口中。
  对于出流量(即准备举行解封的报文),则不需要依靠路由导入,而是在剖析IP协议时就可以分流到GRE模块中处理。以是GRE两个方向的流量路径是不一致的,这个一开始大概不好理解,发起多多手动实践来理解。
  
  
  
  
  
  
  

     Once Day

   

       也信美人终作土,不堪幽梦太急忙......
       如果这篇文章为您带来了资助或开导,不妨点个赞




欢迎光临 ToB企服应用市场:ToB评测及商务社交产业平台 (https://dis.qidao123.com/) Powered by Discuz! X3.4