从零开始自主搭建全套 Seedbox 环境 (2) - 取回篇

在我的上篇Blog中,介绍了Seedbox环境中的下载工具的搭建过程。但其实我们还有一个需求:就是将文件从盒子空间中拖回本地。如果你详细的看了上文,并能认真理解我最后写的Nginx配置,你就会发现我注释了一个一直也没创建也没说明的文件#include snippets/download.conf;

常见的取回方法有以下几类:SFTP、FTP、HTTP、BTSync等,我个人喜欢使用前三类。当然你也可以考虑使用网盘中转,将文件从盒子中首先上传到第三方网盘,再从网盘中取回(常用的网盘服务有Google Drive、OneDrive)。

个人对SFTP和FTP的感觉差不多,但两者均没有合适的本地客户端来提供多线程分片下载的功能(IDM事实上是提供类似支持的),但是可以通过多进程的方式来实现多文件同时下载的能力,SFTP比FTP较为简单的是直接基于SSH服务,无需另外安装其他服务。HTTP因为具有分片下载的能力,但多文件同时下载较为麻烦,特别是出现文件夹嵌套的情况。同时对于盒子空间在国外的用户,使用HTTP下载可以利用上Cloudflare的CDN加速(如果你有域名的话,(随便申一个免费的23333))

我个人喜欢的方法是 单文件或多文件无文件夹层级 - HTTP多文件有文件夹层级 - SFTP或FTP

HTTP

在上一篇下载安装中,我使用了Nginx作为Web服务器。

Nginx默认是不允许列出整个目录的。如需此功能,打开nginx.conf文件或你要启用目录浏览虚拟主机的配置文件,在server或location 段里添加上autoindex on;来启用目录流量,下面是rtinst使用的配置,将其直接放在snippets/download.conf中并取消原有注释,即可轻松使用。

1
2
3
4
5
6
7
8
9
10
11
location ~ ^/download/(.+?)(/.*)?$ {
alias /home/$1$2;
charset UTF-8;
source_charset UTF-8;
set $user $1;
if ($remote_user = '') { break; }
if ($user != $remote_user) { return 403; }
auth_basic "Restricted";
auth_basic_user_file /etc/nginx/.htpasswd;
index index.html index.htm; autoindex on; autoindex_exact_size off;
}

在这个配置中,可以在域名的download文件夹下访问目标用户主目录。

nginx_download.jpg

但是默认的目录流量页面可能过于丑陋,喜欢美观的可以使用fancyindex模块做进一步优化。这也就是我们在安装nginx时候使用nginx-extra包的原因。

关于nginx-*包的区别可以查看该问答:What is the difference between the core, full, extras and light packages for nginx? - Ask Ubuntu

我比较喜欢的两个Nginx-Fancyindex-Theme如下:

TheInsomniac/Nginx-Fancyindex-Theme

Naereen/Nginx-Fancyindex-Theme

其他的你可以使用Nginx-Fancyindex-Theme作为关键词在Github上搜索。

按照对应的README.md下载文件到网站根目录下,并修改原有的下载文件配置就可。

注:nginx-extra包自带的fancyindex模块可能不支持fancyindex_name_length 255;配置项(,即对于过长的文件名会使用…替换过长字符)。如果需要,请下载nginx及ngx-fancyindex进行编译替换2333333

SFTP

无需过多设置,建议使用FileZilla这款同时支持SFTP与FTP的工具来登陆。

FTP

FTP的客户端程序我比较喜欢使用pure-ftpd,因为可以同时监听IPv4和IPv6地址。而vsftpd并不能做到同时监听(如果要同时监听的话,需要使用两份不同的配置文件,一份监听IPv4,一份监听IPv6,并启用)

从包管理器安装也十分方便:apt-get install pure-ftpd

相应的系统管理命令有:

1
2
systemctl status pure-ftpd.service
systemctl restart pure-ftpd.service

添加虚拟用户请用pure-pw命令,如pure-pw useradd rhilip -u rhilip -g rhilip -d /home/rhilip就添加了一个登陆用户名为rhilip,根目录为/home/rhilip的用户。
之后使用pure-pw mkdb更新数据库即可。

之后就可以轻松的使用FileZilla来登陆了(●ˇ∀ˇ●)

ftp_login.jpg

关于FTP启用TLS(即FTPS),请随意Google相关教程吧。比如:SETUP PURE-FTPD ON UBUNTU 16.04 LTS WITH SSL/TLS CERTIFICATES

从零开始自主搭建全套 Seedbox 环境 (1) - 下载篇

感谢 @MMRlove 以成本价为我提供了新的保种盒子(虽然还是100M的KS-2E),既然是新盒子的话,不如尝试下新的东西,然后试了下有名的QuickBox,然而以Apache作为WEB服务的配置让我这个习惯lnmp环境的感觉到了极大的不适,而且部分链接仍然使用ip的形式来访问(即使使用Let’s Encrypt脚本将其替换成域名形式,也是只是部分改成了<domain>:<port>,这样我没法用Cloudflare的CDN加速呀!!!),此外QuickBox对于系统的bash环境改动过大,个人不是很喜欢。而原先使用rtinst脚本因为大幅改进导致我再次使用极不习惯。此外两个脚本默认都是不带ipv6-patch的rutorrent,后面去重新打补丁编译更麻烦,不如自己直接配置方便。

系统配置及安装软件

  • Ubuntu 16.04
  • BBR
  • Nginx with module fancyindex
  • rTorrent + ruTorrent 0.9.4 with libtorrent 0.13.4 (with IPv6 patch and autodl-irssi)
  • Transmission
  • Deluge
  • qBitorrent
  • ffmpeg
  • webmin

这是一篇很长很长的文章,所以我还没写完Orz,另请注意,这是搭建我使用顺手的Seedbox环境,并不一定适用于所有用户。同时目前使用的一些资源来自多处,以后会慢慢整理成一个合适的repo放在Github上。

个人脚本 - Nyaa.si: Base32 to Hex

此脚本已不可用,Nyaa已经默认提供40位hex格式magent链接,相关转换思想实践仍可以使用,故保留。

关于HEX编码和Base32编码的讨论可见:https://ted423.bitcron.com/post/document/magnet

自从Nyaa.se关站后,复活的Nyaa.si对于以前的种子只保留了magnet链接(爬虫和数据库谁去下种子文件嘛,对吧)
然而由于BT网络的特点(保种性差),只有magnet链接的资源很难从peer结点中获取meta信息。对此,国内只有通过某些离线网盘的缓存备份的方式来恢复。

然而在直接复制的时候却发现了百度盘提示:暂时无法找到相关种子的信息。。。
cann't found torrent.jpg

对于新种资源还能理解(毕竟假离线),但是老种的甚至所有资源都应该不至于吧。所以看了下之前别人的提示,原来Nyaa.si提供的magnet链接是Base32格式的,而百度云使用的是Hex格式的。
那就简单了嘛。。写个脚本自动转成对应格式的就行了,果然能认出新的链接了。
can do it.jpg

补充,改成Hex格式的,对于某些bt软件获取meta信息更为有利(个人体感)

脚本代码如下,你也可以选择到 GreasyFork 中安装使用。

跨Pt站点高级搜索工具 Pt-Search

此工具已不维护,请转用 ronggang/PT-Plugins-Plus

工具介绍

基于TamperMonkey插件提供的GM_xmlhttpRequest方法,模拟本地用户请求,获取对应站点搜索结果,整理并在单页面中显示。并可依据搜索结果的发布日期、大小、做种人数、下载人数、完成数信息进行排序。
你无需像其他软件一样复制以及维护你的Cookies及登陆信息,也不需要考虑二次验证或者安全问题。打开浏览器,安装脚本就能使用。(这句话真像搞传销的)

本人暂时无支持国外PT站点搜索的计划,如果你有类似需求请使用该脚本:BT MetaSearch 作为替代。

页面: https://rhilip.github.io/PT-help/ptsearch
配套用户脚本: ptsearch.user.js
百度贴吧介绍页面:2018新年礼包:“Pt-Search”【pt吧】_百度贴吧
Issue反馈页面:Pt-search 反馈页面

搜索展示

51a87ecb0a46f21ffe9b04bdfd246b600d33ae17.jpg


使用说明

不想写(或见贴吧介绍页22楼他人“详细”使用介绍~)

  1. 安装 TamperMonkey 以及脚本文件(在未安装的情况下页面会提示安装)
  2. 页面右下角设置中配置搜索站点
  3. 输入关键词并点击搜索按钮(如果你不输入任何关键词的话,会默认读取种子列表页第一页全部种子)

二次开发

总要求

  1. 二次开发请在fork的基础上修改,并望能在测试无误情况下提交commit及pr。
  2. 禁止汉化展示页面ptsearch.html,禁止修改右上角版权信息及捐赠信息。

新增站点

你需要有一定的Javascript、jQuery、Bootstrap、Bootstrap Table的基础或阅读对应文档的能力。

  1. /json/site.json对应项中添加站点信息,其中,jyw列表存放教育网站点、gw列表存放国内公网站点、wz列表存放外网站点、bt列表存放BT站点。如果某个站点你想添加但不想启用,请放在disable列表中。

  2. 编辑ptsearch.user.js用户脚本。

  3. 在脚本开头添加connect字段允许脚本使用GM_xmlhttpRequests方法连接站点,如// @connect bt.byr.cn此条已不需要,目前脚本使用 // @connect * 来默认请求所有可能站点,但此条依据插件设置,需要用户在向目标站点请求时同意相关请求或直接点击允许该脚本全部网络请求。

  4. 在脚本// 自定义站点请添加到此处注释之后或其他合适位置添加对应站点解析方法。你需要从站点的种子列表中获取 站点简写(site)、种子名称(name)、种子链接(link)、发布日期(pubdate,以unix timestamp形式)、种子大小(size,以bytes计)、做种人数(seeders)、下载人数(leechers)、完成人数(completed) 信息。并构造字典使用BootstrapTable的原生方法table.bootstrapTable('append',param)更新表格(向表格添加新行),但更建议使用包装好的table_append(dict)方法,允许在插入表格信息的同时,将数据打log(依据用户设置)。

  5. 你可以使用writelog(string)方法在合适的解析位置打log。

  6. 请注意,使用CSS选择器定位DOM元素时,因注意因为用户等级(普通用户或管理组)或者设置(时间设置等)的原因,不同用户在搜索页面的dom结构可能有所不同(注意,此处指的是不受其他用户脚本影响的干净页面)。应尽可能使用class属性来定位元素或filter方法来定位元素,仅在无法实现以上定位方法时才使用children、parent、siblings、next、prev等方法。(注意,你不一并必须得使用jQuery进行操作,任何可以正确的定位信息的JS原生方法均可使用。)

  7. 请注意,在配置通用脚本时,应注意时间显示类型此选项会影响NexusPHP种子列表的DOM结构,如果错误,会导致时间结果显示为Invalid Date

  8. 一个典型的基础方法Get_Search_Page已经被定义,你应该使用该方法来获取搜索页面,而不是从GM_xmlhttpRequest开始,除非该方法不能满足你的需求。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
function Get_Search_Page(site, search_prefix, parser_func) {
if (search_site.indexOf(site) > -1) {
writelog("Start Searching in Site " + site + " .");
GM_xmlhttpRequest({
method: 'GET',
url: search_prefix + search_text,
onload: function(res) {
if (!config_not_check_login && res.finalUrl.search("login") > -1) {
writelog("May Not Login in Site " + site + ". With finalUrl: " + res.finalUrl);
} else {
writelog("Get Search Pages Success in Site " + site + ".");
var doc = (new DOMParser()).parseFromString(res.responseText, 'text/html');
var body = doc.querySelector("body");
var page = $(body); // 构造 jQuery 对象
try {
parser_func(res, doc, body, page);
writelog("End of Search in Site " + site + ".");
} catch (error) {
writelog("An error occurred when parser in Site " + site + ". With Error information: " + error + ". Please opening a issues to report at https://github.com/Rhilip/PT-help/issues/2");
}
}
},
onerror: function(res) {
writelog("An error occurred when searching in Site " + site + " .With finalUrl: " + res.finalUrl + ". Your computer may not be able to access this site.");
}
});
}
}

Get_Search_Page这个方法接收以下三个参数:

参数 意义
site 站点名称,用来检查用户是否启用
search_prefix 搜索链接前缀。脚本会自动在此后补加搜索关键词
parser_func 回调函数,用于解析对应页面并生成搜索信息交给bootstrapTable

从上面示例代码从可以看出,你可以看到,parser_func依次提供了4个结果,其中res是原始xmlhttpRequest对象,你可以在GM.xmlHttpRequest - GreaseSpot WikiResponse Object中了解该对象的具体信息,doc是原始的网页代码,body是从原始网页代码提取<body>中的信息,而page则是一个经过jQuery解析的body对象。关于解析搜索页的具体写法,你可以参照已有的其他解析方法来书写。

  1. 以下为一个经典的NexusPHP框架的PT站点解析方法(某一版),此方法已被定义为function NexusPHP(site, url_prefix, search_prefix, torrent_table_selector),对于魔改程度不大的NexusPHP站点你可以直接调用。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
function NexusPHP(site, search_prefix, torrent_table_selector) {
Get_Search_Page(site, search_prefix, function(res, doc, body, page) {
var url_prefix = /pt\.whu\.edu\.cn|whupt\.net|hudbt\.hust\.edu\.cn/.test(res.finalUrl) ? "" : (res.finalUrl.match(/(https?:\/\/[^\/]+?\/).+/) || ['', ''])[1];
writelog("Using The normal parser for NexusPHP in Site: " + site);
if (/没有种子|用准确的关键字重试/.test(res.responseText)) {
writelog("No any torrent find in Site " + site + ".");
return;
}
var tr_list = page.find(torrent_table_selector || "table.torrents:last > tbody > tr:gt(0)");
writelog("Get " + tr_list.length + " records in Site " + site + ".");
for (var i = 0; i < tr_list.length; i++) {
var torrent_data_raw = tr_list.eq(i);
var _tag_name = torrent_data_raw.find("a[href*='hit']");

// 确定日期tag,因用户在站点设置中配置及站点优惠信息的情况的存在,此处dom结构会有不同
// 此外多数站点对于 seeders, leechers, completed 没有额外的定位信息,故要依赖于正确的日期tag
var _tag_date, _date = "0000-00-00 00:00:00";
_tag_date = torrent_data_raw.find("> td").filter(function() {
return /(\d{4}-\d{2}-\d{2}[^\d]+?\d{2}:\d{2}:\d{2})|[分时天月年]/.test($(this).html());
}).last();
if (_tag_date && _tag_date.html()) {
_date = (_tag_date.html().match(time_regex) || ["", "0000-00-00 00:00:00"])[1].replace(/-(\d{2})[^\d]+?(\d{2}):/, "-$1 $2:");
}

var _tag_size = _tag_date.next("td");
var _tag_seeders = _tag_size.next("td"); // torrent_data_raw.find("a[href$='#seeders']")
var _tag_leechers = _tag_seeders.next("td"); // torrent_data_raw.find("a[href$='#leechers']")
var _tag_completed = _tag_leechers.next("td"); // torrent_data_raw.find("a[href^='viewsnatches']")

table_append({
"site": site,
"name": _tag_name.attr("title") || _tag_name.text(),
"link": url_prefix + _tag_name.attr("href"),
"pubdate": Date.parse(_date),
"size": FileSizetoLength(_tag_size.text()),
"seeders": _tag_seeders.text().replace(',', '') || 0, // 获取不到正常信息的时候置0
"leechers": _tag_leechers.text().replace(',', '') || 0,
"completed": _tag_completed.text().replace(',', '') || 0
});
}
});
}
  1. 所有的自定义解析模板应被定义为Site(site:str,search_prefix:str,?)方法,从而允许后期扩展以及调用。不建议将具体脚本调用方法以及方法定义混杂放置。

常见问题

Issue反馈页面上还有部分请移步阅读。

  • Q: 时间结果显示为Invalid Date?
  • A: 本人主要在时间显示类型为发生时间下进行脚本开发,仅对类型设置为已去时间(默认情况)进行了适配,如果存在问题,请在控制面板-网站设定-时间显示类型将其类型设置为发生时间。此外,部分站点设置请保持站点默认设置。

TIM截图20180108224504.jpg

对以下站点强制要求修改时间类型为发生时间:葡萄(SJTU)


  • Q: 一个站为什么只读取搜索结果中前50(100)个结果?
  • A: 本脚本只读取搜索结果的第一页并解析,关于站点默认显示的单页种子数,请在控制面板-网站设定-种子页面-每页种子数 中调整。如果已有结果仍不能搜索到合适结果(如在第二页等情况),请注意调整搜索关键词或跟在站点种子数设置。

  • Q: 为什么搜索结果中有条目信息不在我提供的关键词范围中?
  • A: 本工具直接调用目标站点的搜索功能,与你在对应站点使用相同关键词搜索结果相同。但只提取了主标题信息进行展示,可能存在关键词在副标题、正文中的情况。如果排除以上情况仍有误,建议咨询对应站点(比如使用了非SQL搜索的NPUPT)。

  • Q: 为什么不加站点全部勾选或者全部反选?为什么默认勾选的是BYR?为什么有的站点不能勾选?
  • A: 不想加,本人喜欢,就这样,请自己在右下角站点设置种勾选已启用的站点。此外,勾选全部站点会导致点击搜索瞬间卡住浏览器,所以你应该选择自己需要的站点进行搜索。不能勾选的站点是因为已有适配计划,但未完成站点解析工作,请等待脚本更新。

  • Q: 为什么不没有XXX站点搜索?
  • A: 没号。如果需要我添加请在确认不违反网站规则的情况下 携带网址、账号、密码、一定金额的红包 来告知本人。如果你具有一定Javascript基础,欢迎依据上文二次开发文档,对本脚本进行扩充。本人欢迎任何测试过能正常使用的pr。

  • Q: 为什么在Developer tools的Console面板中有这么多错误提示?
  • A: 脚本使用JQuery解析请求返回页面,在解析过程中会请求部分图片资源,但是多数站点对应资源都是用的是相对地址,这在脚本页面是不存在的,故返回了大量404错误,但这不影响脚本解析。你应该寻找非404错误。已更改解析方法,目前应该不会出现此问题。

  • Q: 怎么进行问题反馈?
  • A: 本人不接受使用方法咨询(这个脚本已经很傻瓜了,别让我瞧不起你),如果你确定该问题的产生原因是因为用户自解析脚本的原因。请在Github上对应repo上开issue并注明Log。

开发日志

  • 2018.01.07 确定思路可行,完成前端展示页面及配套脚本的初步开发
  • 2018.01.08 完成脚本开发,填充第一批站点(可以直接使用NexusPHP解析模板套用的站点)
  • 2018.01.13 修复上版(v20180111)中的一个错误,完善NexusPHP解析模板,完成第二批站点填充。脚本进入长期稳定支持期。
  • 2018.01.30 添加站点HDStreet(原蚂蚁类模板)的支持,但因目前就发现此站点使用该模板,暂时未定义成块方法。修改脚本解析方法,为先使用原生DOMParser()解析原始文本后获取<body>元素再使用jQuery继续解析。
  • 2018.03.26 修改NexusPHP原有解析方法中时间dom解析的方法,使之适配除葡萄(SJTU)以外的所有NexusPHP系站点;修改所有解析方法为块方法。
  • 2018.03.31 增加CCFBits站点

为OpenVZ构架VPS添加IPv6隧道

前段时间的黑五,没注意看不小心淘到了不支持native IPv6的VPS。
没办法╮(╯_╰)╭,只好自己去找方法支持。HE提供的IPv6 tunnel似乎就是最好的选择。

申请IPv6 tunnel

tunnelbroker.net 可以免费为具有公网IP的主机申请5个免费的IPv6隧道地址。
很简单的就不解释了,注册账号,然后点击“Create Regular Tunnel”就行。
如果不会的话,可以自己搜索或者看这篇文章 HE Tunnel Broker IPv4转v6隧道使用图解前面两项我就不做重点展开了

由于OpenVZ构架的限制,不能直接套用HE提供的配置信息。需要使用做其他设置。

启用TUN/TAP

到你VPS控制面板(如SolusVM)自行启用TUN/TAP。一般SolusVM都在这个位置。
turn_on_tuntap.jpg
(ps,如果没有的话,建议发tk问问客服,让他们帮你开。。

获取tb-tun并编译

TB-TUN is an tiny userspace program to build 6to4/tunnelbroker/ISATAP tunnel for Linux. The host kernel should have ipv6 stack and supports TUN/TAP. Generally the program should run with the root privilege.

以root用户直接运行以下命令

1
2
3
4
5
6
apt-get install iproute gcc git
cd /root
git clone https://github.com/acgrid/tb-tun.git
cd tb-tun
gcc tb_userspace.c -l pthread -o tb_userspace
mv tb_userspace /etc/

(简单解释下,安装依赖库,从github上获取源代码,编译,并将编译生成的tb_userspace移动到/etc目录下

创建自启动脚本

nano /etc/init.d/ipv6tb

然后将以下文本复制到文件中,记得将中括号中的内容换成你申请隧道后显示的信息,然后保存退出。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
#! /bin/sh

### BEGIN INIT INFO
# Provides: ipv6
# Required-Start: $local_fs $all
# Required-Stop: $local_fs $network
# Default-Start: 2 3 4 5
# Default-Stop: 0 1 6
# Short-Description: starts the ipv6 tunnel
# Description: ipv6 tunnel start-stop-daemon
### END INIT INFO

# /etc/init.d/ipv6tb

touch /var/lock/ipv6tb

case "$1" in
start)
echo "Starting ipv6tb "
setsid /etc/tb_userspace tb [Server IPv4 Address] [Client IPv4 Address] sit > /dev/null 2>&1 &
sleep 3s # ugly, but doesn't seem to work at startup otherwise
ifconfig tb up
ifconfig tb inet6 add [Routed /64] # Add as many of these as you need from your routed /64 allocation
ifconfig tb mtu 1480
route -A inet6 add ::/0 dev tb
route -A inet6 del ::/0 dev venet0
;;
stop)
echo "Stopping ipv6tb"
ifconfig tb down
route -A inet6 del ::/0 dev tb
killall tb_userspace
;;
*)
echo "Usage: /etc/init.d/ipv6tb {start|stop}"
exit 1
;;
esac

exit 0

为该sh脚本添加可执行权限,以及自启动。

1
2
chmod 755 /etc/init.d/ipv6tb
update-rc.d ipv6tb defaults

手动启动

1
/etc/init.d/ipv6tb start

测试

VPS到国外国内延迟测试

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
root@keepservice:~# ping6 -c 5 www.goolge.com
PING www.goolge.com(ord38s04-in-x03.1e100.net) 56 data bytes
64 bytes from ord38s04-in-x03.1e100.net: icmp_seq=1 ttl=54 time=113 ms
64 bytes from ord38s04-in-x03.1e100.net: icmp_seq=2 ttl=54 time=113 ms
64 bytes from ord38s04-in-x03.1e100.net: icmp_seq=3 ttl=54 time=134 ms
64 bytes from ord38s04-in-x03.1e100.net: icmp_seq=4 ttl=54 time=113 ms
64 bytes from ord38s04-in-x03.1e100.net: icmp_seq=5 ttl=54 time=113 ms

--- www.goolge.com ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4003ms
rtt min/avg/max/mdev = 113.076/117.559/134.913/8.677 ms
root@keepservice:~# ping6 -c 5 bt.byr.cn
PING bt.byr.cn(2001:da8:215:4078:250:56ff:fe97:654d) 56 data bytes
64 bytes from 2001:da8:215:4078:250:56ff:fe97:654d: icmp_seq=1 ttl=51 time=219 ms
64 bytes from 2001:da8:215:4078:250:56ff:fe97:654d: icmp_seq=2 ttl=51 time=219 ms
64 bytes from 2001:da8:215:4078:250:56ff:fe97:654d: icmp_seq=3 ttl=51 time=219 ms
64 bytes from 2001:da8:215:4078:250:56ff:fe97:654d: icmp_seq=4 ttl=51 time=219 ms
64 bytes from 2001:da8:215:4078:250:56ff:fe97:654d: icmp_seq=5 ttl=51 time=265 ms

--- bt.byr.cn ping statistics ---
5 packets transmitted, 5 received, 0% packet loss, time 4004ms
rtt min/avg/max/mdev = 219.121/228.421/265.192/18.390 ms

国内教育网延迟测试
ping_ipv6_tunnel_test.jpg
(似乎处于正常水平233333

从又一家教育网PT站“品知人大”被关闭说起...

说在最前面,本文请不要太当真。谢绝转载,拒绝搞事!


前序

继北理极速关闭后,又一教育网PT站品知人大被关闭。。。回顾北理极速,也是先维护关站,然后拖成无限期关闭的套路。再往前回顾一点,西南交大的蚂蚁PT因为前负责人离校、后续维护缺失的现状宣布关站;天津大学的北洋园自6月份因为服务器硬件损坏的原因一直停摆至今(至今无恢复消息,有内部消息也不告诉你们)。更久远的还有异度空间,北大博雅,北科52v6,重大民主湖,西交菩提,中石大(华北)光华pt等等,一一消逝在历史的潮流中。

TIM截图20171102233635.jpg

存活下来的教育网PT站点似乎日子也过的紧紧巴巴的。

  • 某维再创年度最长关站时间的记录,以前固定在版权月关站,现在又增加了一个开会期间,真不愧是一年关2个月的大站。
  • 北邮人虽然似乎一直没事,但是我想经历过 2017年4月4日晚,5月25日晚 的孩子应该也知道些什么。(啥,不知道??? 不知道的可以看看知乎这两个帖子:如何评价北邮某机房在4月4日发生的起火事件?如何评价 2017 年 5 月 25 日晚北邮人论坛关闭外网访问的事? )。说起来,5月25号那次我还想发文纪念的那,没想到等我自习回来事件就已经反转了2333
    TIM截图20171103075518.jpg
  • 蒲公英也曾在去年年末的时候因为背靠的三四升级服务器的原因向站内成员寻求解决方法,但索性已经顺利解决。蒲公英PT现状说明
  • 还有哈工大的清影PT,自去年年末因为作弊事件的原因宣布无限期关站,磕磕绊绊大半年后修改自身为国内教育网PT站中第一也是唯一的Ratio制站点。但是却关了IPv4的访问,至今无法正常访问。(更: 我大清乙烷~)
  • 再往前追溯一点,去年6月因为水灾原因导致关站的蝴蝶,复站过程艰辛的一塌糊涂。但即使恢复,也再不复之前的盛况了。

TIM截图20171103075248.jpg
TIM截图20171103075303.jpg
TIM截图20171103075358.jpg

缘起

关于PT站点的灰色性,我觉得无意义在本文中反反复复的说明,逼乎上自有正版侠在各个pt站点关站的回答(比如上次北邮人关站风波、比如What.CD关站讨论、又如这次知品人大的关站贴)中叫嚣“教育网、PT不是法外之地”、“授权问题”,看看自然就知道了,公网站点风险都存在,更何况寄生于(挂靠于)高校这种体制内的资源分享站点那?
国家打击盗版,或者说控制思想的风向标这种大方向的,我也觉得自身不具有讨论的背景。自己看着懂就行。

维持稳定的大前提下,一刀切的关站似乎成为了最好的解决方法。此处就可以这样不怀好意的认为(或者说揣测)。更何况近期关闭的品知、极速、以及差点关门的北邮人,均是含有BBS(论坛)的成分在内,其帖子的内容万一跳脱了上位者那根看不见的红线,其结果也就无法想象。(是的,你无法想想热血的大学生们会发出怎样的言论)

但是为什么还会有这种站点的需求,或者说为什么同学们会如此需要这类站点,以至于但它失去的时候如此祭奠是一个很重要的问题?

这里估计要从历史和现状说起。

教育网Pt站点的前身是和公网的有些不同,在于其早些是从校内FTP转型而来的。但随着服务器逐渐老化,以及pt概念在国内的传播,才逐渐转为PT的形式,顺带将资源以及版权从单一的ftp服务器责任人转化分散到pt站点的使用者上(避风港原则)。

而于此同时,仍有多数高校仍然按照校园网使用流量计费,且价格高昂。

所以教育网Pt站点以其以通过IPv6或者内网IPv4之类不计费通道成为获取资源(如高质量电影、大体积游戏、教育资料等)的另一种途径。

未来

逆时代潮流重新开的教育网Pt站点屈指可数,再此不一一列举。但我国的基本国情指出了我国的基本矛盾–> 人民日益增长的美好生活需要和不平衡不充分的发展之间的矛盾。套用到大学生头上,似乎可以这么改写 学生日益增长的网络流量需要和不充分不便宜的校园网流量之间的矛盾

所以现阶段,我们可以看到。随着部分站点的关站,需求人口自然会往其他站点转移。如北理工的极速之星关站后,多数转战NPU(因为该站可以直接使用教育网邮箱在教育网IPv6段下注册),目前该站的北理工用户已经远远超过其他多数学校,只落后于NPU立足的西北工业大学。

我个人觉得这种现象会导致大站更强,因为教育网pt与公网站点不同的一点在于多数用户(小白)更倾向于因为下载速度快的原因来选择pt站点,而不是因为公网的有圆盘首发或者高质量int组。

此外,教育网PT站点完全地依赖于目前免费的IPv6资源。随着我国加快IPv6网络建设,开始要求网络提供商及网络内容服务商支持IPv6。所以不能排除以后,各校园对IPv6开始计费的可能。到那时,可能对所有教育网PT站点都是毁灭性的打击。

Proxifier的IPv6代理相关

Proxifier是与 ProxyCap 一样是一款及其优秀的代理软件。相比于国内的一些垃圾代理软件,如 SSTap-beta 等来说,在IPv6下支援情况良好。

题外话

  • 国内很多软件都很少考虑IPv6 Only环境下的使用。(即使有果爹的政策大棒,但是,依然。。。。。。
  • 关于Proxifier与ProxyCap的具体差别,可以参考他人文章: 简谈我眼中的proxycap和proxifier优缺点。虽然只是一家之言,但纠于两个软件均已稳定,仍可以作为重要参考。

故,在同时使用ProxyCap与Proxifier一段时间后,我推荐使用Proxifier作为系统上主要的代理软件(如果你配置了路由器策略,当我什么都没说)。即使Proxifier不支持UDP、ICMP代理,但是相对与ProxyCap较为繁琐的软件添加、没有较合适的破解版或中文版,入手感觉及其良好。

IPv6化改造部分应用

因为前段时间的重大会议,本人主服务器的IPv4被屏蔽了。导致某个国内主机长时间无法与后端主服务器(国外)数据库连接。(真是个杯具的故事)
但是,虽然IPv4数据包在回国路由上被丢包,但是IPv6的数据包并没有被阻断。于是对该国内主机上的部分应用进行IPv6改造使其正常连接后端数据库。

一、后端数据库改造

原先后端使用的数据库MySQL版本为5.5,在未指定bind-address的情况下,默认监听的是0.0.0.0)。在思考后,选择将数据库直接升级到5.7,在5.6.6之后版本中,这个值默认设置成 *,即同时监听IPv4和IPv6连接。
(参见 https://dev.mysql.com/doc/refman/5.6/en/server-options.html#option_mysqld_bind-address )

–bind-address=addr Type Default
Permitted Values (<= 5.6.5) string 0.0.0.0
Permitted Values (>= 5.6.6) string *

具体的升级过程就不在此唠述,因为,本人偷懒使用了lnmp.org自带的升级工具。

二、SSpanel后端改造

SSpanel后端使用cymysql库与主服务器通讯。但是这个库默认不支持以IPv6的形式与数据库进行连接。如果以IPv6的形式连接数据库会报出如下错误

1
2
3
4
5
6
7
8
9
10
11
>>> import cymysql
>>> conn = cymysql.connect(host='::1', user='root', passwd='', db='database_name', charset='utf8')
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "/usr/local/lib/python2.7/dist-packages/cymysql/__init__.py", line 85, in Connect
return Connection(*args, **kwargs)
File "/usr/local/lib/python2.7/dist-packages/cymysql/connections.py", line 245, in __init__
self._connect()
File "/usr/local/lib/python2.7/dist-packages/cymysql/connections.py", line 410, in _connect
raise OperationalError(2003, "Can't connect to MySQL server on %r (%s)" % (self.host, e.args[0]))
cymysql.err.OperationalError: (2003, "Can't connect to MySQL server on '::1' (-9)")

但是好在 CyMySQL 其实是 PyMySQL 的一个分支,而PyMySQL在这个issue Support IPv6 #118 中已经修复了这个问题。(所以为什么不直接用pymysql嘛,所以为什么cymysql到现在还有没修这个问题嘛。。。。

补:在提交issues To support IPv6 后,CyMySQL v0.9.2已经可以使用IPv6的形式连接客户端。(真速度…..)


那么就自己动手吧。根据PyMySQL中相关issues和commit,修改上述报错中最后提示的/usr/local/lib/python2.7/dist-packages/cymysql/connections.py文件。
做如下patch

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
diff -Naur cymysql/connections.py cymysql-ipv6/connections.py
--- cymysql/connections.py 2017-06-10 03:51:56.000000000 -0400
+++ cymysql-ipv6/connections.py 2017-10-27 05:12:51.125249151 -0400
@@ -398,13 +398,14 @@
self.host_info = "Localhost via UNIX socket"
if DEBUG: print('connected using unix_socket')
else:
- sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
- t = sock.gettimeout()
- sock.settimeout(self.connect_timeout)
- sock.connect((self.host, self.port))
+ sock = socket.create_connection((self.host, self.port), self.connect_timeout)
self.host_info = "socket %s:%d" % (self.host, self.port)
if DEBUG: print('connected using socket')
- sock.settimeout(t)
except socket.error as e:
sock.close()
raise OperationalError(2003, "Can't connect to MySQL server on %r (%s)" % (self.host, e.args[0]))

三、ServerStatus监控脚本改造

原来使用的服务器监控脚本和cymysql的一样情况。虽然脚本的部分地方考虑到了IPv6的情况。如(在这以将ServerStatus中文化的最初repo tenyue/ServerStatus 为例说明):
在监控脚本的L150中,和cymysql一样使用了socket.socket(socket.AF_INET, socket.SOCK_STREAM)这种只支持IPv4形式与服务器通信。

1
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)

但是很奇怪的是这个监控脚本get_network()中判断IPv4、IPv6连接的逻辑又是这样的:如果脚本以IPv4的形式与服务器通信,那么这直接默认监控的主机的IPv4是正常的,那么get_network()接收的参数ip_version就只有6,即只检查监控主机的IPv6是否正常。
没办法,自己fork -> Rhilip/ServerStatus 修改吧。而且个人觉得tenyue的部分修改不这么好,比如:

  • 移除了IPv6的支持(其实是前端不显示)
  • 在添加load 1,5,15的情况下未考虑向前兼容。如果前端接收的字段仍为原先的load,但是后端更新后变成 load_1,load_5,load_15。丢失了原先代表load 1 的load字段。
  • 原有脚本的是tab缩进的,改成4空格23333

Flask

这个相对简单,只要指定host是 ::就行。

1
2
3
4
5
6
7
8
9
10
from flask import Flask
app = Flask(__name__)

@app.route('/')
def hello():
return "Hello world~"


if __name__ == '__main__':
app.run(host="::")

【少女前线】 纲领活动指定关卡整理

仅供参考

E -> 紧急 N -> 夜战

2018.5 暗影密令

阶段 提示文本 对应关卡
第一阶 我很感谢她们替人类承受的责任 5-4E
第二阶 让这段记忆成为你的力量,令你变得再强大一点吧…… 6-4E
第三阶 ……是我们最后的好运,抓住机会吧 3-3N

2018.2 花灯会

阶段 提示文本 对应关卡
第一阶 AR15:我在上演……一场令人感动的重逢。 6-3
第二阶 格琳:刚才我去总部进货时看到的,于是把工作就包了下来。 3-1E
第三阶 M4A1:别……别压着我呀,SOP Ⅱ,你太重了! 4-2E

2017.12 白雪童话

阶段 提示文本 对应关卡
第一阶 克鲁格:安全,信任,只是相对而言 2-1
第二阶 M9:我们是可爱的民用人形,遇到人类时卖个萌就行了! 2-4N
第三阶 - 3-4E

2017.10 Moon·金色月夕

阶段 提示文本 对应关卡
第一阶 炼金术士:早安啊,格里芬的各位 6-6
第二阶 ??:我是铁血的暗杀者 4-1N
第三阶 97式霰:喂,NZ,你的新裙子又到啦!这回的图案是– 5-2N

BYRBT辅助脚本 · Tree View

那是很久很久之前,我在Greasymonkey上随意的找着脚本的时候(那时候应该还没分出Sleazyfork吧),我突然找到了一个这样的脚本:dmhy tree view ,它的功能是将动漫花园的列表状文件列表转换为树状图。。

于是就照搬着写了个用在byr上(主要是看隔壁NPU的觉得很新鲜馁~
脚本地址:Byrbt - Tree View.user.js

脚本展示:
TIM截图20170930225618.jpg