DNAT(Destination Network Address Translation,目的地址转换) 通常被叫做目的映射,SNAT(Source Network Address Translation,源地址转换)通常被叫做源映射。
这是我们在设置Linux网关或者防火墙时经常要用来的两种方式,要理解iptables中DNAT、SNAT和MASQUERADE,我们要先了解一下IP包的结构,如下图所示:
![](https://upload-images.jianshu.io/upload_images/12979420-ab1ef491ca0bad0d.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/589/format/webp)
在任何一个IP数据包中,都会有Source IP Address与Destination IP Address这两个字段,数据包所经过的路由器也是根据这两个字段是判定数据包是由什么地方发过来的,它要将数据包发到什么地方去。
iptables的DNAT与SNAT就是根据这个原理,对Source IP Address与Destination IP Address进行修改,然后我们再看看数据包在iptables中要经过的链(chain):
![](https://upload-images.jianshu.io/upload_images/12979420-6d39247674ee8b54.png?imageMogr2/auto-orient/strip%7CimageView2/2/w/540/format/webp)
图中正菱形的区域是对数据包进行判定转发的地方,在这里,系统会根据IP数据包中的destination ip address中的IP地址对数据包进行分发。
如果destination ip adress是本机地址,数据将会被转交给INPUT链。如果不是本机地址,则交给FORWARD链检测。
这也就是说,我们要做的DNAT要在进入这个菱形转发区域之前,也就是在PREROUTING链中做,比如我们要把访问202.103.96.112的访问转发到192.168.0.112上:
# iptables -t nat -A PREROUTING -d 202.103.96.112 -j DNAT --to-destination 192.168.0.112
这个转换过程当中,其实就是将已经达到这台Linux网关(防火墙)上的数据包上的destination ip address从202.103.96.112修改为192.168.0.112然后交给系统路由进行转发。
而SNAT自然是要在数据包流出这台机器之前的最后一个链也就是POSTROUTING链来进行操作
# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -j SNAT --to-source 58.20.51.66
这个语句就是告诉系统把即将要流出本机的数据的source ip address修改成为58.20.51.66。
这样,数据包在达到目的机器以后,目的机器会将包返回到58.20.51.66也就是本机。
如果不做这个操作,那么你的数据包在传递的过程中,reply的包肯定会丢失。
假如当前系统用的是ADSL/3G/4G动态拨号方式,那么每次拨号,出口IP都会改变,SNAT就会有局限性。
# iptables -t nat -A POSTROUTING -s 192.168.0.0/24 -o eth0 -j MASQUERADE
重点在那个『 MASQUERADE 』!这个设定值就是『IP伪装成为封包出去(-o)的那块装置上的IP』!
不管现在eth0的出口获得了怎样的动态ip,MASQUERADE会自动读取eth0现在的ip地址然后做SNAT出去,这样就实现了很好的动态SNAT地址转换。
总结:
# iptables -t nat -A PREROUTING -d destIP -j DNAT --to-destination newDestIP
# iptables -t nat -A POSTROUTING -s sourceIP -j SNAT --to-source newSourceIP
# iptables -t nat -A POSTROUTING -s sourceIP -o outInterface -j MASQUERADE
应用场景:
ipvs的nat模式
libvirt的net
# virsh net-dumpxml default
<network>
<name>default</name>
<uuid>80b503fc-c775-4393-bc89-8f9912594cb5</uuid>
<forward dev='eno1' mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
<interface dev='eno1'/>
</forward>
<bridge name='virbr0' stp='on' delay='0'/>
<mac address='52:54:00:88:e7:03'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254'/>
</dhcp>
</ip>
</network>
[root@ncpu-lxc2 ~]# iptables -nvL
Chain INPUT (policy ACCEPT 1826K packets, 261M bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- eno1 virbr0 0.0.0.0/0 192.168.122.0/24 ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- virbr0 eno1 192.168.122.0/24 0.0.0.0/0
0 0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0
0 0 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- virbr0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 1764K packets, 263M bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- * virbr0 0.0.0.0/0 0.0.0.0/0 udp dpt:68
# iptables -nvL -t nat
Chain PREROUTING (policy ACCEPT 255K packets, 21M bytes)
pkts bytes target prot opt in out source destination
Chain INPUT (policy ACCEPT 255K packets, 21M bytes)
pkts bytes target prot opt in out source destination
Chain OUTPUT (policy ACCEPT 170 packets, 11596 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 170 packets, 11596 bytes)
pkts bytes target prot opt in out source destination
0 0 RETURN all -- * eno1 192.168.122.0/24 224.0.0.0/24
0 0 RETURN all -- * eno1 192.168.122.0/24 255.255.255.255
0 0 MASQUERADE tcp -- * eno1 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
0 0 MASQUERADE udp -- * eno1 192.168.122.0/24 !192.168.122.0/24 masq ports: 1024-65535
0 0 MASQUERADE all -- * eno1 192.168.122.0/24 !192.168.122.0/24
[root@ncpu-lxc2 ~]#
# iptables -nvL -t filter
Chain INPUT (policy ACCEPT 1828K packets, 261M bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:53
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:53
0 0 ACCEPT udp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 udp dpt:67
0 0 ACCEPT tcp -- virbr0 * 0.0.0.0/0 0.0.0.0/0 tcp dpt:67
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT all -- eno1 virbr0 0.0.0.0/0 192.168.122.0/24 ctstate RELATED,ESTABLISHED
0 0 ACCEPT all -- virbr0 eno1 192.168.122.0/24 0.0.0.0/0
0 0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0
0 0 REJECT all -- * virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
0 0 REJECT all -- virbr0 * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable
Chain OUTPUT (policy ACCEPT 1766K packets, 263M bytes)
pkts bytes target prot opt in out source destination
0 0 ACCEPT udp -- * virbr0 0.0.0.0/0 0.0.0.0/0 udp dpt:68
IPtables中可以灵活的做各种网络地址转换(NAT)
网络地址转换主要有两种:SNAT和DNAT
SNAT是source network address translation的缩写即源地址目标转换
比如,多个PC机使用ADSL路由器共享上网,每个PC机都配置了内网IP。PC机访问外部网络的时候,路由器将数据包的报头中的源地址替换成路由器的ip。当外部网络的服务器比如网站web服务器接到访问请求的时候,他的日志记录下来的是路由器的ip地址,而不是pc机的内网ip。
这是因为,这个服务器收到的数据包的报头里边的“源地址”,已经被替换了。所以叫做SNAT,基于源地址的地址转换。
DNAT是destination network address translation的缩写即目标网络地址转换
典型的应用是,有个web服务器放在内网,配置内网ip,前端有个防火墙,配置公网ip,互联网上的访问者使用公网ip来访问这个网站。当访问的时候,客户端发出一个数据包,这个数据包的报头里边,目标地址写的是防火墙的公网ip。防火墙会把这个数据包的报头改写一次,将目标地址改写成web服务器的内网ip,然后再把这个数据包发送到内网的web服务器上这样,数据包就穿透了防火墙,并从公网ip变成了一个对内网地址的访问了,即DNAT,基于目标的网络地址转换 。
MASQUERADE,地址伪装,在iptables中有着和SNAT相近的效果,但也有一些区别:
SNAT,DNAT,MASQUERADE都是NAT,MASQUERADE是SNAT的一个特例。
SNAT是指在数据包从网卡发送出去的时候,把数据包中的源地址部分替换为指定的IP,这样,接收方就认为数据包的来源是被替换的那个IP的主机。
MASQUERADE是用发送数据的网卡上的IP来替换源IP,因此,对于那些IP不固定的场合,比如拨号网络或者通过dhcp分配IP的情况下,就得用MASQUERADE。
DNAT,就是指数据包从网卡发送出去的时候,修改数据包中的目的IP,表现为如果你想访问A,可是因为网关做了DNAT,把所有访问A的数据包的目的IP全部修改为B,那么,你实际上访问的是B。
因为,路由是按照目的地址来选择的,因此,DNAT是在PREROUTING链上来进行的,而SNAT是在数据包发送出去的时候才进行,因此是在POSTROUTING链上进行的
但使用SNAT的时候,出口ip的地址范围可以是一个,也可以是多个,例如:
iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT –to-source 192.168.5.3
iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT –to-source 192.168.5.3-192.168.5.5
但是,对于SNAT,不管是几个地址,必须明确的指定要SNAT的ip
假如当前系统用的是ADSL动态拨号方式,那么每次拨号,出口ip192.168.5.3都会改变
而且改变的幅度很大,不一定是192.168.5.3到192.168.5.5范围内的地址
这个时候如果按照现在的方式来配置iptables就会出现问题了
因为每次拨号后,服务器地址都会变化,而iptables规则内的ip是不会随着自动变化的
每次地址变化后都必须手工修改一次iptables,把规则里边的固定ip改成新的ip
这样是非常不好用的
比如下边的命令:
iptables -t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j MASQUERADE
如此配置的话,不用指定SNAT的目标ip了
不管现在eth0的出口获得了怎样的动态ip,MASQUERADE会自动读取eth0现在的ip地址然后做SNAT出去
这样就实现了很好的动态SNAT地址转换
对于MASQUERADE,只是计算机的负荷稍微多一点。因为对每个匹配的包,MASQUERADE都要查找可用的IP地址,而不象SNAT用的IP地址是配置好的。当然,这也有好处,就是我们可以使用通过PPP、 PPPOE、SLIP等拨号得到的地址,这些地址可是由ISP的DHCP随机分配的。
我们可能需要将访问主机的7979端口映射到8080端口。也可以iptables重定向完成
iptables -t nat -A PREROUTING -p tcp --dport 7979 -j REDIRECT --to-ports 8080
更改iptables,使之实现nat映射功能
将外网访问192.168.75.5的80端口转发到192.168.75.3:8000端口。
# iptables -t nat -A PREROUTING -d 192.168.75.5 -p tcp --dport 80 -j DNAT --to-destination 192.168.75.3:8000
将192.168.75.3 8000端口将数据返回给客户端时,将源ip改为192.168.75.5
# iptables -t nat -A POSTROUTING -d 192.168.75.3 -p tcp --dport 8000 -j SNAT 192.168.75.5
IPtables中可以灵活的做各种网络地址转换(NAT),网络地址转换主要有两种:SNAT和DNAT。
SNAT是source networkaddress translation的缩写,即源地址目标转换。比如,多个PC机使用ADSL路由器共享上网,每个PC机都配置了内网IP,PC机访问外部网络的时候,路由器将数据包的报头中的源地址替换成路由器的ip,当外部网络的服务器比如网站web服务器接到访问请求的时候,他的日志记录下来的是路由器的ip地址,而不是pc机的内网ip,这是因为,这个服务器收到的数据包的报头里边的“源地址”,已经被替换了,所以叫做SNAT,基于源地址的地址转换。
DNAT是destination networkaddress translation的缩写,即目标网络地址转换,典型的应用是,有个web服务器放在内网配置内网ip,前端有个防火墙配置公网ip,互联网上的访问者使用公网ip来访问这个网站,当访问的时候,客户端发出一个数据包,这个数据包的报头里边,目标地址写的是防火墙的公网ip,防火墙会把这个数据包的报头改写一次,将目标地址改写成web服务器的内网ip,然后再把这个数据包发送到内网的web服务器上,这样,数据包就穿透了防火墙,并从公网ip变成了一个对内网地址的访问了,即DNAT,基于目标的网络地址转换。
MASQUERADE,地址伪装,算是snat中的一种特例,可以实现自动化的snat。
在iptables中有着和SNAT相近的效果,但也有一些区别,但使用SNAT的时候,出口ip的地址范围可以是一个,也可以是多个,例如:
如下命令表示把所有10.8.0.0网段的数据包SNAT成192.168.5.3的ip然后发出去,
iptables-t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source 192.168.5.3
如下命令表示把所有10.8.0.0网段的数据包SNAT成192.168.5.3/192.168.5.4/192.168.5.5等几个ip然后发出去
iptables-t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j SNAT --to-source 192.168.5.3-192.168.5.5
这就是SNAT的使用方法,即可以NAT成一个地址,也可以NAT成多个地址,但是,对于SNAT,不管是几个地址,必须明确的指定要SNAT的ip,假如当前系统用的是ADSL动态拨号方式,那么每次拨号,出口ip192.168.5.3都会改变,而且改变的幅度很大,不一定是192.168.5.3到192.168.5.5范围内的地址,这个时候如果按照现在的方式来配置iptables就会出现问题了,因为每次拨号后,服务器地址都会变化,而iptables规则内的ip是不会随着自动变化的,每次地址变化后都必须手工修改一次iptables,把规则里边的固定ip改成新的ip,这样是非常不好用的。
MASQUERADE就是针对这种场景而设计的,他的作用是,从服务器的网卡上,自动获取当前ip地址来做NAT。
比如下边的命令:
iptables-t nat -A POSTROUTING -s 10.8.0.0/255.255.255.0 -o eth0 -j MASQUERADE
如此配置的话,不用指定SNAT的目标ip了,不管现在eth0的出口获得了怎样的动态ip,MASQUERADE会自动读取eth0现在的ip地址然后做SNAT出去,这样就实现了很好的动态SNAT地址转换。
LVS源码分析一---为什么是LVS?
版权:自由转载,说明出处,保留原作者名,需要商业用途,请联系作者me. 韩波 2009.12.31 email:yahoo邮箱GameProgramHack
刚进入互联网行业不久,从哪里开始呢?云计算,算了吧,... ...。还是从集群技术开始吧。至于集群当然就选LVS了。
个人认为集群技术是所有知名互联网企业都用到的基础技术。要想在互联网行业“混”,个人认为集群技术是必修课。
为什么源码分析?我google,baidu了一下,发现没有LVS源码分析的帖子。那就自己写吧。下个蛋方便后来的小朋友。年老的时候回顾一下co,co,co的这段生活。
先看完http://www.linuxvirtualserver.org/zh/index.html这个再说吧。
以上url读后感:
ipvs的3种技术。
1)VS/NAT机制,第一反应是,netfitler已经实现nat的功能,ipvs不会再自己实现一边相同的功能吧!?!
2)VS/TUN机制,应该和IPsec VPN的实现机制差不多吧。
3)VS/DR机制,以前做集群方案的时候听XX说过,原来起源于ipvs,当时XX还说是商业机密,不告诉我。无语。
ipvs这块总体感觉后续不会遇到多少阻力。
这里有两点值得高兴.
1)LVS是中国人搞的,开源社区很少看到中国人。
2)ipvs是基于netfilter机制的。娃哈哈。
ipvs代码。linux-2.6.31.4
net/netfilter/ipvs/*
include/linux/ip_vs.h
include/net/ip_vs.h
virsh虚拟网络管理命令
配置KVM虚拟机的网络,Bridge和Nat方式
1.bridged(桥接模式)
在bridged模式下,虚拟出来的操作系统就像是局域网中的一台独立的主机,它可以访问网内任何一台机器。同时,由于这个虚拟系统是局域网中的一个独立的主机系统,那么就可以手工配置它的TCP/IP配置信息,以实现通过局域网的网关或路由器访问互联网。
使用bridged模式的虚拟系统和宿主机器的关系,就像连接在同一个Hub上的两台电脑。想让它们相互通讯,你就需要为虚拟系统配置IP地址和子网掩码,否则就无法通信
(参考dhcp服务器是否开启,如果开启,则可以选择dhcp方式自动获取网络地址)。
这种方式最简单,直接将虚拟网卡桥接到一个物理网卡上面,和linux下一个网卡绑定两个不同地址类似,实际上是将网卡设置为混杂模式,从而达到侦听多个IP的能力。
在此种模式下,虚拟机内部的网卡(例如linux下的eth0)直接连到了物理网卡所在的网络上,可以想象为虚拟机和host机处于对等的地位,在网络关系上是平等的,没有谁在谁后面的问题。使用这种方式很简单,前提是你可以得到1个以上的地址。
用KVM配置Bridge方式:
首先需要确定你的host主机上用的网络连接方式为桥接方式,我的机器上的用的是一个叫br0的网桥。创建网桥的方式也很简单,以我的系统为例,网卡一个eno16777736,在目
录/etc/sysconfig/network-scripts/下创建文件ifcfg-br0,然后修改文件ifcfg-eno16777736为:
BOOTPROTO=none
DEVICE=eno16777736
HWADDR=00:0c:29:09:0d:3d
NM_CONTROLLED=no
ONBOOT=yes
BRIDGE=br0
修改文件ifcfg-br0的内容为:
BOOTPROTO=static
DEVICE=br0
TYPE=Bridge
NM_CONTROLLED=no
IPADDR=192.168.7.183
NETMASK=255.255.255.0
GATEWAY=192.168.7.254
在虚拟机的XML配置文件中device下添加interface标签即可,标签如下:
<interface type='bridge'>
<mac address='52:54:00:84:e9:e1'/>
<source bridge='br0'/>
<model type='rtl8139'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
当然也可以先定义一下这个网络,然后在添加到虚拟机的XML文件中,给它起名为br0.xml,这个文件中可以写一些网络的详细配置参数,大致的形式如下:
<network>
<name>br0</name>
<uuid>fb48b969-b9f4-e859-d957-50aedd850fb4</uuid>
<forward mode='bridge'>
<bridge name ='br0'/>
</forward>
</network>
然后用libvirt来定义并开启这个网络,配置文件中的interface标签当然还是不能少,用上面的就好,名字正好一致了:
virsh net-define br0.xml
virsh net-start br0
然后就可已启动客户机,检查网络连接了。
2.NAT(网络地址转换模式)
使用NAT模式,就是让虚拟系统借助NAT(网络地址转换)功能,通过宿主机器所在的网络来访问公网。也就是说,使用NAT模式可以实现在虚拟系统里访问互联网。很显然,如果你只有一个外网地址,此种方式很合适。
KVM虚拟机Nat方式上网:
virsh net-list
查看当前活跃的网络,可以看到一个default网络,这个就是一个默认的Nat网络了。
virsh net-dumpxml default
可以查看该网络的详细配置如下:
<network>
<name>default</name>
<uuid>75dbebde-fc15-4350-8a06-f1432f9e6d30</uuid>
<forward mode='nat'>
<nat>
<port start='1024' end='65535'/>
</nat>
</forward>
<bridge name='virbr0' stp='on' delay='0' />
<mac address='52:54:00:bc:f2:65'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254' />
</dhcp>
</ip>
</network>
可以看到该网络搭建在一个网桥virbr0上,这个网桥在安装并启动libvirt的时候自动生成。然后在客户机的XML配置文件中添加标签interface内容如下:
<interface type='network'>
<mac address='52:54:00:c7:18:b5'/>
<source network='default'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
则可以让客户机用nat方式来上网了,经验证,客户机可以获取到122网段,2到254之间的一个ip地址。
我们可以直接编辑修改default网络的配置:
virsh net-edit default
也可以直接将default网络干掉,然后再重新定义:
virsh net-undefine default
重新创建一个default.xml文件,自定义其中的内容,可以指定某个mac地址对应某个ip,指定某个ip段。例如下面的内容,name对应的是客户机的名字。
<network>
<name>default</name>
<uuid>dc69ff61-6445-4376-b940-8714a3922bf7</uuid>
<forward mode='nat'/>
<bridge name='virbr0' stp='on' delay='0' />
<mac address='52:54:00:81:14:18'/>
<ip address='192.168.122.1' netmask='255.255.255.0'>
<dhcp>
<range start='192.168.122.2' end='192.168.122.254' />
<host mac='00:25:90:eb:4b:bb' name='guest1' ip='192.168.5.13' />
<host mac='00:25:90:eb:34:2c' name='guest2' ip='192.168.7.206' />
<host mac='00:25:90:eb:e5:de' name='guest3' ip='192.168.7.207' />
<host mac='00:25:90:eb:7e:11' name='guest4' ip='192.168.7.208' />
<host mac='00:25:90:eb:b2:11' name='guest5' ip='192.168.7.209' />
</dhcp>
</ip>
</network>
然后用命令:
virsh net-define default.xml
virsh net-start default
启用一个客户机,检查网络时候可用。
KVM 客户机网络连接有两种方式:
用户网络(User Networking):让虚拟机访问主机、互联网或本地网络上的资源的简单方法,但是不能从网络或其他的客户机访问客户机,性能上也需要大的调整。NAT方式。
虚拟网桥(Virtual Bridge):这种方式要比用户网络复杂一些,但是设置好后客户机与互联网,客户机与主机之间的通信都很容易。Bridge方式。
本文主要解释NAT方式的配置。
NAT方式原理
NAT方式是kvm安装后的默认方式。它支持主机与虚拟机的互访,同时也支持虚拟机访问互联网,但不支持外界访问虚拟机。
检查当前的网络设置:
#virsh net-list --all
Name State Autostart
default active yes
default是宿主机安装虚拟机支持模块的时候自动安装的。
检查当前的网络接口:
#ifconfig
eth0 Link encap:Ethernet HWaddr 44:37:E6:4A:62:AD
inet6 addr: fe80::4637:e6ff:fe4a:62ad/64 Scope:Link
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:987782 errors:0 dropped:0 overruns:0 frame:0
TX packets:84155 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:1000
RX bytes:109919111 (104.8 MiB) TX bytes:12695454 (12.1 MiB)
Interrupt:17
lo Link encap:Local Loopback
inet addr:127.0.0.1 Mask:255.0.0.0
inet6 addr: ::1/128 Scope:Host
UP LOOPBACK RUNNING MTU:16436 Metric:1
RX packets:4 errors:0 dropped:0 overruns:0 frame:0
TX packets:4 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:240 (240.0 b) TX bytes:240 (240.0 b)
virbr0 Link encap:Ethernet HWaddr 52:54:00:B9:B0:96
inet addr:192.168.122.1 Bcast:192.168.122.255 Mask:255.255.255.0
UP BROADCAST RUNNING MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:2126 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:0
RX bytes:0 (0.0 b) TX bytes:100387 (98.0 KiB)
virbr0-nic Link encap:Ethernet HWaddr 52:54:00:B9:B0:96
BROADCAST MULTICAST MTU:1500 Metric:1
RX packets:0 errors:0 dropped:0 overruns:0 frame:0
TX packets:0 errors:0 dropped:0 overruns:0 carrier:0
collisions:0 txqueuelen:500
RX bytes:0 (0.0 b) TX bytes:0 (0.0 b)
其中virbr0是由宿主机虚拟机支持模块安装时产生的虚拟网络接口,也是一个switch和bridge,负责把内容分发到各虚拟机。
virbr0是一个桥接器,接收所有到网络192.168.122.*的内容。从下面命令可以验证:
brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.525400b9b096 yes virbr0-nic
route
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.122.0 * 255.255.255.0 U 0 0 0 virbr0
同时,虚拟机支持模块会修改iptables规则,通过命令可以查看:
iptables -t nat -L -nv
Chain PREROUTING (policy ACCEPT 16924 packets, 2759K bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 2009 packets, 125K bytes)
pkts bytes target prot opt in out source destination
421 31847 MASQUERADE all -- 192.168.122.0/24 !192.168.122.0/24 ----------->这条是关键,它配置了NAT功能。
Chain OUTPUT (policy ACCEPT 2011 packets, 125K bytes)
pkts bytes target prot opt in out source destination
iptables -t filter -L -nv
Chain INPUT (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
1 74 ACCEPT udp -- virbr0 0.0.0.0/0 0.0.0.0/0 udp dpt:53 ---->由libvirt脚本自动写入
0 0 ACCEPT tcp -- virbr0 0.0.0.0/0 0.0.0.0/0 tcp dpt:53 ---->由libvirt脚本自动写入
3 984 ACCEPT udp -- virbr0 0.0.0.0/0 0.0.0.0/0 udp dpt:67 ---->由libvirt脚本自动写入
0 0 ACCEPT tcp -- virbr0 0.0.0.0/0 0.0.0.0/0 tcp dpt:67 ---->由libvirt脚本自动写入
178K 195M ACCEPT all -- 0.0.0.0/0 0.0.0.0/0 state RELATED,ESTABLISHED ---->iptables的系统预设
2 168 ACCEPT icmp -- 0.0.0.0/0 0.0.0.0/0 ---->iptables的系统预设
1148 216K ACCEPT all -- lo 0.0.0.0/0 0.0.0.0/0 ---->iptables的系统预设
1 60 ACCEPT tcp -- 0.0.0.0/0 0.0.0.0/0 state NEW tcp dpt:22 ---->iptables的系统预设
16564 2721K REJECT all -- 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited ---->iptables的系统预设
Chain FORWARD (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
3726 3485K ACCEPT all -- virbr0 0.0.0.0/0 192.168.122.0/24 state RELATED,ESTABLISHED ---->由libvirt脚本自动写入
3491 399K ACCEPT all -- virbr0 192.168.122.0/24 0.0.0.0/0 ---->由libvirt脚本自动写入
0 0 ACCEPT all -- virbr0 virbr0 0.0.0.0/0 0.0.0.0/0 ---->由libvirt脚本自动写入
0 0 REJECT all -- virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable ---->由libvirt脚本自动写入
0 0 REJECT all -- virbr0 0.0.0.0/0 0.0.0.0/0 reject-with icmp-port-unreachable ---->由libvirt脚本自动写入
0 0 REJECT all -- * 0.0.0.0/0 0.0.0.0/0 reject-with icmp-host-prohibited ---->iptables的系统预设
Chain OUTPUT (policy ACCEPT 181K packets, 138M bytes)
pkts bytes target prot opt in out source destination
如果没有default的话,或者需要扩展自己的虚拟网络,可以使用命令重新安装NAT。
NAT方式的适用范围
桌面主机虚拟化。
创建步骤
#virsh net-define /usr/share/libvirt/networks/default.xml
此命令定义一个虚拟网络,default.xml的内容:
<network>
<name>default</name>
<bridge name="virbr0" />
<forward/>
<ip address="192.168.122.1" netmask="255.255.255.0">
<dhcp>
<range start="192.168.122.2" end="192.168.122.254" />
</dhcp>
</ip>
</network>
也可以修改xml,创建自己的虚拟网络。
标记为自动启动:
#virsh net-autostart default
Network default marked as autostarted
启动网络:
#virsh net-start default
Network default started
网络启动后可以用命令brctl show 查看和验证。
修改/etc/sysctl.conf中参数,允许ip转发:
net.ipv4.ip_forward=1
客户机安装
客户机安装时注意,网络要选择用NAT方式。
编辑修改虚拟机配置文件 /etc/libvirt/qemu/v1.xml,增加如下内容
<interface type='network'>
<mac address='52:54:00:4f:1b:07'/>
<source network='default'/>
<model type='virtio'/>
<address type='pci' domain='0x0000' bus='0x00' slot='0x03' function='0x0'/>
</interface>
虚拟机启动后,验证网络接口是否正常:
brctl show
bridge name bridge id STP enabled interfaces
virbr0 8000.525400b9b096 yes virbr0-nic
vnet0
Bridge方式的影响
Bridge方式配置出来的接口对NAT方式没有影响,因为NAT方式并没有使用物理网卡。但作为客户机,只能选择其中的一种。
Bridge方式即虚拟网桥的网络连接方式,是客户机和子网里面的机器能够互相通信。可以使虚拟机成为网络中具有独立IP的主机。
场景说明:KVM虚拟机之前没有设置为Bridge模式,然后就直接创建虚拟机了(当时网卡模式选择的为default),后来调整KVM网卡模式为Bridge后,虚拟机没法正常联网。
[root@node160 ~]# virsh shudown CentOS-7.3-X86_64
[root@node160 ~]# virsh edit CentOS-7.3-X86_64
将xml配置文件中的:
<interface type=‘network‘>
<mac address=‘52:54:00:e4:7c:77‘/>
<source network=‘default‘/>
<model type=‘virtio‘/>
<address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x03‘ function=‘0x0‘/>
</interface>
修改为:
<interface type=‘bridge‘>
<mac address=‘52:54:00:e4:7c:77‘/>
<source bridge=‘br0‘/>
<model type=‘virtio‘/>
<address type=‘pci‘ domain=‘0x0000‘ bus=‘0x00‘ slot=‘0x03‘ function=‘0x0‘/>
</interface>
由于kvm虚拟机使用的是bridge模式,可以把virbr0接口(即NAT方式里面的default虚拟网络)删除
[root@node160 ~]# ip add list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP qlen 1000
link/ether 00:0c:29:14:2b:9a brd ff:ff:ff:ff:ff:ff
4: virbr0: <NO-CARRIER,BROADCAST,MULTICAST,UP> mtu 1500 qdisc noqueue state DOWN qlen 1000
link/ether 52:54:00:9f:ad:48 brd ff:ff:ff:ff:ff:ff
inet 192.168.122.1/24 brd 192.168.122.255 scope global virbr0
valid_lft forever preferred_lft forever
5: virbr0-nic: <BROADCAST,MULTICAST> mtu 1500 qdisc pfifo_fast master virbr0 state DOWN qlen 1000
link/ether 52:54:00:9f:ad:48 brd ff:ff:ff:ff:ff:ff
7: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 00:0c:29:14:2b:9a brd ff:ff:ff:ff:ff:ff
inet 10.10.10.160/24 brd 10.10.10.255 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe14:2b9a/64 scope link
valid_lft forever preferred_lft forever
8: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 1000
link/ether fe:54:00:71:7b:aa brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fe71:7baa/64 scope link
valid_lft forever preferred_lft forever
10: vnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 1000
link/ether fe:54:00:e4:7c:77 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fee4:7c77/64 scope link
valid_lft forever preferred_lft forever
[root@node160 ~]# virsh net-list --all
Name State Autostart Persistent
default active yes yes
[root@node160 ~]# brctl show
bridge namebridge idSTP enabledinterfaces
br08000.000c29142b9anoeth0
vnet0
vnet1
virbr08000.5254009fad48yesvirbr0-nic
[root@node160 ~]# virsh net-destroy default
Network default destroyed
[root@node160 ~]# virsh net-undefine default
Network default has been undefined
配置完成后,再次查看网卡信息
[root@node160 ~]# ip add list
1: lo: <LOOPBACK,UP,LOWER_UP> mtu 65536 qdisc noqueue state UNKNOWN qlen 1
link/loopback 00:00:00:00:00:00 brd 00:00:00:00:00:00
inet 127.0.0.1/8 scope host lo
valid_lft forever preferred_lft forever
inet6 ::1/128 scope host
valid_lft forever preferred_lft forever
2: eth0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UP qlen 1000
link/ether 00:0c:29:14:2b:9a brd ff:ff:ff:ff:ff:ff
7: br0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc noqueue state UP qlen 1000
link/ether 00:0c:29:14:2b:9a brd ff:ff:ff:ff:ff:ff
inet 10.10.10.160/24 brd 10.10.10.255 scope global br0
valid_lft forever preferred_lft forever
inet6 fe80::20c:29ff:fe14:2b9a/64 scope link
valid_lft forever preferred_lft forever
8: vnet0: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 1000
link/ether fe:54:00:71:7b:aa brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fe71:7baa/64 scope link
valid_lft forever preferred_lft forever
10: vnet1: <BROADCAST,MULTICAST,UP,LOWER_UP> mtu 1500 qdisc pfifo_fast master br0 state UNKNOWN qlen 1000
link/ether fe:54:00:e4:7c:77 brd ff:ff:ff:ff:ff:ff
inet6 fe80::fc54:ff:fee4:7c77/64 scope link
valid_lft forever preferred_lft forever