|  | 
 
| -- 路由
 什么是路由,什么是路由表?
 路由就是跨网络访问
 路由表是记录路由信息的表(可以单路由表,也可以多路由表)
 
 我们现在讨论的是单路由表,你在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
 到达电信用户家里路由器
 
 
 | 
 |