那么为什么LVS是在第四层做负载均衡?
首先LVS不像HAProxy等七层软负载面向的是HTTP包,所以七层负载可以做的URL解析等工作,LVS无法完成。其次,某次用户访问是与服务端建立连接后交换数据包实现的,如果在第三层网络层做负载均衡,那么将失去「连接」的语义。软负载面向的对象应该是一个已经建立连接的用户,而不是一个孤零零的IP包。后面会看到,实际上LVS的机器代替真实的服务器与用户通过TCP三次握手建立了连接,所以LVS是需要关心「连接」级别的状态的。
Full-NAT
无论是DR还是NAT模式,不可避免的都有一个问题:LVS和RS必须在同一个VLAN下,否则LVS无法作为RS的网关。
这引发的两个问题是:
1、同一个VLAN的限制导致运维不方便,跨VLAN的RS无法接入。
2、LVS的水平扩展受到制约。当RS水平扩容时,总有一天其上的单点LVS会成为瓶颈。
Full-NAT由此而生,解决的是LVS和RS跨VLAN的问题,而跨VLAN问题解决后,LVS和RS不再存在VLAN上的从属关系,可以做到多个LVS对应多个RS,解决水平扩容的问题。
Full-NAT相比NAT的主要改进是,在SNAT/DNAT的基础上,加上另一种转换
在包从LVS转到RS的过程中,源地址从客户端IP被替换成了LVS的内网IP。
内网IP之间可以通过多个交换机跨VLAN通信。
当RS处理完接受到的包,返回时,会将这个包返回给LVS的内网IP,这一步也不受限于VLAN。
LVS收到包后,在NAT模式修改源地址的基础上,再把RS发来的包中的目标地址从LVS内网IP改为客户端的IP。
Full-NAT主要的思想是把网关和其下机器的通信,改为了普通的网络通信,从而解决了跨VLAN的问题。采用这种方式,LVS和RS的部署在VLAN上将不再有任何限制,大大提高了运维部署的便利性。
4、Session
客户端与服务端的通信,一次请求可能包含多个TCP包,LVS必须保证同一连接的TCP包,必须被转发到同一台RS,否则就乱套了。为了确保这一点,LVS内部维护着一个Session的Hash表,通过客户端的某些信息可以找到应该转发到哪一台RS上。
5、LVS集群化
采用Full-NAT模式后,可以搭建LVS的集群
6、容灾
容灾分为RS的容灾和LVS的容灾。
RS的容灾可以通过LVS定期健康检测实现,如果某台RS失去心跳,则认为其已经下线,不会在转发到该RS上。
LVS的容灾可以通过主备+心跳的方式实现。主LVS失去心跳后,备LVS可以作为热备立即替换。
容灾主要是靠KeepAlived来做的。
负载均衡可以采用硬件设备,也可以采用软件负载。
商用硬件负载设备成本通常较高(一台几十万上百万很正常),所以在条件允许的情况下我们会采用软负载,软负载解决的两个核心问题是:选谁、转发,其中最著名的是LVS(Linux Virtual Server)。
VS是四层负载均衡,也就是说建立在OSI模型的第四层——传输层之上,传输层上有我们熟悉的TCP/UDP,LVS支持TCP/UDP的负载均衡。
LVS的转发主要通过修改IP地址(NAT模式,分为源地址修改SNAT和目标地址修改DNAT)、修改目标MAC(DR模式)来实现。
那么为什么LVS是在第四层做负载均衡?
首先LVS不像HAProxy等七层软负载面向的是HTTP包,所以七层负载可以做的URL解析等工作,LVS无法完成。其次,某次用户访问是与服务端建立连接后交换数据包实现的,如果在第三层网络层做负载均衡,那么将失去「连接」的语义。软负载面向的对象应该是一个已经建立连接的用户,而不是一个孤零零的IP包。后面会看到,实际上LVS的机器代替真实的服务器与用户通过TCP三次握手建立了连接,所以LVS是需要关心「连接」级别的状态的。
LVS的工作模式主要有4种:
DR
NAT
TUNNEL
Full-NAT
这里挑选常用的DR、NAT、Full-NAT来简单介绍一下。
1、DR
dr
请求由LVS接受,由真实提供服务的服务器(RealServer, RS)直接返回给用户,返回的时候不经过LVS。
DR模式下需要LVS和绑定同一个VIP(RS通过将VIP绑定在loopback实现)。
一个请求过来时,LVS只需要将网络帧的MAC地址修改为某一台RS的MAC,该包就会被转发到相应的RS处理,注意此时的源IP和目标IP都没变,LVS只是做了一下移花接木。
RS收到LVS转发来的包,链路层发现MAC是自己的,到上面的网络层,发现IP也是自己的,于是这个包被合法地接受,RS感知不到前面有LVS的存在。
而当RS返回响应时,只要直接向源IP(即用户的IP)返回即可,不再经过LVS。
DR模式是性能最好的一种模式。
2、NAT
nat
NAT(Network Address Translation)是一种外网和内网地址映射的技术。
NAT模式下,网络报的进出都要经过LVS的处理。LVS需要作为RS的网关。
当包到达LVS时,LVS做目标地址转换(DNAT),将目标IP改为RS的IP。RS接收到包以后,仿佛是客户端直接发给它的一样。
RS处理完,返回响应时,源IP是RS IP,目标IP是客户端的IP。
这时RS的包通过网关(LVS)中转,LVS会做源地址转换(SNAT),将包的源地址改为VIP,这样,这个包对客户端看起来就仿佛是LVS直接返回给它的。客户端无法感知到后端RS的存在。
3、Full-NAT
无论是DR还是NAT模式,不可避免的都有一个问题:LVS和RS必须在同一个VLAN下,否则LVS无法作为RS的网关。
这引发的两个问题是:
1、同一个VLAN的限制导致运维不方便,跨VLAN的RS无法接入。
2、LVS的水平扩展受到制约。当RS水平扩容时,总有一天其上的单点LVS会成为瓶颈。
Full-NAT由此而生,解决的是LVS和RS跨VLAN的问题,而跨VLAN问题解决后,LVS和RS不再存在VLAN上的从属关系,可以做到多个LVS对应多个RS,解决水平扩容的问题。
Full-NAT相比NAT的主要改进是,在SNAT/DNAT的基础上,加上另一种转换,转换过程如下:
fullnat
在包从LVS转到RS的过程中,源地址从客户端IP被替换成了LVS的内网IP。
内网IP之间可以通过多个交换机跨VLAN通信。
当RS处理完接受到的包,返回时,会将这个包返回给LVS的内网IP,这一步也不受限于VLAN。
LVS收到包后,在NAT模式修改源地址的基础上,再把RS发来的包中的目标地址从LVS内网IP改为客户端的IP。
Full-NAT主要的思想是把网关和其下机器的通信,改为了普通的网络通信,从而解决了跨VLAN的问题。采用这种方式,LVS和RS的部署在VLAN上将不再有任何限制,大大提高了运维部署的便利性。
4、Session
客户端与服务端的通信,一次请求可能包含多个TCP包,LVS必须保证同一连接的TCP包,必须被转发到同一台RS,否则就乱套了。为了确保这一点,LVS内部维护着一个Session的Hash表,通过客户端的某些信息可以找到应该转发到哪一台RS上。
5、LVS集群化
采用Full-NAT模式后,可以搭建LVS的集群
LVS DR、NAT、FULL NAT、IP TUNNEL区别
1.是否需要lvs vip跟realserver 在同一个网段:
DR 模式因为只修改 package的 MAC地址通过ARP广播的形势找到rs,所以要求LVS 的VIP 和rs的IP 必须在同一个网段内。其余模式可以允许vip和rs不在同一个网段。
2.是否需要在rs绑定LVS vip 的IP 地址:
rs收到package后会判断dst ip是否是自己的ip,如果不是就直接丢掉包;因为DR模式dst 没有修改还是LVS的VIP;所以需要在rs上面绑定vip;IP TUNNEL 模式只是对package 重新包装一层,rs解析后的IP包的DST仍然是LVS的vip;也需要在rs上面绑定vip;其他的都不需要。
3.四种模式的性能比较:
因为DR模式,IP TUNELL模式都是在package in 时经过LVS ;在package out是直接返回给client;所以二者的性能比NAT 模式高;但IP TUNNEL 因为是TUNNEL 模式比较复杂,其性能不如DR模式;FULL NAT模式因为不仅要更换DST IP还更换SOURCE IP所以性能比NAT下降10%。
所以,4中模式的性能如下:DR –> IP TUNNEL —>NAT —–>FULL NAT
交换机路由器命令
给路由器配置IP地址
Router#:conf t 进入全局模式
Router(config)#int f 端口 进入端口模式
Router(config-if)#:ip address ip+子网掩码 配置IP和子网掩码
Router(config-if)#:no shutdown 开启端口
给交换机配置虚拟端口IP地址
Switch#:conf t 进入全局模式
Switch(config)# interface vlan 1 进入虚拟端口
Switch(config-if)# ip address IP+子网掩码 配置IP和子网掩码
Switch(config-if)# no shutdown 开启端口
Switch(config)#ip default-gateway 默认网关 给交换机配置默认网关
Switch# show int f(端口) 查看端口状态
Switch(config)# hostname 名称 更改主机名称
Switch# show version 查看交换机系统及版本信息
Switch# show mac-address-table 查看MAC地址表
Switch(config-if)# duplex {full(全双工) half(半双工)auto(自动协商)} 配置接口模式
Switch(config-if)# speed 10/100/1000 auto 配置接口速率
Switch# show arp 查看ARP缓存表
Switch# clear arp-cache 清除ARP缓存表
Switch(config)#:arp ip地址 mac地址 arpa 绑定ARP条目
Router(config)#:ip route 目的网段 子网掩码 下一跳路由器的接口IP 配置静态路由
Router(config)#:ip route 0.0.0.0 0.0.0.0 下一跳路由器的接口IP 配置默认路由
{ 代表任何网络 }
Router#:show ip route 查看路由表
#:show running-config 简写 sh run 查看路由(交换)机当前配置信息
#:show startup-config 简写 sh star 查看路由(交换)机已保存配置信息
#:copy running-config startup-config 等效命令 write (wr) 保存当前配置信息
#:erase nvram 等效命令:delete {nvram/startup-config} 删除已保存的配置
配置Console口密码
(config)#line console 0 进入console 0 端口配置
(config-line)#password 密码 配置密码
(config-line)#login 保存配置
配置进特权密码
(config)#:enable password 密码 配置明文密码
(config)#:enable secret 密码 配置密文密码
(config)#:service password-encryption 将所有明文密码更改成密文密码
配置远程管理密码(必须有特权密码)
(config)#:line vty o ?(?可以是具体数) 进入终端配置
(config-line)#password 密码 配置密码
(config-line)#login 保存配置
扩展知识:(config)#:username 设备用户名 password 设备密码
(config)#:line vty 0 4
(config-line)#:login local (使用设备用户名和密码)
telnet IP 远程登陆路由(交换)机
TFTP备份路由器镜像
Router#copy flash tftp
Source filename []? 填写源IOS镜像文件名
address or name of remote host[] ? 填写FTP服务器IP地址
Destination filename [源IOS文件名]? 填写目标文件名
TFTP升级或还原路由器镜像
Router#copy tftp flash
address or name of remote host[] ? 写FTP服务器的IP地址
Source filename[]? 填写FTP服务器上路由镜像
Destination filename (IOS文件名) 确认回车
FTP备份路由器镜像
Router(config)#:ip ftp username 用户名 在路由器上配置ftp的用户名
Router(config)#:ip ftp passwore 密码 在路由器上配置ftp的用密码
Router#copy flash ftp 备份IOS
Source filename []? 填写源IOS镜像文件名
address or name of remote host[] ? 填写FTP服务器IP地址
Destination filename [c2600-i-mz.122-28.bin]? 填写目标文件名
FTP升级或还原路由器镜像
Router(config)#:ip ftp username 用户名 在路由器上配置ftp的用户名
Router(config)#:ip ftp passwore 密码 在路由器上配置ftp的用密码
Router#copy ftp flash 升级或还原路由器IOS
address or name of remote host[] ? 写FTP服务器的IP地址
Source filename[]? 填写FTP服务器上路由镜像
Destination filename (IOS文件名) 确认回车
VLAN基本配置
VLAN数据库配置模式下创建VLAN
Switch#:vlan database 进入vlan数据库模式
Switch(vlan)#: vlan (vlan-id) name vlan名称 创建vlanID 和vlan名称
Switch(vlan)#:exit 退出和保存
全局模式下创建VLAN
Switch(config)#:vlan vlan-id 创建vlanID
Switch(config-vlan)#:name 名字 设置vlan名称
Switch(config)#:no vlan vlan-id 删除vlan
Switch(config-if)#:switchport mode access 定义端口模式
Switch(config-if)#:switchport access vlan-id 将端口分配到VLAN中
Switch(config)#:default 端口号 将接口还原到默认配置状态
Switch#:show vlan brief 查看VLAN信息
Switch#:show vlan id vlan-id 查看某个vlan信息
Trunk配置
Switch(config)#:interface {FastEthernet GigabitEthernet} slot/port 进入端口
Switch(config-if)#:switchport trunk encapsulation {isl dot1q negotiate} 选择封装类型
Switch(config-if)#:switchport mode {dynamic{desirable / auto} trunk} 将接口配置为Trunk
Switch(config-if)#:switchport trunk native vlan vlan-id 指定本真VLAN
Switch(config-if)#:switchport trunk allowed vlan remove vlan-id Trunk中删除VLAN
Switch(config-if)#:switchport trunk allowed vlan add vlan-id Trunk中添加VLAN
Switch#:show interface interface-id switchport 验证接口模式
以太网通道的配置
Switch(config)#:interface range fastEthernet 0/1-2 进入端口
Switch(config-if-range)#: channel-group 1 mode on 捆绑通道
Switch#:show etherchannel 1 summary 查看以太网配置
单臂路由的配置 : 将交换机连接路由器的端口配置成Trunk模式
Router(config)#:inter f0/0.1 进入路由器子端口
Router(config-subif)#:encapsulation dot1q vlan-id 给子端口封装VLAN标签
Router(config-subif)#:ip add ip+子网掩码 给子端口配置IP
路由器配置DHCP
Router(config)#:ip dhcp pool pool-name 定义地址池 和地址池名称
Router(dhcp-config)#: network IP地址段+子网掩码 动态分配IP地址段
Router(dhcp-config)#: default-router 网管IP 设定网关地址
Router(dhcp-config)#: dns-server DNS地址 为客户端配置DNS地址
Router(dhcp-config)#: lease 天数 设定地址的租期(单位“天”)
Router(config)#:ip dhcp excluded-address IP IP 预留静态分配的IP地址段或者IP地址
VTP配置
Switch(config)#:vtp domain 名字 创建VTP域
Switch(config)#:vtp mode { server(服务器模式) client(客户机模式) transparent(透明模式)} 配置交换机VTP模式
Switch(config)#:vtp password 密码 配置VTP密码
Switch(config)#:vtp pruning 配置VTP修剪
Switch(config)#:vtp version 2 配置VTP版本号
Switch#:show vtp password 查看VTP密码
Switch#:show vtp status 查看其他VTP信息
三层交换
3L-Switch(config) # ip routing 开启路由功能
3L-Switch# vlan database 进入vlan数据库模式
3L-Switch#(vlan)#vlan (vlan-id) name vlan名称 创建vlanID 和vlan名称
3L-Switch#(vlan)#exit 退出和保存
3L-Switch(config) #int vlan 2 进入VLAN
3L-Switch(config-if)# ip add 192.168.1.1 255.255.255.0 给VLAN添加IP地址
3L-Switch(config) #int range f0/23 -24 进入和二层交换机连接的端口
3L-Switch(config-if-range) #switchport trunk encapsulation dot1q 指定借口封装方式为802.1q
3L-Switch(config-if-range) #switchport mode trunk 指定借口的模式为Trunk
三层交换配置DHCP中继 1、进入到VLAN中 配置命令如下
3L-Switch(config-if)#ip helper-address DHCP服务器的IP
有几个VLAN就配置几个VLAN
STP生成树协议 只能在交换机上配置
配置PVST+的命令
Switch(config) #spanning-tree vlan 1 开启生成树命令
Switch(config) #spanning-tree vlan 1 priority 4096 配置VLAN的网桥优先级
Switch(config) #spanning-tree vlan 1 root primary 指定交换机为VLAN1的根网桥
Switch(config) #spanning-tree vlan 2 root secondary 指定交换机为VLAN2的备网桥
进入端口模式
Switch(config-if) #spanning-tree vlan 1 cost 2-100 更改该端口的端口成本
Switch(config-if) #spanning-tree vlan 1 port-priority 0-128 更改该端口的端口优先级
Switch(config-if) #spanning-tree portfast 将该端口配置成速端口(不参加选举根端口和指定端口)
HSRP 热备份路由协议 (在三层交换上要基于VLAN配置,在路由器上要基于路由器端口配置)
1、进入VLAN虚接口端口配置模式下
Switch(config-if) # standby 2 ip 192.168.1.1 (2:组号 192.168.1.1是虚拟路由器的IP地址)
2、配置HSRP的优先级
Switch(config-if) # standby 2 priority 200 (数字越大优先级越高,默认是100)
3、配置HSRP的占先权
Switch(config-if) # standby 2 preempt
4、配置Hello消息的计时器
Switch(config-if) # standby 2 timers 2 8 (默认数字是 3 10) 这条命令可以不用配置
5、配置HSRP的端口跟踪
Switch(config-if) # standby 2 track f0/1 100 (该端口是连接外网路由器的端口,后面的数字是当端口失效时,路由器的热备份优先级将降低该数值)
标准ACL配置命令:
(允许)(拒绝)
router(config)# access-list 列表号 { permit deny } 源ip或网段 + 反子网掩码
(代替反子网掩码)
router(config)# access-list 1 permit host 192.168.2.2
(代替所有网络)
router(config)# access-list 1 deny any
router(config)# no access-list 1 删除标准ACL
将ACL应用于接口
(进) (出)
router(config-if)# ip access-group 列表号 { in out}
扩展ACL
(表号) (允许) (拒绝) Router(config)# access-list "100-199"{ permit | deny } (协议) (如果是具体IP可以用host+具体IP不用加子网掩码) protocol 源IP 反子网掩码 目标IP 反子网掩码 (小于)(大于)(等于)(不等于) lt gt eq neq 加端口号或者服务 Router(config)# access-list 100 deny any any (拒绝所有)
示例:Router(config)# access-list 100 permit ip 192.168.1.0 0.0.0.255
192.168.2.0 0.0.0.255
删除ACL:Router(config)# no access-list 100 (入口)出口)
将ACL应用到端口 Router(config-if)# ip access-list 100 { in | out }
命名ACL
(标准) (扩展)
Router(config)# ip access-list {standard|extended} 名字
标准命名ACL
Router(config-std-nacl)# { permit | deny }源IP或网段
扩展命名ACL
Router(config-std-nacl)#{permit|deny}{协议}源地址 目标地址 端口号
NAT(网络地址转换)
Router# show ip nat translations 查看当前存在的转换条目
Router# show ip nat statistics 查看NAT的统计信息
静态NAT (内部端口)(源地址)(静态转换)
Router(config)# ip nat inside source static 内部局部地址 内部全局地址
(外部端口)(内部端口)
Router(config-if)# ip nat { outside | inside }
如果要做NAT端口映射 要在内部局部地址前加协议名称,在后面加端口号 并在整个命名后面
加“ extendable ”
动态NAT
1、在内部和外部端口启用NAT
2、定义内部网络中允许访问外部网络的ACL
命令:Router(config)# access-list 1 permit 源IP网段 反子网掩码
3、定义合法内部全局IP地址池
命令:Router(config)# ip nat pool one 起始IP 结束IP netmask 子网掩码
4、实现网络地址转换
命令:Router(config)# ip nat inside source list 1 pool one
PAT(端口多路复用)
1、在内部和外部端口启用NAT
2、定义内部网络中允许访问外部网络的ACL
命令:Router(config)# access-list 1 permit 源IP网段 反子网掩码
3、定义合法内部全局IP地址池 (起始IP和结束IP相同)
命令:Router(config)# ip nat pool one 起始IP 结束IP netmask 子网掩码
4、实现网络地址转换
命令:Router(config)# ip nat inside source list 1 pool one overload
RIP 动态路由协议(距离矢量)
版本1和版本2的区别:V1版本时广播 ,宣告路由信息时不携带网络掩码
V2版本时组播,宣告路由信息时携带网络掩码(可以用于不规则ip地址)
router# show ip rout 查询路由表
router# show ip protocols 查看路由协议
RIP v1版本
router(config)# router rip
router(config-router)network + 端口网段
RIP v2版本
router(config)# router rip
router(config-router) version 2 启动RIP v2版本
router(config-router) no auto-summary 关闭路由汇总功能
router(config-router) network + 端口网段
OSPF 动态路由协议(链路状态)
router# show ip route ospf 只查看OSPF学习到的路由
router# show ip protocol 查看OSPF配置信息
router# show ip ospf 查看OSPF的配置
router# show ip ospf database 查看LSA数据信息
router# show ip ospf interface 查看接口上OSPF配置信息
router# show ip ospf neighbor 查看邻居列表及状态
router# show ip ospf virtual-link 查看虚链路状态
router(config)# router ospf 1
router(config-router)# rouer-id 配置可以手动选举DR和BDR (区域号)
router(config-router)# network + 端口网段 +反子网掩码 area 0 (代表骨干区域)
区域边界路由器(ABR) 自治系统边界路由器(ASBR)
LSA通告 :LSA1(路由器LSA:Router Link States)
LSA2(网络LSA:Net Link States)
LSA3(网络汇总LSA:Summary Net Link States)
LSA4(ASBR汇总LSA:Summary ASB Link States)
LSA5(自治系统外部LSA:Type-5 AS External Link States)
LSA7(NSSA外部LSA:Type-7 AS External Link States)
配置末梢区域和完全末梢区域
router(config-router)# area 1 stub(当配置完全末梢区域时在ABR路由器上后面加:{no-summary})
NSSA 区域配置 : NSSA区域内的所有路由器都需要配置NSSA
router(config-router)# area 1 nssa(当配置NSSA区域时在ABR路由器上后面加:{no-summary})
路由注入配置 (就是配置ASBR路由器)
RIP 和OSPF 之间进行注入命令的示例:
命令是在ASBR路由器上配置
router(config)# router ospf 1
router(config-router)# redistribute rip metric 200 subneta
router(config)# router rip
router(config-router)# redistribute ospf 1 metric 10
在ASBR路由器上注入静态路由、默认路由、直连路由:
router(config)# router ospf 1
router(config-router)# default-information originate 注入默认路由
router(config-router)# redistribute static subnets 注入静态路由
router(config-router)# redistribute connected subnets 注入直连路由
OSPF路由协议地址汇总
区域间路由汇总:
router(config-router)# area 1 range 网段+子网
外部路由汇总:
router(config-router)# summary-address 网段+子网
虚链路配置 :在将要穿过的区域中的ABR路由器上互相指定对方路由器的loopbac0 配置的IP地址
R1(config-router)# area 1 virtual-link 2.2.2.2
R2(config-router)# area 1 virtual-link 1.1.1.1
使用小凡桥接到VMware 虚拟网卡
1、用真实机 cmd 中输入“getmac” 查看网卡的信息 并把“TCPIP” 更改成NPF
ASA状态化防火墙基本配置
ciscoasa# show conn detail 查看Conn表
ciscoasa# show route 查看路由表
ciscoasa# write memory 保存配置
ciscoasa# clear configure all 清除未保存的配置
ciscoasa# clear configure access-list 清除所有ACL
ciscoasa# clear configure access-list 命名 清除单条命名ACL
ciscoasa# write erase 清除已保存的配置
ciscoasa# show xlate detail 查看NAT转换表
ciscoasa# conf t
ciscoasa(config)# hostname ASA 更改主机名
ciscoasa(config)# enable password 111.com 配置特权密码
ciscoasa(config)# password 222.com 配置远程登录密码
接口的安全级别
inside (连接内网的端口,安全级别高:100)
outside(连接外网的端口,安全级别低: 0 )
dmz (一般用于服务器发布,安全级别低于100,高于0)
接口配置命令
ciscoasa(config-if)# nameif {inside/outside/dmz} 要先定义端口的方向
ciscoasa(config-if)# security-level 1-99 配置端口的安全级别
在ASA上配置ACL:1、允许入内网连接 2、控制访问外网连接的流量 :ASA默认规则禁止入站连接
命名ACL
ciscoasa(config)# access-list 命名 { permit/deny } ip host IP host ip 配置ACL
ciscoasa(config)# access-list 命名 { permit/deny } ip ip地址 子网掩码 any :禁止子网流量出站
ciscoasa(config)# access-group 命名 in int { inside/outside } 将ACL调用到端口
ASA上配置静态路由
ciscoasa(config)# route outside ip网段 子网掩码 下一跳IP地址
远程管理ASA
配置Telnet 接入 :默认禁止从外部端口使用,只允许内网使用
ciscoasa(config)# telnet ip地址或网段+子网掩码 inside
ciscoasa(config)# telnet timeout +分钟 配置连接空闲超时时间
配置SSH接入
ciscoasa(config)# domain-name 域名 配置ASA的域名
ciscoasa(config)# crypto key generate rsa modulus 1024 生成RAS密钥
ciscoasa(config)# ssh ip网段 +子网掩码 inside 允许一个网段接入
ciscoasa(config)# ssh 0 0 inside 允许所有IP接入
ciscoasa(config)# ssh version 2 配置SSH版本为2
PC1# ssh -v 2 -L pix ip地址
ASA应用NAT
动态NAT配置:多地址转换成多地址
ciscoasa(config)# nat (inside) 1 IP网段+子网掩码
ciscoasa(config)# global (outside) 1 全局地址池
ciscoasa(config)# nat (inside) 100 inside区域内所有网段实施动态NAT
动态PAT: 多地址转换成一个地址
ciscoasa(config)# nat (inside) 1 IP网段+子网掩码
ciscoasa(config)# global (outside) 1 { IP地址 或者 interface }
问题1:为什么会有超过1500的大包?
之前在交换机上,报文发送时会查看mtu,如果超出,总是会分片;但在服务器上,如果有的网卡支持TSO/GSO/GRO,那么发送的报文大小会超过mtu,也就是上面我们看到的1912这种报文。网卡 LSO/LRO、GSO/GRO、TSO :
GSO(generic-segmentation-offload)/ TSO(TCP-segmentation-offload) 所谓的GSO,实际上是对TSO的增强。TSO将tcp协议的一些处理下放到网卡完成以减轻协议栈处理占用CPU的负载。通常以太网的MTU是1500Bytes,除去IP头(标准情况下20Bytes)、TCP头(标准情况下20Bytes),TCP的MSS (Max Segment Size)大小是1460Bytes。当应用层下发的数据超过了mss时,协议栈会对这样的payload进行分片,保证生成的报文长度不超过MTU的大小。但是对于支持TSO/GSO的网卡而言,就没这个必要了,可以把最多64K大小的payload直接往下传给协议栈,此时IP层也不会进行分片,一直会传给网卡驱动,支持TSO/GSO的网卡会自己生成TCP/IP包头和帧头,这样可以offload很多协议栈上的内存操作,checksum计算等原本靠CPU来做的工作都移给了网卡。
GRO(generic-receive-offload)/ LRO(large-receive-offload) LRO通过将接收到的多个TCP数据聚合成一个大的数据包,然后传递给网络协议栈处理,以减少上层协议栈处理 开销,提高系统接收TCP数据包的能力。 而GRO的基本思想跟LRO类似,克服了LRO的一些缺点,更通用。后续的驱动都使用GRO的接口,而不是LRO。
问题1的解决方法很简单,将涉及到的硬件关闭TSO/GSO/GRO/LRO即可。
$ ethtool -K etho tso off
$ ethtool -K etho gso off
$ ethtool -K etho gro off
$ ethtool -K etho lro off
$ ethtool -k eth0
Features for eth0:
rx-checksumming: on
tx-checksumming: on
scatter-gather: on
tcp-segmentation-offload: off
udp-fragmentation-offload: off
generic-segmentation-offload: off
generic-receive-offload: off
large-receive-offload: off
rx-vlan-offload: on
tx-vlan-offload: on
ntuple-filters: on
receive-hashing: on
不过这样重启后就失效了,还是需要写到配置文件里去。
todo:还不知道怎么在ifcfg-ethx里记录,所以我把上面几条命令写到/etc/rc.local里了。
问题2:为什么超过mtu的报文,LVS返回了ICMP差错报文?
额。没有为什么,支持Fullnat以后,内核对于超过mtu的报文会直接丢弃并返回ICMP差错报文,具体查看patch里代码:
+/* Response transmit icmp to client
吐槽一下,内核真的没法accept这样的patch:
收到目的地址是virtual service的报文,不管报文端口号跟virtual service的端口对不对的上,全部做转发
超过mtu的报文直接drop
问题3:为什么我们实验室的环境并没有出现这个问题?
这个问题困扰了我好几天。一开始是怀疑客户现场对LVS的ADS侧配置了聚合口,但真的不科学。后来看了下实验室环境的LVS虚拟机里的ethtool,才恍然大悟。
原因说起来也很简单,我们的LVS是个虚拟机,其网卡是qemu-kvm虚拟的。实验室环境网卡的Device model是Hypervisor default,在qemu-kvm环境里实际是老旧的RTL8139网卡,它不支持TSO等特性;而在客户现场的Device model是virtio,它支持TSO等,所以LVS在内核里会收到超过mtu的报文。
七层负载均衡工作在OSI模型的应用层,因为它需要解析应用层流量,所以七层负载均衡在接到客户端的流量以后,还需要一个完整的TCP/IP协议栈。七层负载均衡会与客户端建立一条完整的连接并将应用层的请求流量解析出来,再按照调度算法选择一个应用服务器,并与应用服务器建立另外一条连接将请求发送过去,因此七层负载均衡的主要工作就是代理。
既然四层负载均衡做的主要工作是转发,那就存在一个转发模式的问题,目前主要有四层转发模式:DR模式、NAT模式、TUNNEL模式、FULLNAT模式。
DR模式也叫作三角传输,通过修改数据包的目的MAC地址来让流量经过二层转发到达应用服务器,这样应用服务器就可以直接将应答发给应用服务器,性能比较好。由于这种模式需要依赖二层转发,因此它要求负载均衡服务器和应用服务器必须在一个二层可达的环境内,并且需要在应用服务器上配置VIP。
NAT模式通过修改数据包的目的IP地址,让流量到达应用服务器,这样做的好处是数据包的目的IP就是应用服务器的IP,因此不需要再在应用服务器上配置VIP了。缺点是由于这种模式修改了目的IP地址,这样如果应用服务器直接将应答包发给客户端的话,其源IP是应用服务器的IP,客户端就不会正常接收这个应答,因此我们需要让流量继续回到负载均衡,负载均衡将应答包的源IP改回VIP再发到客户端,这样才可以保证正常通信,所以NAT模式要求负载均衡需要以网关的形式存在于网络中。
TUNNEL模式的优缺点和DR是一样的,并且TUNNEL模式要求应用服务器必须支持TUNNEL功能。
FULLNAT模式是在NAT模式的基础上做一次源地址转换(即SNAT),做SNAT的好处是可以让应答流量经过正常的三层路由回到负载均衡上,这样负载均衡就不需要以网关的形式存在于网络中了,对网络环境要求比较低,缺点是由于做了SNAT,应用服务器会丢失客户端的真实IP地址。
首先介绍一下RSS(Receive Side Scaling),RSS是一个通过数据包的元组信息将数据包散列到不同网卡队列的功能,这时候不同的CPU再去对应的网卡队列读取数据进行处理,就可以充分利用CPU资源。之前介绍MGW使用FULLNAT的模式,FULLNAT会将数据包的元组信息全部改变,这样同一个连接,请求和应答方向的数据包有可能会被RSS散列到不同的网卡队列中,在不同的网卡队列也就意味着在被不同的CPU进行处理,这时候在访问session结构的时候就需要对这个结构进行加锁保护。
解决这个问题的方法有两种,一种就是在做SNAT选端口的时候,通过选择一个端口lport0让RSS(cip0, cport0, vip0, vport0) = RSS(dip0, dport0, lip0, lport0)相等;另外一种方法就是我们为每个CPU分配一个localip,在做SNAT选IP的时候,不同的CPU选择自己的localip,等应答回来以后,再通过lip和CPU的映射关系,将指定目的IP的数据包送到指定队列上。
由于第二种方法恰好可以被网卡的flow director特性支持,因此我们选择了第二种方法来去掉session结构的锁。
flow director可以根据一定策略将指定的数据包送到指定网卡队列,其在网卡中的优先级要比RSS高,因此我们在做初始化的时候就为每个CPU分配一个localip,比如为cpu0分配lip0,为cpu1分配lip1,为cpu2分配lip2,为cpu3分配lip3。 当一个请求包(cip0, cport0, vip0, vport0)到达负载均衡后,被RSS散列到了队列0上,这时这个包被cpu0处理。cpu0在对其做fullnat时,选择cpu0自己的localip lip0,然后将数据包(lip0, lport0, dip0, dport0)发到应用服务器,在应用服务器应答后,应答数据包(dip0, dport0, lip0,
lport0)被发到了负载均衡服务器。此时我们就可以在flow director下一条将目的IP为lip0的数据包送到队列0的规则,这样应答数据包就会被送到队列0让cpu0处理。这时候CPU在对同一个连接两个方向的数据包进行处理的时候就是完全串行的一个操作,也就不要再对session结构进行加锁保护了。
上下文切换
在设计时,希望控制平面与数据平面完全分离,数据平面专心做自己的处理,不被任事件打断。因此将CPU分成两组,一组用作数据平面一组用做控制平面。同时,对数据平面的CPU进行CPU隔离,这样控制平面的进程就不会调度到数据平面的这组CPU上面了;对数据平面的线程进行CPU绑定,这样就可以让每个数据线程独占一个CPU。 其他的控制平面的程序比如Linux kernel、 SSH等都跑在控制平面的这组CPU上。
MGW如何做到高可靠
下面从MGW集群、MGW单机以及应用服务器层这三个层介绍MGW如何在每一层实现高可靠。
集群的高可靠
MGW使用OSPF+ECMP的模式组成集群,通过ECMP将数据包散列到集群中各个节点上,再通过OSPF保证单台机器故障以后将这台机器的路由动态的剔除出去,这样ecmp就不会再给这台机器分发流量,也就做到了动态的failover。
传统的ecmp算法有一个很严重的问题,当集群中节点数量发生变化以后,会导致大部分流量的路径发生改变,发生改变的流量到达其他MGW节点上时是找不到自己的session结构的,这就会导致大量的连接出现异常,对业务影响很大,并且当我们在对集群做升级操作时会将每个节点都进行一次下线操作,这样就加重了这个问题的影响。
一种解决方式是使用支持一致性hash的交换机,这样在节点发生变化的时候,只有发生变化的节点上面的连接会有影响,其他连接都会保持正常,但是支持这种算法的交换机比较少,并且也没有完全实现高可用,因此我们做了集群间的session同步功能。
集群中每个节点都会全量的将自己的session同步出去,使集群中每个节点都维护一份全局的session表,因此无论节点变化以后流量的路径以任何形式改变,这些流量都可以找到自己的session结构,也就是说可以被正常的转发,这样就可以在集群中节点数量发生变化时保证所有连接正常。
在设计的过程中主要考虑了两个问题:第一个是故障切换,第二个是故障恢复以及扩容。
故障切换
在故障切换的问题上,我们希望在机器故障以后,交换机可以立刻将流量切到其他机器上,因为流量不切走,意味着到达这台机器流量会被全部丢掉,产生大量丢包。经过调研测试发现,当交换机侧全部使用物理接口并且服务器侧对接口进行断电时,交换机会瞬间将流量切换到其他机器上。通过一个100ms发两个包的测试(客户端和服务端各发一个),这种操作方法是0丢包的。
由于故障切换主要依赖于交换机的感知,当服务器上出现一些异常,交换机感知不到时,交换机就无法进行故障切换操作,因此需要一个健康自检程序,每半秒进行一次健康自检,当发现服务器存在异常时就对服务器执行网口断电操作,从而让流量立刻切走。
故障切换主要依赖于网口断电操作并且网卡驱动是跑在主程序里面的,当主程序挂掉以后,就无法再对网口执行断电操作了,因此为了解决这个问题,主进程会捕获异常信号,当发现异常时就对网卡进行断电操作,在断电操作结束以后再继续将信号发给系统进行处理。
经过以上设计,MGW可以做到升级操作0丢包,主程序故障0丢包,其他异常(网线等)会有一个最长500ms的丢包,因为这种异常需要靠自检程序去检测,而自检程序的周期是500ms。
故障恢复与扩容
无论是在进行故障恢复还是扩容操作,都会导致集群节点数量发生变化,这样也就会导致流量路径发生变化。当变化的流量到达集群中原有的节点时,因为原有节点都维护着一个全局的session表,因此这些流量是可以被正常转发的;但是如果流量到达了新机器上,这个机器是没有全局session表的,那么这部分流量就会全部被丢弃。为了解决这个问题,MGW在上线以后会经历一个预上线的中间状态,在这个状态上,MGW不会让交换机感知到自己上线了,这样交换机也就不会把流量切过来。首先MGW会对集群中其他节点发送一个批量同步的请求,其他节点收到请求以后会将自己的session全量的同步到新上线的节点上,新上线节点在收到全部session以后才会让交换机感知到自己上线,这时交换机再将流量切过来就可以正常被转发出去了。
在这个过程中主要存在两点问题。
第一个问题是,由于集群中并没有一个主控节点来维护一个全局的状态,如果request报丢失或者session同步的数据丢失的话,那新上线节点就没办法维护一个全局的session状态。但是考虑到所有节点都维护着一个全局的session表,因此所有节点拥有的session数量都是相同的,那么就可以在所有节点每次做完批量同步以后发送一个finish消息,finish消息中带着自己拥有的session数量。当新上线节点收到finish消息以后,便会以自己的session数量与finish中的数量做对比。当达到数量要求以后,新上线节点就控制自己进行上线操作。否则在等待一定的超时时间以后,重新进行一次批量同步操作,直到达到要求为止。
另外一个问题是在进行批量同步操作时,如果出现了新建连接,那么新建连接就不会通过批量同步同步到新上线的机器上。如果新建连接特别多,就会导致新上线机器一直达不到要求。因此,需要保证处于预上线状态的机器能接收到增量同步数据,因为新建连接可以通过增量同步同步出来。通过增量同步和批量同步就可以保证新上线机器可以最终获得一个全局的session表。
路由器
路由器(英语:Router,又称路径器)是一种电讯网络设备,提供路由与转送两种重要机制,可以决定数据包从来源端到目的端所经过的路由路径(host 到 host 之间的传输路径),这个过程称为路由;将路由器输入端的数据包移送至适当的路由器输出端(在路由器内部进行),这称为转送。路由工作在 OSI 模型的第三层——即网络层,例如网际协议(IP)。
基本概念
路由器就是连接两个以上个别网络的设备。
由于位于两个或更多个网络的交汇处,从而可在它们之间传递分组(一种数据的组织形式)。路由器与交换机在概念上有一定重叠但也有不同:交换机泛指工作于任何网络层次的数据中继设备(尽管多指网桥),而路由器则更专注于网络层。
路由器与交换机的差别,路由器是属于 OSI 第三层的产品,交換机是 OSI 第二层的产品。第二层的产品功能在于,将网络上各个计算机的 MAC 地址记在 MAC 地址表中,当局域网中的计算机要经过交換机去交换传递数据时,就查询交換机上的 MAC 地址表中的信息,将数据包发送给指定的计算机,而不会像第一层的产品(如集线器)每台在网络中的计算机都发送。而路由器除了有交換机的功能外,更拥有路由表作为发送数据包时的依据,在有多种选择的路径中选择最佳的路径。此外,并可以连接两个以上不同网段的网络,而交換机只能连接两个。并具有 IP 分享的功能,如:区分哪些数据包是要发送至 WAN。路由表存储了(向前往)某一网络的最佳路径,该路径的“路由度量值”以及下一个(跳路由器)。参考条目路由获得这个过程的详细描述。
WAN 口和 LAN口
路由器通常包含一个 WAN 口多个 LAN 口(PS: 有些特殊的路由器包含多个 WAN 口)。
广域网(英语:Wide Area Network,缩写为 WAN),又称广域网、外网、公网。是连接不同地区局域网或城域网计算机通信的远程网。通常跨接很大的物理范围,所覆盖的范围从几十公里到几千公里,它能连接多个地区、城市和国家,或横跨几个洲并能提供远距离通信,形成国际性的远程网络。广域网并不等同于互联网。
局域网(Local Area Network,简称 LAN)是连接住宅、学校、实验室、大学校园或办公大楼等有限区域内计算机的计算机网络。相比之下,广域网(WAN)不仅覆盖较大的地理距离,而且还通常涉及固接专线和对于互联网的链接。 相比来说互联网则更为广阔,是连接全球商业和个人计算机的系统。
通常情况下,宽带安装好以后使用网线连接光猫和路由器 WAN 口,其他设备连接路由器 LAN 口或者无线网络即可浏览互联网。
路由器的六种无线模式
无线访问节点 (AP「Access Point」)
该模式下路由器的无线网卡就像一个”无线 HUB”,负责建立无线路由器和电脑之间的数据链路(相当于无形的网线)。正常情况下,家用的无线路由器的无线连接都默认工作在此模式下。
客户端 (Client)
像笔记本电脑上的无线网卡那样工作,仅连接其它的无线网络,而不发射自己的无线网络信号。对于无线路由器来说,这种模式相当于启用了一个无线的 WAN 口,且下面的电脑只能通过有线方式接到此设备。内部的LAN口组成的局域网和连接上的无线网段处于相同的 IP 地址段。内部的 DHCP 请求也会被转发到主无线网络上。
客户端网桥 (Client Bridge)
和“客户端”模式一样,相当于启用了一个无线的 WAN 口,且下面的电脑只能通过有线方式接到此设备。不过,该模式下无线路由器仍然提供 DHCP 及 NAT 功能,内部 LAN 口组成的单独 IP 地址段局域网,通过无线路由器上自己的网关,连上外部主网络。
Adhoc
Adhoc 有个形象的比喻,就像是将两台电脑之间直接找根网线连起来,只不过在这里这根网线是个无线的。最常见的使用adhoc连接的设备多数是一些手持游戏机。该模式在无线路由器上使用的场合比较罕见。
中继 (Repeater)
顾名思义,中继就是一边是接受信号,一边又发射自己的无线信号。在这种模式下无线路由器以无线网卡客户身份接入主 AP,然后再以新增虚拟界面(Virtual Interfaces)来为客户端提供无线接入。该模式的最大意义在于可以解决无线信号受到距离或者障碍物的影响不能传输到更远的问题。
接入到该无线路由器上的电脑终端,是和主无线网网络处在相同的 IP 地址段。内部的 DHCP 请求,也会被转发到主无线网络上。
中继桥接 (Repeater Bridge)
和”中继”模式一样,可以解决无线信号受到距离或者障碍物的影响不能传输到更远的问题。不过,这种模式下无线路由器仍然提供 DHCP 及 NAT 功能,即所有的内部 LAN 口以及无线客户接入组成的是一个单独的局域网网段。
DHCP
动态主机设置协议(英语:Dynamic Host Configuration Protocol,缩写:DHCP)是一个用于局域网的网络协议,位于 OSI 模型的应用层,使用 UDP 协议工作,主要有两个用途:
用于内部网或网络服务供应商自动分配IP地址给用户
用于内部网管理员作为对所有计算机作中央管理的手段
解析 DHCP 的工作方式
当一台机器新加入一个网络的时候,肯定一脸懵,啥情况都不知道,只知道自己的 MAC 地址。怎么办?先吼一句,我来啦,有人吗?这时候的沟通基本靠“吼”。这一步,我们称为 DHCP Discover。
新来的机器使用 IP 地址 0.0.0.0 发送了一个广播包,目的 IP 地址为 255.255.255.255。广播包封装了 UDP,UDP 封装了 BOOTP。其实 DHCP 是 BOOTP 的增强版,但是如果你去抓包的话,很可能看到的名称还是 BOOTP 协议。
在这个广播包里面,新人大声喊:我是新来的(Boot request),我的 MAC 地址是这个,我还没有 IP,谁能给租给我个 IP 地址!
如果一个网络管理员在网络里面配置了 DHCP Server 的话,他就相当于这些 IP 的管理员。他立刻能知道来了一个“新人”。这个时候,我们可以体会 MAC 地址唯一的重要性了。当一台机器带着自己的 MAC 地址加入一个网络的时候,MAC 是它唯一的身份,如果连这个都重复了,就没办法配置了。
只有 MAC 唯一,IP 管理员才能知道这是一个新人,需要租给它一个 IP 地址,这个过程我们称为 DHCP Offer。同时,DHCP Server 为此客户保留为它提供的 IP 地址,从而不会为其他 DHCP 客户分配此 IP 地址。
DHCP Offer 的格式就像这样,里面有给新人分配的地址。
DHCP Server 仍然使用广播地址作为目的地址,因为,此时请求分配 IP 的新人还没有自己的 IP。DHCP Server 回复说,我分配了一个可用的 IP 给你,你看如何?除此之外,服务器还发送了子网掩码、网关和 IP 地址租用期等信息。
新来的机器很开心,它的“吼”得到了回复,并且有人愿意租给它一个 IP 地址了,这意味着它可以在网络上立足了。当然更令人开心的是,如果有多个 DHCP Server,这台新机器会收到多个 IP 地址,简直受宠若惊。
它会选择其中一个 DHCP Offer,一般是最先到达的那个,并且会向网络发送一个 DHCP Request 广播数据包,包中包含客户端的 MAC 地址、接受的租约中的 IP 地址、提供此租约的 DHCP 服务器地址等,并告诉所有 DHCP Server 它将接受哪一台服务器提供的 IP 地址,告诉其他 DHCP 服务器,谢谢你们的接纳,并请求撤销它们提供的 IP 地址,以便提供给下一个 IP 租用请求者。
此时,由于还没有得到 DHCP Server 的最后确认,客户端仍然使用 0.0.0.0 为源 IP 地址、255.255.255.255 为目标地址进行广播。在 BOOTP 里面,接受某个 DHCP Server 的分配的 IP。
当 DHCP Server 接收到客户机的 DHCP request 之后,会广播返回给客户机一个 DHCP ACK 消息包,表明已经接受客户机的选择,并将这一 IP 地址的合法租用信息和其他的配置信息都放入该广播包,发给客户机,欢迎它加入网络大家庭。
最终租约达成的时候,还是需要广播一下,让大家都知道。
IP 地址的收回和续租
既然是租房子,就是有租期的。租期到了,管理员就要将 IP 收回。
如果不用的话,收回就收回了。就像你租房子一样,如果还要续租的话,不能到了时间再续租,而是要提前一段时间给房东说。DHCP 也是这样。
客户机会在租期过去 50% 的时候,直接向为其提供 IP 地址的 DHCP Server 发送 DHCP request 消息包。客户机接收到该服务器回应的 DHCP ACK 消息包,会根据包中所提供的新的租期以及其他已经更新的 TCP/IP 参数,更新自己的配置。这样,IP 租用更新就完成了。
好了,一切看起来完美。DHCP 协议大部分人都知道,但是其实里面隐藏着一个细节,很多人可能不会去注意。接下来,我就讲一个有意思的事情:网络管理员不仅能自动分配 IP 地址,还能帮你自动安装操作系统!
NAT
网络地址转换(英语:Network Address Translation,缩写:NAT;又称网络掩蔽、IP 掩蔽)在计算机网络中是一种在IP数据包通过路由器或防火墙时重写来源 IP 地址或目的 IP 地址的技术。这种技术被普遍使用在有多台主机但只通过一个公有 IP 地址访问因特网的私有网络中。它是一个方便且得到了广泛应用的技术。当然,NAT 也让主机之间的通信变得复杂,导致了通信效率的降低。
NAT 转换规则
对于 TCP/UDP 使用
Host ‘s 私有 IPv4 + Port <——> NAT 公网 IPv4 + Port
对于ICMP使用
Host ‘s 私有 IPv4 + session ID <——> NAT 公网 IPv4 + session ID
规则其实非常好理解,由于 session ID 在 NAT 设备上是独一无二的,所以NAT可以很容易区别局域网内部的不同 host。
至于其它传输协议,NAT 使用的也是类似 session ID 的转换规则,即使用可以将不同 host 轻易分辨出来的字段做键值(KEY),动态创建映射表项,做双向的地址+ KEY 的转换。
不同类型的 NAT
完全圆锥型 NAT(Full cone NAT),即一对一(one-to-one)NAT
一旦一个内部地址(iAddr:port)映射到外部地址(eAddr:port),所有发自 iAddr:port 的包都经由 eAddr:port 向外发送。任意外部主机都能通过给 eAddr:port 发包到达 iAddr:port(注:port不需要一样)
受限圆锥型 NAT(Address-Restricted cone NAT)
内部客户端必须首先发送数据包到对方(IP=X.X.X.X),然后才能接收来自 X.X.X.X 的数据包。在限制方面,唯一的要求是数据包是来自 X.X.X.X。
内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自 iAddr:port1 的包都经由 eAddr:port2 向外发送。外部主机(hostAddr:any)能通过给 eAddr:port2 发包到达 iAddr:port1。(注:any指外部主机源端口不受限制,但是目的端口必须是 port2。只有外部主机数据包的目的 IP 为 内部客户端的所映射的外部 ip,且目的端口为 port2 时数据包才被放行。)
端口受限圆锥型NAT(Port-Restricted cone NAT)
类似受限制锥形NAT(Restricted cone NAT),但是还有端口限制。
一旦一个内部地址(iAddr:port1)映射到外部地址(eAddr:port2),所有发自 iAddr:port1 的包都经由 eAddr:port2 向外发送。
在受限圆锥型NAT基础上增加了外部主机源端口必须是固定的。
对称 NAT(Symmetric NAT)
每一个来自相同内部 IP 与端口,到一个特定目的地地址和端口的请求,都映射到一个独特的外部 IP 地址和端口。
同一内部 IP 与端口发到不同的目的地和端口的信息包,都使用不同的映射
只有曾经收到过内部主机数据的外部主机,才能够把数据包发回
UPnP
通用即插即用(英语:Universal Plug and Play,简称UPnP)是由“通用即插即用论坛”(UPnP™ Forum)推广的一套网络协议。该协议的目标是使家庭网络(数据共享、通信和娱乐)和公司网络中的各种设备能够相互无缝连接,并简化相关网络的实现。UPnP 通过定义和发布基于开放、因特网通讯网协议标准的 UPnP 设备控制协议来实现这一目标。
可以理解为有了 UPnP 软件可以根据需求让路由器进行动态地进行端口映射。而不是你去路由器后台一个个手动设置。
提升 NAT 类型
一般来说,我们希望 NAT 层数越少越好。每多一层 NAT 就意味着更加复杂的情况与配置。依旧是典型的网络拓扑:
入户光纤① → 猫② → 路由器③ → 终端设备
我们目标是把 NAT 降到1层(只有③),当然这是目标,但不是必须的。
拿到公网 IP
拥有公网 IP 对于 P2P 应用来说绝对是一个基础要求,这可以省掉许多麻烦(使①不发生 NAT)。如何确定自己是不是公网 IP 也很简单。访问这里你可以得到一个 IP 地址,把它与路由器中显示的 WAN 口 IP 进行比较,如果一致那么就是公网 IP 了。
如果不一致,那么只能联系运营商,自己是没有办法的。一般来说一级运营商(电信/联通)比较容易,而一些二级甚至三级运营商(长城)就没什么希望了。如果拿不到公网 IP,只能期望运营商不要把 NAT 类型限制太死吧。
光猫改为桥接模式
区分桥接与路由模式
现在原来越多的猫“越权管理”,增加了路由功能,也就是说猫和路由器一体化了。每一个路由器可以理解为一层网络,我们不希望层数过多。同时猫的路由功能往往不完善,难以进行高级配置。而桥接模式就是让猫回归本质,只负责信号转换。
区分路由与桥接模式最方便的办法是:如果你的路由器(电脑)直接连到猫上就可以上网,那么是路由模式;如果路由器需要配置 PPPoE 拨号那么就是桥接模式。
更改模式
一般来说更改模式需要猫的超级密码,这个用户是没有的。请联系运营商客服请求修改。改为桥接后②也不会发生 NAT 了。
警告:没能力折腾的不建议自己破解改。更改桥接模式之后记得重新配置路由器,输入宽带账号密码才可以正常上网。
更改路由器设置
首先要修改 NAT 类型,并不是所有的路由器或者路由器系统都支持这一设置。打开 NAT 并将类型设置为最宽松的 NAT1(Full cone NAT)。
接着启用 UPnP,绝大部分路由器都支持的,耐心找一找。如果真的不支持那我建议换路由器。
如果不支持上述的 NAT 类型设置,我们还有一个大招。大部分的路由器都支持 DMZ (非军事化区),DMZ 指定的设备完全暴露在公网上。但是一个网络一般只能够设置1个 DMZ,显然如果设置多个路由器就不知道应该把数据包交给谁了。由于 DMZ 是和 IP 绑定的,而 IP 是动态分配的。所有首先我们将 IP 与 MAC 绑定(不同的路由器设置不同),然后将此 IP 设置为 DMZ 即可。
更改系统设置
最后如果你的系统启用了防火墙那么记得将需要的程序添加例外,或者关闭防火墙(不推荐)。最后进行测试,NAT 类型应该可以提升到完全圆锥型NAT(Full cone NAT)。
无线中继和桥接
以 hiboy 的老毛子 Padavan 系统路由器为例,介绍一下无线中继和桥接的异同:
无线中继:选择 AP + AP Client,接 LAN 就要关闭本路由 DHCP,上级路由开启 DHCP,本路由的 IP 不能和上级一样,但要在一个网段里。例子:一个是 192.168.1.1,另一个是 192.168.1.2。
无线桥接:选择 AP + AP Client,接 WAN 就要开启本路由 DHCP,上级路由开启 DHCP,本路由的 IP 不能和上级同网段。例子:一个是 192.168.1.1,另一个是 192.168.2.1。
DNS
DNS负责提供域名解析服务,当访问某个站点时,实际上首先需要通过该站点域名的DNS服务器来获取域名指向的IP地址,在这一过程中,DNS服务器完成了域名到IP地址的映射,同样,这样映射也可以是一对多的,这时候,DNS服务器便充当了负载均衡调度器,它就像http重定向转换策略一样,将用户的请求分散到多台服务器上,但是它的实现机制完全不同。
下图展示百度有三个IP地址:
百度DNS
优点:
可以根据用户IP来进行智能解析。DNS服务器可以在所有可用的A记录中寻找离用记最近的一台服务器。
动态DNS:在每次IP地址变更时,及时更新DNS服务器。当然,因为缓存,一定的延迟不可避免。
缺点:
没有用户能直接看到DNS解析到了哪一台实际服务器,加服务器运维人员的调试带来了不便。
策略的局限性。例如你无法将HTTP请求的上下文引入到调度策略中,而在前面介绍的基于HTTP重定向的负载均衡系统中,调度器工作在HTTP层面,它可以充分理解HTTP请求后根据站点的应用逻辑来设计调度策略,比如根据请求不同的URL来进行合理的过滤和转移。
如果要根据实际服务器的实时负载差异来调整调度策略,这需要DNS服务器在每次解析操作时分析各服务器的健康状态,对于DNS服务器来说,这种自定义开发存在较高的门槛,更何况大多数站点只是使用第三方DNS服务。
DNS记录缓存,各级节点的DNS服务器不同程序的缓存会让你晕头转向。
基于以上几点,DNS服务器并不能很好地完成工作量均衡分配,最后,是否选择基于DNS的负载均衡方式完全取决于你的需要。
HTTP重定向
当http代理(比如浏览器)向web服务器请求某个URL后,web服务器可以通过http响应头信息中的Location标记来返回一个新的URL。这意味着HTTP代理需要继续请求这个新的URL,完成自动跳转。
吞吐率限制
主站点服务器的吞吐率平均分配到了被转移的服务器。现假设使用RR(Round Robin)调度策略,子服务器的最大吞吐率为1000reqs/s,那么主服务器的吞吐率要达到3000reqs/s才能完全发挥三台子服务器的作用,那么如果有100台子服务器,那么主服务器的吞吐率可想而知得有大?相反,如果主服务的最大吞吐率为6000reqs/s,那么平均分配到子服务器的吞吐率为2000reqs/s,而现子服务器的最大吞吐率为1000reqs/s,因此就得增加子服务器的数量,增加到6个才能满足。
重定向访问深度不同
有的重定向一个静态页面,有的重定向相比复杂的动态页面,那么实际服务器的负载差异是不可预料的,而主站服务器却一无所知。因此整站使用重定向方法做负载均衡不太好。
我们需要权衡转移请求的开销和处理实际请求的开销,前者相对于后者越小,那么重定向的意义就越大,例如下载。你可以去很多镜像下载网站试下,会发现基本下载都使用了Location做了重定向。
LVS(四层)
以下内容参考自LVS
NAT
通过将请求报文的目标地址和目标端口修改为挑选出的某RS的RIP和PORT实现转发;
特点:
RIP和DIP必须在同一IP网络,且使用私网地址RS的网关应该指向DIP(保证响应报文必须经由VS)
请求和响应报文都要经由director转发;极高负载的场景中,Director可能会成为系统性能瓶颈
支持端口映射
VS必须为Linux,RS可以是任意的OS
调度器上需要两块网卡,一个配置vip 一个配置dip
NAT
FULLNAT
非标准模型, ipvs默认不支持,ipvsadm也不支持。
NAT模式的扩展(阿里云的四层SLB使用的是此方式,因为此种方式下负载均衡器和后端服务器的部署不需要部署在同一网络内)
通过同时修改请求报文的源IP地址(cip–>dip)和目标IP地址(vip –> rip)实现转发
特点:
调度器和后端服务器可以不在同一IP网络中
RS收到的请求报文的源IP为DIP,因此其响应报文将发送给DIP;
请求报文和响应报文都必须经由director;
支持端口映射;
RS可使用任意OS;
fullNAT
DR
直接路由
通过为请求报文重新封装一个MAC首部进行转发,源MAC是DIP所在接口的MAC,目标MAC是挑选出的某RS的RIP所在接口的MAC地址;IP首部不会发生变化(源IP为CIP,目标IP始终为VIP)
RS跟Director必须在同一物理网络中;RS的网关必须不能指向DIP
请求报文必须由Director调度,但响应报文必须不能经由Director
不支持端口映射
各RS可以使用大多数的OS;一般是linux
情形1: RIP DIP VIP 都在一个网络, 都是公网IP 地址
dr-same
情形2: VIP 是公网ip地址, RIP,DIP是私有地址, 情况要复制些, RS要通过另一个路由出去
dr-nosame
注意:
一个路由其可以有多个网络接口
一个交换机可以承载多个ip网络
所以路由器1和路由器2可以使用同一个
私网交换机和公网交换机也可以用同一个
TUN
ip tunnel,ip隧道
转发方式:不修改请求报文的IP首部(源IP为CIP,目标IP为VIP),而是在原有的IP首部之外再次封装一个IP首部(源IP为DIP,目标IP为RIP)
RIP,DIP,VIP全得是公网地址
RS的网关不能也不可能指向DIP
请求报文经由Director调度,但响应报文将直接发给CIP
不支持端口映射
RS的OS必须支持IP隧道功能;
容易超出MTU, 弊端比较大
tunnel
反向代理(七层)
这个肯定大家都有所接触,因为几乎所有主流的Web服务器都热衷于支持基于反向代理的负载均衡。
相比前面的HTTP重定向和DNS解析,反向代理的调度器扮演的是用户和实际服务器中间人的角色:
任何对于实际服务器的HTTP请求都必须经过调度器
调度器必须等待实际服务器的HTTP响应,并将它反馈给用户(前两种方式不需要经过调度反馈,是实际服务器直接发送给用户)
优点:
调度策略丰富。例如可以为不同的实际服务器设置不同的权重,以达到能者多劳的效果。
对反向代理服务器的并发处理能力要求高,因为它工作在HTTP层面。
反向代理服务器可以监控后端服务器,比如系统负载、响应时间、是否可用、TCP连接数、流量等,从而根据这些数据调整负载均衡的策略。
反射代理服务器可以让用户在一次会话周期内的所有请求始终转发到一台特定的后端服务器上(粘滞会话),这样的好处一是保持session的本地访问,二是防止后端服务器的动态内存缓存的资源浪费。
缺点:
反向代理服务器进行转发操作本身是需要一定开销的,比如创建线程、与后端服务器建立TCP连接、接收后端服务器返回的处理结果、分析HTTP头部信息、用户空间和内核空间的频繁切换等,虽然这部分时间并不长,但是当后端服务器处理请求的时间非常短时,转发的开销就显得尤为突出。例如请求静态文件,更适合使用前面介绍的基于DNS的负载均衡方式。
硬件
一般工作在四层。
性能较高,但是价格昂贵。