
虽然目前IPv6技术逐渐普及,将来每一个网民都会有一个合法的公网IP地址,众多的VPN技术和NAT技术渐渐的会退出历史舞台,但是需要时间!我绝对相信祖国在网络时代不会被任何人欺负!!

GRE机制特点
1.对网络传输载体设备处理能力要求不高!
2.支持多种三层协议!
3.具有一定的检测性。
这也是在企业中一些基础浅层应用里GRE协议往往会起着较大的作用

设备处理能力方面
举例两种典型基础协议来说明GRE协议:
①Dot1Q:干道协议,可以穿透VPN。
②ISL:交换内链路协议,思科的私有协议。
这两种协议本质上最大的区别ISL协议属于包裹报文改变报文结构,而Dot1Q属于嵌入式改变报文结构。
这样,我们可以分析出GRE为何简单了,因为从难度上来看:包裹<嵌入式的!
就是因为GRE协议的机制过于简单,所以对于网络的两端设备的载荷要求能力是特别的低!
GRE可以支持多种三层协议。
支持ipx nowell等......这种网络协议已经淘汰,我也知之甚少。
就是因为GRE协议对三层IP协议契合度非常高!配置也简单,所以针对华为设备在构建网络架构时成本会非常低,很多路由器设备都支持!而思科设备只是K系列的才能够支持。

具有一定加密性
安全性肯定会比在透明传输要强一些!
在VPN网络中,最终的网络架构一定是点对点的网络拓扑!两者之间一定有一条虚拟的线路,谁也不能保证这条虚拟链路是永久存在的!因此VPN检测机制是必要的!GRE检测机制就是keepalive这个协议!这个协议可是常常应用在BGP网络之中!


GRE工作原理
如图所示:抛开NAT转发技术,部署VPN首先会建立一条“隧道”!当来自主机A的数据进入R1路由器的1号接口。

GRE配置完成后,当来自主机A的数据进入R1路由器的1号接口,网络在全部通畅的前提下,IP报文的头部一定是30.0.0.2。R1路由器接到主机A的数据,首先一定是取出数据报文中的IP地址,进行匹配路由表,从而进行是否转发!!即使你GRE配置完成,隧道建立成功!按照路由器的工作原理,R1也不会查看GRE的配置,还是按照路由表的转发寻找出接口!因此,我们可以认为路由器不会对所有的流量进行封装GRE,要对感兴趣流进行封装!缺省情况下,路由设备会对进入的流量进行判断是否加密封装!


路由设备如何发现感兴趣流
分析思路:
1.保持路由转发原理。
2.判断GRE流量--根据是否为隧道接口。
3.最终转发流量通过物理接口转发。
在遵守路由转发的工作原理前提下,我们配置GRE的时候,会配置两端的地址!如图所示:隧道的两端配置的地址是为感兴趣流做准备!我们通过配置静态路由,来实现主机A到主机B的隧道的表面连接。从主机A上来看:感兴趣流的下一跳地址一定是100.0.0.2 ,因此这条路由条目在路由设备中是存在的,来自主机A去往主机B的数据流在经过R1的时候,这条路由条目是存在的!
设备判断数据流是是否为感兴趣数据流,主要依靠出接口是不是属于GRE的虚拟接口(隧道接口),最终路由器通过路由转发表发现这个下一跳地址对应的是(隧道接口)虚拟接口,就认为这些数据需要封装GRE协议,其他数据对应的接口为普通的物理接口,按照正常流量转发!
记住数据是离开路由设备进行封装,从客户端发出是纯净的IP报文!

设备判断数据流是是否为感兴趣数据流,主要依靠出接口是不是属于GRE的接口。

GRE封装原理
GRE中文翻译:通用路由封装协议 !从字面上来看,通用路由封装协议,封装的是什么?
在大部分企业中所应用的三层协议是IP报文,因此,我们可以认为GRE所封装的对象一定是网络层三层网络协议!
GRE本身就是一个协议,它的作用就是给IP报文“穿上马甲”,但是这件马甲可不是随意乱穿的!这个“马甲”穿不好会导致对方主机不认!(目标IP不是自己的)VPN的核心技术就是改变了报文的结构!

这里的封装必须是严谨的!大学里我们学过网络封装技术,那时候老师跟我们讲过,但凡一种网络封装技术,其基本的构成要素分为三个部分:乘客协议,封装协议,运输协议!
GRE头部的随意添加会导致报文结构发生变化,因为GRE头部并不是IP协议,即使封装成功,对端的路由设备是不认这个头部的,会丢弃这个报文。因此,协议开发者会在GRE头部前面增加一个ipx的IP报文。


对端设备如何判断GRE流量
不管怎样封装,IP报文的头部不会变,解封装后查看IP报文头部的目标IP地址是自己虚拟接口的地址!就可认为这是封装了GRE协议的报文流量。

接下来,路由设备会剥离运输协议---ipx(这里我举例是IPx 不要跟真正的IPx协议搞混),露出GRE协议,在通过GRE协议拆掉GRE报头,这样就一步步拆掉,露出真正的数据!
当时我有个疑问,既然这样一步一步的解封装,还不如一下就拆开,用的着这么麻烦吗?
如图所示:这就是解封装的流程.......


总结
封装过程:
①收到某个协议(这里不仅仅指的是IP协议,设备还会收到其他的协议)的报文,交给该协议报文处理。
②协议根据报文头部中的目标IP地址在路由表中查找出接口,从而确定如何转发该报文,若发现出接口是Tunnel接口,则对报文进行GRE封装。(Tunnel接口传输的协议不一定是GRE,可以是ipsec 等等)

③根据传输协议对报文添加传输协议的头部(原地址是隧道原地址,目标地址是隧道的目标地址。)
④根据运输协议的头部地址(隧道的目标地址),查找相对应的出接口发送最终封装好的报文。
封装演示,如图所示:
主机A发送给主机B的数据(指的是IP协议),在经过R1设备时,(IP协议)数据的封装发生了变化:由于路由器的工作原理,收到IP协议,将IP头部地址取出,查路由表对照出接口进行路由转发!(若出接口是tunnel接口,路由设备会认为该报文封装是隧道协议)

解封过程:
对端设备收到报文(这个报文在对端的设备看来是标准的IP报文,设备是不知道这个报文是否为GRE封装报文,会按照正常的解封操作),根据头部的目标地址确定是否为发送到本设备的报文,如果不是并不是采取丢弃行为,而是继续查找路由表,看看属不属于其他路由设备的!如果是自己的IP地址就摘掉该协议的头部,找到其出接口。
在路由设备解封掉最外层的运输协议,最终得到原始的协议报文,对其露出的原始报文(这里的原始报文指的封装协议和乘客协议,即GRE协议和IP报文)查看目标地址,如果是自己的Tunnel接口,路由设备就会判断出这个报文是否为GRE封装,最后对原始数据进行后续的转发处理。

华为官方定义:
封装操作是通过一个逻辑接口来实现的,这个逻辑接口就是鼎鼎有名的Tunnel接口,Tunnel即隧道,从名字上可以看出这个逻辑接口就是为隧道而生,Tunnel接口上带有新IP头的原地址和目的地址信息,报文进入Tunnel接口后,路由设备会对报文封装GRE头和新的IP头。到后面就是我们前面所分析的,设备将报文通过路由传送到Tunnel接口,这里的路由传送分为两种方式:
①静态路由
②动态路由

GRE实验演示
GRE配置思路:
创建Tunnel接口。
配置隧道接口IP地址。
指定隧道协议。
配置隧道的源、目标地址。(指的本端和对端路由设备的真实物理接口地址)

实验拓扑
图中,R2/R3路由设备为运营商角色,R1和R4进行“局域网互相通讯”时,会产生一条虚拟隧道,R1和R4两台设备根本不可能直连!走的实际物理链路就是R2-R3运营商的物理链路!
4台路由器都运行OSPF协议,实现全网互通
ospf区域为0。
route-id在此省略。
宣告各自的网络接口网段。
在各自的接口下使能OSPF。

如图所示:测试R1 ping 40.100.0.2这个地址, 实现全网互通!


Tunnel接口创建
理解成虚拟接口,和Loopback接口等同,站在R1设备视图模式下:
在ENSP模拟器中路由设备有三个接口板槽,可以取值为0-1023个虚拟接口,跟设备的物理接口没有任何关系,这里我取0/0/0,在实际的生产环境中,配置的虚拟接口建议成对配置,这里我R1和R2的Tunnel接口都是0/0/0
[R1]interface Tunnel 0/0/0
双方都要配置,R4省略......


配置隧道接口IP地址
[R1-Tunnel0/0/0]ip address 100.0.0.1 24
双方都要配置!R4省略......

Tunnel接口地址必须配置,如果不配置IP地址,Tunnel接口就是down的状态!

Tunnel接口地址使用私网地址即可,隧道两端的虚拟接口地址并没有真正的参与报文封装,都是由真实的物理接口进行介入!

指定虚拟接口的协议类型
[R1-Tunnel0/0/0]tunnel-protocol gre
双方都要配置!R4省略......
我们需要一个隧道跑什么协议!这里指定的是gre协议!


配置隧道的源地址和目标地址
[R1-Tunnel0/0/0]source 39.100.0.2
[R1-Tunnel0/0/0]destination 40.100.0.2 (一定要和描述的单词区别开来!)
因为隧道的两端地址不能够在传输中路由,要保持隧道的路由状态就要配置隧道的源地址和目标地址。其中,隧道的源地址是R1出接口的地址,目的地址是R4的入接口地址!双方都要配置!R4省略(R4的源和目标地址和R1互调)......


查看R1路由表:在路由表中,100.0.0.0出现在了路由表中,对应的接口是Tunnel0/0/0,39.100.0.0对应的是物理接口。

但是在R1上去往4.0.0.1的路由条目现在是不存在的!需要配置一条:
[R1]ip route-static 4.0.0.0 24 Tunnel 0/0/0
[R4]ip route-static 10.0.0.0 24 Tunnel 0/0/0(R4上也需要配置)

再次查看R1路由表:明显的看到4.0.0.0这条路由条目的接口地址为tunnel0/0/0
因此,R1设备收到目标地址为4.0.0.0的数据报文,R1就会将此报文按照路由转发到Tunnel接口之中,而Tunnel 0/0/0这个接口地址被我配置成了100.0.0.1/24,这样就和隧道地址对应上!


GRE协议分析
提问:
①R1上的4.0.0.0 24 的路由路由条目下一跳地址是否可以改成R1的隧道原地址?
答:是不可以的,原因在于R1的直连路由就是100.0.0.1,而这个直连路由是的地址下一跳是不可达的地址!

提问:
②将R1上的4.0.0.0 24 的路由条目接口地址改成如图所示:是否可以?
答:是不行的!原因在于R1的下一跳地址不可达(不存在),这样的路由条目是无效的!

在R1路由设备上收到了不管源地址是什么,但是目标地址为4.0.0.0的报文就通过路由转发表转发到了Tunnel接口,在隧道接口根据配置进行GRE封装!


R1上ping 4.0.0.1,我们指定源地址10.0.0.1,目标地址是4.0.0.1,通过抓取R2的G0/0/0接口,观察报文封装变化:
两次Ping,为何源地址不一样?
原地址为100.0.0.1的报文截图:

在R1设备上 ping 4.0.0.1的数据包通过抓包查看到了IP报文的源地址是100.0.0.1

学到这个环节的时候,我天真的认为源地址一定是R1的出接口地址--39.100.0.2,查看R1的路由表发现去往4.0.0.0的路由条目的接口是tunnel接口,也就是说,站在R1上 Ping 4.0.0.0的报文是从tunnel 0/0/0接口发出的,所以源地址是100.0.0.1!

站在R1上指定源地址 ping -a 10.0.0.1 4.0.0.1(更符合模拟pc端发出的数据包),这时,源地址就是Loopback接口的地址,目标是4.0.0.1并且封装GRE协议。

举例:在R1上ping -a 10.0.0.1 4.0.0.1 (模拟PC端发出的Ping包)
当去往4.0.0.1的报文到达tunnel接口中,指定了封装协议,并且tunnel接口里面配置了源地址100.0.0.1,目标地址10.0.0.2,数据报文的IP报文的源地址和目标地址如下:sip 10.0.0.1 dip:4.0.0.1

总之,不管是站在R1上 ping 4.0.0.1或者 ping -a 10.0.0.1 4.0.0.1,两者的共同目标地址一定是4.0.0.1 ,而4.0.0.1这条路由条目是存在的(但是这条路由是不可达的且)!

数据到达tunnel0/0/0接口后,被封装上GRE头部,通过抓包,是看不到GRE头部里有任何IP地址的,没有任何办法进行数据传输:

到这里的时候,由于路由条目不可达,GRE封装里面又没有办法进行传输,之前的配置的隧道源地址和目标地址就起了至关重要的作用:

由于隧道的源地址和目标地址和真实的IP地址相对应,在传输协议中进行封装真实的IP地址,报文才能传输出去,这种逻辑关系尤为重要!

R4收到目标地址是自己的数据报文后,此报文头部被剥离后(露出GRE协议和原始的IP协议),R4是如何判断出露出来的是GRE和ip协议混合的隧道报文呢?(路由设备是不会盲目的拆掉接收到的所有报文,这样的话设备负担量是超级大的!)
设备是依靠GRE协议的协议号来判断是否是GRE报文,如图所示:

表明协议号的作用是让对端设备知晓该报文是GRE报文,因此R4在拆掉最外层的运输协议后,不再花费CPU寻找支持的协议,快速的认定是GRE协议,交给GRE协议处理,最后进行路由转发!
在封装过程中,可以看到封装后的GRE报文会有个新的IP头,这个新IP头部中包含了protocol字段,字段中标识了内层协议类型---47代表了GRE报文。

R4去往R1的回应报文反推即可!


GRE安全机制
在浩瀚的互联网上,如果有黑客恶意伪装成R1向R4发送gre报文,伪装者不就可以顺利的访问我R4里面的网络资源了吧!如图所示:

关键字验证
配置关键字验证后,R1和R4不会对所有收到的GRE报文都进行处理,只会处理与自身建立的GRE隧道的对端设备发来的GRE报文,如图所示:这个功能是由Key字段来实现!

两端设备在建立隧道式,通过key字段的值来验证对端的身份,只有两端设置的key字段的值完全相同才能建立隧道:
[R1-Tunnel0/0/0]gre key 123456
[R2-Tunnel0/0/0]gre key 123456


Key: 0x0001e240 转换为十进制就是123456


GRE的保活机制
GRE的安全机制可以实现隧道两端设备的互访,并保证报文传输的完整性,但是由于GRE协议本身是一种无状态类型的隧道(所谓无状态是指隧道的本端并不维护与对端的状态),如果隧道对端出现故障,隧道本端是如何感受的到呢?因此我们必须要为GRE提供Keepalive保活机制!
GRE隧道有一个缺陷:不带有安全加密功能,隧道中的报文都是明文传输。实际生产环境中配合ipsec使用,后续会分享。

首先要区别GRE协议和keepalive协议是两个独立体!
开启Keepalive功能,会开启一个计时器,周期性的发送报文,如果可达将计数器-1,在没有收到对方的回应报文,本端会将不可达计数器+1。不可达计数器达到上限,隧道关闭,本端隧道设备依旧会发keepalive报文,目的在于检测隧道,并及时恢复链路。
但是在实际的场景中,链路状态往往很复杂,类型不可控、长短不可控,带宽不可控。本端设备如何判别报文视为不可达呢?也就是超时时间具体是多少?
本端隧道设备既然无法确定超时时间,它发送一个keepalive 报文,立马将状态成为不可达,将不可达的计数器+1。
在华为官方定义:keepalive功能是单向的,对端设备是否开启此功能不影响本端,理论上对端也能识别本端发送来的keepalive报文,官方建议两端开启这个功能。
R1和R2开启keepalive的功能:
[R1-Tunnel0/0/0]keepalive

演示到这里,我当时认为有了GRE隧道之后,数据的传输就没有什么问题,其实,GRE隧道自身有一个缺陷,不带有安全加密功能,只能说是穿了个透明的马甲,隧道传输的报文都是明文在传输,在实际的生产环境中,很少单纯使用GRE,通常搭配IP-sec协议一同使用!





