2.21测试版

BEP 5 对 get_peers 的描述是 valuesnodes二选一。其他客户端如果回复时同时返回的话,BitComet也能兼容处理。如果BitComet要加上同时返回,需要考虑UDP包整体大小,防止超过MTU被分包。

mtu的话上面算了一下,可能ipv6要砍一下默认50返回,具体数据要等做出来后才知道,现在是预估值头部大小

问了一下AI, 64:ff9b::2666:7f0638.102.127.6的NAT64 / IPv4-embedded IPv6 地址,推测是 B 所在网络或系统用 NAT64 方式把 A 的 IPv4 38.102.127.6 表示成了 IPv6 目的地址 64:ff9b::2666:7f06,B又把这个“对端视角地址”误当成了 A 的真实 IPv6 WAN IP。下一版增加一下 NAT64 IPv4-embedded IPv6 地址的识别和处理

禁用DHT开关的情况下也会出现统计页面里面显示出这个错误的对外ip,能够确定这个就是beta12版本开始出现的问题

Beta16 已发布,欢迎试用

打包错了吧,版本还是昨天17号的beta15

重新上传了

可以,正常起效果了,dns在600秒ttl过期后,服务器会自动进行轮询做均衡负载

回复其他人get_peers的时候,现在正常有nodes了
其它人在找到3个peer的同时可以进一步从得知的nodes其它节点继续查询获取更多peer

上一版协议头是93字节,这一版同时给对方请求包Get_peers回 nodes 节点的情况,协议头是312字节
等于存储5个peer需要312+8*5=352实际内容字节,352+8+20=380mtu

这就是说这一版本为了不超过1380的安全mtu(1352实际内容)
返回8个ipv6 nodes节点(每个38字节,和一个11字节前缀头)协议头是408字节,ip包为40字节(1332实际内容)
绝对安全值
ipv4最多返回130个
ipv6最多返回44个

如果ipv6返回50个那么就会发生分片,只有设置为44个才是安全的

Beta16 测试
abc打洞正常
ab反向回连打洞正常
新增的增强版ab反向回连打洞正常

dht打洞正常
但是有点难搜索到,可能是只有10个announce_peer宣告包太少的问题,导致别人搜不到
不知道是不是DHT协议规范限制默认只发10个get_peers包和10个announce_peer包?

发现问题
本地发送get_peers包后,如果对方返回有peer,那么就不会继续向获取到的node节点进一步查询了
抓包无法看到任何后续的一次get_peers包,当前只有对方没返回peer的时候才会进一步查询
希望可以做一下对方返回peer的同时继续和获取到的node节点进行一次get_peers查询

本地发送announce_peer包的时候好像有问题?很多DHT节点返回错误invalid token
看了下宣告包里token确实空的?但是同样的版本服务器上又是好的,因为没运行客户端超过30分钟吗

原来我都宣告失败了,怪不得DHT打洞难成功,服务器老是搜索不到自己,,,不知道哪一个beta版本开始的,我都没注意
本地请求的8个announce_peer无响应,2个返回invalid token

连接dht经常有一个114.16.196.15 或者 15.204.110.111、15.235.117.43 等等的ip UTP卡住65秒才断开,好像是1分钟后本地发起5次Active,对方没回就断开

完整的抓包,是个dht爬虫,对方客户端ua是dht-spy/1.0

抓包查看到,对方获取了元数据ut_metadata,本地也发送成功了,应该可以缩短下发完元数据后的超时,别卡60秒那么久,对方获取完元数据就跑路了,不会进行后续下载

把强制UTP改成禁用后,这个DHT爬虫会用TCP来爬,TCP就没有卡住在用户列表的问题,甚至瞬间完成速度太快,用户列表都是空的,没显示对方的信息,也没留下脚印在bt_disconnected,只能在抓包软件看到

应该改进一下UTP发送元数据,对方都回了ACK确认包了,代表发送成功完成了,就没必要卡住60秒了

应该是发送get_peers,但是对方没回复,导致未收到token,后续无法正常发送announce_peer所以为空?不知道怎么的重启下客户端又好了,可能是DHT的ID发生了变化

产生这个问题的原因应该就是上面这个,发起的get_peers太少,大多数没有回应,没有成功拿node字段继续发一次get_peers,导致10秒之后的后续发announce_peer变成空了

还有,作为B的时候,能不能不要隐藏A传来的PEX啊,utorrent其它软件都没隐藏PEX的
要是你觉得会污染用户列表显示的话,要不然你改成专家模式下不隐藏也可以啊

算了一下,IPv6 标准里要求的最小链路 MTU 是1280,减去 IPv6 header 40 及 UDP header 8 之后,DHT 包长度上限是 1232。对于DHT 的 get_peers 回复而言:

如果回复50个peers,则还能带 2 个node6,计算如下:(1232 - 93 - (3+16+2) * 50 - 3) / (20 + 16 + 2) = 2.26
如果带8个node6,则只能回复 39 个peers,计算如下:(1232 - 93 - (20+16+2) * 8 - 12) / (3+16+2) = 39.19

我觉得还是按照 get_peers 的语义,优先返回 50个peers更好。

目前的代码是会检查返回peer时附带的node节点id,如果比“回复者自身 id”更接近 info_hash,则会被跳过,以保证只向更近节点收敛,避免无意义扩散。不过可以优化一下,再多做一次“附加扩展查询”,允许最多查询一轮返回的 nodes。

看了一下,代码里有bug,annouce前没有检查是否已实际拿到token,下一版修复

感谢反馈,下一版加上处理, metadata 完整发送后, 5~10 秒后无真实交互则断开

抓包看到nodes的前缀是11字节 不知道你3和12怎么来的
不应该用安全mtu1380算吗 你用了最小mtu去了
ipv6返回4个节点的情况下,那么返回50个peer是安全的
(38x4+11+93-1332)/21=51

可以改成ipv6下返回peer的时候只返回4个节点,如果不存在peer字段才返回8节点

也可以检查下发送get_peers后是否回应了,没回应可以和远一点距离的人做annouce,至少成功宣告出去了不是吗

对,多做一次get_peers的操作很合理,反正现在的情况就是距离最近的几个可能都没回应,可以从远一点的地方去找peer
本地看到虽然远一点,但是在其他用户的身份看,可能他自身就是最近的,这样就能扩散出去了
这样也可以帮助后续annouce成功率

Beta17 已发布,欢迎试用

1個讚

终于和v2.20一样,B的PEX显示出来了,前几版本不知道你为什么要隐藏起来

偶然还会卡住到65秒,不过还可以现在基本控制在15秒了

找到token为空这bug的触发条件了,停止任务重新开始没有任何问题
是在追踪器选项卡右键更新dht就会触发token为空announce宣告失败的情况
原因是没有和停止开始一样,延迟10秒在宣告导致的token为空,任务上右键手动更新dht的时候,get_peers和announce_peer两种包是一同发送的,这里忘记做10秒延迟了

可以做一下这个?现在beta17版本因为token为空导致不进行annouce发包,引发了缺少10个announce_peer情况下,当前版本只发了6到7个的announce_peer包

从get_peers附加扩展查询补齐到10个annouce?

感觉没起效果,dht这东西不太好测试,如果你觉得没问题了应该没问题了
就是假设从14.53.186.212获取到peer对方同时携带node返回8个,已知2个node,未知6个node
后续本地get_peers成功向这6个 185.202.172.210、67.21.89.45、119.123.2.139、23.95.248.83、208.87.240.21、107.173.127.78 这6个node继续进行一次查询get_peers了,获取到了更多新的peer

感觉可以同时对这些附加查询的节点发announce,凑够到10个
或者这里单独额外对所有的附加查询的节点发送announce,不计算在10个限额内
其它人发查询get_peers找info_hash路过这6个节点的时候,annouce成功率大幅提升

主要这个不太好人眼观察
比“回复者自身 id”更接近 info_hash,则会被跳过

ipv6 get_peers 返回对方的发送包如果携带peers的时候, 控制mtu大小node节点还没改成4个,当前还是8个

因为这个peer实际上是本机的外网地址,放在peer列表里会通常都连接不上,即使连上了也会因为peer_id与本机相同被立即断开,给普通用户造成困扰。其唯一有价值的信息,即本机的外网uTP port,在peer列表首行的本机信息里也有地方显示了。不过在专家模式下作为调试诊断信息显示出来也没问题,现在已经标记为特殊的peer来源了,不会再去尝试连接。

感谢反馈,找到代码bug了,下一版修复

看了一下代码,目前最多向10个peer announce。我再完善一下,尽量填满10个

我改一下

感觉utp发完元数据后可以收到对方ACK确认后,立即发个FIN包断开甚至不用等15秒,让后续重连就行了

以前添加这种dht节点的方式还有作用吗?这些引导节点已经被DNS解析封锁,想试试制作种子把ip添加进去
node://router.bittorrent.com:6881/

制作种子的时候添加,没有成功添加到种子文件里,也没有尝试对这个ip发dht请求
node://67.215.246.10:6881/

或者添加另一个比特彗星用户的ip地址,发送一个find_node包通过对方引导连上DHT网络

制作种子文件无法添加node://形式 自定义ip地址进去种子里面

种子文件里面自带的这些nodes也没有请求

直接发find_node包可能不合理,发一个ping包好一点?收到回复成功就加入到dht节点数new中

目前代码是优先添加活跃dht节点,用户填写的 node://ip:port 仅当没有活跃节点时作为备份节点添加。可以退出BitComet后,把 %appdata%\BitComet\rules\dhtnodes.dat 临时改名,再启动BitComet,这时用户填写的 node://ip:port 一定会被加入torrent文件。

这个方法成功了

制作完成后,从种子存档删除,退出比特彗星在把dhtnodes.dat删除,重开比特彗星,重新添加种子文件,但是并没有看到对添加的ip发起dht的ping请求

不过有成功放在new里面,不知道多久之后才会对这dht节点发ping请求