|
--
路由
什么是路由,什么是路由表?
路由就是跨网络访问
路由表是记录路由信息的表(可以单路由表,也可以多路由表)
我们现在讨论的是单路由表,你在linux下用route -n查看
# route -n
Kernel IP routing table
Destination Gateway Genmask Flags Metric Ref Use Iface
192.168.1.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet8
172.16.13.0 0.0.0.0 255.255.255.0 U 0 0 0 vmnet1
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
169.254.0.0 0.0.0.0 255.255.0.0 U 1005 0 0 eth0
0.0.0.0 10.1.1.1 0.0.0.0 UG 0 0 0 eth0
我在本机访问一个IP,先找路由表里是否有你访问的网段,有的话则从这个路由条目后面指定的网卡出去;如果路由表里没有你访问的网段,则会找默认路由(也就是网关);如果网关也没有的话,则会报错网络不可达。
加网关只能加你已经有的路由网段里的一个IP才行(此IP不一定存在)
问题:一个linux上能有几个有效网关?
准确来说:一个路由表上可以加多个网关,但只有一个生效。但一台linux是可以做多路由表的,一个路由表一个有效网关,多路由表就是多个网关了。
问题:我一台linux上如果有双网卡,请问可不可以两个网卡配置同网段的不同IP呢?
假设我的eth0 10.1.1.10
eth1 10.1.1.11
如果两个网卡同网段,则会有下面两条路由
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth0
10.1.1.0 0.0.0.0 255.255.255.0 U 0 0 0 eth1
它会实现从两张网卡进来的包,却从一张网卡出去,问题就产生了。
也有解决方法(比如多路由表)
静态路由
如下图的实验:
用真实机虚拟的hostonly网络vmnet1模拟IP为1.1.1.1,三台虚拟机都是双网卡(全连接hostonly的vmnet1网络),IP分配如下(掩码假设全为24位),做实验的话使用iptables -F把所有的防火墙规则清空
宿主机 VM1 VM2 VM3
eth1 --> eth0 eth1
2.2.2.2 <-- 2.2.2.3 4.4.4.4
IP_forward IP_forward
vmnet1 eth0 eth1 eth0
1.1.1.1 --> 1.1.1.2 3.3.3.3 <--- 3.3.3.4
从1.1.1.1 ping 1.1.1.2
在宿主机上ping 1.1.1.2,能通
从1.1.1.1 ping 2.2.2.2
ping 2.2.2.2 不能通
解决方法:
1,在宿主机上加路由
route add -net 2.2.2.0 netmask 255.255.255.0 dev vmnet1
或者
route add -net 2.2.2.0/24 dev vmnet1
2,加网关
route del -net 2.2.2.0 netmask 255.255.255.0 dev vmnet1 --先删除上面的路由
route add default gw 1.1.1.2
在宿主机加了一个网关指向1.1.1.2的基础上,我再继续在宿主机上ping 2.2.2.3 不能ping
解决方法:
在vm2上加网关指向2.2.2.2
route add default gw 2.2.2.2
还要在VM1上打开ip_forward,打开方法有两种
1,# echo 1 > /proc/sys/net/ipv4/ip_forward --马上生效,但重启后就不生效了
2,# vim /etc/sysctl.conf
net.ipv4.ip_forward = 1 --改为1
# sysctl -p --保存后,使用此命令让它永久生效
继续ping 3.3.3.3 不通
解决:再在VM1上route add default gw 2.2.2.3
继续ping 3.3.3.4 不通
解决:在VM2上打开ip_forward
还要在VM3上route add default gw 3.3.3.3
继续ping 4.4.4.4 不通
解决:如果在VM2上加一个网关指向3.3.3.4,其实是有问题的,因为VM2上这样就有两个网关了。如果你不使用多路由表的做法,这两个网关只能有一个网关有效。
所以加网关的方式不可行,只能在VM2加路由
route add -net 4.4.4.0 netmask 255.255.255.0 dev eth1
上面终于从1.1.1.1ping到4.4.4.4
如果我把上面的所有网关和ip_forward去掉,然后手动加上路由(也就是说四台机都有四个网段的路由),你会发现也一样从1.1.1.1能ping通4.4.4.4
那么如果还有5网段,6网段,7网段,甚至更多(类似因特网),手动把全世界所有的路由加上也是不可能的事。实际的做法就是使用路由协议(rip,ospf,bgp等)来做,这就是动态路由了。
linux下可以安装类似zebra这样的软路由软件,可以把linux模拟成一台cisco路由器来进行配置。
注意:上面所有网卡都在同网络,你可以换一种方式再去尝试:1网段用vmnet1来模拟,2网段用vmnet2来模拟,3网段用vmnet3来模拟,4网段用vmnet4来模拟
====================================================================
准备两台虚拟机和真实机一起三台机做实验
--下面图中10.1.1.0/24网段为外网,1.1.1.0/24网段为内网(虽然实际环境里10.1.1.0/24网段是内网保留网段,1.1.1.0/24网段是公网网段,但我这里只是内网模拟实验为了方便而已,你自己也可以定义自己的网段都行)
内网 iptables网关 外网
1.1.1.128 ----> 1.1.1.1 vmnet1
网关指向
打开ip_forward
10.1.1.35 eth0 <----- 10.1.1.36
网关指向
--注意:模拟上面的环境时,宿主机可以模拟中间的双网卡网关,但不能模拟内网或外网其中一台(原因是宿主机本来就是与虚拟的所有网段是直通的,你如果把它做为内网,则它会直接连接外网而不会走中间的网关)
--所以两种模拟方法:1,宿主机模拟网关,两台虚拟机分别模拟内外网;2,不要宿主机,三台虚拟机来模拟,中间的双网卡网关使用一台双网关的虚拟机模拟,另两台用单两卡来模拟
把gateway加上路由功能
echo "1" > /proc/sys/net/ipv4/ip_forward --临时生效
vim /etc/sysctl.conf
net.ipv4.ip_forward = 1
sysctl -p --改完后使用此命令,使之修改永久生效
路由功能加了后,网关都指向了gateway这台物理机,那么 两个网段的这两台机就能互相ping通
例一:禁止内网1.1.1.128和外网10.1.1.36互ping
iptables -A FORWARD -p icmp -s 1.1.1.128 -j DROP
或者
iptables -A FORWARD -p icmp -s 10.1.1.36 -j DROP
例二:禁止内网1.1.1.128上外网的10.1.1.36这个网站
iptables -A FORWARD -p tcp --dport 80 -s 1.1.1.128 -d 10.1.1.36 -j DROP
--这样的做法,如果要做网络管理(控制内部员工上网的行为,用iptables来做就比较繁锁,可以选用squid这种代理网关)
======================================================================
问题:这里我们模拟内外网的访问,网关互指,中间网关打开ip_forward,但实际的网络访问环境中,外网客户会把网关指向你公司的网关吗?
内网 iptables网关 外网
1.1.1.128 ----> 1.1.1.1 vmnet1
网关指向
打开ip_forward
10.1.1.35 eth0 10.1.1.36
把上图先去掉外网上的网关(因为实际情况下,别人公司的外网服务器不可能把网关指向你),去掉这个网关后,内外网就不能通了,要靠做NAT才能通
张三 李四 王五
发信人:张三 发信人:李四 发信人:王五
收信人:王五 ---> 收信人:王五 -----------> 收信人:李四
|
发信人:王五 |
<----- 收信人:张三 <---------------|
SIP:1.1.1.128 DIP:10.1.1.36
到达中间iptables网关,需要做SNAT
SIP:10.1.1.35 DIP:10.1.1.36
到达外网服务器,然后返回
SIP:10.1.1.36 DIP:10.1.1.35
回到中间iptables网关,会自动做DNAT
SIP:10.1.1.36 DIP:1.1.1.128
解决方法:在中间网关机器上写规则
实现内网可以上外网的web
iptables -t nat -A POSTROUTING -p tcp --dport 80 -o eth0 -j SNAT --to-source 10.1.1.35
实现内网可以ping外网
iptables -t nat -A POSTROUTING -p icmp -o eth0 -j SNAT --to-source 10.1.1.35
下面这条不写协议,也就表示所有内网上外网的都会做SNAT成10.1.1.35这个IP地址
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 10.1.1.35
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE --这条命令和上条命令实现的效果是一样的,但区别在于MASQUERADE可以动态SNAT成你的公网IP(用于公网IP不固定的情况,比如家用的ADSL拔号上网)
做了SNAT后,并且可以10.1.1.36的/var/log/httpd/access_log里验证得到:在你做NAT之前,靠双网关互指访问网站,它的访问日志里全是你内网的IP。而做了NAT之后,日志里是你公网的IP。
============================================================
练习1:
现在我的172.16.2.35是通过公司路由器172.16.1.1可以实际上外网的
请问,我一个hostonly网段的虚拟机1.1.1.128如何才能通过NAT上外网
虚拟机上DNS和网关要不要指,怎么指?
hostonly虚拟机 宿主机 公司路由器 公司外网IP
vmnet1 eth0
1.1.1.128 ----> 1.1.1.1 172.16.2.35 --> 172.16.1.1 113.102.157.61
DNS指向8.8.8.8
在虚拟机上把网关指向1.1.1.1,把DNS指向8.8.8.8;那么包的过程如下
DNS包
SIP:1.1.1.128 DIP:8.8.8.8
到达真实机
SIP:1.1.1.128 DIP:8.8.8.8
到达路由器SNAT
SIP:113.102.157.61 DIP:8.8.8.8
到达DNS服务器返回
SIP:8.8.8.8 SIP:113.102.157.61
返回路由器自动DNAT
SIP:8.8.8.8 DIP:1.1.1.128
--通过分析得到DNS数据包从路由器无法回到虚拟机(他这里是回到1.1.1.128,如果这是一个公网IP,则回到公网去了;就算是你是一个内网IP,他也无法回到你的内网)
解决方法:
在中间的真实机上做 SNAT --to-source 172.16.2.8
并且打开ip_forward
做完之后,数据包过程如下
DNS包
SIP:1.1.1.128 DIP:8.8.8.8
到达真实机
SIP:172.16.2.8 DIP:8.8.8.8
到达路由器SNAT
SIP:113.102.157.61 DIP:8.8.8.8
到达DNS服务器返回
SIP:8.8.8.8 SIP:113.102.157.61
返回路由器自动DNAT
SIP:8.8.8.8 DIP:172.16.2.8
返回到真实机自动DNAT
SIP:8.8.8.8 DIP:1.1.1.128
总结:
满足四个条件,这个hostonly虚拟机就可以上外网
1,虚拟机网关指向宿主机的同网段IP(我这个例子里是指向1.1.1.1)
2,DNS指向公网DNS服务器(我这里是指向8.8.8.8);这里DNS也可以指向1.1.1.1,但是要在宿主机上多做一条DNAT,把udp的53端口目标地址DNAT成8.8.8.8
3,宿主机打开ip_forward(因为写NAT规则都需要这个要求)
4,宿主机上写一条SNAT把虚拟机上网的所有数据包SNAT成宿主机上外网的IP(我这里为172.16.2.8)
iptables -t nat -A POSTROUTING -o eth0 -j SNAT --to-source 172.16.2.8
或者
iptables -t nat -A POSTROUTING -o eth0 -j MASQUERADE
================================================================
DNAT 目的地址转换
也就是外网是客户端,要访问我们内网的服务器,客户端只是访问外网IP,内网里不同的服务器不同的IP,可以使用DNAT把不同的请求转换到不同的内网服务器
客户端
|
外网IP |
网关
内网IP |
|
|
邮件 web DNS
1.1.1.127 1.1.1.128 1.1.1.129
iptables -t nat -A PREROUTING -i eth0 -p tcp -m multiport --dport 25,110 -j DNAT --to-destination 1.1.1.127
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j DNAT --to-destination 1.1.1.128
iptables -t nat -A PREROUTING -i eth0 -p udp --dport 53 -j DNAT --to-destination 1.1.1.129
NPT 网络端口转换
客户端 10.1.1.36
|
|
web 10.1.1.35
默认情况web是监听80端口,如果我把web改成监听8080.那么客户端在elinks 10.1.1.35时就访问不到,除非elinks 10.1.1.35:8080
在web服务器上写上一条端口转换的iptables规则,把访问80的转成8080.然后客户端再去elinks 10.1.1.35不用写端口也可以访问成功
# iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
===================================================================
练习2:
要求:写出这个电信用户访问到双线web服务器时并返回的IP变化过程(只写源IP,目标IP,和做SNAT还是DNAT等)
你觉得架构会不会有问题?
192.168.1.100 192.168.2.100
电信用户 网通用户
| |
192.168.1.1 | | 192.168.2.1
电信用户家里路由器 网通用户家里路由器
51.1.2.3 | | 61.1.2.3
| |
| |
71.1.2.3 | | 81.1.2.3
公司电信路由器 公司网通路由器
10.1.1.1 | | 172.16.2.1
| |
| |
10.1.1.100 eth0 双线web服务器 eth1 172.16.2.100
这里应该有智能DNS(DNS服务器会通过SIP是电信还是网通,来智能的解析同一个网站的DIP;在此例中,电信用户会被解析访问71.1.2.3,网通用户会被解析访问81.1.2.3)
sip:192.168.1.100 dip:71.1.2.3
到达电信用户家里路由器
|
|