IP隧道技术之ipip

IP隧道技术

简介

IP 隧道(IP tunneling):是将一个IP报文封装在另一个IP报文的技术,这可以使得目标为一个IP地址的数据报文能被封装和转发到另一个IP地址。IP隧道技术亦称为IP封装技术(IP encapsulation)。IP隧道主要用于移动主机和虚拟私有网络(Virtual Private Network),在其中隧道都是静态建立的,隧道一端有一个IP地址,另一端也有唯一的IP地址。

Linux系统内核实现的IP隧道技术主要有三种(PPP、PPTP和L2TP等协议或软件不是基于内核模块的):IPIP (IPv4 in IPv4),GRE (IPv4/IPv6 over IPv4) ,SIT (IPv6 over IPv4) 。这三种隧道技术都需要内核模块 tunnel4.ko 的支持。

  • IPIP :需要内核模块ipip.ko,是最简单的一种。它具有最低的开销,但是只能封装IPv4单播流量,因此您将无法设置OSPF,RIP或任何其他基于多播的协议,只能为唯一的隧道端点对设置一个隧道
  • GRE : 需要内核模块ip_gre.ko ,GRE隧道可以封装IPv4 / IPv6单播/多播流量,因此它是动态路由网络的事实上的隧道标准。可以为唯一的隧道端点对最多设置64K隧道
  • SIT :代表"Simple Internet Transition",需要内核模块sit.ko。其主要目的是互连位于全球IPv4 Internet中的隔离的IPv6网络。SIT的工作方式类似于IPIP。内核模块是ipv6,加载后,无法卸载ipv6模块。您可以从隧道代理获取自己的IPv6前缀和SIT隧道 。

内核模块

隧道 内核模块 虚拟网卡
IPIP ipip.ko tunl0
GRE ip_gre.ko gre0
SIT sit.ko sit0

ip tunnel

shell 复制代码
$ ip tunnel help
Usage: ip tunnel { add | change | del | show | prl | 6rd } [ NAME ]
	 [ mode { ipip | gre | sit | isatap | vti } ] [ remote ADDR ] [ local ADDR ]
	 [ [i|o]seq ] [ [i|o]key KEY ] [ [i|o]csum ]
	 [ prl-default ADDR ] [ prl-nodefault ADDR ] [ prl-delete ADDR ]
	 [ 6rd-prefix ADDR ] [ 6rd-relay_prefix ADDR ] [ 6rd-reset ]
	 [ ttl TTL ] [ tos TOS ] [ [no]pmtudisc ] [ dev PHYS_DEV ]

Where:	NAME := STRING
	ADDR := { IP_ADDRESS | any }
	TOS  := { STRING | 00..ff | inherit | inherit/STRING | inherit/00..ff }
	TTL  := { 1..255 | inherit }
	KEY  := { DOTTED_QUAD | NUMBER }

# mode 代表不同的 IPIP 隧道类型

ipip

one to one

A 节点

shell 复制代码
# ip link add name mybr0 type bridge
# ip addr add 10.42.1.1/24 dev mybr0
# ip link set dev mybr0 up

B 节点

shell 复制代码
# ip link add name mybr0 type bridge
# ip addr add 10.42.2.1/24 dev mybr0
# ip link set dev mybr0 up

现在 A 节点的10.42.1.1/24是不通 B 节点的 10.42.2.1/24

A 节点上添加隧道,指定了remote和local,为点对点的隧道

shell 复制代码
# modprobe ipip
# ip tunnel add tunl0 mode ipip remote 172.16.232.194 local 172.16.232.172
# ip addr add 10.42.1.1/24 dev tunl0
# ip link set tunl0 up

A 节点上添加10.42.2.0/24路由,执行点对点的tunl0
# ip route add 10.42.2.0/24 dev tunl0

B 节点上也添加隧道

shell 复制代码
# modprobe ipip
# ip tunnel add tunl0 mode ipip remote 172.16.232.172 local 172.16.232.194
# ip addr add 10.42.2.1/24 dev tunl0
# ip link set tunl0 up

B 节点上添加10.42.1.0/24路由,执行点对点的tunl0
# ip route add 10.42.1.0/24 dev tunl0

现在,A、B节点上的10.42.1.0/24、10.42.2.0/24 就实现了互通

one to many

实际上,在创建 IPIP 隧道的时候完全可以不指定 remote 地址,只要在 TUN 设备上增加对应的路由,IPIP 隧道就知道如何封装新的 IP 数据包并发送到路由指定的目标地址。

shell 复制代码
A: 172.16.165.33   10.42.1.0/24
B: 172.16.165.244  10.42.2.0/24
C: 172.16.168.113  10.42.3.0/24

A 节点上创建隧道,并把B、C的路由指向tunl0

shell 复制代码
# modprobe ipip
# ip tunnel add tunl0 mode ipip
# ip link set tunl0 up
# ip addr add 10.42.1.0/32 dev tunl0
# ip route add 10.42.2.0/24 via 172.16.165.244 dev tunl0 onlink
# ip route add 10.42.3.0/24 via 172.16.168.113 dev tunl0 onlink

B 节点、 C节点同理

shell 复制代码
B 节点
# modprobe ipip
# ip tunnel add tunl0 mode ipip
# ip link set tunl0 up
# ip addr add 10.42.2.0/32 dev tunl0
# ip route add 10.42.1.0/24 via 172.16.165.33 dev tunl0 onlink
# ip route add 10.42.3.0/24 via 172.16.168.113 dev tunl0 onlink
C 节点
# modprobe ipip
# ip tunnel add tunl0 mode ipip
# ip link set tunl0 up
# ip addr add 10.42.3.0/32 dev tunl0
# ip route add 10.42.1.0/24 via 172.16.165.33 dev tunl0 onlink
# ip route add 10.42.2.0/24 via 172.16.165.244 dev tunl0 onlink

现在,A、B、C节点上的10.42.1.0/24、10.42.2.0/24、10.42.3.0/24 就实现了互通

使用ipip实现三层软网关

客户端

bash 复制代码
# 加载ipip模块,实现基于三层的软网关
$ sudo /usr/sbin/modprobe ipip
# 添加default路由,并测试到114的联通性
$ sudo ip link set tunl0 up
$ sudp ip r add default via $gw dev tunl0 onlink

# /etc/network/interfaces固化tunl0的软网关配置
$ vi /etc/network/interfaces
auto bond0
  ......
  post-up ip link set tunl0 up
  post-up ip r add default via 10.122.43.252 dev tunl0 onlink

服务端

bash 复制代码
$ echo 1 > /proc/sys/net/ipv4/ip_forward
$ sudo vi /etc/network/interfaces # 启动tunl口
auto tunl0
iface tunl0 inet manual
  up ip link set tunl0 up
down ip link set tunl0 down
$ sudo ifup tunl0
$ cat /etc/shorewall/masq # nat的地址
bond1.564 10.122.40.0/22
bond1.564 10.239.81.0/26
bond1.564 10.239.83.64/26
bond1.564 10.239.83.128/26
bond1.564 10.239.83.192/26

$ sudo iptables -L -n -t nat
Chain PREROUTING (policy ACCEPT)
target     prot opt source               destination

Chain INPUT (policy ACCEPT)
target     prot opt source               destination

Chain OUTPUT (policy ACCEPT)
target     prot opt source               destination

Chain POSTROUTING (policy ACCEPT)
target     prot opt source               destination
bond1.564_masq  all  --  0.0.0.0/0            0.0.0.0/0

Chain bond1.564_masq (1 references)
target     prot opt source               destination
MASQUERADE  all  --  10.122.40.0/22       0.0.0.0/0
MASQUERADE  all  --  10.239.81.0/26       0.0.0.0/0
MASQUERADE  all  --  10.239.83.64/26      0.0.0.0/0
MASQUERADE  all  --  10.239.83.128/26     0.0.0.0/0 # snat的ip段
MASQUERADE  all  --  10.239.83.192/26     0.0.0.0/0

如果做了2层snat,例如装机、容器里,将源ip不是本机的转换为本机ip

bash 复制代码
iptables -t nat -A POSTROUTING ! -s `hostname -I` -o tunl0 -j SNAT --to `hostname -I`

异常可以通过抓包分析

bash 复制代码
sudo tcpdump -eni any net $需要nat的地址
相关推荐
程序员-珍7 分钟前
虚拟机ip突然看不了了
linux·网络·网络协议·tcp/ip·centos
码农小白1 小时前
linux驱动:(22)中断节点和中断函数
linux·运维·服务器
4647的码农历程1 小时前
Linux网络编程 -- 网络基础
linux·运维·网络
C++忠实粉丝2 小时前
Linux环境基础开发工具使用(2)
linux·运维·服务器
康熙38bdc3 小时前
Linux 环境变量
linux·运维·服务器
hakesashou3 小时前
python如何比较字符串
linux·开发语言·python
Ljubim.te3 小时前
Linux基于CentOS学习【进程状态】【进程优先级】【调度与切换】【进程挂起】【进程饥饿】
linux·学习·centos
cooldream20094 小时前
Linux性能调优技巧
linux
QMCY_jason4 小时前
Ubuntu 安装RUST
linux·ubuntu·rust
慕雪华年4 小时前
【WSL】wsl中ubuntu无法通过useradd添加用户
linux·ubuntu·elasticsearch