一、IP隧道技术

IP隧道技术:是路由器把一种网络层协议封装到另一个协议中以跨过网络传送到另一个路由器的处理过程。IP 隧道(IP tunneling)是将一个IP报文封装在另一个IP报文的技术,这可以使得目标为一个IP地址的数据报文能被封装和转发到另一个IP地址。IP隧道技术亦称为IP封装技术(IP encapsulation)。IP隧道主要用于移动主机和虚拟私有网络(Virtual Private Network),在其中隧道都是静态建立的,隧道一端有一个IP地址,另一端也有唯一的IP地址。移动IPv4主要有三种隧道技术,它们分别是:IP in IP、最小封装以及通用路由封装。更多信息可以参看百度百科:IP隧道 和 隧道技术 。

Linux系统内核实现的IP隧道技术主要有三种(PPP、PPTP和L2TP等协议或软件不是基于内核模块的):ipip、gre、sit 。这三种隧道技术都需要内核模块 tunnel4.ko 的支持。

  • ipip 需要内核模块 ipip.ko ,该方式最为简单!但是你不能通过IP-in-IP隧道转发广播或者IPv6数据包。你只是连接了两个一般情况下无法直接通讯的IPv4网络而已。至于兼容性,这部分代码已经有很长一段历史了,它的兼容性可以上溯到1.3版的内核。据网上查到信息,Linux的IP-in-IP隧道不能与其他操作系统或路由器互相通讯。它很简单,也很有效。
  • GRE 需要内核模块 ip_gre.ko ,GRE是最初由CISCO开发出来的隧道协议,能够做一些IP-in-IP隧道做不到的事情。比如,你可以使用GRE隧道传输多播数据包和IPv6数据包。
  • sit 他的作用是连接 ipv4 与 ipv6 的网络。个人感觉不如gre使用广泛 。

三个模块的信息如下:

  1. # sit模块
  2. [root@localhost ~]# modinfo sit
  3. filename: /lib/modules/2.6.32-642.el6.x86_64/kernel/net/ipv6/sit.ko
  4. alias: netdev-sit0
  5. license: GPL
  6. srcversion: AF73F62BA39C407E20C4F05
  7. depends: ipv6,tunnel4
  8. vermagic: 2.6.32-642.el6.x86_64 SMP mod_unload modversions
  9. # ipip模块
  10. [root@localhost ~]# modinfo ipip
  11. filename: /lib/modules/2.6.32-642.el6.x86_64/kernel/net/ipv4/ipip.ko
  12. alias: netdev-tunl0
  13. license: GPL
  14. srcversion: AF7433BD67CBFC54C10C108
  15. depends: tunnel4
  16. vermagic: 2.6.32-642.el6.x86_64 SMP mod_unload modversions
  17. # ip_gre模块
  18. [root@localhost ~]# modinfo ip_gre
  19. filename: /lib/modules/2.6.32-642.el6.x86_64/kernel/net/ipv4/ip_gre.ko
  20. alias: netdev-gretap0
  21. alias: netdev-gre0
  22. alias: rtnl-link-gretap
  23. alias: rtnl-link-gre
  24. license: GPL
  25. srcversion: 163303A830259507CA00C15
  26. depends: ip_tunnel
  27. vermagic: 2.6.32-642.el6.x86_64 SMP mod_unload modversions

二、ip tunnel 配置

实际应用中,以上提到的三种ip tunnel 技术和VPN技术一样,多用于跨公网的网络中(当然跨网段的内网环境也适用)。如上图所示,我搞了两台虚机,其中eth0网段就类似于常见的公网网络。 eth1网络为各自的私网 。最终实现效果是实现两台主机的 eth1网络可以互通。这里测试中使用的是基于gre模式进行的实现,如果使用ipip、sit,只需要把modprobe后面的模块换掉,把ip tunnel 命令中mode后面的字符替换掉即可。

1、ipv4网络中的配置

a主机配置如下:

  1. #modprobe ipip
  2. #modprobe ip_gre
  3. #ip tunnel add tun0 mode gre remote 192.168.122.90 local 192.168.122.80 ttl 64
  4. #ip link set tun0 up
  5. #ip addr add 192.168.1.80 peer 192.168.2.90 dev tun0
  6. #ip route add 192.168.2.0/24 dev tun0
  7. #iptables -F

b主机配置如下:

  1. #modprobe ipip
  2. #modprobe ip_gre
  3. #ip tunnel add tun0 mode gre remote 192.168.122.80 local 192.168.122.90 ttl 64
  4. #ip link set tun0 up
  5. #ip addr add 192.168.2.90 peer 192.168.1.80 dev tun0
  6. #ip route add 192.168.1.0/24 dev tun0
  7. #iptables -F

两边互ping发现可以ping ,即为实验成功。这里需要注意iptables项,执行iptables -F是必须的,不然两边不通。如果在需要开启防火墙的情况下,也可以执行如下步骤:

  1. iptables -I INPUT -p gre -j ACCEPT
  2. firewall-cmd --permanent --direct --add-rule ipv4 filter INPUT 0 -i eth0 -p gre -j ACCEPT (rhel7下默认使有的firewalld)

假如这边还有台主机C,C主机只有一块网卡,其IP为192.168.1.100,和a主机同在eth1网段,可以将a主机配置为一个简单的种由器,其可以访问b主机的IP 192.168.2.90 。只需要在a主机中做如下配置即可。

  1. echo 1 > /proc/sys/net/ipv4/ip_forward
  2. iptables -t nat -I POSTROUTING -o eth0 -j MASQUERADE

注意:该场景下,需要将C主机的网关指向a主机 。

2、ipv6网络中的配置

两台主机的信息如下:

  1. a. PC1 eth0:2001::1/64; eth1:192.168.1.1/24;
  2. b. PC2 eth0:2001::2/64; eth1:192.168.2.1/24;

配置如下:

  1. a主机配置
  2. #modprobe ip6_tunnel
  3. #ip -6 tunnel add tun0 mode ipip6 remote 2001::2 local 2001::1 ttl 64
  4. #ip link set tun0 up
  5. #ip addr add 192.168.1.1 peer 192.168.2.1 dev tun0
  6. #ip route add 192.168.2.0/24 dev tun0
  7. #iptables -F
  8. b主机配置
  9. #modprobe ip6_tunnel
  10. #ip -6 tunnel add tun0 mode ipip6 remote 2001::1 local 2001::2 ttl 64
  11. #ip link set tun0 up
  12. #ip addr add 192.168.2.1 peer 192.168.1.1 dev tun0
  13. #ip route add 192.168.1.0/24 dev tun0
  14. #iptables -F

三、其他及拓展

提到的linux下的三种模块级的tunnel技术传输都是不加密的,这是和 很多VPN技术比较大的一个区别。同时三都之间在实现原理上也略有区别。

上图是ipip tunnel 的原理图,明显是其点对点的一种tunnel 。这个非常容易理解,这也是其不能广播的原因。据网上的资料说sit 也属于点对点的tunnel,这个由于未翻阅到sit tunnel 比较详细的信息,不能确定其属于不属于简单的点对点 tunnel ,个人感觉sit 不属于简单的点对点 tunnel ,因为在一些路由网络设备中发现其有支持,和gre tunnel 一样。

由于ip tunnel 技术目前只技术linux技术 ,所以上面的两台主机只能运行在类linux主机上。

重点说下gre tunnel,除了外层的 IP 头和内层的 IP 头之间多了一个GRE头之外,它最大的不同是, tunnel不是建立在最终的 host 上,而是在中间的 router 上 !换句话说,对于端点host A 和 host B来说,该tunnel是透明的(对比上面的 ipip tunnel)。添加外部的 IP 头是在 router A 上完成的,而去掉外面的 IP 头是在 router B上完成的,两个端点的 host 上几乎什么都不用做(除了配置路由,把发送到 10.0.2.0 的包路由到 router A)!

从这个原理就可以了解到,gre tunnel 是支持广播和多播的。所以除了上面的route A和route B需要为类linux平台,上面的host a 和host b选用什么类型的系统无所谓。

发送过程是很简单的,因为 router A 上配置了一条路由规则,凡是发往 10.0.2.0 网络的包都要经过 netb 这个 tunnel 设备,在内核中经过 forward 之后就最终到达这个 GRE tunnel 设备的 ndo_start_xmit(),也就是 ipgre_tunnel_xmit() 函数。这个函数所做的事情无非就是通过 tunnel 的 header_ops 构造一个新的头,并把对应的外部 IP 地址填进去,最后发送出去。

稍微难理解的是接收过程,即 router B 上面进行的操作。这里需要指出的一点是,GRE tunnel 自己定义了一个新的 IP proto,也就是 IPPROTO_GRE。当 router B 收到从 router A 过来的这个包时,它暂时还不知道这个是 GRE 的包,它首先会把它当作普通的 IP 包处理。因为外部的 IP 头的目的地址是该路由器的地址,所以它自己会接收这个包,把它交给上层,到了 IP 层之后才发现这个包不是 TCP,UDP,而是 GRE,这时内核会转交给 GRE 模块处理。

GRE 模块注册了一个 hook:

  1. static const struct gre_protocol ipgre_protocol = {
  2. . handler = ipgre_rcv,
  3. . err_handler = ipgre_err,
  4. } ;

所以真正处理这个包的函数是 ipgre_rcv() 。ipgre_rcv() 所做的工作是:通过外层IP 头找到对应的 tunnel,然后剥去外层 IP 头,把这个“新的”包重新交给 IP 栈去处理,像接收到普通 IP 包一样。到了这里,“新的”包处理和其它普通的 IP 包已经没有什么两样了:根据 IP 头中目的地址转发给相应的 host。注意:这里我所谓的“新的”包其实并不新,内核用的还是同一个copy,只是skbuff 里相应的指针变了。

五、参考页面

http://blog.chinaunix.net/uid-23392781-id-2426607.html (linux的tunnel技术实现 代码级分析)

http://www.chinaunix.net/old_jh/4/1055425.html (linux tunnel 技术)

http://docs.oracle.com/cd/E26926_01/html/E25874/gepbe.html (IP 隧道概述)

https://wiki.linuxfoundation.org/networking/tunneling (wiki页面,三种tunnel的配置)

http://www.iana.org/assignments/protocol-numbers/protocol-numbers.xml (协议相关)

 参考文章:http://www.361way.com/linux-tunnel/5199.html

Linux ipip隧道及实现的更多相关文章

  1. linux gre隧道创建

    目录 linux gre隧道创建 实验环境 实验目的 实验步骤 1.在host A(10.10.10.47)上面操作 2.在host B(192.168.0.118)上面操作 实验结果 还原实验环境 ...

  2. linux连接工具隧道模式

    使用linux连接工具,比如putty,xshell可以使用隧道模式跳转登录其他服务器 A->B B->C 比如正常情况下,A主机能访问B主机,B主机能访问C主机,那么就可以设置隧道模式让 ...

  3. Linux SSH隧道技术(端口转发,socket代理)

    动态转发(SOCKS5代理): 命令格式:ssh -D <local port> <SSH Server> ssh -fnND 0.0.0.0:20058 172.16.50. ...

  4. linux SSH 隧道

    一 什么是SSH隧道 首 先看下面这张图,我们所面临的大部分情况都和它类似.我们的电脑在右上角,通过公司带有防火墙功能的路由器接入互联网(当然可能还有交换机什么的在中间连 接着你和路由器,但是在我们的 ...

  5. [Linux] SSH隧道本地端口转发访问远程服务中的数据库

    当我的本地没有安装任何数据库服务的时候,可以直接通过我本地的端口访问远程机器上的数据库服务,实现这样的效果就可以使用本地转发功能 实际测试本地端口转发,把本地的9006端口转发给远程服务器的115.1 ...

  6. 什么是 IP 隧道,Linux 怎么实现隧道通信?

    本文首发于我的公众号 Linux云计算网络(id: cloud_dev),专注于干货分享,号内有 10T 书籍和视频资源,后台回复「1024」即可领取,欢迎大家关注,二维码文末可以扫. 通过之前的文章 ...

  7. Linux的Network Tunnel技术

    Linux的Network Tunnel技术 概要 Linux上可以使用ip tunnel命令创建多种类型的tunnel. 在 man ip-tunnel 中可以得知以下几种类型的tunnel: MO ...

  8. linux(Ubuntu/Centos) iproute 路由IP地址等命令集合,查看端口链接

    原 linux(Ubuntu/Centos) iproute 路由IP地址等命令集合,查看端口链接 2017年03月20日 16:55:57 风来了- 阅读数:2291 标签: centoslinux ...

  9. ubantu与CentOS虚拟机之间搭建GRE隧道

    Author       : Email         : vip_13031075266@163.com Date          : 2020.01.23 Copyright : 未经同意不得 ...

随机推荐

  1. 邓_PPT

    如何拯救一份丑到爆的PPT? "小邓,这是我做的PPT,你优化优化,明天早上给我,上午客户来要用." 领导,你这是PPT嘛,明明就是word嘛. "小张啊,你看看我这个P ...

  2. 月薪20k以上的高级程序员需要学习哪些技术呢?

    课程内容: 源码分析.分布式架构.微服务架构.性能优化.团队协作效率.双十一项目实战 适用对象: 1-5年或更长软件开发经验,没有工作经验但基础非常扎实,对java工作机制,常用设计思想,常用java ...

  3. MySQL主从复制的配置

    环境 操作系统:CentOS-6.6-x86_64-bin-DVD1.iso MySQL版本:mysql-5.6.26.tar.gz 主节点IP:192.168.1.205     主机名:edu-m ...

  4. MySQL Index Merge Optimization

    Index Merge用在通过一些range scans得到检索数据行和合并成一个整体.合并可以通过 unions,intersections,或者unions-intersection运用在底层的扫 ...

  5. Mac下Charles Contents乱码解决办法

    用到Charles,下载最新的4.0.1版本,但是发生乱码问题.百度好久才找到个靠谱的,那些说什么在Info.plist文件加字符串的,都是假的,反正我是试了都没用,这里记下详细的操作步骤解决: 1. ...

  6. 5dfda1332b67817b0f2d7839242021ce'Java数据结构和算法

    1.return 一个空的集合,而不是 null 如果一个程序返回一个没有任何值的集合,请确保一个空集合返回,而不是空元素.这样你就不用去写一大堆 "if else" 判断null ...

  7. SuperSocket基础一

    SuperSocket基础(一)——————基本概念 项目中之前一直使用TCP socket服务框架,但是不利于扩展.最近刚接触到开源的superSocket感觉很不错,特记录一下.官方开源地址:ht ...

  8. php 利用Gd库添加文字水印乱码的问题及解决方案

    最近一个项目进行了服务器迁移,部署后发现 ,其中一个为图片添加水印文字的功能出现了乱码问题,确认功能代码不存在问题,同时项目代码都是使用UTF-8编码,不存在编码问题,也检查排除了字体文件出现问题的可 ...

  9. 两层嵌套list,选取list中最长的list的长度

    # coding=utf-8 import pandas as pd file_path = "test_aa.xlsx" dt = pd.read_excel(file_path ...

  10. jquery取前、后、父、子元素

    前.prev(); 后.next(); 父.parent(); 子.children(); 注意:前的前是.prev().prev(),例如前元素无i,但前的前的i元素有i,不能写成.prev('i' ...