1.5 Route
Linux创建Router并没有像创建虚拟Bridge那样,有一个直接的命令brctl,而且它间接的命令也没有,不能创建虚拟路由器.……因为它就是路由器(Router) !
不过Linux默认没有打开路由转发功能。可以用这个命令验证一下:
cat /proc/sys/net/ipv4/ip_forward
0
0 --> 表示没有开启路由功能
1 -->打开Linux的路由转发功能
临时修改(重启失效):
echo "1" /proc/sys/net/ipv4/ip_forward
1 /proc/sys/net/ipv4/ip_forward
永久修改:
vim /etc/sysctl.conf
net.ipv4.ip_forward=1
:wq!
加载配置
sysctl -p
net.ipv4.ip_forward = 1
测试用例:
NS1/tap1与NS2/tap2不在同一个网段中,中间需要经一个路由器进行转发才能互通。图中的Router是一个示意,其实就是Linux开通了路由转发功能。
当我们添加了tap并给其绑定IP地址时,Linux会自动生成直连路由。
(1)创建 veth pair
ip link add tap2 type veth peer name tap2_peer
ip link add tap3 type veth peer name tap3_peer
(2)创建namespacce
ip netns add ns1
ip netns add ns2
(3)把tab迁移到namespace
ip link set tap2 netns ns1
ip link set tap3 netns ns2
(4)配置tap ip地址
ifconfig tap2_peer 192.168.100.1/24
ifconfig tap3_peer 192.168.200.1/24
ip netns exec ns1 ifconfig tap2 192.168.100.2/24 up
ip netns exec ns2 ifconfig tap3 192.168.200.2/24 up
(5)将tap设置为up
ip link set tap2_peer up
ip link set tap3_peer up
(6)ping一下(不通)
ip netns exec ns1 ping 192.168.200.2
connect: Network is unreachable
查看一下路由表
ip netns exec ns1 route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 tap2
从上图可以看出ns1并没有到达192.168.200.0/24的路由,此时我们就需要手动添加,
(7)ns1 ns2都添加静态路由,分别到达对方的网段
ip netns exec ns1 route add -net 192.168.200.0 netmask 255.255.255.0 gw 192.168.100.1
ip netns exec ns2 route add -net 192.168.100.0 netmask 255.255.255.0 gw 192.168.200.1
(8)再次查看路由表
ip netns exec ns1 route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 tap2
192.168.200.0 192.168.100.1 255.255.255.0 UG 0 0 0 tap2
(9)在ping一下
ip netns exec ns1 ping 192.168.200.2
PING 192.168.200.2 (192.168.200.2) 56(84) bytes of data.
64 bytes from 192.168.200.2: icmp_seq=1 ttl=64 time=0.083 ms
64 bytes from 192.168.200.2: icmp_seq=2 ttl=64 time=0.034 ms
64 bytes from 192.168.200.2: icmp_seq=3 ttl=64 time=0.036 ms
^C
--- 192.168.200.2 ping statistics ---
3 packets transmitted, 3 received, 0% packet loss, time 1999ms
rtt min/avg/max/mdev = 0.034/0.051/0.083/0.022 ms
1.6 tun
tun是一个网络层(IP)的点对点设备,它启用了IP层隧道功能。Linux原生支持的三层隧道,可以通过命令行ip tunnel help查看:
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 }
以下是Linux原生支持的三层隧道
测试用例:
测试图解:
(1)tap1与tap2配置能ping通上面弄过了这里不在重复了
(2)当tap1和tap2配通以后,如果我们不把图2-10中的tun1和tun2暂时当做tun设备,而是当做两个“死”设备(比如当做是两个不做任何配置的网卡),那么这个时候tun1和tun2就像两个孤岛,不仅互相不通,而且跟tap1、tap2也没有关系。如下图所示
这个时候,我们就需要对tun1、tun2做相关配置,以使这两个两个孤岛能够互相通信。我们以ipip tunnel为例进行配置。
(3)加载ipip模块,Linux默认没有此模块
加载
modprobe ipip
查看
lsmod | grep ipip
ipip 13465 0
tunnel4 13252 1 ipip
ip_tunnel 25163 1 ipip
(4)在ns1 创建tun1和ipip tunnel
ip netns exec ns1 ip tunnel add tun1 mode ipip remote 192.168.200.2 local 192.168.100.2 ttl 255
ip netns exec ns1 ip link set tun1 up
ip netns exec ns1 ip addr add 192.168.50.10 peer 192.168.60.10 dev tun1
(5)在ns2 创建tun1和ipip tunnel
ip netns exec ns2 ip tunnel add tun2 mode ipip remote 192.168.100.2 local 192.168.200.2 ttl 255
ip netns exec ns2 ip link set tun2 up
ip netns exec ns2 ip addr add 192.168.60.10 peer 192.168.50.10 dev tun2
命令行解释:
(6)ping
ip netns exec ns1 ping 192.168.60.10
PING 192.168.60.10 (192.168.60.10) 56(84) bytes of data.
64 bytes from 192.168.60.10: icmp_seq=1 ttl=64 time=0.058 ms
64 bytes from 192.168.60.10: icmp_seq=2 ttl=64 time=0.046 ms
^C
--- 192.168.60.10 ping statistics ---
2 packets transmitted, 2 received, 0% packet loss, time 999ms
rtt min/avg/max/mdev = 0.046/0.052/0.058/0.006 ms
(7) 查看
ip netns exec ns1 ifconfig -a
tun1: flags=209<UP,POINTOPOINT,RUNNING,NOARP> mtu 1480
inet 192.168.50.10 netmask 255.255.255.255 destination 192.168.60.10
tunnel txqueuelen 1000 (IPIP Tunnel)
RX packets 2 bytes 168 (168.0 B)
RX errors 0 dropped 0 overruns 0 frame 0
TX packets 2 bytes 168 (168.0 B)
TX errors 0 dropped 0 overruns 0 carrier 0 collisions 0
tun1是一个ipip tunnel的一个端口,IP是192.168.50.10,其对端是192.168.60.10
(8)查看路由表
ip netns exec ns1 route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.60.10 0.0.0.0 255.255.255.255 UH 0 0 0 tun1
192.168.100.0 0.0.0.0 255.255.255.0 U 0 0 0 tap2
192.168.200.0 192.168.100.1 255.255.255.0 UG 0 0 0 tap2
增加了tun设备的ns1的路由表
总结:到达目的地192.168.60.10 的路由的一个直连路由从tun1出去即可
1.7 iptables
iptables与前文介绍的tap/tun等不同,它并不是一个网络设备。不过它们又有相同点:都是Linux的软件。通过iptables可以实现防火墙、NAT等功能,不过这句话也对,也不对。说它对,我们确实是通过iptables相关的命令行,实现了防火墙、NAT的功能;说它不对,是因为iptables其实只是一个运行在用户空间的命令行工具,真正实现这些功能的是运行在内核空间的netfilter模块。它们之间的关系如下图所示
(1)NAT
- NAT (Network Address
Translation,网络地址转换),顾名思义,就是从一个IP地址转换为另一个IP地址。当然,这里面的根本原因还是IP地址不够用的问题(解决IP地址枯竭的方法一个是IPv6,另一个就是NAT)。所以NAT,大家基本做的还是公网地址与私网地址的互相转换。如果一定要在公网地址之间互相转换,或者私网地址之间互相转换,技术上是支持的,只是这样的场景非常非常少。 - NAT,从实现技术角度来说,分为:静态NAT、动态NAT和端口多路复用三种方案。
- 静态NAT (Static NAT),有两个特征(如下图所示)。
- 私网IP地址与公网IP地址的转换规则是静态指定的,比如10.10.10.1与50.0.0.1互相转换,这个是静态指定好的。
- 私网IP地址与公网IP地址是1:1,即一个私网IP地址对应1个公网IP地址。
动态NAT
- —般情况是公网IP比私网IP地址少的时候,用到动态NAT方案。如果公网IP地址比私网IP地址还多(或者相等),则用静态NAT就可以了,没必要这么麻烦。
- 动态NAT,就是一批私网IP与公网IP地址之间不是固定的转换关系,而是在IP报文处理过程中由NAT模块进行动态匹配。虽然,公网IP比私网IP地址少,但是,同时在线的私网IP需求小于等于公网IP数量,不然某些私网IP将得不到正确的转换,从而导致网络通信失败。
动态NAT,有三个特征(如下图所示)
- 私网与公网IP地址之间不是固定匹配转换的,而是变化的;
- 两者之间的转换规则不是静态指定的,而是动态匹配的;
- 私网IP地址与公网IP地址之间是m : n,-般m < n
(3)端口多路复用/PAT
- 如果私网IP地址有多个,而公网IP地址只有一个,那么,静态NAT显然是不行了,动态NAT也基本不行(只有一个公网IP,不够用)。此时,就需要用到端口多路复用。多个私网IP映射到同一个公网IP,不同的私网IP利用端口号进行区分,这里的端口号指的是TCP/UDP端口号。所以端口复用又叫PAT(Port Address Translation) 。
端口多路复用(PAT)的特征是(如下图所示);
- 私网IP:公网IP = m : 1;
- 以公网IP+端口号来区分私网IP。
(4) SNAT/DNAT
- 前面说的是静态NAT ( Static
NAT)、动态NAT。很遗憾,不能简称SNAT、DNAT,因为SNAT/DNAT有另外的含义,是另外的缩写。要区分SNAT (Source NetworkAddress Translation,源地址转换)与DNAT ( Destination NetworkAddressTranslation,目的地址转换)这两个功能可以简单地由连接发起者是谁来区分。 - 内部地址要访问公网上的服务时(如Web访问),内部地址会主动发起连接,由路由器或者防火墙上的网关对内部地址做个地址转换,将内部地址的私有IP转换为公网的公有IP,网关的这个地址转换称为SNAT,主要用于内部共享IP访问外部。
- 当内部需要提供对外服务时(如对外发布Web网站),外部地址发起主动连接,由路由器或者防火墙上的网关接收这个连接,然后将连接转换到内部,此过程是由带有公网IP的网关替代内部服务来接收外部的连接,然后在内部做地址转换,此转换称为DNAT,主要用于内部服务对外发布。
(2)Netfilter中的NAT Chain
- 说chain有点太学究,大白话就是时刻点。通过前文介绍我们知道,NAT一共在三个时刻点对IP报文做了处理。下面我们一个一个描述。
(1)NAT-PREROUTING(DNAT)
NAT-PREROUTING (DNAT)的处理时刻点,如下图所示
- IP报文流的顺序是图中的“1-2-3-4-5”,在图2-21中A处,即PREROUTING时刻点进行NAT处理。IP报文的目的地址是IP1(公网IP),这个IP1就是Linux内核空间对外(公网)呈现的IP地址(说明这样的IP地址可以有多个)。当报文到达PREROUTING这个时刻点时,NAT模块会做处理。如果需要(即提前做了相关NAT配置),NAT模块会将目的IP从IP1转换成IP2(这个是提前配置好的),这也就是所谓的DNAT。
(3)NAT-PREROUTING(SNAT)
- IP报文流的顺序是图中的“1-2-3-4-5”,在图中“E”处,即POSTROUTING时刻点进行NAT处理。IP报文的源地址是IP3(私网lP),这个报文最后经过POSTROUTING这个时刻点时,如果需要(即提前做了相关NAT配置),NAT模块会做处理。NAT模块会将源IP从IP3转换成lP1(这个是提前配置好的),这也就是所谓的SNAT。这个IP1就是Linux内核空间对外(公网)呈现的IP地址(说明,这样的lP地址可以有多个)。
(4)NAT-OUTPUT(DNAT)
(5)小结
Linux内核空间Netfilter模块的NAT处理,一共有三个Chain(处理时刻点),如下图表示:
(6)Firwwall
iptables中的Firewall(防火墙)概念,属于网络防火墙的概念,如下图所示:
图中的“某些”规则决定了其是否属于“网络”防火墙。iptables中的防火墙的这些规则就是基于TCP/IP协议栈的规则,所以我们称之为网络防火墙。这些规则有:
-
in-interface (入网络接口名),数据包从哪个网络接口进入;
-
out-interface (出网络接口名),数据包从哪个网络接口输出;
-
protocol(协议类型),数据包的协议,如TCP、UDP和ICMP等;
-
source (源地址(或子网) ),数据包的源IP地址(或子网);
-
destination(目标地址(或子网)),数据包的目标lIP地址(或子网);
-
sport(源端口号),数据包的源端口号;
-
dport (目的端口号),数据包的目的端口号。
符合这些规则的,可以设置为通过(ACCEPT),反之,则不通过(DROP) 。或者,符合这些规则的,设置为不通过(DROP);反之,则通过(ACCEPT) 。
(7)mangle
mangle表主要用于修改数据包的ToS (Typeof Service,服务类型)、TTL ( Time toLive,生存周期)以及为数据包设置Mark标记,以实现QoS(Quality of Service,服务质量)调整以及策略路由等应用。
netfilter模块中的mangle处理的时刻点如下图所示:
(Netfilter中的Mangle的处理时刻点)
网络虚拟基础总结
tap、 tun、 veth pair在Linux中都被称为设备,但是在与日常概念的类比中,常常被称作接口。Neutron利用这些“接口”进行Bridge之间的连接、Bridge与VM(虚拟机)的连接、Bridge与Router之间的连接。三者与物理网卡之间的对比关系,如下图所示。
- 反而是Router、Bridge这些在Linux中没有被称为设备的网络功能,反而在日常概念中常常被称为设备。Bridge提供二层转发功能,Router提供三层转发功能。Router还常常借助iptable提供SNAT/DNAT功能。Bridge也常常借助iptable提供Firewall功能。
- 在Neutron中,隔离是一个非常重要的特性,利用namespace做隔离也是Neutron的一个非常重要的手段。