mtu 1500 qdisc noop state DOWN
link/ether 06:1a:7d:f9:4d:37 brd ff:ff:ff:ff:ff:ff
其中eth0 192.168.0.104/24 是无线上网,和无线路由一个网段的地址,直接上网用。
eth1 172.16.149.129/24 是私有地址,作为私有地址,与主机互联。
虚拟机宿机系统路由表:
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.0.0 0.0.0.0 255.255.255.0 U 1 0 0 eth0
172.16.149.0 0.0.0.0 255.255.255.0 U 1 0 0 eth1
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 eth1
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 eth0
1.4 虚拟机nat命令设置
编译好内核,设置虚拟机的nat
执行命令:
$ sudo iptables -t nat -A POSTROUTING -s 172.16.149.0/24 -o eth0 -j SNAT --to 192.168.0.104
这条命令的意思是,在POSTROUTING挂载点,在家一个nat,将我虚拟机内私有的ip网段172.16.149.0/24地址 做源地址nat, nat成 我本机的对外的上网的地址192.168.0.104,并从192.168.0.104所在网段的网口发送出去。
这样,我主机地址inet 172.16.149.1/24就可以通过虚拟机做snat上网,当然,在没做这个设置之前,我的虚拟机是通过主机上网的。所以网段是inet 172.16.149.1/24。
执行一下之后,察看一下,察看一下,是否设置成功且正确:
$ sudo iptables -t nat -vL -n
Chain PREROUTING (policy ACCEPT 0 packets, 0 bytes)
pkts bytes target prot opt in out source destination
Chain POSTROUTING (policy ACCEPT 1 packets, 71 bytes)
pkts bytes target prot opt in out source destination
0 0 SNAT all -- * eth0 172.16.149.0/24 0.0.0.0/0 to:192.168.0.104
Chain OUTPUT (policy ACCEPT 1 packets, 71 bytes)
pkts bytes target prot opt in out source destination
可以看见在挂载点postrouting增加了一个snat,source源地址是172.16.149.0/24,out出口设备是eth0。
1.5 开启主机转发功能
这个功能一定要开启,如果不开启是无法完成上网的。
其中echo 1到配置文件,是使当前环境转发有效,回头一会我们还会用这个知识点来验证我们的路由确实是完全通过虚拟机上网的。
$ sudo echo 1 > /proc/sys/net/ipv4/ip_forward
这个配置,是让系统运行起来,就默认执行开启路由转发功能
$ sudo vi /etc/sysctl.conf
取消 # net.ipv4.ip_forward = 1 的注释,保存退出
到此虚拟机环境设置完毕。
2 主机环境配置
主机只需要改变下路由,由原来的192.168.0.1及对应的出口网卡设备,改为从虚拟机的私有ip地址及网卡设备上网
重点和难点都在虚拟机当中,当并未设置虚拟机上网时,主机的路由表如下:
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 192.168.0.1 0.0.0.0 UG 0 0 0 wlan0
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 wlan0
172.16.149.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet1
172.16.159.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet8
192.168.0.0 0.0.0.0 255.255.255.0 U 2 0 0 wlan0
第一条就是默认路由,意思是说,当下边这四行Destination 目的地址不是我169.254.0.0、172.16.149.0 、172.16.159.0、192.168.0.0 这个四个网段是,走一个默认路由,那就是由192.168.0.1 这个ip做默认路由,由网口wlan0发送出去,ip地址和网卡都指定是有意义的,例如我的笔记本在无线和有线的网线都用上时,就会可能会出现网关ip相同,但面临选择一个不同的网卡接口做出口的情形,而在很多时候,可能有线和无线都启用时,系统会更倾向将有线作为上网的默认网关,先前我搭建了一个台式机通过有线接入笔记本,再由笔记本无线上网时,便出现了一个,笔记本默认反过来将我的台式机当了网关上网,没文化真可怕啊,真是让人哭笑不得。
而下边这四条,在一个包到达系统时,会在默认网关之前先被检查,如果是这个包当中的一个目的地址,就将包从对应的网卡设备发送出去。
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 wlan0
172.16.149.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet1
172.16.159.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet8
192.168.0.0 0.0.0.0 255.255.255.0 U 2 0 0 wlan0
我们在我们的主机ubuntu12.04上做如下配置
删除默认路由:
sudo route del default
看下路由表,默认网关已经被删掉了
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 wlan0
172.16.149.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet1
172.16.159.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet8
192.168.0.0 0.0.0.0 255.255.255.0 U 2 0 0 wlan0
检查下网络是不是真的不通了:
$ ping hao123.com
connect: Network is unreachable
ping不通
增加指向虚拟机的默认网关:
$ sudo route add default gw 172.16.149.129 dev vmnet1
这条命令需要大家,察看自己虚拟机内宿机对应的私有地址为何,并且找到主机与之对应的网卡接口是哪个
不难看出,主机路由是这条:
172.16.149.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet1
宿机内系统对应的ip地址是这个:
eth1: mtu 1500 qdisc pfifo_fast state UNKNOWN qlen 1000
link/ether 00:0c:29:df:76:dd brd ff:ff:ff:ff:ff:ff
inet 172.16.149.129/24 brd 172.16.149.255 scope global eth1
inet6 fe80::20c:29ff:fedf:76dd/64 scope link
valid_lft forever preferred_lft forever
大家如果想尝试,自己根据自己的情况搞。
不过大家也许也发现了,这样一来,有个怪异的现象就产生了,172.16.149.1将172.16.149.129作为了默认路由,颠覆了我们平时的网关的概念,.1反过来通过其他的.x的ip上网,这不是倒反天罡么,不过其实这就是地址指定的问题,就如张三李四的名号一样,本质没什么特别的,不带来任何不良的影响,继续用便是。
察看路由:
$ route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
0.0.0.0 172.16.149.129 0.0.0.0 UG 0 0 0 vmnet1
169.254.0.0 0.0.0.0 255.255.0.0 U 1000 0 0 wlan0
172.16.149.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet1
172.16.159.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet8
192.168.0.0 0.0.0.0 255.255.255.0 U 2 0 0 wlan0
增加第一条,默认网关,指到了虚拟机。
3.验证路由:
3.1 失败案例:
这样我的环境就搭成了,现在我们来验证,我们的路由,真的是从我们虚拟机当中宿机上的网,并且从我们虚拟机宿机回来的包。
我这么描述是有典故的,我先前将虚拟机和主机设置成了同一网段,都让他们和无线路由器的ip网段192.168.0.1在同一个网段,而让主机的默认路由地址指向虚拟机地址,这么做确实能让数据包上行从虚拟机出去,但是下行却未经过虚拟机,而是从物理接口,直接回到了主机上,绕过了宿机,因为无线网关和主机乃至宿机,都在同一网段,无线设备直接将回包回给了主机,绕过了宿机。
通过抓包就能看出来,当我们在宿机上对eth0和eth1进行tcpdump抓包时,我们只能看到上行流量,看不见下行流量。
3.2 验证过程:
现在我们验证我们我上下行流量均通过宿机上网:
3.2.1 主机ubuntu12.04执行ping命令:
$ ping hao123.com
PING hao123.com (123.125.114.224) 56(84) bytes of data.
64 bytes from 123.125.114.224: icmp_req=1 ttl=55 time=4.21 ms
然后主机不要动,让他继续ping
3.2.2 我们在宿机上做操作:
3.2.2.1 宿机对私有ip地址网卡接口抓包:
sudo tcpdump -i eth1 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
14:11:21.627820 IP 172.16.149.1 > 123.125.114.224: ICMP echo request, id 5803, seq 41, length 64
14:11:21.633852 IP 123.125.114.224 > 172.16.149.1: ICMP echo reply, id 5803, seq 41, length 64
14:11:21.640808 IP 172.16.149.1 > 192.168.1.1: ICMP 172.16.149.1 udp port 9570 unreachable, length 136
14:11:26.640770 IP 172.16.149.1 > 123.125.114.224: ICMP echo request, id 5803, seq 42, length 64
14:11:26.644774 IP 123.125.114.224 > 172.16.149.1: ICMP echo reply, id 5803, seq 42, length 64
其中tcpdump 命令中-i 是interface接口,icmp是ping命令使用的icmp协议,-nn是让tcpdump抓包迅速出效果,不进行dns地址转换等,就是执行命令就能看见有包,如果有包的话,而不是等待一会才有包。
3.2.2.2 再抓宿机上网接口:
$ sudo tcpdump -i eth0 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
14:15:38.584486 IP 192.168.0.104 > 123.125.114.224: ICMP echo request, id 5803, seq 93, length 64
14:15:38.587805 IP 123.125.114.224 > 192.168.0.104: ICMP echo reply, id 5803, seq 93, length 64
14:15:43.602075 IP 192.168.0.104 > 123.125.114.224: ICMP echo request, id 5803, seq 94, length 64
14:15:43.610451 IP 123.125.114.224 > 192.168.0.104: ICMP echo reply, id 5803, seq 94, length 64
也有上行和下行。
3.3 利用宿机转发开启和关闭做个阻断,然主机不能通过宿机上网
切换到超级用户权限下,如果不切换,执行命令会出现没有权限的提示,加sudo也不行
$ sudo -i
关闭转发:
# echo 0 > /proc/sys/net/ipv4/ip_forward
这时候我们观察我们的主机一直在执行的ping命令,很显然,已经不没效果了,看不见有新效果了。
我们在宿机上对私有地址网卡抓包:
$ sudo tcpdump -i eth1 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth1, link-type EN10MB (Ethernet), capture size 96 bytes
14:20:42.727803 IP 172.16.149.1 > 123.125.114.224: ICMP echo request, id 5803, seq 280, length 64
14:20:43.727962 IP 172.16.149.1 > 123.125.114.224: ICMP echo request, id 5803, seq 281, length 64
14:20:44.727805 IP 172.16.149.1 > 123.125.114.224: ICMP echo request, id 5803, seq 282, length 64
14:20:45.727789 IP 172.16.149.1 > 123.125.114.224: ICMP echo request, id 5803, seq 283, length 64
14:20:46.727803 IP 172.16.149.1 > 123.125.114.224: ICMP echo request, id 5803, seq 284, length 64
光有上行,么的下行了。
对宿机上网接口抓包,干脆没有包:
$ sudo tcpdump -i eth0 icmp -nn
tcpdump: verbose output suppressed, use -v or -vv for full protocol decode
listening on eth0, link-type EN10MB (Ethernet), capture size 96 bytes
3.4 宿机重新开启转发规则:
依然是超级用户模式下
# echo 1 > /proc/sys/net/ipv4/ip_forward
最直观的反应就是主机上看ping命令效果:
看下边第122个请求和420个之间,缺少的数量,就是刚才我们关闭转发规则期间,少的包数。
唯一瑕疵的地方,就是我习惯性的用QQ解图快捷键ctrl+alt+a截图,在第403个请求上多几个小乱码,有点对不起观众了,不过大家都懂得,除了是一个码农之外,俺还是个不折不扣的都比吊死+社交控。
到此为止,利用vmware内宿机做路由nat转发,让主机上网的内容,叙述完毕,希望此文能给做此方面工作的,一点借鉴和一些可行性的指导。
社交控里有一句话,我觉得挺适合程序员的分享的原则和思想,“如果聊天不是为了装逼,那将毫无意义。”
还有一点就是,说给看的人,也说给自己,不管别人说的东西好不好,正确与否,都应该花几十秒钟考虑一下,也许他的理论并不能指导你的行动,但他的思路可能会给你一个前进的方向。
主机通过虚拟机内宿机上网,到此结束,谢谢收看,我们下次再见。
参考文章:
iptables的nat设置:
ubuntu做路由表配置:
http://www.cnblogs.com/arrongao/p/4280522.html