部分光猫开启公网IPv6入站,光猫无需桥接直连

价值不大,这个为研究参考,实际上光猫有PMTU黑洞等问题,最好的方法还是路由拔号


超级密码获取
telnet 192.168.1.1
账号:CMCCAdmin
密码:你的光猫后面的user密码+@C1

超级密码获取方法
插入U盘,
cp /userconfig/cfg/db_ciot_user_cfg.xml /mnt/usb1_1/

然后routerpassview 打开db_ciot_user_cfg.xml 文件

搜 DM name=“User” val=
然后你就可以看见超级密码了

这个超密是有时效性的,失效了就再获取db_ciot_user_cfg.xml 文件查看

开启Telnet
使用超级密码登陆后

访问:http://192.168.1.1:8080/enableTelnet.html

即可启用 telnet,同时页面也有用户名和密码

无视SU密码,进入ROOT
telnet 192.168.1.1 链接到光猫

用户名和密码均是 telnetuser

然后输入英文符号 ; 回车

这时 $ 符号消失就进入root用户了

Login: telnetuser
Password:
$;
sh: syntax error: unexpected ";"
echo $USER
root
开启IPv6入站
默认规则在转发 FORWARD 表中加入了 DROP 丢弃了所有入站请求

是光猫将流量转发给下级路由的,通配 DROP 的规则删掉即可

查看FORWARD表
# 查看所有表
ip6tables -nvL --line-number

#查看FORWARD表
ip6tables -nvL FORWARD --line-numbers

Chain FORWARD (policy ACCEPT 65441 packets, 5616K bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     6546  521K TCPMSS     tcp      any    ppp1.3  anywhere             anywhere             tcp flags:SYN,RST/SYN TCPMSS clamp to PMTU
2     6387  492K TCPMSS     tcp      ppp1.3 any     anywhere             anywhere             tcp flags:SYN,RST/SYN TCPMSS clamp to PMTU
3    4021K  770M rtchain    all      any    any     anywhere             anywhere
4        0     0 DROP       all      veip0.1 any     anywhere             anywhere
5        0     0 DROP       all      veip0.2 any     anywhere             anywhere
6    4018K  769M forward_npt  all      any    any     anywhere             anywhere
7     5476 1857K SKIPLOG    icmpv6    any    br0     anywhere             anywhere             ipv6-icmp destination-unreachable
8      399  137K SKIPLOG    icmpv6    any    ppp1.3  anywhere             anywhere             ipv6-icmp destination-unreachable
9    53521   19M ACCEPT     all      ppp1.3 any     anywhere             anywhere             ctstate RELATED,ESTABLISHED
10       0     0 LOG        tcp      ppp1.3 any     anywhere             anywhere             tcp flags:FIN,SYN,RST,ACK/SYN limit: avg 6/hour burst 5 LOG level alert prefix "Intrusion -> "
11    1801  209K DROP       all      ppp1.3 any     anywhere             anywhere
删除DROP规则
我这里规则是第11条所以删除11条,以自己标号为准

#删除规则11
ip6tables -D FORWARD 11

ip6tables -nvL FORWARD --line-numbers
Chain FORWARD (policy ACCEPT 8 packets, 524 bytes)
num   pkts bytes target     prot opt in     out     source               destination
1     6730  535K TCPMSS     tcp      *      ppp1.3  ::/0                 ::/0                 tcp flags:0x06/0x02 TCPMSS clamp to PMTU
2     7023  542K TCPMSS     tcp      ppp1.3 *       ::/0                 ::/0                 tcp flags:0x06/0x02 TCPMSS clamp to PMTU
3    4024K  770M rtchain    all      *      *       ::/0                 ::/0
4        0     0 DROP       all      veip0.1 *       ::/0                 ::/0
5        0     0 DROP       all      veip0.2 *       ::/0                 ::/0
6    4020K  770M forward_npt  all      *      *       ::/0                 ::/0
7     5496 1860K SKIPLOG    icmpv6    *      br0     ::/0                 ::/0                 ipv6-icmptype 1
8      405  139K SKIPLOG    icmpv6    *      ppp1.3  ::/0                 ::/0                 ipv6-icmptype 1
9    54396   19M ACCEPT     all      ppp1.3 *       ::/0                 ::/0                 ctstate RELATED,ESTABLISHED
10       5   400 LOG        tcp      ppp1.3 *       ::/0                 ::/0                 tcp flags:0x17/0x02 limit: avg 6/hour 

高级规则
在drop之前加入有效,也就是需要排在前面而非最后,这个指定放行的端口,而非全部放行,保证了安全

允许指定端口(假设要放行 22, 80, 443)
ip6tables -I FORWARD 1 -i ppp1.3 -p tcp --dport 22 -j ACCEPT   # SSH
ip6tables -I FORWARD 2 -i ppp1.3 -p tcp --dport 80 -j ACCEPT   # HTTP
ip6tables -I FORWARD 3 -i ppp1.3 -p tcp --dport 443 -j ACCEPT  # HTTPS

允许返回流量(防止连接被中断)
ip6tables -I FORWARD 4 -m state --state ESTABLISHED,RELATED -j ACCEPT
恢复DROP规则
在第11条加入DROP规则,或者重启光猫

ip6tables -I FORWARD 11 -i ppp1.3 -j DROP
持久化
暂未找到能持久化的方法

使用 ip6tables-save 保存的值无变化

网络设置MTU (最大传输单元)

MTU (最大传输单元)是网络设备传输的信息包最大值。对于各种路由器,最佳的MTU值通常都是默认值。


各种应用下的最佳MTU值
设置MTU大小是一个反复试验的过程: 由最大值1500开始下降,直至问题解决。使用下列值之一或许能解决一些由MTU值引起的问题:
1500. 以太网信息包最大值,也是默认值。是没有PPPoE的网络连接的典型设置。是各种路由器、网络适配器和交换机的默认设置
1492. PPPoE 的最佳值
1472. 使用 ping 的最大值 (大于此值的信息包会先被分解)
1468. DHCP的最佳值
1430. PPTP 的最佳值
576. 拨号连接到ISP的标准值
好了,注意一下,以上资料是正常普通情况下MTU的值,不同地区不同运营商不同机房或许也会导致MTU值的不一致!
如何查看MTU值呢?
电脑直接插网线到modem进行ADSL拨号上网,在cmd命令下输入:
netsh interface ipv4 show subinterfaces
如何测试MTU值的最大值?
MTU值越大,发包量就大,发包时间减小,理论上是可以提高网络的。怎样测试自己的MTU值的最大值呢?
首先,在CMD命令下输入:
ping -f -l 1500 www.baidu.com
1500是默认值,先来测试一下是否能达到1500.
命令返回:“需要拆分数据包但是设置 DF。” 说明MTU值过大!我们把MTU值降低试试

ping -f -l 1450 www.baidu.com
PING值出来了,说明MTU设置1450可以通过。

再测试一下1451。
ping -f -l 1451 www.baidu.com
命令返回:“需要拆分数据包但是设置 DF。” 说明MTU值最大就是1450了。

于是有人就疑问,为什么在modem下测试是1478,而ping值测试 是1450?
上面ping得到的MTU值不能直接用于本地设置上,还应在此基础上加上28(数据包头大小28字节),因此最终在WAN设置页面修改MTU大小为1478。
最后,我就在路由器的WAN接口设置MTU值1478.
------------------------------------------------------------------------------------------------------
按照上面方法,我能ping通的MTU最大值是1464,再加上28(数据包头大小28字节),应该设置的值为1492,刚好是PPPoE的最佳值

解决IPV6 PMTU黑洞导致某些手机APP图片加载时间过长,小米BE6500PRO为例

之前有尝试过降低MTU大小的方法,但是改之后当时很好用,第二天又会超出大小,还要接着改。看大佬的文章最好的解决办法是打开路由器中的MSS钳制(用于在TCP连接建立时,收发双方可以通知对方通信时每一个报文段所能承载的最大数据长度。而MTU则是数据链路层的最大传输单元,限制了数据包的大小。MSS通常受限于MTU,最佳情况下MSS=MTU-40,以太网环境中最大MSS为1460字节)功能,可是小米路由器不支持这个功能,即使放在光猫拨号也不能解决问题。我的解决办法是,将IPV6设置中局域网获取IP方式改为“仅DHCPv6”

因为安卓设备只支持SLAAC(无状态地址自动指派)的方式获取IPV6地址,但是WIN10和IOS设备都支持DHCPv6的方式获取,所以通过这种方式禁止安卓设备获取IPV6地址。(这几种选项具体的差别可以参考:家用路由IPV6配置指南)因为目前我用IPV6的需求只是需要家里的电脑和NAS设备有公网IP,手机端不是一定需要IPV6地址,也算一种曲线救国的方式了吧。

本地网突破VLAN

VLAN是网络交换机的一种技术,可以把不同的电脑划分在不同的网络中,使其不能互相通信,以达到提高安全性和网络性能的目的。要跨越VLAN通信,必须借助路由器或者3层交换模块。

我市的ADSL网在接入层使用了Cisco的Catalyst6509型三层交换机,在端口上设置了VLAN,把同一IP段的用户相互隔开。这样一来,安全性倒是高了,可惜平时打游戏、共享文件都不方便,需要通过其他IP段的朋友中转。于是突破VLAN成了当务之急。

我所在的段,IP地址为10.145.254.x,网关为10.145.254.1,采用24位的掩码。因为是同一IP段,所以电脑不会自动通过路由器转发数据,而妄想通过直接通信的方式联络对方电脑。在VLAN环境下,ARP是收不到回应的,因此直接通信也就被禁止了。 

要想实现互通,必须强制电脑把数据发给路由器。

大家知道,路由器判断一个数据包是否应该转发,是以其2层地址和3层地址为依据的。如果该数据包的目标MAC地址不是路由器接口的MAC地址,那么这个包根本不是给路由器的,而是HUB产生的1层广播包;如果目标MAC地址与路由器接口的MAC地址相同,但目标IP地址并不是路由器接口的IP地址,这个包就应该被路由出去;如果目标MAC地址和IP地址都与路由器接口相匹配,那这个数据包是发给路由器本身的。

电脑在发送数据时,先判断目标和自己是否在同一IP网段。如果在同一网段,则发送ARP请求,查询对方的MAC地址,然后封包发送;如果不在同一IP网段,则发送数据包,并把包头中目标MAC地址设置为本子网的路由器接口的MAC地址,而目标IP地址则是最终接收数据的电脑的IP地址的数据包。路由器收到数据以后,就会把它转发出去。

要强制电脑把本来直接发送的数据发给路由器,可以从ARP协议上下手,也可以从判断是否同一网段的过程下手。

使用ARP的方法如下:

1、使用arp -a命令查看已知的MAC列表。因为目前VLAN里只有网关和本身,所以这里只显示网关的MAC地址:

  Internet Address      Physical Address      Type

10.145.254.1          00-d0-04-14-af-fc     dynamic

2、使用arp -s命令把要与之通信的电脑的IP地址和网关的MAC地址强行捆绑。这样,这台电脑就会把发给对方的数据发给路由器。对方的机器也要运行这个命令,不过IP地址要指定为这一台。比如10.145.254.a和10.145.254.b通信,要在10.145.254.a上运行arp -s 10.145.254.b 00-d0-04-14-af-fc ,而在10.145.254.b上运行arp -s 10.145.254.a 00-d0-04-14-af-fc 

经过这样的设置,电脑还以为自己在直接发送数据,而路由器以为自己收到了需要路由的数据包。这其实是一种ARP欺骗技术。

使用同子网判断的方法如下:

双方使用route命令,建立一条“主机路由”。所谓主机路由,就是针对一台电脑而不是一个IP网段的路由项目,其目标掩码为255.255.255.255。

在10.145.254.a上运行route ADD 10.145.254.b MASK 255.255.255.255  10.145.254.1 ,在10.145.254.b上运行route ADD 10.145.254.a MASK 255.255.255.255  10.145.254.1即可。根据路由的最长匹配原则,电脑在发送数据时会选择掩码里1比较多的那一项,也就是主机路由(32位掩码),而不会认为对方和自己同一子网(24位掩码)。

使用以上两种方法,就可以突破VLAN的限制了。除了CS的LAN Gane还不能正常运行(Internet Game正常)以外,其他软件均运行正常。

现在是一个高人的介绍哈:

第一:如果该数据包的目标MAC地址不是路由器接口的MAC地址,那么这个包根本不是给路由器的,而是HUB产生的1层广播包;

点评:这句话表达有失偏颇!问题的关键在于“HUB产生的1层广播报文”这是一句让人昏倒在地的说法哦!

分析:

1、路由器可以分解为一个独立的物理层+数据链路层+网络层构成转发决策机构!当然路由器还有自己的七层(严格的说是TCP/IP的第四层应用层)。现在我们仅仅需要关心的就是路由器的二层+三层这两个层面;

2、如果路由器一个interface接受到的报文的DMAC不等于interface的MAC,那么路由器认为这个报文不是自己的,或者这个报文不需要自己进行处理,所以路由器将直接discard这个报文!

所以“HUB产生的1层广播报文”犯下了严重的阶级路线错误!

第二:如果目标MAC地址与路由器接口的MAC地址相同,但目标IP地址并不是路由器接口的IP地址,这个包就应该被路由出去;

点评:这句话表达基本上没有什么错误!

分析:

1、路由器接口接收到报文如果DMAC=路由器接口自身的MAC,那么路由器将尽义务进行下一步的处理,那就是到底将这个报文进行路由转发还是给我CPU自己使用;

2、但是究竟是进行转发还是提交给CPU,这已经不是二层是事情了,各司其职嘛。二层协议栈还要将这个报文的二层帧头、FCS这个尾巴去掉提交给三层!

3、三层收到IP包之后,那么判断这个IP包的DIP等不等于接口IP地址,如果不等于,那么表示的是这个报文不需要提交CPU高层协议栈。需要进行路由转发处理!

一旦路由器作出路由转发处理,那么路由器接下来的工作是不是就是查询路由表,看看把这个瘟神从那个接口送走了之!

第三:如果目标MAC地址和IP地址都与路由器接口相匹配,那这个数据包是发给路由器本身的。

点评:这句话表达没有什么错误!

分析:

1、这个观点还是延续的上一个说法,那就是路由器二层协议栈将报文的帧头、FCS尾巴去掉之后,提交给协议栈的三层---网络层;

2、三层收到IP包之后,那么判断这个IP包的DIP等不等于接口IP地址,如果不等于,那么表示的是这个报文不需要提交CPU高层协议栈。需要进行路由转发处理!

3、那么如果DIP=接口IP,三层就认为这个报文需要提交给CPU来处理!

一旦路由器作出判定,这个报文需要提交给CPU,那么三层协议栈就需要将报文的IP包头删除,将剩余的部分(就是IP包的内容部分哈)提交给四层或者直接提交给ICMP等协议高层处理

下面是高人的一个交换原理的模型图片,出处[url]www.cditlab.com[/url]

摘自
https://blog.51cto.com/xiong/17780

一文读懂QUIC 协议:更快、更稳、更高效的网络通信

原文

你是否也有这样的困扰:打开APP巨耗时、刷剧一直在缓冲、追热搜打不开页面、信号稍微差点就直接加载失败……

如果有一个协议能让你的上网速度,在不需要任何修改的情况下就能提升20%,特别是网络差的环境下能够提升30%以上;如果有一个协议可以让你在WiFi和蜂窝数据切换时,网络完全不断开、直播不卡顿、视频不缓冲;你愿意去了解一下它吗?它就是QUIC协议。本文将从QUIC的背景、原理、实践部署等方面来详细介绍。

一:网络协议栈  

1.1 什么叫网络协议?  

类似于我们生活中签署的合同一样,比如买卖合同是为了约束买卖双方的行为按照合同的要求履行,网络协议是为了约束网络通信过程中各方(客户端、服务端及中间设备)必须按照协议的规定进行通信,它制定了数据包的格式、数据交互的过程等等,网络中的所有设备都必须严格遵守才可以全网互联。

在网络协议栈中,是有分层的,每一层负责不同的事务。我们讨论最多的有三个:应用层、传输层、网络层。应用层主要是针对应用软件进行约束,比如你访问网站需要按照HTTP协议格式和要求进行,你发送电子邮件需要遵守SMTP等邮件协议的格式和要求;传输层主要负责数据包在网络中的传输问题,比如如何保证数据传输的时候的安全性和可靠性、数据包丢了怎么处理;网络层,也叫路由转发层,主要负责数据包从出发地到目的地,应该怎样选择路径才能更快的到达。合理的网络协议能够让用户上网更快!    

1.2 HTTP/3协议  

HTTP/3是第三个主要版本的HTTP协议。与其前任HTTP/1.1和HTTP/2不同,在HTTP/3中,弃用TCP协议,改为使用基于UDP协议的QUIC协议实现。所以,HTTP/3的核心在于QUIC协议。显然,HTTP/3属于应用层协议,而它使用的QUIC协议属于传输层协议。

1.3 我们需要HTTP/3协议吗  

很多人可能都会有这样一个疑问,为什么在 2015 年才标准化了 HTTP/2 ,这么快就需要 HTTP/3?

我们知道,HTTP/2通过引入“流”的概念,实现了多路复用。简单来说,假设你访问某个网站需要请求10个资源,你使用HTTP1.1协议只能串行地发请求,资源1请求成功之后才能发送资源2的请求,以此类推,这个过程是非常耗时的。如果想10个请求并发,不需要串行等待的话,在HTTP1.1中,应用就需要为一个域名同时建立10个TCP连接才行(一般浏览器不允许建立这么多),这无疑是对资源的极大的浪费。HTTP/2的多路复用解决了这一问题,能使多条请求并发。

但现实很残酷,为什么很多业务用了HTTP/2,反倒不如HTTP1.1呢?

第一:多流并发带来了请求优先级的问题,因为有的请求客户端(比如浏览器)希望它能尽快返回,有的请求可以晚点返回;又或者有的请求需要依赖别的请求的资源来展示。流的优先级表示了这个请求被处理的优先级,比如客户端请求的关键的CSS和JS资源是必须高优先级返回的,图片视频等资源可以晚一点响应。         
流的优先级的设置是一个难以平衡或者难以做到公平合理的事情,如果设置稍微不恰当,就会导致有些请求很慢,这在用户看来,就是用了HTTP/2之后,怎么有的请求变慢了。    

第二:HTTP/2解决了HTTP协议层面的队头阻塞,但是TCP的队头阻塞仍然没有解决,所有的流都在一条TCP连接上,如果万一序号小的某个包丢了,那么TCP为了保证到达的有序性,必须等这个包到达后才能滑动窗口,即使后面的序号大的包已经到达了也不能被应用程序读取。这就导致了在多条流并发的时候,某条流的某个包丢了,序号在该包后面的其他流的数据都不能被应用程序读取。这种情况下如果换做HTTP1.1,由于HTTP1.1是多条连接,某个连接上的请求丢包了,并不影响其他连接。所以在丢包比较严重的情况下,HTTP/2整体效果大概率不如HTTP1.1

事实上,我们并不是真的需要新的 HTTP 版本,而是需要对底层传输控制协议(TCP) 进行升级。

1.4 QUIC协议栈  

图片

图0-QUIC协议栈    

QUIC协议实现在用户态,建立在内核态的UDP的基础之上,集成了TCP的可靠传输特性,集成了TLS1.3协议,保证了用户数据传输的安全。

二:QUIC协议的优秀特性  

2.1 建连快  

数据的发送和接收,要想保证安全和可靠,一定是需要连接的。TCP需要,QUIC也同样需要。连接到底是什么?连接是一个通道,是在一个客户端和一个服务端之间的唯一一条可信的通道,主要是为了安全考虑,建立了连接,也就是建立了可信通道,服务器对这个客户端“很放心”,对于服务器来说:你想跟我进行通信,得先让我认识一下你,我得先确认一下你是好人,是有资格跟我通信的。那么这个确认对方身份的过程,就是建立连接的过程。

传统基于TCP的HTTPS的建连过程为什么如此慢?它需要TCP和TLS两个建连过程。如图1所示(传统HTTPS请求流程图):    

图片

图1-传统HTTPS请求流程图

对于一个小请求(用户数据量较小)而言,传输数据只需要1个RTT,但是光建连就花掉了3个RTT,这是非常不划算的,这里建连包括两个过程:TCP建连需要1个RTT,TLS建连需要2个RTT。RTT:Round Trip Time,数据包在网络上一个来回的时间。

为什么需要两个过程?可恶就可恶在这个地方,TCP和TLS没办法合并,因为TCP是在内核里完成的,TLS是在用户态。也许有人会说把干掉内核里的TCP,把TCP挪出来放到用户态,然后就可以和TLS一起处理了。首先,你干不掉内核里的TCP,TCP太古老了,全世界的服务器的TCP都固化在内核里了。所以,既然干不掉TCP,那我不用它了,我再自创一个传输层协议,放到用户态,然后再结合TLS,这样不就可以把两个建连过程合二为一了吗?是的,这就是QUIC。

2.1.1 QUIC的1-RTT建连    

如图2所示,是QUIC的连接建立过程:初次建连只需要1个RTT即可完成建连。后续再次建连就可以使用0-RTT特性

图片

图2-QUIC建连过程图

QUIC的1-RTT建连:客户端与服务端初次建连(之前从未进行通信过),或者长时间没有通信过(0-RTT过期了),只能进行1-RTT建连。只有先进行一次完整的1-RTT建连,后续一段时间内的通信才可以进行0-RTT建连。

如图3所示:QUIC的1-RTT建连可以分成两个部分。QUIC连接信息部分和TLS1.3握手部分。    

图片

图3-QUIC建连抓包

QUIC连接:协商QUIC版本号、协商quic传输参数、生成连接ID、确定Packet Number等信息,类似于TCP的SYN报文;保证通信的两端确认过彼此,是对的人。

TLS1.3握手:标准协议,非对称加密,目的是为了协商出 对称密钥,然后后续传输的数据使用这个对称密钥进行加密和解密,保护数据不被窃取。

我们重点看QUIC的TLS1.3握手过程。    

图片

图4-QUIC的1-RTT握手流程

我们通过图4可以看到,整个握手过程需要 2次握手(第三次握手是带了数据的),所以整个握手过程只需要1-RTT(RTT是指数据包在网络上的一个来回)的时间。

1-RTT的握手主要包含两个过程:

1.客户端发送Client Hello给服务端;

2.服务端回复Server Hello给客户端;

我们通过下图中图5和图6来看Client Hello和Server Hello具体都做了啥:

第一次握手(Client Hello报文)    

图片

图5-Client Hello报文

首先,Client Hello在扩展字段里标明了支持的TLS版本(Supported Version:TLS1.3)。值得注意的是Version字段必须要是TLS1.2,这是因为TLS1.2已经在互联网上存在了10年。网络中大量的网络中间设备都十分老旧,这些网络设备会识别中间的TLS握手头部,所以TLS1.3的出现如果引入了未知的TLS Version 必然会存在大量的握手失败。    

图片

图6-Client Hello报文

其次,ClientHello中包含了非常重要的key_share扩展:客户端在发送之前,会自己根据DHE算法生成一个公私钥对。发送Client Hello报文的时候会把这个公钥发过去,那么这个公钥就存在于key_share中,key_share还包含了客户端所选择的曲线X25519。总之,key_share是客户端提前生成好的公钥信息。

最后,Client Hello里还包括了:客户端支持的算法套、客户端所支持的椭圆曲线以及签名算法、psk的模式等等,一起发给服务端。    

图片

图7-Client Hello报文

第二次握手:(Server Hello报文)    

图片

图8-Server Hello报文

服务端自己根据DHE算法也生成了一个公私钥对,同样的,Key_share扩展信息中也包含了 服务端的公钥信息。服务端通过ServerHello报文将这些信息发送给客户端。

至此为止,双方(客户端服务端)都拿到了对方的公钥信息,然后结合自己的私钥信息,生成pre-master key,在这里官方的叫法是(client_handshake_traffic_secret和server_handshake_traffic_secret),然后根据以下算法进行算出key和iv,使用key和iv对Server Hello之后所有的握手消息进行加密。

注意:在握手完成之后,服务端会发送一个New Session Ticket报文给客户端,这个包非常重要,这是0-RTT实现的基础。    

图片

图9-New Session Ticket报文

2.1.2 QUIC的0-RTT握手  

这个功能类似于TLS1.2的会话复用,或者说0-RTT是基于会话复用功能的。

图片

图10- QUIC的0-RTT流程图

通过上面图10我们可以看到,client和server在建连时,仍然需要两次握手,仍然需要1个rtt,但是为什么我们说这是0-rtt呢,是因为client在发送第一个包client hello时,就带上了数据(HTTP 请求),从什么时候开始发送数据这个角度上来看,的确是0-RTT。

我们通过抓包来看0-RTT的过程:

图片

图11- QUIC的0-RTT抓包

所以真正在实现0-RTT的时候,请求的数据并不会跟Initial报文(内含Client Hello)一起发送,而是单独一个数据包(0-RTT包)进行发送,只不过是跟Initial包同时进行发送而已。

图片

图12- QUIC的0-RTT包    

我们单独看Initial报文发现,除了pre_share_key、early-data标识等信息与1-RTT时不同,其他并无区别。

2.1.3 QUIC建连需要注意的问题  

第一,QUIC实现的时候,必须缓存收到的乱序加密帧,这个缓存至少要大于4096字节。当然可以选择缓存更多的数据,更大的缓存上限意味着可以交换更大的密钥或证书。终端的缓存区大小不必在整个连接生命周期内保持不变。这里记住:乱序帧一定要缓存下来。如果不缓存,会导致连接失败。如果终端的缓存区不够用了,则其可以通过暂时扩大缓存空间确保握手完成。如果终端不扩大其缓存,则其必须以错误码CRYPTO_BUFFER_EXCEEDED关闭连接。

第二,0-RTT存在前向安全问题,请慎用!

2.2连接迁移  

QUIC通过连接ID实现了连接迁移。

我们经常需要在WiFi和4G之间进行切换,比如我们在家里时使用WiFi,出门在路上,切换到4G或5G,到了商场,又连上了商场的WiFi,到了餐厅,又切换到了餐厅的WiFi,所以我们的日常生活中需要经常性的切换网络,那每一次的切换网络,都将导致我们的IP地址发生变化。

传统的TCP协议是以四元组(源IP地址、源端口号、目的ID地址、目的端口号)来标识一条连接,那么一旦四元组的任何一个元素发生了改变,这条连接就会断掉,那么这条连接中正在传输的数据就会断掉,切换到新的网络后可能需要重新去建立连接,然后重新发送数据。这将会导致用户的网络会“卡”一下。    

但是,QUIC不再以四元组作为唯一标识,QUIC使用连接ID来标识一条连接,无论你的网络如何切换,只要连接ID不变,那么这条连接就不会断,这就叫连接迁移!

图片

图13-QUIC连接迁移介绍

2.2.1连接ID  

每条连接拥有一组连接标识符,也就是连接ID,每个连接ID都能标识这条连接。连接ID是由一端独立选择的,每个端(客户端和服务端统称为端)选择连接ID供对端使用。也就是说,客户端生成的连接ID供服务端使用(服务端发送数据时使用客户端生成的连接ID作为目的连接ID),反过来一样的。

连接ID的主要功能是确保底层协议(UDP、IP及更底层的协议栈)发生地址变更(比如IP地址变了,或者端口号变了)时不会导致一个QUIC连接的数据包被传输到错误的QUIC终端(客户端和服务端统称为终端)上。

2.2.2 QUIC的连接迁移过程    

QUIC限制连接迁移为仅客户端可以发起,客户端负责发起所有迁移。如果客户端接收到了一个未知的服务器发来的数据包,那么客户端必须丢弃这些数据包。

如图14所示,连接迁移过程总共需要四个步骤。

1.连接迁移之前,客户端使用IP1和服务端进行通信;

2.客户端IP变成IP2,并且使用IP2发送非探测帧给服务端;

3.启动路径验证(双方都需要互相验证),通过PATH_CHANLLENGE帧和PATH_RESPONSE帧进行验证。

4.验证通过后,使用IP2进行通信。

图片

图14- 连接迁移流程图   

2.3 解决TCP队头阻塞问题  

在HTTP/2中引入了流的概念。目的是实现 多个请求在同一个连接上并发,从而提升网页加载的效率。

图片

图15-QUIC解决TCP队头阻塞问题

由图15来看,假设有两个请求同时发送,红色的是请求1,蓝色的是请求2,这两个请求在两条不同的流中进行传输。假设在传输过程中,请求1的某个数据包丢了,如果是TCP,即使请求2的所有数据包都收到了,但是也只能阻塞在内核缓冲区中,无法交给应用层。但是QUIC就不一样了,请求1的数据包丢了只会阻塞请求1,请求2不会受到阻塞。

有些人不禁发问,不是说HTTP2也有流的概念吗,为什么只有QUIC才能解决呢,这个根本原因就在于,HTTP2的传输层用的TCP,TCP的实现是在内核态的,而流是实现在用户态度,TCP是看不到“流”的,所以在TCP中,它不知道这个数据包是请求1还是请求2的,只会根据seq number来判断包的先后顺序。

2.4 更优的拥塞控制算法  

拥塞控制算法中最重要的一个参数是 RTT,RTT的准确性决定了拥塞控制算法的准确性;然而,TCP的RTT测量往往不准确,QUIC的RTT测量是准确的。    

图片

图16-TCP计算RTT

如图16所示:由于网络中经常出现丢包,需要重传,在TCP协议中,初始包和重传包的序号是一样的,拥塞控制算法进行计算RTT的时候,无法区别是初始包还是重传包,这将导致RTT的计算值要么偏大,要么偏小。

图片

图17-QUIC计算RTT    

如图17所示:QUIC通过Packet Number来标识包的序号,而且规定Packet Number只能单调递增,这也就解决了初始包和重传包的二义性。从而保证RTT的值是准确的。

另外,不同于TCP,QUIC的拥塞控制算法是可插拔的,由于其实现在用户态,服务可以根据不同的业务,甚至不同的连接灵活选择使用不同的拥塞控制算法。(Reno、New Reno、Cubic、BBR等算法都有自己适合的场景)

2.5 QUIC的两级流量控制  

很多人搞不清楚流量控制与拥塞控制的区别。二者有本质上的区别。

流量控制要解决的问题是:接收方控制发送方的数据发送的速度,就是我的接收能力就那么大点,你别发太快了,你发太快了我承受不住,会给你丢掉 你还得重新发。         
拥塞控制要解决的问题是:数据在网络的传输过程中,是否网络有拥塞,是否有丢包,是否有乱序等问题。如果中间传输的时候网络特别卡,数据包丢在中间了,发送方就需要重传,那么怎么判断是否拥塞了,重传要怎么重传法,按照什么算法进行发送数据才能尽可能避免数据包在中间路径丢掉,这是拥塞控制的核心。

所以,流量控制解决的是接收方的接收能力问题,一般采用滑动窗口算法;拥塞控制要解决的是中间传输的时候网络是否拥堵的问题,一般采用慢启动、拥塞避免、拥塞恢复、快速重传等算法。                       

图片

图18-QUIC流量控制

QUIC是双级流控,不仅有连接这一个级别的流控,还有流这个级别的流控。如下图所示,每个流都有自己的可用窗口,可用窗口的大小取决于最大窗口数减去发送出去的最大偏移数,跟中间已经发送出去的数据包,是否按顺序收到了对端的ACK 无关。

3.QUIC协议如何优化  

QUIC协议定义了很多优秀的功能,但是在实现的过程中,我们会遇到很多问题导致无法达到预期的性能,比如0-RTT率很低,连接迁移失败率很高等等。

3.1 QUIC的0-RTT成功率不高  

导致0-RTT成功率不高的原因一般有如下几个:

1.服务端一般都是集群,对于客户端来说,处理请求的服务端是不固定的,新的请求到来时,如果当前client没有请求过该服务器,则服务器上没有相关会话信息,会把该请求当做一个新的连接来处理,重新走1-RTT。    

针对此种情况,我们可以考虑集群中所有的服务器使用相同的ticket文件。

2.客户端IP不是固定的,在发生连接迁移时,服务端下发的token融合了客户端的IP,这个IP变化了的话,携带token服务端校验不过,0-RTT会失败。

针对这个问题,我们可以考虑采用如图19所示的方法,使用设备信息或者APP信息来生成token,唯一标识一个客户端。

图片

图19- 使用设备信息提高0-RTT的成功率

3.Session Ticket过期时间默认是2天,超过2天后就会导致0-RTT失败,然后降级走1-RTT。可以考虑增长过期时间。

3.2 实现连接迁移并不容易  

连接迁移的实现,不可避开的两个问题:一个是四层负载均衡器对连接迁移的影响,一个是七层负载均衡器对连接迁移的影响。

四层负载均衡器的影响:LVS、DPVS等四层负载均衡工具基于四元组进行转发,当连接迁移发生时,四元组会发生变化,该组件就会把同一个请求的数据包发送到不同的后端服务器上,导致连接迁移失败;    

七层负载均衡器的影响(QUIC服务器多核的影响):由于多核的影响,一般服务器会有多个QUIC服务端进程,每个进程负载处理不同的连接。内核收到数据包后,会根据二元组(源IP、源port)选择已经存在的连接,并把数据包交给对应的socket。在连接迁移发生时,源地址发生改变,可能会让接下来的数据包去到不同的进程,影响socket数据的接收。

如何解决以上两个问题?DPVS要想支持QUIC的连接迁移,就不能再以四元组进行转发,需要以连接ID进行转发,需要建立 连接ID与对应的后端服务器的对应关系;

QUIC服务器也是一样的,内核就不能用四元组来进行查找socket,四元组查找不到时,就必须使用连接ID进行查找socket。但是内核代码又不能去修改(不可能去更新所有服务器的内核版本),那么我们可以使用eBPF的方法进行解决。如下图20所示:

图片

图20-多核QUIC服务器解决连接迁移问题    

3.3 UDP被限速或禁闭  

业内统计数据全球有7%地区的运营商对UDP有限速或者禁闭,除了运营商还有很多企业、公共场合也会限制UDP流量甚至禁用UDP。这对使用UDP来承载QUIC协议的场景会带来致命的伤害。对此,我们可以采用多路竞速的方式使用TCP和QUIC同时建连。除了在建连进行竞速以外,还可以对网络QUIC和TCP的传输延时进行实时监控和对比,如果有链路对UDP进行了限速,可以动态从QUIC切换到TCP。

图片

图21-QUIC和TCP协议竞速       

3.4 QUIC对CPU消耗大  

相对于TCP,为什么QUIC更消耗资源?

1.QUIC在用户态实现,需要更多的内核空间与用户空间的数据拷贝和上下文切换;

2.QUIC的ACK报文也是加密的,TCP是明文的。

3.内核知道TCP连接的状态,不用为每一个数据包去做诸如查找目的路由、防火墙规则等操作,只需要在tcp连接建立的时候做一次即可,然而QUIC不行;

总的来说,QUIC服务端消耗CPU的地方主要有三个:密码算法的开销;udp收发包的开销;协议栈的开销;    

针对这些,我们可以适当采取优化措施来:

1.使用Intel硬件加速卡卸载TLS握手

2.开启GSO功能。

3.数据在传输过程中,可以将一轮中所有的ACK解析后再同时进行处理,避免处理大量的ACK。

4.适当将QUIC的包长限制调高(比如从默认的1200调到1400个字节)

5.减少协议栈的内存拷贝

4.QUIC的性能  

从公开的数据来看,国内各个厂(腾讯、阿里、字节、华为、OPPO、网易等等)使用了QUIC协议后,都有很大的提升,比如网易上了QUIC后,响应速度提升45%,请求错误率降低50%;比如字节火山引擎使用QUIC后,建连耗时降低20%~30%;比如腾讯使用QUIC后,在腾讯会议、直播、游戏等场景耗时也降低30%;

总结  

QUIC协议的出现,为HTTP/3奠定了基础。这是近些年在web协议上最大的变革,也是最优秀的一次实践。面对新的协议,我们总是有着各种各样的担忧,诚然,QUIC协议在稳定性上在成熟度上,的确还不如TCP协议,但是经过近几年的发展,成熟度已经相当不错了,Nginx近期也发布了1.25.0版本,支持了QUIC协议。所以面对这样优秀的协议,我们希望更多的公司,更多的业务参与进来使用QUIC,推动QUIC更好的发展,推动用户上网速度更快!         

玩客云刷openwrt后记

最近折腾了玩客云刷机OpenWrt作为旁路由的方案,分享给大家,有需要的朋友折腾。

「玩客云硬件参数:」

  • CPU是晶晨S805 ,4核心 1.5GHZ
  • 双USB2.0
  • 千兆单网口
  • 1GB内存+8GB存储

这个配置平平无奇,主要的硬伤是cpu32位的,usb2.0传输速度只有20M/秒左右,下载速度跑不满千兆带宽,好的地方是千兆网口。

「刷机准备工具:」

  1. WIN10电脑一台
  2. 双公头USB线一根
  3. 矿渣玩客云
  4. 螺丝刀、吹风机

玩客云刷机openwrt两种方法:

「方法一」直刷openwrt 这个网上资源只有一个,snail 大神制作的固件,固件没插件,需要自己安装。

「方法二」刷armbian安装docker在安装openwrt,这个有比较多的适合固件,openwrt版本新,插件多,本次选这个方案。

刷机资源分享

刷机固件、软件,使用阿里云分享,不限速,需要转存后下载,然后解压!

玩客云openwrt刷机包:


https://www.aliyundrive.com/s/ZM3oScBDcck「提取码: y75j」

第一步:刷入底包 update

WIN10打开烧录软件,选择update镜像,点开始。

关键步骤,先短接触点,再接通玩客云主板电源。需要说明的是,玩客云有两种版本,它们的短接位置也是不一样的。

我的是老主板,上图短接位置,图片来源:@Powersee大神

这个是新版(也就是玩客云主板上标注的有v1.3的主板),短接点是在正面。

拆机后、usb插入玩客云「靠近HDMI的接口」、另一头接入电脑usb、短接焊点、通电。

正常情况,会出现上图的一个线程,开始写入。如果有错误,换一个usb接口,多试几次。

这个固件很小,很快就会写完,一般几秒钟,提示烧录成功后,先点”停止“,然后关闭,拔掉电源、拔掉USB。

第二步:玩客云刷入armbian5.9系统

这一步分为好几个部分:

  1. U盘写入armbian5.88系统
  2. armbian5.88写入玩客云EMMC
  3. U盘写入armbian5.9系统
  4. U盘启armbian5.9系统ssh登陆写入EMMC

打开写入U盘镜像软件,选择镜像,确认U盘名称,点flash开始写入。

等待几分钟,写入速度和U盘传输速度有关,一般是几分钟,提示成功后,关闭软件,拔出U盘。

把U盘插入玩客云靠近网口的USB,然后通电,指示灯会蓝色→绿色→蓝紫闪烁→蓝色,证明刷机成功,过程好几分钟,多等下。

打开写入软件,选armbian5.9的镜像,写入U盘,过程比前面快一点,这个镜像小一些,同样步骤操作。

armbian5.9系统写入完成后,把U盘插入玩客云靠近网口的USB,用网线接入路由器LAN口,通电开机。

过一会打开路由器后台,找到”aml-s812“的设备IP地址,复制。

WIN10电脑打开putty软件,其他ssh工具也可以,填入上面的IP地址

登陆,用户名:root 默认密码:1234

进入目录 cd /boot/install ,写入emmc命令,等待写入完成,耗时几分钟。

刷入 emmc命令:

    cd /boot/install  sudo ./install.sh   

完成后,拔电源,拔掉U盘,终于ARMBIAN系统刷机完成。

第三步:docker环境搭建

国内网络连接不稳定,需要更换软件源,然后更新系统,之后才能安装docker。

「换Debian源」

    nano /etc/apt/sources.list

进入编辑器后,粘贴下面代码

    deb https://mirrors.ustc.edu.cn/debian/ bullseye main non-free contrib     deb-src https://mirrors.ustc.edu.cn/debian/ bullseye main non-free contrib     deb https://mirrors.ustc.edu.cn/debian-security/ bullseye-security main     deb-src https://mirrors.ustc.edu.cn/debian-security/ bullseye-security main     deb https://mirrors.ustc.edu.cn/debian/ bullseye-updates main non-free contrib     deb-src https://mirrors.ustc.edu.cn/debian/ bullseye-updates main non-free contrib     deb https://mirrors.ustc.edu.cn/debian/ bullseye-backports main non-free contrib     deb-src https://mirrors.ustc.edu.cn/debian/ bullseye-backports main non-free contrib

然后保存,退出。

「更新软件」

    apt-get update && apt-get upgrade   

我在更新时出错:The following signatures couldn’t be verified because the public key is not available: NO_PUBKEY 0E98404D386FA1D9 NO_PUBKEY 6ED0E7B82643E131 NO_PUBKEY 605C66F00D6C9793

这时就要把提示的这两个密钥加进sudo apt-key adv –keyserver keyserver.ubuntu.com –recv-keys 605C66F00D6C9793

选择有Y就选Y,有默认的情况就选N

这里选择 NO

「安装docker」

等待代码跑完后,docker -v 查看下版本,证明安装成功!

安装OpenWrt

镜像一:https://www.right.com.cn/forum/thread-8024126-1-1.html

镜像二:https://hub.docker.com/r/xuanaimai/onecloud

本次安装的是镜像一,比较精简,功能够用;镜像二功能很全,根据自己需要选择。

「打开网卡混杂模式」

    ip link set eth0 promisc on

「创建网络」

    docker network create -d macvlan --subnet=192.168.100.0/24 --gateway=192.168.100.1 -o parent=eth0 macnet  

自己根据 玩客云 所在网段修改,如:玩客云IP:192.168.1.175,则192.168.0.0/24 改成 192.168.1.0/24,192.168.0.1改成主路由地址

「拉取镜像」

    docker pull jyhking/onecloud:1.1docker run -itd --name=OneCloud --restart=always --network=macnet --privileged=true jyhking/onecloud:1.1 /sbin/init

要用后面的那个比较全的镜像就用以下
docker pull xuanaimai/onecloud:21-09-15
docker run -itd --name=OneCloud --restart=always --network=macnet --privileged=true xuanaimai/onecloud:21-09-15 /sbin/init   

我拉镜像时出错:error pulling image configuration: Get “https://production.cloudflare.docker.com/registry-v2/docker/registry/v2/blobs/sha256/d7/d78565d1532457f322286aa8463048d8704ca4d089f4afc631928666cb7a2ded/data?verify=1720441198-8KibCckc%2F932Kur0VblpYsiYTLc%3D”: dial tcp [2a03:2880:f11a:83:face:b00c:0:25de]:443: i/o timeout
这时一般是可能是DNS问题,

解决方法:在/etc/resolv.conf文件中新增一个参数

保存,重启docker,再拉镜像,如果还不行可以试下代理先在命令行设置HTTP_PROXY=http://54.69.7.14:26535



openwrt镜像运行成功,然后打开路由器后台,找到openwrt地址。

「用户名:root 密码: password」

「玩客云旁路由设置:」

  • LAN口固定IP地址,网关指向主路由IP地址,(一般桥接也关了)
  • 关闭DHCP服务器
  • 关闭IPV6
  • 防火墙自定义规则添加下面代码iptables -t nat -I POSTROUTING eth0 -j MASQUERADE

进openclash,配置文件订阅,添加,加订阅,如果是v2ray等要点选 订阅转换服务地址

这时把电脑网关设置为旁路由地址就可上网

原文https://mao.fan/article/36

Linux中使用curl命令发送带参数的get请求和post请求

  1. curl与wget 命令的区别
    相似之处:wget 和 cURL 都可以下载内容,都可以向互联网发送请求并返回请求项,也可以进行 HTTP POST 请求,它们都是命令行工具,可以设计成可脚本化应用到bash脚本中。

wget特点:简单直接、可直接下载程序、支持递归下载、使用方便。

curl特点:多功能工具、支持多种网络协议、安全、支持 gzip 压缩技术。

   选择使用 curl还是使用 wget?

根据实际情况而定。如果想快速下载并且没有担心参数标识的需求,使用轻便有效的 wget。如果你想做一些更复杂的使用,直觉告诉你,你应该选择 curl。

curl可以理解为命令行网页浏览器,能处理好多事情,并且支持多种网络协议,可交互访问在线内容。不同的是curlL 不会渲染接收到的相应信息。

这里主要说明下curl命令发送带参数的get和post请求如何使用。

  1. curl命令Get请求
    语法:curl命令 + 请求接口的地址

curl http://baidu.com

如果需要,可根据情况进行重定向 curl http://baidu.com > page.hrml

注意:

问题:如果请求的URL含有&转义字符,会提示参数不对,报错?

crul http://172.16.134.9:1153/mp_mcss/vcn-image.do?mode=2&fileUuid=92dc1c25980d4a1c9b59d928a092e478 > 2.jpg

原因:由于URL中&不转义,curl请求时会分开访问。

解决办法:

1) URL连接上加上双引号

crul “http://172.16.134.9:1153/mp_mcss/vcn-image.do?mode=2&fileUuid=92dc1c25980d4a1c9b59d928a092e478” > 2.jpg

2) URL连接&前加\ 就可以取消转义

  1. curl命令Post请求
    举例:带header和body的POST请求

curl -v -XPOST -H “Content-Type:application/json” http://172.24.7.63:36963/VIID/MotorVehicles -d ‘ {“DataType” : “Face”} ‘

说明:

-v 详细的请求信息

-XPOST 指定请求凡是为POST请求

-H 指定请求头部

-d 指定传送数据为json格式

注意:

1) 如果传送json数据过大,由于数据长度限制会出现curl失败?

解决方案:将json写成文件形式报错,例如data.json

curl -v -XPOST -H “Content-Type:application/json” http://172.24.7.63:36963/VIID/MotorVehicles -d @data.json

至于,DELETE和PUT请求可参考网上资源。

原文链接:https://blog.csdn.net/finghting321/article/details/105733140/

下载用机顶盒

在机顶盒刷个hi-nas,然后进终端,装python3,再开机就运行py文件

systemd是现代Linux系统中用于初始化系统组件和管理系统进程的标准。以下是创建一个systemd服务用于开机就启动这个文件,基本步骤:

  1. 创建一个服务文件,例如/etc/systemd/system/myservice.service,内容可能如下:
[Unit]
Description=My Python Service
After=network.target

[Service]
User=yourusername
ExecStart=/usr/bin/python3 /path/to/your_script.py
Restart=always
WorkingDirectory=/path/to/your_script_directory

[Install]
WantedBy=multi-user.target

请将yourusername替换为你的用户名,/path/to/your_script.py替换为你的Python脚本的实际路径,/path/to/your_script_directory替换为你的Python脚本所在的目录。

  1. 重新加载systemd配置以识别新服务:
sudo systemctl daemon-reload
  1. 启动服务:
复制sudo systemctl start myservice.service
  1. 使服务在开机时自动启动:
sudo systemctl enable myservice.service
  1. 检查服务状态:
sudo systemctl status myservice.service

以下是用到的py文件

import requests
import time
import datetime
from concurrent.futures import ThreadPoolExecutor
import random
#import logging

#logging.basicConfig(level=logging.INFO, format='%(asctime)s - %(name)s - %(levelname)s - %(message)s')

urlList = ['https://dldir1v6.qq.com/weixin/Windows/WeChatSetup.exe', 'https://qrsj.gdl.netease.com/LauncherGame__697327.exe', 'https://downloadclient03.ztgame.com.cn/ztmianfei/client/zhengtu_setup_20231228.zip', 'https://pm.myapp.com/invc/xfspeed/qqpcmgr/download/QQPCDownload320059.exe', 'https://d4.a.kwimgs.com/kos/nlav12667/5.35.1/KwaiLive-Setup-5.35.1.2005-ReleaseFull.exe', 'https://sta-op.douyucdn.cn/dypc-client/pkg/DYTool/20240510183635704/master_DYToolEX_6.3.1.3.472.exe', 'https://download.huya.com/huyapc/install/HuyaClientInstall.exe']
thread = 5  #线程数量
goal = 0  #消耗的流量单位GB
if goal > 0:
    goal = goal * 1024 * 1024 * 1024  #GB转为B

wasted = 0  #已消费的流量
runing = 0  #正在运行的数量
#线程池
executor = ThreadPoolExecutor(max_workers=thread)
#下载连接池
session = requests.Session()
adapter = requests.adapters.HTTPAdapter(pool_connections=thread, pool_maxsize=thread+1, max_retries=1, pool_block=False)
session.mount('http://', adapter)
session.mount('https://', adapter)




# 下载文件
def download(url):
    try:
        global runing
        runing += 1
        response = session.get(url, stream=True, timeout=(10, 30))  # 连接超时10秒,读取超时30秒
        if response.status_code == 200:
            download_start_time = time.time()  # 开始下载的时间
            for chunk in response.iter_content(chunk_size=10240):  # 按块读取文件内容
                if chunk:  # 确保chunk不为空
                    pass  # 处理文件内容,例如写入文件

                # 检查下载是否超过30分钟
                if time.time() - download_start_time > 1000:  # 1800秒 = 30分钟
                    #print(f"Download has exceeded 30 minutes: {url}")
                    break  # 终止下载循环

    # except requests.exceptions.RequestException as e:  # 捕获requests异常
    #     print(f"Request failed: {e}")
    # except Exception as e:  # 捕获其他异常
    #     print(f"An error occurred: {e}")
    finally:
        runing -= 1
        if response:
            response.close()  # 关闭下载连接


def startDownload():
    time.sleep(random.randint(1, 10))
    global wasted
    wasted = 0
    # 开始下载
    i = thread
    while i > 0:
        executor.submit(download, random.choice(urlList))
        # 休眠0.01秒-0.1秒
        time.sleep(random.randint(1, 10) / 100)
        i -= 1


if __name__ == "__main__":
    startDownload()
    while True:
        # 获取当前时间
        curtime = datetime.datetime.now()
        hour = curtime.hour
        if 6 <= hour < 18:
            if (goal == 0 or wasted < goal) and runing < thread:
                #logging.info("补充下载链接数:%s", thread - runing)
                i = thread - runing
                while i > 0:
                    executor.submit(download, random.choice(urlList))
                    time.sleep(random.randint(1, 10) / 100)
                    i -= 1
            time.sleep(95)
        elif 18 <= hour < 24:
            if (goal == 0 or wasted < goal) and runing < thread:
                #logging.info("补充下载链接数:%s", thread - runing)
                i = thread - runing - 2
                while i > 0:
                    executor.submit(download, random.choice(urlList))
                    time.sleep(random.randint(1, 10) / 100)
                    i -= 1
            time.sleep(95)
        else:
            if (goal==0 or wasted < goal) and runing < thread:
                #logging.info("补充下载链接数:%s", thread - runing)
                i = thread - runing - 1
                while i> 0:
                    executor.submit(download, random.choice(urlList))
                    time.sleep(random.randint(1, 10) / 100)
                    i-=1
            time.sleep(95)







服务器部署Navidrome开源音乐服务器

可以用来自建云端音乐播放器,让你在任何地方通过浏览器或者手机来收听自己的音乐,兼容 Subsonic、Aironic 播放器

支持各大平台,包括:

  • Windows
  • macOS
  • Linux
  • Docker

这次用docker安装,先安装docker,我是直接用宝塔装了个docker管理器,

然后进终端

mkdir -p /opt/docker/navidrome && cd /opt/docker/navidrome && mkdir -p /music && chmod 755 -R /music

新建docker-compose.yaml文件并编辑

执行以下命令,新建 docker-compose.yaml 文件并编辑

nano docker-compose.yaml

然后输入以下配置内容,然后 Ctrl X + y +回车 退出并保存即可。

---
version: "3"
services:
  navidrome:
    image: deluan/navidrome:latest
    ports:
      - 2079:4533
    restart: unless-stopped
    environment:
      ND_SCANSCHEDULE: 1h
      ND_LOGLEVEL: info
      ND_SESSIONTIMEOUT: 24h
      ND_BASEURL: ""
      ND_DEFAULTLANGUAGE: zh-Hans
      #设置默认语言为简体中文
      ND_ENABLESHARING: "true"
      #开启共享功能
    volumes:
      - /opt/docker/navidrome:/data
      - /music:/music:ro

docker-compose.yaml 文件中 2079 为暴露端口,4533上传页面,如被占用,请自行更改替换,需要在云服务器的控制台防火墙开放相应端口!然后放音乐文件的文件夹设置的根目录下的music

docker compose up -d
启动容器
浏览器访问服务器 IP:2079 即可访问,还可以配置反向代理加个域名,还可以用支持Subsonic/Madsonic/Airsonic 的客户端来播放。
各种第三方客户端:

iOS: play:Sub, substreamer, Amperfy and iSub
Android: DSub, Subtracks, substreamer, Ultrasonic  Audinaut
推荐https://ultrasonic.gitlab.io/download/
Web: Subplayer, Airsonic Refix, Aurial, Jamstash and Subfire
Desktop: Sublime Music (Linux) and Sonixd (Windows/Linux/macOS)
CLI: Jellycli (Windows/Linux) and STMP (Linux/macOS)
Connected Speakers:
Sonos: bonob
Alexa: AskSonic
Other:
Subsonic Kodi Plugin
Navidrome Kodi Plugin
HTTPDirFS

BGP、OSPF

边界网关协议(Border Gateway Protocol,简称BGP)和开放最短路径优先协议(Open Shortest Path First,简称OSPF)是两种最常见的动态路由协议,BGP在大型网络中具有动态路由优势,而OSPF具有更高效的路径选择和收敛速度。

OSPF和BGP路由协议之间最主要的区别是前者属于IGP(内部网关协议),而后者则属于EGP(外部网关协议)。OSPF是以链路状态为根据进行选路,一般运行在AS自治系统内部,而BGP协议是建立在IGP协议基础之上的高级路由选择协议,它被设计用于在完全不同的网络(被称为自治系统(ASes))之间共享路由信息。一般是由ISP服务提供商运用在各个AS自治系统之间。

OSPF是一种内部网关协议,在公司的私有局域网中最常使用。OSPF通常被认为比BGP更易于部署和管理,在大多数企业环境中,运行OSPF几乎不需要手动调整。

OSPF路由协议是用于网际层(IP)网络的链路状态路由协议。该协议使用链路状态路由算法的内部网关协议(IGP),在单一自治系统(AS)内部工作。基于IP,协议号是89。封装在IP报文中传输

1、OSPF路由协议是属于IGP(内部网关协议),各个ospf路由器维护一张全网的链路状态数据库。采用SPF算法(最短路径优先算法),通过发送Hellow来建立邻居关系并且更新自己的路由表。

OSPF维护一个本地派生和学习网络的数据库。如果到远端网络有多条OSPF路径,OSPF会根据计算出的成本或度量值选择一条路径。到远端网络的路径开销是根据计算的参考带宽除以接口带宽得出的。参考带宽是OSPF中用来量化链路速度的一个指标。

如何计算路径成本

数字越低,连接速度越快。例如,100mbps链路的OSPF参考带宽为10,1gbps链路的OSPF参考带宽为1,网络管理员可以根据需要调整这个计算。

路径开销=参考总带宽/接口带宽

OSPF使用路径带宽作为决定路径选择的主要因素,因此,与BGP相比,它更有可能根据网络性能选择最优路径。

与BGP不同的是,运行OSPF需要大量的CPU和内存,因此,它并不适合超大型网络。

虽然OSPF可以扩展到处理具有数百条路由的大型网络,但管理员必须注意使用手动调整来减少处理和内存开销,这一点比BGP更重要。

OSPF的收敛速度比BGP快。

网络收敛是指当网络中断时,路由器调整到目标网络的路径的速度。

由于其收敛速度和基于网络性能选择路径的能力,OSPF在企业局域网和私有数据中心中是一个更好的选择。

动态路由协议可以根据路由操作分为链路状态距离向量,它们之间的区别基于邻居如何通信、发送路由更新和收敛,最初,在 Internet 连接之前,网络域较小,RIP 等距离矢量协议就足够了,范式转变为纯 IP 互联网连接模型,具有更大的网络域和复杂的流量路由,为了可扩展性和性能,距离矢量路由协议正在被链路状态协议所取代。

距离矢量路由协议定期向所有连接的邻居通告其路由表,无论是否发生拓扑更改或邻居发送请求,都会发生这种情况,当出现链路故障时,整个网络域都会出现完整路由表的泛滥,这会导致收敛速度变慢,随着网络域变大,收敛速度会呈指数级恶化。由于路由器没有准确更新的路由信息,还存在路由不稳定和抖动。

OSPF 和 IS-IS 被认为是链路状态协议。RIP 确实是唯一剩下的纯距离矢量协议,并且已经更新了 RIPv2 增强功能。EIGRP 被归类为高级距离矢量协议,具有距离矢量和链路状态协议的特性。EIGRP 只有一个邻居拓扑表,而不是一个完整的网络拓扑数据库。与链路状态协议类似,EIGRP 确实形成邻居邻接并发送事件触发的更新,而不是定期的完整路由表更新。

BGP 是一种路径向量协议

几种基本的网络攻击原理

1.1 TCP SYN拒绝服务攻击

一般情况下,一个TCP连接的建立需要经过三次握手的过程,即:

1、 建立发起者向目标计算机发送一个TCP SYN报文;

2、目标计算机收到这个SYN报文后,在内存中创建TCP连接控制块(TCB),然后向发起者回送一个TCP ACK报文,等待发起者的回应;

3、 发起者收到TCP ACK报文后,再回应一个ACK报文,这样TCP连接就建立起来了。

利用这个过程,一些恶意的攻击者可以进行所谓的TCP SYN拒绝服务攻击:

1、 攻击者向目标计算机发送一个TCP SYN报文;

2、目标计算机收到这个报文后,建立TCP连接控制结构(TCB),并回应一个ACK,等待发起者的回应;

3、而发起者则不向目标计算机回应ACK报文,这样导致目标计算机一致处于等待状态。

可以看出,目标计算机如果接收到大量的TCP SYN报文,而没有收到发起者的第三次ACK回应,会一直等待,处于这样尴尬状态的半连接如果很多,则会把目标计算机的资源(TCB控制结构,TCB,一般情况下是有限的)耗尽,而不能响应正常的TCP连接请求。

1.2 ICMP洪水

正常情况下,为了对网络进行诊断,一些诊断程序,比如PING等,会发出ICMP响应请求报文(ICMP ECHO),接收计算机接收到ICMP ECHO后,会回应一个ICMP ECHO Reply报文。而这个过程是需要CPU处理的,有的情况下还可能消耗掉大量的资源,比如处理分片的时候。这样如果攻击者向目标计算机发送大量的ICMP ECHO报文(产生ICMP洪水),则目标计算机会忙于处理这些ECHO报文,而无法继续处理其它的网络数据报文,这也是一种拒绝服务攻击(DOS)。

1.3 UDP洪水

原理与ICMP洪水类似,攻击者通过发送大量的UDP报文给目标计算机,导致目标计算机忙于处理这些UDP报文而无法继续处理正常的报文。

1.4 端口扫描

根据TCP协议规范,当一台计算机收到一个TCP连接建立请求报文(TCP SYN)的时候,做这样的处理:

1、 如果请求的TCP端口是开放的,则回应一个TCP ACK报文,并建立TCP连接控制结构(TCB);

2、 如果请求的TCP端口没有开放,则回应一个TCP RST(TCP头部中的RST标志设为1)报文,告诉发起计算机,该端口没有开放。

相应地,如果IP协议栈收到一个UDP报文,做如下处理:

1、如果该报文的目标端口开放,则把该UDP报文送上层协议(UDP)处理,不回应任何报文(上层协议根据处理结果而回应的报文例外);

2、如果该报文的目标端口没有开放,则向发起者回应一个ICMP不可达报文,告诉发起者计算机该UDP报文的端口不可达。

利用这个原理,攻击者计算机便可以通过发送合适的报文,判断目标计算机哪些TCP或UDP端口是开放的,过程如下:

1、发出端口号从0开始依次递增的TCP SYN或UDP报文(端口号是一个16比特的数字,这样最大为65535,数量很有限);

2、如果收到了针对这个TCP报文的RST报文,或针对这个UDP报文的ICMP不可达报文,则说明这个端口没有开放;

3、相反,如果收到了针对这个TCP SYN报文的ACK报文,或者没有接收到任何针对该UDP报文的ICMP报文,则说明该TCP端口是开放的,UDP端口可能开放(因为有的实现中可能不回应ICMP不可达报文,即使该UDP端口没有开放)。

这样继续下去,便可以很容易的判断出目标计算机开放了哪些TCP或UDP端口,然后针对端口的具体数字,进行下一步攻击,这就是所谓的端口扫描攻击。

1.5 分片IP报文攻击

为了传送一个大的IP报文,IP协议栈需要根据链路接口的MTU对该IP报文进行分片,通过填充适当的IP头中的分片指示字段,接收计算机可以很容易的把这些IP分片报文组装起来。

目标计算机在处理这些分片报文的时候,会把先到的分片报文缓存起来,然后一直等待后续的分片报文,这个过程会消耗掉一部分内存,以及一些IP协议栈的数据结构。如果攻击者给目标计算机只发送一片分片报文,而不发送所有的分片报文,这样攻击者计算机便会一直等待(直到一个内部计时器到时),如果攻击者发送了大量的分片报文,就会消耗掉目标计算机的资源,而导致不能相应正常的IP报文,这也是一种DOS攻击。

1.6 SYN比特和FIN比特同时设置

在TCP报文的报头中,有几个标志字段:

1、 SYN:连接建立标志,TCP SYN报文就是把这个标志设置为1,来请求建立连接;

2、 ACK:回应标志,在一个TCP连接中,除了第一个报文(TCP SYN)外,所有报文都设置该字段,作为对上一个报文的相应;

3、 FIN: 结束标志,当一台计算机接收到一个设置了FIN标志的TCP报文后,会拆除这个TCP连接;

4、 RST:复位标志,当IP协议栈接收到一个目标端口不存在的TCP报文的时候,会回应一个RST标志设置的报文;

5、 PSH:通知协议栈尽快把TCP数据提交给上层程序处理。

正常情况下,SYN标志(连接请求标志)和FIN标志(连接拆除标志)是不能同时出现在一个TCP报文中的。而且RFC也没有规定IP协议栈如何处理这样的畸形报文,因此,各个操作系统的协议栈在收到这样的报文后的处理方式也不同,攻击者就可以利用这个特征,通过发送SYN和FIN同时设置的报文,来判断操作系统的类型,然后针对该操作系统,进行进一步的攻击。

1.7 没有设置任何标志的TCP报文攻击

正常情况下,任何TCP报文都会设置SYN,FIN,ACK,RST,PSH五个标志中的至少一个标志,第一个TCP报文(TCP连接请求报文)设置SYN标志,后续报文都设置ACK标志。有的协议栈基于这样的假设,没有针对不设置任何标志的TCP报文的处理过程,因此,这样的协议栈如果收到了这样的报文,可能会崩溃。攻击者利用了这个特点,对目标计算机进行攻击。

1.8 设置了FIN标志却没有设置ACK标志的TCP报文攻击

正常情况下,ACK标志在除了第一个报文(SYN报文)外,所有的报文都设置,包括TCP连接拆除报文(FIN标志设置的报文)。但有的攻击者却可能向目标计算机发送设置了FIN标志却没有设置ACK标志的TCP报文,这样可能导致目标计算机崩溃。

1.9 死亡之PING

TCP/IP规范要求IP报文的长度在一定范围内(比如,0-64K),但有的攻击计算机可能向目标计算机发出大于64K长度的PING报文,导致目标计算机IP协议栈崩溃。

1.10 地址猜测攻击

跟端口扫描攻击类似,攻击者通过发送目标地址变化的大量的ICMP ECHO报文,来判断目标计算机是否存在。如果收到了对应的ECMP ECHO REPLY报文,则说明目标计算机是存在的,便可以针对该计算机进行下一步的攻击。

 1.11 泪滴攻击

对于一些大的IP包,需要对其进行分片传送,这是为了迎合链路层的MTU(最大传输单元)的要求。比如,一个4500字节的IP包,在MTU为1500的链路上传输的时候,就需要分成三个IP包。

在IP报头中有一个偏移字段和一个分片标志(MF),如果MF标志设置为1,则表面这个IP包是一个大IP包的片断,其中偏移字段指出了这个片断在整个IP包中的位置。例如,对一个4500字节的IP包进行分片(MTU为1500),则三个片断中偏移字段的值依次为:0,1500,3000。这样接收端就可以根据这些信息成功的组装该IP包。

如果一个攻击者打破这种正常情况,把偏移字段设置成不正确的值,即可能出现重合或断开的情况,就可能导致目标操作系统崩溃。比如,把上述偏移设置为0,1300,3000。这就是所谓的泪滴攻击。

1.12 带源路由选项的IP报文

为了实现一些附加功能,IP协议规范在IP报头中增加了选项字段,这个字段可以有选择的携带一些数据,以指明中间设备(路由器)或最终目标计算机对这些IP报文进行额外的处理。

源路由选项便是其中一个,从名字中就可以看出,源路由选项的目的,是指导中间设备(路由器)如何转发该数据报文的,即明确指明了报文的传输路径。比如,让一个IP报文明确的经过三台路由器R1,R2,R3,则可以在源路由选项中明确指明这三个路由器的接口地址,这样不论三台路由器上的路由表如何,这个IP报文就会依次经过R1,R2,R3。而且这些带源路由选项的IP报文在传输的过程中,其源地址不断改变,目标地址也不断改变,因此,通过合适的设置源路由选项,攻击者便可以伪造一些合法的IP地址,而蒙混进入网络。

1.13 带记录路由选项的IP报文

记录路由选项也是一个IP选项,携带了该选项的IP报文,每经过一台路由器,该路由器便把自己的接口地址填在选项字段里面。这样这些报文在到达目的地的时候,选项数据里面便记录了该报文经过的整个路径。

通过这样的报文可以很容易的判断该报文经过的路径,从而使攻击者可以很容易的寻找其中的攻击弱点。

1.14 未知协议字段的IP报文

在IP报文头中,有一个协议字段,这个字段指明了该IP报文承载了何种协议,比如,如果该字段值为1,则表明该IP报文承载了ICMP报文,如果为6,则是TCP,等等。目前情况下,已经分配的该字段的值都是小于100的,因此,一个带大于100的协议字段的IP报文,可能就是不合法的,这样的报文可能对一些计算机操作系统的协议栈进行破坏。

1.15 IP地址欺骗

一般情况下,路由器在转发报文的时候,只根据报文的目的地址查路由表,而不管报文的源地址是什么,因此,这样就可能面临一种危险:如果一个攻击者向一台目标计算机发出一个报文,而把报文的源地址填写为第三方的一个IP地址,这样这个报文在到达目标计算机后,目标计算机便可能向毫无知觉的第三方计算机回应。这便是所谓的IP地址欺骗攻击。

比较著名的SQL Server蠕虫病毒,就是采用了这种原理。该病毒(可以理解为一个攻击者)向一台运行SQL Server解析服务的服务器发送一个解析服务的UDP报文,该报文的源地址填写为另外一台运行SQL Server解析程序(SQL Server 2000以后版本)的服务器,这样由于SQL Server 解析服务的一个漏洞,就可能使得该UDP报文在这两台服务器之间往复,最终导致服务器或网络瘫痪。

 1.17 Land攻击

LAND攻击利用了TCP连接建立的三次握手过程,通过向一个目标计算机发送一个TCP SYN报文(连接建立请求报文)而完成对目标计算机的攻击。与正常的TCP SYN报文不同的是,LAND攻击报文的源IP地址和目的IP地址是相同的,都是目标计算机的IP地址。这样目标计算机接收到这个SYN报文后,就会向该报文的源地址发送一个ACK报文,并建立一个TCP连接控制结构(TCB),而该报文的源地址就是自己,因此,这个ACK报文就发给了自己。这样如果攻击者发送了足够多的SYN报文,则目标计算机的TCB可能会耗尽,最终不能正常服务。这也是一种DOS攻击。

1.19 Smurf攻击

ICMP ECHO请求包用来对网络进行诊断,当一台计算机接收到这样一个报文后,会向报文的源地址回应一个ICMP ECHO REPLY。一般情况下,计算机是不检查该ECHO请求的源地址的,因此,如果一个恶意的攻击者把ECHO的源地址设置为一个广播地址,这样计算机在恢复REPLY的时候,就会以广播地址为目的地址,这样本地网络上所有的计算机都必须处理这些广播报文。如果攻击者发送的ECHO 请求报文足够多,产生的REPLY广播报文就可能把整个网络淹没。这就是所谓的smurf攻击。

除了把ECHO报文的源地址设置为广播地址外,攻击者还可能把源地址设置为一个子网广播地址,这样,该子网所在的计算机就可能受影响。

 1.20 虚拟终端(VTY)耗尽攻击

这是一种针对网络设备的攻击,比如路由器,交换机等。这些网络设备为了便于远程管理,一般设置了一些TELNET用户界面,即用户可以通过TELNET到该设备上,对这些设备进行管理。

一般情况下,这些设备的TELNET用户界面个数是有限制的,比如,5个或10个等。这样,如果一个攻击者同时同一台网络设备建立了5个或10个TELNET连接,这些设备的远程管理界面便被占尽,这样合法用户如果再对这些设备进行远程管理,则会因为TELNET连接资源被占用而失败。

1.21 路由协议攻击

网络设备之间为了交换路由信息,常常运行一些动态的路由协议,这些路由协议可以完成诸如路由表的建立,路由信息的分发等功能。常见的路由协议有RIP,OSPF,IS-IS,BGP等。这些路由协议在方便路由信息管理和传递的同时,也存在一些缺陷,如果攻击者利用了路由协议的这些权限,对网络进行攻击,可能造成网络设备路由表紊乱(这足可以导致网络中断),网络设备资源大量消耗,甚至导致网络设备瘫痪。

下面列举一些常见路由协议的攻击方式及原理:

1.21.1 针对RIP协议的攻击

RIP,即路由信息协议,是通过周期性(一般情况下为30S)的路由更新报文来维护路由表的,一台运行RIP路由协议的路由器,如果从一个接口上接收到了一个路由更新报文,它就会分析其中包含的路由信息,并与自己的路由表作出比较,如果该路由器认为这些路由信息比自己所掌握的要有效,它便把这些路由信息引入自己的路由表中。

这样如果一个攻击者向一台运行RIP协议的路由器发送了人为构造的带破坏性的路由更新报文,就很容易的把路由器的路由表搞紊乱,从而导致网络中断。

如果运行RIP路由协议的路由器启用了路由更新信息的HMAC验证,则可从很大程度上避免这种攻击。

1.21.2 针对OSPF路由协议的攻击

OSPF,即开放最短路径优先,是一种应用广泛的链路状态路由协议。该路由协议基于链路状态算法,具有收敛速度快,平稳,杜绝环路等优点,十分适合大型的计算机网络使用。OSPF路由协议通过建立邻接关系,来交换路由器的本地链路信息,然后形成一个整网的链路状态数据库,针对该数据库,路由器就可以很容易的计算出路由表。

可以看出,如果一个攻击者冒充一台合法路由器与网络中的一台路由器建立邻接关系,并向攻击路由器输入大量的链路状态广播(LSA,组成链路状态数据库的数据单元),就会引导路由器形成错误的网络拓扑结构,从而导致整个网络的路由表紊乱,导致整个网络瘫痪。

当前版本的WINDOWS 操作系统(WIN 2K/XP等)都实现了OSPF路由协议功能,因此一个攻击者可以很容易的利用这些操作系统自带的路由功能模块进行攻击。

跟RIP类似,如果OSPF启用了报文验证功能(HMAC验证),则可以从很大程度上避免这种攻击。

1.21.3 针对IS-IS路由协议的攻击

IS-IS路由协议,即中间系统到中间系统,是ISO提出来对ISO的CLNS网络服务进行路由的一种协议,这种协议也是基于链路状态的,原理与OSPF类似。IS-IS路由协议经过扩展,可以运行在IP网络中,对IP报文进行选路。这种路由协议也是通过建立邻居关系,收集路由器本地链路状态的手段来完成链路状态数据库同步的。该协议的邻居关系建立比OSPF简单,而且也省略了OSPF特有的一些特性,使该协议简单明了,伸缩性更强。

对该协议的攻击与OSPF类似,通过一种模拟软件与运行该协议的路由器建立邻居关系,然后传颂给攻击路由器大量的链路状态数据单元(LSP),可以导致整个网络路由器的链路状态数据库不一致(因为整个网络中所有路由器的链路状态数据库都需要同步到相同的状态),从而导致路由表与实际情况不符,致使网络中断。

与OSPF类似,如果运行该路由协议的路由器启用了IS-IS协议单元(PDU)HMAC验证功能,则可以从很大程度上避免这种攻击。

1.22 针对设备转发表的攻击

为了合理有限的转发数据,网络设备上一般都建立一些寄存器表项,比如MAC地址表,ARP表,路由表,快速转发表,以及一些基于更多报文头字段的表格,比如多层交换表,流项目表等。这些表结构都存储在设备本地的内存中,或者芯片的片上内存中,数量有限。如果一个攻击者通过发送合适的数据报,促使设备建立大量的此类表格,就会使设备的存储结构消耗尽,从而不能正常的转发数据或崩溃。

下面针对几种常见的表项,介绍其攻击原理:

1.22.1 针对MAC地址表的攻击

MAC地址表一般存在于以太网交换机上,以太网通过分析接收到的数据幀的目的MAC地址,来查本地的MAC地址表,然后作出合适的转发决定。

这些MAC地址表一般是通过学习获取的,交换机在接收到一个数据幀后,有一个学习的过程,该过程是这样的:

a) 提取数据幀的源MAC地址和接收到该数据幀的端口号;

b) 查MAC地址表,看该MAC地址是否存在,以及对应的端口是否符合;

c) 如果该MAC地址在本地MAC地址表中不存在,则创建一个MAC地址表项;

d) 如果存在,但对应的出端口跟接收到该数据幀的端口不符,则更新该表;

e) 如果存在,且端口符合,则进行下一步处理。

分析这个过程可以看出,如果一个攻击者向一台交换机发送大量源MAC地址不同的数据幀,则该交换机就可能把自己本地的MAC地址表学满。一旦MAC地址表溢出,则交换机就不能继续学习正确的MAC表项,结果是可能产生大量的网络冗余数据,甚至可能使交换机崩溃。

而构造一些源MAC地址不同的数据幀,是非常容易的事情。

 1.22.2 针对ARP表的攻击

ARP表是IP地址和MAC地址的映射关系表,任何实现了IP协议栈的设备,一般情况下都通过该表维护IP地址和MAC地址的对应关系,这是为了避免ARP解析而造成的广播数据报文对网络造成冲击。ARP表的建立一般情况下是通过二个途径:

1、主动解析,如果一台计算机想与另外一台不知道MAC地址的计算机通信,则该计算机主动发ARP请求,通过ARP协议建立(前提是这两台计算机位于同一个IP子网上);

2、被动请求,如果一台计算机接收到了一台计算机的ARP请求,则首先在本地建立请求计算机的IP地址和MAC地址的对应表。

因此,如果一个攻击者通过变换不同的IP地址和MAC地址,向同一台设备,比如三层交换机发送大量的ARP请求,则被攻击设备可能会因为ARP缓存溢出而崩溃。

针对ARP表项,还有一个可能的攻击就是误导计算机建立正确的ARP表。根据ARP协议,如果一台计算机接收到了一个ARP请求报文,在满足下列两个条件的情况下,该计算机会用ARP请求报文中的源IP地址和源MAC地址更新自己的ARP缓存:

1、 如果发起该ARP请求的IP地址在自己本地的ARP缓存中;

2、 请求的目标IP地址不是自己的。

可以举一个例子说明这个过程,假设有三台计算机A,B,C,其中B已经正确建立了A和C计算机的ARP表项。假设A是攻击者,此时,A发出一个ARP请求报文,该请求报文这样构造:

1、 源IP地址是C的IP地址,源MAC地址是A的MAC地址;

2、 请求的目标IP地址是A的IP地址。

这样计算机B在收到这个ARP请求报文后(ARP请求是广播报文,网络上所有设备都能收到),发现B的ARP表项已经在自己的缓存中,但MAC地址与收到的请求的源MAC地址不符,于是根据ARP协议,使用ARP请求的源MAC地址(即A的MAC地址)更新自己的ARP表。

这样B的ARP混存中就存在这样的错误ARP表项:C的IP地址跟A的MAC地址对应。这样的结果是,B发给C的数据都被计算机A接收到。

1.22.3 针对流项目表的攻击

有的网络设备为了加快转发效率,建立了所谓的流缓存。所谓流,可以理解为一台计算机的一个进程到另外一台计算机的一个进程之间的数据流。如果表现在TCP/IP协议上,则是由(源IP地址,目的IP地址,协议号,源端口号,目的端口号)五元组共同确定的所有数据报文。

一个流缓存表一般由该五元组为索引,每当设备接收到一个IP报文后,会首先分析IP报头,把对应的五元组数据提取出来,进行一个HASH运算,然后根据运算结果查询流缓存,如果查找成功,则根据查找的结果进行处理,如果查找失败,则新建一个流缓存项,查路由表,根据路由表查询结果填完整这个流缓存,然后对数据报文进行转发(具体转发是在流项目创建前还是创建后并不重要)。

可以看出,如果一个攻击者发出大量的源IP地址或者目的IP地址变化的数据报文,就可能导致设备创建大量的流项目,因为不同的源IP地址和不同的目标IP地址对应不同的流。这样可能导致流缓存溢出。

泛洪(flooding) 交换机和网桥使用的一种数据流传递技术,将某个接口收到的数据流从除该接口之外的所有接口发送出去。
  SYN泛洪攻击。SYN攻击利用的是TCP的三次握手机制,攻击端利用伪造的IP地址向被攻击端发出请求,而被攻击端发出的响应报文将永远发送不到目的地,那么被攻击端在等待关闭这个连接的过程中消耗了资源,如果有成千上万的这种连接,主机资源将被耗尽,从而达到攻击的目的。我们可以利用路由器的TCP拦截功能,使网络上的主机受到保护(以Cisco路由器为例)。
  DHCP报文泛洪攻击
  DHCP报文泛洪攻击是指:恶意用户利用工具伪造大量DHCP报文发送到服务器,一方面恶意耗尽了IP资源,使得合法用户无法获得IP资源;另一方面,如果交换机上开启了DHCP Snooping功能,会将接收到的DHCP报文上送到CPU。因此大量的DHCP报文攻击设备会使DHCP服务器高负荷运行,甚至会导致设备瘫痪。
  ARP报文泛洪攻击
  ARP报文泛洪类似DHCP泛洪,同样是恶意用户发出大量的ARP报文,造成L3设备的ARP表项溢出,影响正常用户的转发。