Simple-Tracker / qBittorrent-ClientBlocker

一款适用于 qBittorrent/Transmission (Beta)/BitComet (Beta, Partial) 的客户端屏蔽器, 默认屏蔽包括但不限于迅雷等客户端. A client blocker compatible with qBittorrent/Transmission (Beta)/BitComet (Beta, Partial) which is prohibited to include but not limited to clients such as Xunlei.
MIT License
840 stars 20 forks source link

关于 增强自动屏蔽_相对 的实现疑问 #39

Closed fonqL closed 4 months ago

fonqL commented 4 months ago

异常peer的判定表达式十分奇怪:

$$ \frac{MyOldUploaded}{MyNewUploaded} > ratio * \frac{PeerOldProgress}{PeerNewProgress} $$

我不太明白这个不等式的意义,上传量变化率和进度变化率?这是错误实现吗?比如peer进度一直不变,则不等式右边一直等于ratio,而左边永远小于1,则不等式永远不会成立吧 参照增强自动屏蔽_绝对(IsProgressNotMatchUploaded)的实现,不应该是类似这样的吗?:

$$ MyNewUploaded-MyOldUploaded > ratio TorrentSize (PeerNewProgress-PeerOldProgress) $$

Simple-Tracker commented 4 months ago

感谢反馈!

可能写反了! 回头检查一下, 并追加于此.

变化率可以是新值和老值的比值, 所以唯一的问题应该是写反了. 左边的上传量是从客户端统计的实际上传量, 所以左边的理想上应该是逐步增加, 而右边则不会变化 (对于恶意客户端), 因此最终此规则是可以达到所需目标的 (如果没有写反的话...).

由于有起始判断大小设置的存在, 除非用户设置, 右边不会为 0, 这样可以避免永远达成条件的错误.

fonqL commented 4 months ago

左边的理想上应该是逐步增加

那也不对啊,实际上左边等于

$$ \frac{MyNewUploaded}{MyOldUploaded}=\frac{MyOldUploaded+\Delta{x}}{MyOldUploaded} $$

$\Delta{x}$ 是一段时间内的上传量,跟网速有关,可以认为是远小于Torrent大小的常量。所以累计的已上传量 $MyOldUploaded$ 逐渐增长是使比值下降并逐渐趋近1的。

并且我觉得就不能这么相比,即使右边变形为

$$ \frac{TorrentSize PeerNewProgress}{TorrentSize PeerOldProgress} $$

这个比较也没有意义(恶意行为嫌疑)。这会造成极高的误判率:比如上传量现在是10M,以前是1M,而peer进度报告现在是50%,以前是49%,比率稍微小一点(<10)就被误判为恶意peer,无论torrent大还是小都一样。

Simple-Tracker commented 4 months ago

是我疏忽了, 左边理论确实是趋向于 1, 但实际上由于时间间隔较大一般是稳定在 1 以上的 (除非下载完成). ratio 就是为避免误判率的.

调换顺序后的式子左侧是为统计实际上传量变化倍率, 右侧是为 Peer 报告进度变化倍率.

假设 1: Peer 本次统计到实际上传量 20MB, 上次 10MB. 本次百分比 19%, 上次百分比 12%, 防误判倍率 2. 则新的左式实际上传量变化倍率即: 20/10 = 2, 相比之前的变化是 2 倍. 而右式 Peer 报告进度变化倍率 19%/12%=1.583 倍, 再考虑防误判 ratio 是 1.583*2 约为 3. 则由于 2 不大于 3, 就不会触发封禁. 但若防误判倍率为 1, 则会被封禁.

假设 2: Peer 本次统计到实际上传量 20MB, 上次 10MB. 本次百分比 0%, 上次百分比 0%, 防误判倍率 2. 则左式还是 2. 右式 0/0 实际上是一个特殊情况, 最后结果做了处理仍为 0. 则 2 > 0, 而这是一种特殊情况 (0%), 但由于本次和上次间隔了一定时间, 且上传量变化超过了一定幅度 (默认 10MB), 此处符合, 所以会实际封禁.

Simple-Tracker commented 4 months ago

我又想了想原来的式子: 左式如果老的上传是 10MB, 新的上传是 20MB, 那么 10/20=0.5 即 50%. 而 Peer 报告变化进度 12% 到 13%, 那么 0.12/0.13>0.9 即 90%, 所以可以很直观的发现它们之间的差异是 40%. 显然, Peer 少报了一些变化进度. 所以原式子理论上也是可以行得通的, 应该没什么问题. 但最后:

relativeUploadedPrecent > (peerReportProgress * float64(config.BanByRelativePUAntiErrorRatio)

50% > 90% * 3, 这一步是有误的, 可能使永远无法进入判定.

可能应该说这个百分比反了, 若是 1-0.12/0.13=0.1=10%, 那么就是正确的. 所以两者的百分比现在其实是都反向了.

Edit: 嗯, 可能还要考虑 Torrent 本身的大小, Relative 现在没有这个信息. 设 Torrent 大小为 1000MB, 则上述进度假设原本是 11%, 新的会是 12%, 确实也是约为 90%. 设 Torrent 大小为 10000MB, 1.1%/1.2%, 还是约为 90%. 所以在考虑 Peer 报告进度时无需考虑 Torrent 本身大小了.

数学不好好烧脑.

fonqL commented 4 months ago

嗯。。我认为上传“倍率”跟进度“倍率”根本没关联,有关联的等式早已写到顶楼,下面变换个形式再说说。

$$ \Delta{MyUploaded} > ratio TorrentSize \Delta{PeerProgress} $$

为什么不这样实现呢?我觉得这是恶意行为的合理判定。意思是,客户端在一段时间内的上传量理应小于Peer一段时间内的接受量。否则,Peer的进度绝对是错的。这个原理跟增强自动屏蔽的绝对值的判定是一样的:已上传的总量不能小于Peer已接收的量。 绝对值判定的意义是逐渐提升Peer正确汇报进度的下界,并防止Peer多次重复下载。相对值的意义判定是防止Peer乱跳进度条。

下面给出简单的严格推导: 理想的良好Peer进度应该满足的性质是:

$$ TorrentSize * PeerProgress = \sum_{i} Uploaded_i $$

其中 $Uploaded_i$ 表示用户i的累计上传量。就是qbittorrent-peer窗口的那一列吧。累计下载量等于所有用户的累计上传量的意思。 然后,变化量就有性质:

$$ TorrentSize * \Delta{PeerProgress} = \sum_{i} \Delta{Uploaded_i} $$

一段时间内的下载量当然应该等于一段时间内所有用户的上传量。

最少有一个用户上传,所以 $i$ 最小是1,所以理论上良好的Peer应该满足:

$$ TorrentSize * \Delta{PeerProgress} \ge \Delta{Uploaded_i} $$

不满足的就是恶意Peer。然后把>=改成<就行了,并且在左边加个ratio因子给点宽容。然后颠倒不等式左右两边就得到了最上面的恶意Peer判定不等式。 推导完成

Simple-Tracker commented 4 months ago

核心原因是在于: 我们只储存了 peerMap, 没有储存 TorrentSize, 所以我们希望避开它.

上传百分比这个就没啥好讲的. 进度百分比本身是考虑了 Torrent 大小, 但当两个进度求比值, 则 Torrent 大小将被消去, 进而可以被转化并近似为 Peer 侧报告上传量的百分比 (可能有滞后, 所以引入 ratio).

此处和项目本身可能有些百分比和倍率的混淆, 虽然它们两者是可以互相转换的.

fonqL commented 4 months ago

核心原因是在于: 我们只储存了 peerMap, 没有储存 TorrentSize, 所以我们希望避开它.

看了看代码,了解了。但是仍然希望能得到修改。要不我提个pull request?

Simple-Tracker commented 4 months ago

我又想了想原来的式子: 左式如果老的上传是 10MB, 新的上传是 20MB, 那么 10/20=0.5 即 50%. 而 Peer 报告变化进度 12% 到 13%, 那么 0.12/0.13>0.9 即 90%, 所以可以很直观的发现它们之间的差异是 40%. 显然, Peer 少报了一些变化进度. 所以原式子理论上也是可以行得通的, 应该没什么问题. 但最后:

relativeUploadedPrecent > (peerReportProgress * float64(config.BanByRelativePUAntiErrorRatio)

50% > 90% * 3, 这一步是有误的, 可能使永远无法进入判定.

可能应该说这个百分比反了, 若是 1-0.12/0.13=0.1=10%, 那么就是正确的. 所以两者的百分比现在其实是都反向了.

Edit: 嗯, 可能还要考虑 Torrent 本身的大小, Relative 现在没有这个信息. 设 Torrent 大小为 1000MB, 则上述进度假设原本是 11%, 新的会是 12%, 确实也是约为 90%. 设 Torrent 大小为 10000MB, 1.1%/1.2%, 还是约为 90%. 所以在考虑 Peer 报告进度时无需考虑 Torrent 本身大小了.

~数学不好好烧脑.~

上个草图, 从图中可以很明显的观察到 TorrentSize 因为被消去不会产生影响. 不过作差应该也能产生类似结果的. IMG_0701

若是可以的话当然欢迎提交 Pull Request! 不过若是能不使用 TorrentSize 的话对节省存储 lastPeerMap 的资源有帮助.

尽管我不一定看得懂

Simple-Tracker commented 4 months ago

由于已实现上述草图先行关闭, 若有问题可再度打开!

shelfofclub commented 4 months ago

MyNewUploaded−MyOldUploaded>ratio∗TorrentSize∗(PeerNewProgress−PeerOldProgress)

我比较赞同这种朴素的思路,考核差值。 没能理解 $\frac{new}{old}$ 的思路。

https://github.com/Simple-Tracker/qBittorrent-ClientBlocker/blob/10725ffe49fcea1488ee201657435d48d44d5430/console.go#L164-L182 在现在的代码中似乎已有了种子大小的信息。

核心原因是在于: 我们只储存了 peerMap, 没有储存 TorrentSize, 所以我们希望避开它.

不知这个size是否真实有效?

Simple-Tracker commented 4 months ago

MyNewUploaded−MyOldUploaded>ratio∗TorrentSize∗(PeerNewProgress−PeerOldProgress)

我比较赞同这种朴素的思路,考核差值。 没能理解 newold 的思路。

https://github.com/Simple-Tracker/qBittorrent-ClientBlocker/blob/10725ffe49fcea1488ee201657435d48d44d5430/console.go#L164-L182

在现在的代码中似乎已有了种子大小的信息。

核心原因是在于: 我们只储存了 peerMap, 没有储存 TorrentSize, 所以我们希望避开它.

不知这个size是否真实有效?

这是在改造过程中为了 PR 修改/加入其它算法做的一点努力, Size 是来自 qBittorrent, 所以屏蔽器本身并无力保证是否真实有效. 目前版本就我们上述的草图来看, 效果理应不应有明显区别.