<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0"
	xmlns:content="http://purl.org/rss/1.0/modules/content/"
	xmlns:wfw="http://wellformedweb.org/CommentAPI/"
	xmlns:dc="http://purl.org/dc/elements/1.1/"
	xmlns:atom="http://www.w3.org/2005/Atom"
	xmlns:sy="http://purl.org/rss/1.0/modules/syndication/"
	xmlns:slash="http://purl.org/rss/1.0/modules/slash/"
	>

<channel>
	<title>Soul Of Free Loop &#187; 网络</title>
	<atom:link href="https://zohead.com/archives/category/network/feed/" rel="self" type="application/rss+xml" />
	<link>https://zohead.com</link>
	<description>Uranus Zhou&#039;s Blog</description>
	<lastBuildDate>Sat, 19 Jul 2025 15:42:46 +0000</lastBuildDate>
	<language>zh-CN</language>
		<sy:updatePeriod>hourly</sy:updatePeriod>
		<sy:updateFrequency>1</sy:updateFrequency>
	<generator>http://wordpress.org/?v=3.8</generator>
	<item>
		<title>特斯拉听播客的几种姿势</title>
		<link>https://zohead.com/archives/tesla-podcast/</link>
		<comments>https://zohead.com/archives/tesla-podcast/#comments</comments>
		<pubDate>Sun, 13 Aug 2023 08:33:05 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[Cloud Caster]]></category>
		<category><![CDATA[Model Y]]></category>
		<category><![CDATA[Podgrab]]></category>
		<category><![CDATA[Podyssey]]></category>
		<category><![CDATA[RSS]]></category>
		<category><![CDATA[喜马拉雅]]></category>
		<category><![CDATA[播客]]></category>
		<category><![CDATA[特斯拉]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1860</guid>
		<description><![CDATA[去年购买的特斯拉 Model Y 标准续航版，目前已经开了差不多 16000 公里，家人用下来总体还是比较满意的。为了方便实时路况导航和听歌之类的，我还订购了 ¥9.99 / 月的高级车载娱乐服务包。一般如果开车的路程稍微长一点，我都习惯听一听订阅的各种播客来打发时间。 自带喜马拉雅 特斯拉默认只能用自带的喜马拉雅来听播客，虽然喜马拉雅的特斯拉车机版本已经比 Android 版本的喜马拉雅干净清爽多了，不过喜马拉雅也有一些限制，主要是不能自己添加 RSS 订阅源，另外基本没有英文的播客节目，有一些不太和谐的中文播客也没有，或者是只有中国版。 当然如果你只是需要在路上简单听一些常见的中文播客，那 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>去年购买的特斯拉 Model Y 标准续航版，目前已经开了差不多 16000 公里，家人用下来总体还是比较满意的。为了方便实时路况导航和听歌之类的，我还订购了 ¥9.99 / 月的高级车载娱乐服务包。一般如果开车的路程稍微长一点，我都习惯听一听订阅的各种播客来打发时间。</p>
<h2 id="ximalaya">自带喜马拉雅</h2>
<p>特斯拉默认只能用自带的喜马拉雅来听播客，虽然喜马拉雅的特斯拉车机版本已经比 Android 版本的喜马拉雅干净清爽多了，不过喜马拉雅也有一些限制，主要是不能自己添加 RSS 订阅源，另外基本没有英文的播客节目，有一些不太和谐的中文播客也没有，或者是只有中国版。</p>
<p>当然如果你只是需要在路上简单听一些常见的中文播客，那特斯拉自带的喜马拉雅应该也比较适合了。</p>
<h2 id="third-podcast">第三方播客服务</h2>
<p>不过还好特斯拉车机还是带了一个还算能用的浏览器，我们就可以通过访问其它播客服务网站来自由听播客了，主要需求还是：</p>
<ul>
<li>支持自行添加播客 RSS 订阅源；</li>
<li>由于直接使用特斯拉自带的流量卡，需要国内能直接访问，也不想在特斯拉上折腾翻墙了；</li>
<li>播客节目的播放历史、进度最好支持在云端保存，这样在其它设备上访问播客服务网站或使用相应的 App 就能同步使用了。</li>
</ul>
<p>目前特斯拉自带的 QQ 音乐、网易云音乐、喜马拉雅 等车载娱乐服务在进行账户登录时，都需要对应的手机端 App 来扫码登录。如果在特斯拉上通过浏览器访问播客服务，也需要考虑账户登录的问题。由于特斯拉浏览器自带的输入法功能有限，也有点难用，使用第三方播客服务进行输入用户名和密码等登录操作最好也别太复杂。</p>
<h3 id="cloud-caster">Cloud Caster</h3>
<p><a href="http://www.cloud-caster.com/">Cloud Caster</a> 本来是我首选的播客服务，基本能满足上面所有的需求，Cloud Caster 没有移动端 App，只要有浏览器就可以访问收听播客，播放列表和进度也能通过云端同步。</p>
<p>Cloud Caster 主要专注于收听播客功能，没有提供播客托管以及社区、评论之类乱七八糟的功能，其界面也比较清淡克制：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737370805/cloud-caster.png" alt="Cloud Caster"></p>
<p>不过像上面截图的清淡克制效果也是有前提的：浏览器需要开启 Ad Block 之类的广告过滤功能，否则页面的左边、右边以及下方都有显眼的广告。当然，目前 Cloud Caster 基本是由网站主个人维护的，也没有什么商业支持，因此网站上加上这些广告来覆盖服务器支出我觉得也很正常。</p>
<p>特斯拉自带的浏览器并不支持像广告过滤之类的扩展功能，因此如果要在车上使用 Cloud Caster 就必须忍受广告了。如果你喜欢 Cloud Caster 的服务，可以通过他们的 <a href="http://www.cloud-caster.com/Home/SupportUs">捐助</a> 页面来支持一下咯。</p>
<p>Cloud Caster 只支持网站的用户名和密码登录，登录时选中记住用户选项，也可以保存用户会话一段时间，偶尔需要输入用户名和密码重新登录也还能接受。</p>
<p>另外 Cloud Caster 目前也有点小问题，主要体现在某些像 <a href="https://xyzfm.space/">小宇宙播客</a> 之类的 RSS 源可能无法正常解析，或者无法更新最新的节目，所以我也基本是当作备用。</p>
<h3 id="podyssey">Podyssey</h3>
<p><a href="https://podyssey.fm/">Podyssey</a> 是我在发现 Cloud Caster 的问题后发现的另一个播客服务，Podyssey 主要特点在于提供了一个给众多用户发现和讨论 Podcast 播客节目的平台，其首页就是 Discover 发现界面：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737442881/podyssey-discover.png" alt="Podyssey Discover"></p>
<p>Podyssey 也为 Podcast 播客创作者提供服务，创作者可以添加和分享自己录制的播客节目，并与收听者进行互动，不过看起来并没有播客音视频的托管服务。</p>
<p>Podyssey 也有 Android 和苹果的移动端 App，不过还好都没有广告，虽然界面看起来都稍微有点简陋：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737442882/podyssey-podcast.png" alt="Podyssey 播客"></p>
<p>使用一段时间之后我发现，Podyssey 的主要问题在于无法通过云端保存播客节目的播放进度，无论 App 端还是 Web 端，播放进度都是保存在客户端本地的，当然手机 App 端的播放进度也无法同步到 Web 浏览器端，不过这个其实对我来说影响倒是不大。</p>
<p>然而另外一个问题就稍微有点不能接受，虽然我订阅的播客基本都能在 Podyssey 中找到，但 Podyssey 其实并没有提供通过 RSS 源来订阅播客的功能，这样就显得稍微有点封闭了。</p>
<p>Podyssey 还存在用户登录方式比较奇葩的问题，默认只能输入邮箱地址登录，然后需要在收到的邮件里点击 Podyssey 发送的临时登录地址就可以自动登录。</p>
<p>这样在电脑上当然没什么问题，不过在车上登录就需要多一步把手机邮箱里的临时登录地址发到车上的步骤，登录操作虽然只需要偶尔做一下，但在特斯拉上使用 Podyssey 还是显得有点麻烦的，就继续当备用服务了。</p>
<h2 id="podgrab">自建 Podgrab</h2>
<p>用了一段时间上面的 Cloud Caster、Podyssey 还有其它第三方播客服务，我发现这些服务基本都有一些或大或小的限制或问题，最终还是倾向自建 Podcast 播客服务，搜索了一番之后，还是找到了 <a href="https://github.com/akhilrex/podgrab">Podgrab</a> 这个开源项目。</p>
<p>Podgrab 项目的官方定位就是 <strong>self-hosted podcast manager</strong>，支持通过 RSS 源来订阅播客（也可以直接搜索订阅 iTunes 上的播客），当然顺带也支持 OPML 的导入和导出，还可以自动下载新的播客节目并进行管理，并附带了一个比较简单的播客播放器。Podgrab 还可以对播客节目进行标记，方便后续进行快速筛选查看。</p>
<p>由于 Podgrab 后台程序是由 Golang 编写的，因此天然就可以支持跨平台使用。如果你的服务器或者 NAS 存储支持 Docker 功能，那可以直接使用下面官方的镜像地址进行安装：</p>
<p><a href="https://hub.docker.com/r/akhilrex/podgrab/">https://hub.docker.com/r/akhilrex/podgrab/</a></p>
<p>我为了使用方便，就直接在目前网站所在的 VPS 服务器上运行的，不过由于没有自带 Docker 支持，就先在 Linux 系统上编译好之后上传到 VPS 系统里运行了。Podgrab 的编译操作也很简单，只要安装了 Golang 环境，按照官方的 <a href="https://github.com/akhilrex/podgrab/blob/master/docs/ubuntu-install.md">Building from source / Ubuntu Installation Guide</a> 文章来编译应该就没什么问题。</p>
<p>VPS 服务器上最好单独指定一个目录来存放 Podgrab 程序和相关的下载文件，例如我建立了一个 <code>/usr/local/bin/podgrab</code> 目录，然后把编译好的 <code>podgrab</code> 可执行程序文件也上传到这个目录里。</p>
<p>其次是最重要的 Podgrab 配置文件，在刚才的目录下新建一个 <code>.env</code> 环境变量配置文件：</p>
<pre class="brush: bash; title: ; notranslate">
root@debian:/usr/local/bin/podgrab# cat &gt; .env 
CONFIG=.
DATA=./assets
CHECK_FREQUENCY=30
PASSWORD=XXXXX
PORT=8080
</pre>
<p>Podgrab 项目主页也有环境变量的说明，主要是：</p>
<ul>
<li><code>CHECK_FREQUENCY</code>：检查新播客节目的间隔时间，以分钟为单位；</li>
<li><code>PASSWORD</code>：设置密码认证，默认为空就是不需要密码认证，如果像我一样需要在 VPS 服务器上运行 Podgrab，强烈建议启用密码认证；</li>
<li><code>PORT</code>：Podgrab 的监听端口，默认为 <code>8080</code>。</li>
</ul>
<p>配置完成之后，就可以直接运行 <code>./podgrab</code> 命令启动 Podgrab 了，你也可以根据需要按照官方的说明自己配置成服务方式来运行哦。</p>
<p>最后使用 <code>http://host:8800</code>（假设用的就是默认端口）就可以直接访问 Podgrab 管理界面了，如果启用了密码认证，需要注意用户名是固定的 <code>podgrab</code>。</p>
<p>Podgrab 默认的深色风格界面还是挺清爽耐看的，而且和特斯拉的车机系统界面也比较搭，首页可以选择以网格或列表的形式显示：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737442877/podgrab.png" alt="Podgrab"></p>
<p>节目列表界面也就是显示标题、描述以及一些操作按钮：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737442878/podgrab-episode.png" alt="Podgrab 节目列表"></p>
<p>由于我只需要能在特斯拉的浏览器打开 Podgrab 听播客，而且自带了高级车载娱乐服务包，完全可以在行驶途中使用车载流量播放播客节目，因此也基本不需要 Podgrab 的播客节目下载功能，为了节省 VPS 服务器的存储空间，我在 Podgrab 的设置界面把以下选项也关闭了：</p>
<ul>
<li>Download episodes whenever new podcast is added</li>
<li>Automatically download new episodes to the disk</li>
</ul>
<p>这样我在订阅了 27 个播客，并默认缓存所有节目信息后，VPS 服务器的存储空间也就占用了不到 30MB。</p>
<p>Podgrab 自带的播放器界面看起来就稍微有点简陋，不过在车上也够用了：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737442880/podgrab-player.png" alt="Podgrab 播放器"></p>
<p>需要说明的是虽然 Podgrab 内播客节目的播放完成状态是保存在服务器上的，无论在什么客户端使用浏览器打开 Podgrab 看到的播放是否状态是自动同步的；但是具体某个节目的临时播放进度是保存在客户端浏览器本地的，不过实际用起来也基本没什么影响，而且得益于 Podgrab 项目是开源的，如果需要在服务器上保存节目的播放进度也可以自己修改代码来实现哦。</p>
<p>另外即使开启了密码认证，我们也可以使用 <code>http://podgrab:PASSWORD@host:8800</code> 形式的地址直接指定用户名和密码来访问 Podgrab，然后我们把这个地址添加到特斯拉浏览器的收藏夹，这样就能实现打开浏览器点击一下就进入 Podgrab 了，用起来也比 Cloud Caster 和 Podyssey 更加便利了。</p>
<p>综合对比下来，目前看起来还是 Podgrab 自建的方式更符合我的需求，我和夫人在驾车时试用 Cloud Caster 和 Podyssey 一段时间后，现在都换 Podgrab 来收听播客了。Podgrab 除了因为 VPS 服务器在国外加载节目列表偶尔稍等慢一点之外，用起来还是很顺畅的，后面有空了我再改一下 Podgrab 代码来实现保存播放进度到服务器，最后祝大家玩的开心哦。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/tesla-podcast/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>香橙派R1 Plus LTS软路由体验</title>
		<link>https://zohead.com/archives/r1-plus-lts/</link>
		<comments>https://zohead.com/archives/r1-plus-lts/#comments</comments>
		<pubDate>Sun, 21 Aug 2022 12:32:40 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[数码]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[OpenWRT]]></category>
		<category><![CDATA[R1 Plus LTS]]></category>
		<category><![CDATA[红米]]></category>
		<category><![CDATA[路由器]]></category>
		<category><![CDATA[香橙派]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1768</guid>
		<description><![CDATA[去年家里装修好之后为了一步到位就打算把无线网络也升级到 WiFi 6 了，不过可惜买的时候没注意，选了有点坑的 红米 AX3000 路由器（不是老的红米 AX6，这款的实际产品型号为：RA81）。这款路由器用的是高通 IPQ5000 处理器，集成 256MB 内存，WiFi 6 功能用起来虽然也没有太大的问题，只是开机运行时间久了总会有卡卡的感觉，最主要小米的魔改系统没有给 SSH 权限，而网上其它小米路由器的破解 SSH 方法对这款路由器并不起作用。 最近我想了想还是准备上个采用标准 OpenWRT 系统的软路由，红米 AX3000 路由器就准备只用来发射 WiFi 信号了。软路由原本考虑很 [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>去年家里装修好之后为了一步到位就打算把无线网络也升级到 WiFi 6 了，不过可惜买的时候没注意，选了有点坑的 <a href="https://www.mi.com/shop/buy/detail?product_id=14538" target="_blank">红米 AX3000 路由器</a>（不是老的红米 AX6，这款的实际产品型号为：RA81）。这款路由器用的是高通 IPQ5000 处理器，集成 256MB 内存，WiFi 6 功能用起来虽然也没有太大的问题，只是开机运行时间久了总会有卡卡的感觉，最主要小米的魔改系统没有给 SSH 权限，而网上其它小米路由器的破解 SSH 方法对这款路由器并不起作用。</p>
<p>最近我想了想还是准备上个采用标准 OpenWRT 系统的软路由，红米 AX3000 路由器就准备只用来发射 WiFi 信号了。软路由原本考虑很多网友用过的友善 <a href="https://www.friendlyelec.com/index.php?route=product/product&amp;path=69&amp;product_id=282" target="_blank">NanoPi R2S</a>，只是最近这款软路由的溢价实在有点多，一番了解之后还是定下了迅龙推出的与 R2S 配置基本相同的 <a href="http://www.orangepi.cn/html/hardWare/computerAndMicrocontrollers/details/Orange-Pi-R1-Plus-LTS-Router.html" target="_blank">Orange Pi R1 Plus LTS</a> 软路由。</p>
<h2 id="intro">介绍</h2>
<p>R1 Plus LTS 软路由的基本硬件参数如下：</p>
<table>
<thead>
<tr>
<th>项目</th>
<th>内容</th>
</tr>
</thead>
<tbody>
<tr>
<td>CPU</td>
<td>Rockchip RK3328</td>
</tr>
<tr>
<td>GPU</td>
<td>Mali-450MP2</td>
</tr>
<tr>
<td>内存</td>
<td>1GB LPDDR3</td>
</tr>
<tr>
<td>WAN</td>
<td>裕太微 YT8531C 10M/100M/1000M 以太网</td>
</tr>
<tr>
<td>LAN</td>
<td>Realtek RTL8153B 10M/100M/1000M USB 以太网</td>
</tr>
<tr>
<td>尺寸</td>
<td>63mm X 60.6mm X 27.25mm</td>
</tr>
<tr>
<td>重量</td>
<td>175g</td>
</tr>
</tbody>
</table>
<p>其实香橙派之前还出了一款 R1 Plus 软路由，与我买的 R1 Plus LTS 区别也很小：</p>
<ul>
<li>R1 Plus 用的是 1GB DDR4 内存；</li>
<li>R1 Plus 的 WAN 口使用的是 Realtek RTL8211E PHY。</li>
</ul>
<p>所以 R1 Plus LTS 相当于是 R1 Plus 的低配版，只是可能由于芯片短缺等原因 R1 Plus 现在也基本上买不到了。</p>
<p>我购买的 R1 Plus LTS 软路由是自带官方金属外壳的，而且开发板本身都已经装好固定了的，因此主板本身我也就没拆了，看看软路由的外观：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737442932/r1pluslts-appearance.jpg" alt="R1 Plus LTS 软路由"></p>
<p>前面是 TF 卡槽以及 SYS、LAN、WAN 指示灯，后面就是供电接口以及两个网口了。</p>
<p>本来打算用闲置的华为手机充电器，又考虑到放在家里需要长期稳定运行，我也顺便买了官方的 5V 3A USB Type-C 电源适配器：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737442932/r1pluslts-charger.jpg" alt="R1 Plus LTS 电源适配器"></p>
<h2 id="system">系统</h2>
<p>我找了一张老的 8GB TF 卡做系统盘，为了稳定也用的是官方提供的最新 OpenWrt 21.02.1 r16325-88151b8303 版本系统，也不考虑第三方固件提供的各种花里胡哨的功能了。</p>
<p>为了方便我也没有使用官方用户手册里推荐的 <code>Win32Diskimager</code> 或者 <code>balenaEtcher</code> 之类的工具来烧写镜像，直接用 Linux 自带的 <code>dd</code> 命令进行烧写：</p>
<blockquote>
<p><strong>备注</strong></p>
<p>我的笔记本自带了 PCIe 的读卡器，所以这里的 <code>dd</code> 命令写的是 <code>/dev/mmcblk0</code> 设备，如果用的是 USB 读卡器，应该就要换成 <code>/dev/sdb</code> 之类的设备。</p>
</blockquote>
<pre class="brush: bash; title: ; notranslate">
~# dd if=openwrt-rockchip-armv8-xunlong_orangepi-r1-plus-lts-ext4-sysupgrade.img of=/dev/mmcblk0 bs=1024k
</pre>
<p>由于 <code>dd</code> 命令没有校验的功能，烧写完成之后可以强制检查一下系统是否正确：</p>
<pre class="brush: bash; title: ; notranslate">
~# e2fsck -f /dev/mmcblk0p2
</pre>
<p>系统烧写完成之后就可以插到软路由上启动了，OpenWRT 系统第一次启动的时候会自动扩容 rootfs 分区，启动完成之后可以登录系统确认 rootfs 分区大小是否正确。</p>
<p>首先通过 SSH 登录或者 LuCI Web 管理界面修改 OpenWRT 的镜像源，这里我用的是清华的镜像源：</p>
<pre class="brush: bash; title: ; notranslate">
~# cat /etc/opkg/distfeeds.conf
src/gz openwrt_core https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/21.02.1/targets/rockchip/armv8/packages
src/gz openwrt_base https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/21.02.1/packages/aarch64_generic/base
~# cat /etc/opkg/customfeeds.conf
src/gz openwrt_luci https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/21.02.1/packages/aarch64_generic/luci
src/gz openwrt_packages https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/21.02.1/packages/aarch64_generic/packages
src/gz openwrt_routing https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/21.02.1/packages/aarch64_generic/routing
src/gz openwrt_telephony https://mirrors.tuna.tsinghua.edu.cn/openwrt/releases/21.02.1/packages/aarch64_generic/telephony
</pre>
<p>香橙派官方提供的 OpenWRT 系统自带了 Adblock、Squid、Transmission 甚至 Docker 等软件的支持，用户也可以自行卸载，例如卸载 MiniDLNA：</p>
<pre class="brush: bash; title: ; notranslate">
~# opkg remove luci-i18n-minidlna-zh-cn luci-app-minidlna minidlna
</pre>
<p>通过 SSH 登录可以看到 OpenWRT 系统的 Linux 内核是 5.4 版本的，应该也够用了：</p>
<pre class="brush: bash; title: ; notranslate">
~# uname -a
Linux R1PlusLTS 5.4.154 #0 SMP PREEMPT Sun Oct 24 09:01:35 2021 aarch64 GNU/Linux
</pre>
<p>然后是 CPU 信息：</p>
<pre class="brush: bash; title: ; notranslate">
~# cat /proc/cpuinfo
processor    : 0
BogoMIPS    : 48.00
Features    : fp asimd evtstrm aes pmull sha1 sha2 crc32 cpuid
CPU implementer : 0x41
CPU architecture: 8
CPU variant   : 0x0
CPU part    : 0xd03
CPU revision  : 4
</pre>
<h2 id="luci-issue">LuCI 问题</h2>
<p>值得一提的是我使用 Chrome 浏览器访问 OpenWRT 的 LuCI Web 管理界面经常出现类似 <code>_(...).format is not a function</code> 这样的报错，控制台还有其它错误：</p>
<pre class="brush: plain; title: ; notranslate">
A listener indicated an asynchronous response by returning true, but the message channel closed before a response was received
</pre>
<p>后来发现使用 Chrome 无痕式窗口访问 LuCI Web 界面就没有问题，因此怀疑是某些 Chrome 扩展导致的，经常一番禁用扩展并测试，确认是由 <a href="https://chrome.google.com/webstore/detail/tronlink/ibnejdfjmmkpcnlpebklmnkoeoihofec" target="_blank">TronLink</a> 这个波场官方的钱包导致的，禁用 TronLink 扩展就可以正常访问 LuCI 界面。</p>
<p>不过为了能正常使用 TronLink 钱包，我还是在 TronLink 扩展的详情页将 <strong>允许此扩展程序读取和更改您在所访问的网站上留存的所有数据</strong> 选项由 <strong>在所有网站上</strong> 改为了 <strong>点击时</strong>，这样 LuCI 界面和 TronLink 就都可以用了。</p>
<h2 id="performance">性能</h2>
<p>这里我就不做常见的 CPU 性能、加解密性能测试了，因为 RK3328 的性能已经有好多网友测试过了，我主要关注 LAN 口 RTL8153B USB 网卡的性能。</p>
<p>我的笔记本直接带了千兆有线网卡，这样我就将笔记本通过千兆网线接到软路由的 LAN 口，用 <code>iperf</code> 命令做一下简单的测试了，先看看 LAN 口接收数据的性能：</p>
<pre class="brush: bash; title: ; notranslate">
~# iperf -s -w 512K
------------------------------------------------------------
Server listening on TCP port 5001
TCP window size: 1.00 MByte (WARNING: requested 512 KByte)
------------------------------------------------------------
[ 4] local 192.168.2.1 port 5001 connected with 192.168.2.57 port 65244
[ ID] Interval    Transfer   Bandwidth
[ 4] 0.0-30.0 sec 3.31 GBytes  949 Mbits/sec
</pre>
<p>接着我又测试了 LAN 口发送数据的性能：</p>
<pre class="brush: bash; title: ; notranslate">
root@R1PlusLTS:~# iperf -c 192.168.2.57 -w 512K -t 30
------------------------------------------------------------
Client connecting to 192.168.2.57, TCP port 5001
TCP window size: 1.00 MByte (WARNING: requested 512 KByte)
------------------------------------------------------------
[ 3] local 192.168.2.1 port 44562 connected with 192.168.2.57 port 5001
[ ID] Interval    Transfer   Bandwidth
[ 3] 0.0-30.0 sec 3.30 GBytes  946 Mbits/sec
</pre>
<h2 id="summary">总结</h2>
<p>最后我把 R1 Plus LTS 软路由的联网配置好之后，将原来的红米 AX3000 路由器的 WAN 口接到 R1 Plus LTS 的 LAN 口，并把 AX3000 从 <strong>普通路由</strong> 模式切换为 <strong>有线中继</strong> 模式，这样原有的手机之类的无线终端设备就能继续上网了：</p>
<p><img src="https://images.weserv.nl/?url=http://res.cloudinary.com/digwht2y0/image/upload/v1737370582/ax3000-ap.png" alt="红米 AX3000 有线中继"></p>
<p>由于 R1 Plus LTS 软路由只有一个 LAN 口，家里的 NAS 服务器只能接在红米 AX3000 路由器上了。还好 AX3000 使用有线中继模式之后，终端设备与软路由也还在同一网段，而且上面的测试结果可以看出软路由的 LAN 口性能也不是瓶颈，我用支持 WiFi 6 的电脑和手机访问 NAS 服务器的速度也没什么问题，可以满足日常使用需求了。</p>
<p>最后说一下 R1 Plus LTS 软路由的散热，我购买的是自带官方金属外壳的版本，这两个月连续运行下来我发现也挺稳定的，通过命令可以查看 CPU 温度：</p>
<pre class="brush: bash; title: ; notranslate">
root@R1PlusLTS:~# cat /sys/class/thermal/thermal_zone0/temp
56818
</pre>
<p>上面结果中的 57 摄氏度是在南京接近 40 度的高温下室内不开空调看到的，实际使用下来我还没有遇到温度超过 60 摄氏度的情况，看起来挺过这个最热夏天之后，R1 Plus LTS 软路由就可以留下来暂定长期使用了。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/r1-plus-lts/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>使用kcptun曲线访问Arukas容器</title>
		<link>https://zohead.com/archives/arukas-kcptun/</link>
		<comments>https://zohead.com/archives/arukas-kcptun/#comments</comments>
		<pubDate>Wed, 06 Mar 2019 17:08:16 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[网络]]></category>
		<category><![CDATA[Arukas]]></category>
		<category><![CDATA[Docker]]></category>
		<category><![CDATA[Endpoint]]></category>
		<category><![CDATA[kcptun]]></category>
		<category><![CDATA[OpenWRT]]></category>
		<category><![CDATA[Shadowsocks]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[樱花]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1573</guid>
		<description><![CDATA[新版 Arukas 容器现状 2017 年我写了两篇介绍日本 Arukas 樱花容器服务的文章，那个时候主要用来跑 Shadowsocks 梯子服务。后来不知道是否因为国内用户蜂拥而至，Arukas 容器基本所有的 IP 地址都被封了，接着 Arukas 也停止提供服务，直到去年才恢复。最近住处的移动宽带不知何故连接一直使用的美国 VPS 速度很慢，因此我想着可以试试新版本 Arukas 容器的效果。 恢复后的新版 Arukas 服务直接把原来的账户都给删除了，用户都需要重新注册，实际使用还必须绑定有效的信用卡，容器配置可以参考其官网（需要爬墙）： https://arukas.io/en/# [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="new-arukas">新版 Arukas 容器现状</h2>
<p>2017 年我写了两篇介绍日本 <a href="https://zohead.com/archives/tag/arukas/">Arukas</a> 樱花容器服务的文章，那个时候主要用来跑 Shadowsocks 梯子服务。后来不知道是否因为国内用户蜂拥而至，Arukas 容器基本所有的 IP 地址都被封了，接着 Arukas 也停止提供服务，直到去年才恢复。最近住处的移动宽带不知何故连接一直使用的美国 VPS 速度很慢，因此我想着可以试试新版本 Arukas 容器的效果。</p>
<p>恢复后的新版 Arukas 服务直接把原来的账户都给删除了，用户都需要重新注册，实际使用还必须绑定有效的信用卡，容器配置可以参考其官网（需要爬墙）：</p>
<p><a href="https://arukas.io/en/#pricing" target="_blank">https://arukas.io/en/#pricing</a></p>
<p>每个账户可以最多创建一个免费容器，免费容器配置如下：</p>
<ul>
<li>每个月 730 小时运行时间；</li>
<li>0.1 vCPU；</li>
<li>128 MB 内存；</li>
<li>100 GB 流量；</li>
<li>仍然不支持外部存储；</li>
<li>支持绑定域名（针对 Endpoint）；</li>
<li>仍然只支持 Docker Hub 库，而且只支持修改 <code>CMD</code> 启动命令。</li>
</ul>
<p>可以看到新版 Arukas 免费容器的配置是有点捉襟见肘，还好我也只是拿来访问 Google 服务之类的，对流量需求不大，如果你经常要看 YouTube 视频之类的，那就不用考虑 Arukas 容器咯。</p>
<p>按照原来写的 <a href="https://zohead.com/archives/arukas-ge-tt/">Arukas容器使用ge.tt替代Endpoint域名</a> 文章重新部署 Shadowsocks 容器，我发现还算欣慰的是 Arukas 提供的 Endpoint 域名还没有被封锁，容器内 Web 服务器提供的内容可以通过 Endpoint 域名访问。</p>
<p>如果你只需要跑一个简单的静态网站，对资源和流量要求也不高的话，那 Arukas 容器也是挺不错的，毕竟还支持绑定自定义的域名。不过 Arukas 的 Endpoint 域名转发服务仍然只支持 HTTPS 访问，而且 Endpoint 地址应该只对容器开放的第一个内部端口有效，只支持 HTTP 协议，不支持 TCP 或者 UDP。如果用 Arukas 容器来跑动态网站，那有可能效果不太理想。</p>
<p>不出意料的是我准备搭梯子的时候，发现墙对 Arukas 封锁的比较彻底，测试了多个 IP 地址都无法正常连接，为此考虑修改原来的容器试试通过 kcptun 进行转发访问。</p>
<h2 id="arukas-shadowsocks-mod">Shadowsocks 容器修改</h2>
<p>我原来制作的 Arukas 专用 Shadowsocks 容器是基于 <a href="https://github.com/phusion/baseimage-docker" target="_blank">Baseimage-docker</a> 镜像修改的，增加 kcptun 支持也很简单。访问 kcptun 的官方 GitHub release 页面：</p>
<p><a href="https://github.com/xtaci/kcptun/releases" target="_blank">https://github.com/xtaci/kcptun/releases</a></p>
<p>下载 Linux amd64 版本的 kcptun 程序，我们也只需要将服务端程序加到原来的 Shadowsocks 容器镜像中，并简单修改下 <code>/etc/my_init.d/01_start_ss_ssh.sh</code> 启动脚本（支持 kcptun 的修改已高亮显示）：</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/bash

# Enable SSH
rm -f /etc/service/sshd/down
/etc/my_init.d/00_regen_ssh_host_keys.sh
touch /etc/service/sshd/down

# Setup SSH key
if [ &quot;x$SSH_AUTHORIZED_KEYS&quot; = &quot;x&quot; ]; then
	/usr/sbin/enable_insecure_key
else
	mkdir ~/.ssh
	echo &quot;$SSH_AUTHORIZED_KEYS&quot; | sed 's/\\n/\n/g' &gt; ~/.ssh/authorized_keys
	chmod 400 ~/.ssh/authorized_keys
fi

# Start web server
env | grep -E '^MARATHON_HOST=|MARATHON_PORT_' &gt; /home/wwwroot/default/marathon.conf
if [ &quot;x$MARATHON_HOST&quot; != &quot;x&quot; ]; then
	getent hosts $MARATHON_HOST | awk '{print &quot;MARATHON_HOST_IP=&quot;$1; exit;}' &gt;&gt; /home/wwwroot/default/marathon.conf
fi

start-stop-daemon -S -b -n tmp-httpd -d /home/wwwroot/default -x /usr/bin/python3 -- -m http.server 80

# Start ShadowSocks
env | grep '^SHADOWSOCKS_CFGS_' | awk -F '=' '{print $1;}' | while read T_NAME; do
	SS_NAME=&quot;${T_NAME:17}&quot;
	echo &quot;${!T_NAME}&quot; &gt; /etc/shadowsocks-libev/${SS_NAME}.json
	start-stop-daemon -n ss-$SS_NAME -x /usr/bin/ss-server -b -S -- -c /etc/shadowsocks-libev/${SS_NAME}.json -u --fast-open
done

# Start kcptun
env | grep '^KCPTUN_CFGS_' | awk -F '=' '{print $1;}' | while read T_NAME; do
	KCP_NAME=&quot;${T_NAME:12}&quot;
	echo &quot;${!T_NAME}&quot; &gt; /etc/kcptun/${KCP_NAME}.json
	start-stop-daemon -n kcp-$KCP_NAME -x /usr/bin/kcptun_server -b -S -- -c /etc/kcptun/${KCP_NAME}.json
done

if [ &quot;x$GETT_TOKEN&quot; != &quot;x&quot; ]; then
	if [ &quot;x$HOME&quot; = &quot;x&quot; ]; then
		export HOME=&quot;/root&quot;
	fi
	echo -n &quot;$GETT_TOKEN&quot; &gt; ~/.gett-token
	if [ &quot;x$GETT_SHARE_NAME&quot; != &quot;x&quot; ]; then
		python3 /usr/local/gett/uploader.py -l http://ge.tt/$GETT_SHARE_NAME | awk '{if (substr($5,1,13)==&quot;http://ge.tt/&quot;) {print $5;}}' | xargs python3 /usr/local/gett/uploader.py --delete
		python3 /usr/local/gett/uploader.py -s http://ge.tt/$GETT_SHARE_NAME /home/wwwroot/default/marathon.conf
	fi
fi

exec /usr/sbin/sshd -D -e -u 0
</pre>
<p>新版支持 kcptun 访问 Shadowsocks 的 Arukas 专用容器安装包下载地址，仍然支持 SSH 登录以及通过 Endpoint 地址或者 <a href="https://zohead.com/archives/ge-tt-cli-api/">ge.tt</a> 分享获取容器当前地址和端口：</p>
<p><a href="https://zohead.com/downloads/arukas-baseimage-xenial-ss.tar.gz">https://zohead.com/downloads/arukas-baseimage-xenial-ss.tar.gz</a></p>
<p>原有的 <code>CMD</code> 启动命令以及以 <code>SHADOWSOCKS_CFGS_</code> 开头的 Shadowsocks 配置变量和 <code>SSH_AUTHORIZED_KEYS</code> SSH 证书变量配置都没有变化。</p>
<p>此次增加了以 <code>KCPTUN_CFGS_</code> 开头的 kcptun 配置变量，当然别忘了容器端口配置中也得指定一个新的 UDP 端口给 kcptun 服务使用。</p>
<p>例如我现有的 Shadowsocks 服务配置变量：</p>
<pre class="brush: jscript; title: ; notranslate">
SHADOWSOCKS_CFGS_xxx={ &quot;server&quot;:&quot;0.0.0.0&quot;, &quot;server_port&quot;:17374, &quot;local_port&quot;:1080, &quot;password&quot;:&quot;arukas-ss-svr&quot;, &quot;timeout&quot;:30, &quot;method&quot;:&quot;aes-256-cfb&quot; }
</pre>
<p>现在需要在 Arukas 容器中运行 kcptun 服务器进行 UDP 转发，可以添加一个 kcptun 配置变量（仍然是 JSON 格式，需要写成一行）：</p>
<pre class="brush: jscript; title: ; notranslate">
KCPTUN_CFGS_xxx = { &quot;listen&quot;: &quot;:29900&quot;, &quot;target&quot;: &quot;127.0.0.1:17374&quot;, &quot;key&quot;: &quot;arukas-kcp-svr&quot;, &quot;crypt&quot;: &quot;xor&quot;, &quot;mode&quot;: &quot;fast2&quot;, &quot;mtu&quot;: 1350, &quot;sndwnd&quot;: 128, &quot;rcvwnd&quot;: 128, &quot;datashard&quot;: 0, &quot;parityshard&quot;: 0, &quot;dscp&quot;: 46, &quot;nocomp&quot;: true, &quot;acknodelay&quot;: false, &quot;nodelay&quot;: 0, &quot;interval&quot;: 40, &quot;resend&quot;: 2, &quot;nc&quot;: 1, &quot;sockbuf&quot;: 4194304, &quot;keepalive&quot;: 10, &quot;log&quot;: &quot;/var/log/kcptun.log&quot; }
</pre>
<p>这里我指定 kcptun 服务器绑定默认的 29900 UDP 端口（Arukas 容器端口配置中即需要开放 29900 UDP 端口），转发地址即指向本地的 Shadowsocks 服务器端口。</p>
<blockquote>
<p><strong>提示</strong></p>
<p>上面贴出来的我使用的 kcptun 配置并不是最佳配置，只是由于我的 OpenWRT 路由器运算能力比较孱弱，避免出现路由器上的 kcptun 客户端导致 CPU 占用过高的问题。</p>
<p>kcptun 的配置稍微有点复杂，需要根据用户实际网络环境修改，这里我就不详细介绍了，请参考 <a href="https://github.com/xtaci/kcptun" target="_blank">GitHub</a> 项目主页的说明。</p>
</blockquote>
<h2 id="android-kcptun-test">Android kcptun 测试</h2>
<p>我们可以首先用 Android 手机测试通过 kcptun 连接 Arukas 容器的 Shadowsocks 服务，在手机上安装 <a href="https://play.google.com/store/apps/details?id=com.github.shadowsocks" target="_blank">Shadowsocks</a> App 和专用的 <a href="https://play.google.com/store/apps/details?id=com.github.shadowsocks.plugin.kcptun" target="_blank">kcptun</a> 插件。</p>
<p>安装完成之后 Shadowsocks 配置文件中就可以选择 kcptun 插件，需要注意你如果使用的是像我的 Nubia Z17 这种魔改版手机，可能需要在 <strong>手机管家</strong> 之类的系统设置中开启 kcptun 的自启动权限，防止出现 Shadowsocks App 无法启动 kcptun 的问题。</p>
<p>Shadowsocks App 连接的服务器地址也需要更换为 Arukas 容器实际地址和 kcptun 服务的外部访问端口，kcptun 插件的配置则保持与服务端一致即可，我的配置如下：</p>
<pre class="brush: plain; title: ; notranslate">
dscp=46;nocomp;mtu=1350;datashard=0;parityshard=0;mode=fast2;key=arukas-kcp-svr;crypt=xor
</pre>
<p>Android kcptun 插件的配置使用 <code>key=value</code> 的格式，中间以分号隔开，如果只有 <code>key</code> 没有 <code>value</code> 则表示启用该参数（true），具体配置参数可以点击 kcptun 插件的 <code>?</code> 按钮查看详细说明。</p>
<h2 id="openwrt-kcptun-script">OpenWRT 自动更新配置脚本</h2>
<p>使用 kcptun 之后，OpenWRT 路由器上的 Shadowsocks 配置也不太一样了，例如我的 <code>/etc/shadowsocks-arukas.json</code> 配置文件就可以保持不变了（固定连接本地 kcptun 地址和端口）：</p>
<pre class="brush: jscript; title: ; notranslate">
{
	&quot;server&quot; : &quot;127.0.0.1&quot;,
	&quot;server_port&quot; : &quot;17374&quot;,
	&quot;password&quot;: &quot;arukas-ss-svr&quot;,
	&quot;local_port&quot;: &quot;1080&quot;,
	&quot;timeout&quot; : &quot;30&quot;,
	&quot;method&quot;: &quot;aes-256-cfb&quot;
}
</pre>
<p>相应的增加 kcptun 客户端的配置文件 <code>/etc/kcptun-arukas.json</code>，<code>key</code> 密码与容器中 kcptun 服务器密码一致，<code>remoteaddr</code> 就是容器 kcptun 服务 UDP 监听的外部访问地址和端口：</p>
<pre class="brush: jscript; title: ; notranslate">
{
&quot;localaddr&quot;: &quot;:17374&quot;,
&quot;remoteaddr&quot;: &quot;&quot;,
&quot;key&quot;: &quot;arukas-kcp-svr&quot;,
&quot;crypt&quot;: &quot;xor&quot;,
&quot;mode&quot;: &quot;fast2&quot;,
&quot;mtu&quot;: 1350,
&quot;sndwnd&quot;: 128,
&quot;rcvwnd&quot;: 128,
&quot;datashard&quot;: 0,
&quot;parityshard&quot;: 0,
&quot;dscp&quot;: 46,
&quot;nocomp&quot;: true,
&quot;acknodelay&quot;: false,
&quot;nodelay&quot;: 0,
&quot;interval&quot;: 40,
&quot;resend&quot;: 2,
&quot;nc&quot;: 1,
&quot;sockbuf&quot;: 4194304,
&quot;keepalive&quot;: 10
}
</pre>
<p>为了支持 kcptun，我也稍微改了下 OpenWRT 路由器的 <code>arukas-ss.sh</code> 自动更新配置脚本，为了使用方便我把 kcptun 客户端的启动和停止操作也放到 <code>/etc/init.d/shadowsocks</code> 服务脚本中了，其它路由器请自行修改此脚本：</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh
ARUKAS_ENDPOINT=&quot;&quot;
GETT_SHRNAME=&quot;&quot;
RESTART_SHADOWSOCKS=&quot;no&quot;

[ $# -ge 2 ] || exit 1

[ -f /tmp/.marathon.conf ] &amp;&amp; mv /tmp/.marathon.conf /tmp/.marathon.conf.bak

IND=0
while [ $IND -lt 5 ]; do
	let IND++
	[ -f /tmp/.marathon.conf ] &amp;&amp; rm -f /tmp/.marathon.conf
	if [ &quot;x$GETT_SHRNAME&quot; != &quot;x&quot; ]; then
		T_FILEID=`curl -s -k -f http://api.ge.tt/1/shares/$GETT_SHRNAME | sed -e 's/^.*&quot;fileid&quot;[^:]*:[^&quot;]*&quot;//' -e 's/&quot;.*$//'`
		if [ &quot;x$T_FILEID&quot; != &quot;x&quot; ]; then
			curl -s -k -f -o /tmp/.marathon.conf -L -e &quot;http://ge.tt/$GETT_SHRNAME&quot; &quot;http://api.ge.tt/1/files/$GETT_SHRNAME/$T_FILEID/blob?download&quot;
			[ $? -eq 0 ] &amp;&amp; break
		fi
	fi
	curl -s -k -f -o /tmp/.marathon.conf https://$ARUKAS_ENDPOINT.arukascloud.io/marathon.conf
	[ $? -eq 0 ] &amp;&amp; break
	sleep 1
done

[ -s /tmp/.marathon.conf ] || exit 1
echo &quot;Fetch server config after $IND tries.&quot;

if [ -f /tmp/.marathon.conf.bak ]; then
	cmp -s /tmp/.marathon.conf /tmp/.marathon.conf.bak
	if [ $? -eq 0 ]; then
		rm -f /tmp/.marathon.conf
		exit 0
	fi
fi

. /tmp/.marathon.conf 2&gt;/dev/null
if [ &quot;x$MARATHON_HOST&quot; = &quot;x&quot; ]; then
	rm -f /tmp/.marathon.conf
	exit 1
fi

if [ &quot;x$MARATHON_HOST_IP&quot; != &quot;x&quot; ]; then
	MARATHON_HOST=&quot;$MARATHON_HOST_IP&quot;
fi

while [ $# -gt 2 ]; do
	CMD=&quot;echo \${MARATHON_PORT_$2}&quot;
	TMP_PORT=`eval $CMD`

	if [ -f $1 -a &quot;x$TMP_PORT&quot; != &quot;x&quot; ]; then
		if [ &quot;x$3&quot; = &quot;xshadowsocks&quot; ]; then
			sed -i -e 's/&quot;server&quot;[^:]*:[^,]*,/&quot;server&quot; : &quot;'$MARATHON_HOST'&quot;,/' -e 's/&quot;server_port&quot;[^:]*:[^,]*,/&quot;server_port&quot; : &quot;'$TMP_PORT'&quot;,/' $1
			grep -q '^CONFIG.*='$1 /etc/init.d/shadowsocks
			[ $? -eq 0 ] &amp;&amp; RESTART_SHADOWSOCKS=&quot;yes&quot;
		elif [ &quot;x$3&quot; = &quot;xkcptun&quot; ]; then
			sed -i 's/&quot;remoteaddr&quot;[^:]*:[^,]*,/&quot;remoteaddr&quot; : &quot;'$MARATHON_HOST':'$TMP_PORT'&quot;,/' $1
			grep -q '^KCPTUN_CONFIG.*='$1 /etc/init.d/shadowsocks
			[ $? -eq 0 ] &amp;&amp; RESTART_SHADOWSOCKS=&quot;yes&quot;
		fi
	fi
	shift
	shift
	shift
done

if [ &quot;x$RESTART_SHADOWSOCKS&quot; = &quot;xyes&quot; ]; then
	/etc/init.d/shadowsocks restart
fi
</pre>
<p>使用之前请修改脚本最上面的 <code>ARUKAS_ENDPOINT</code> 和 <code>GETT_SHRNAME</code> 变量，分别为 Arukas 容器的 Endpoint 名（Arukas Endpoint 地址可访问的情况下建议优先使用）和 ge.tt 分享名。</p>
<p>为了区分 Shadowsocks 和 kcptun 配置文件，我对脚本调用方式也做了修改，增加了指定配置类型的参数（<code>shadowsocks</code> 或 <code>kcptun</code>），例如我的 crontab 配置：</p>
<pre class="brush: plain; title: ; notranslate">
30 * * * * /etc/arukas-ss.sh /etc/kcptun-arukas.json 29900 kcptun
</pre>
<p>这样路由器就可以自动更新 kcptun 客户端配置文件中的 <code>remoteaddr</code> 项了。</p>
<p>我的渣渣移动宽带环境下电脑通过路由器 kcptun 爬墙看 YouTube 视频效果如下：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442943/shadowsocks-kcptun-speed.png" alt="Arukas 容器 Shadowsocks kcptun 速度"></p>
<p>受限于路由器硬件的性能，Arukas 网络的 kcptun 速度并没有完全发挥出来，不过还是比原先的美国 VPS 要好多了，最后祝大家在开会的特殊阶段也能把梯子搭的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/arukas-kcptun/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>广电宽带DNS访问某些国内网站的问题</title>
		<link>https://zohead.com/archives/bcnet-dns/</link>
		<comments>https://zohead.com/archives/bcnet-dns/#comments</comments>
		<pubDate>Sat, 28 Oct 2017 03:44:15 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[网络]]></category>
		<category><![CDATA[dnsmasq]]></category>
		<category><![CDATA[ipset]]></category>
		<category><![CDATA[pdnsd]]></category>
		<category><![CDATA[广电]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1508</guid>
		<description><![CDATA[问题说明 有段时间没有更新博客了，最近全国都处于重要的开会期间，不出所料常用的爬墙路线都被各种封锁，而我在的住处使用的广电宽带也出幺蛾子了。前两周我发现突然无法访问 www.ip138.com、www.chinaz.com 之类的国内网站，浏览器上的表现似乎是没有正常打开连接就中断了。 通过在本地运行 nslookup 命令解析这些域名我才发现，这些网站在我的电脑上根本没有解析到任何有效的 IP 地址，难怪无法正常访问了。 为此我登录到 OpenWRT 路由器，直接在路由器系统上运行 nslookup 命令解析这些无法访问的域名，从返回的结果才看出端倪： 可以看到百度域名可以返回正确的结果，因 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="dns-problem">问题说明</h2>
<p>有段时间没有更新博客了，最近全国都处于重要的开会期间，不出所料常用的爬墙路线都被各种封锁，而我在的住处使用的广电宽带也出幺蛾子了。前两周我发现突然无法访问 www.ip138.com、www.chinaz.com 之类的国内网站，浏览器上的表现似乎是没有正常打开连接就中断了。</p>
<p>通过在本地运行 nslookup 命令解析这些域名我才发现，这些网站在我的电脑上根本没有解析到任何有效的 IP 地址，难怪无法正常访问了。</p>
<p>为此我登录到 OpenWRT 路由器，直接在路由器系统上运行 nslookup 命令解析这些无法访问的域名，从返回的结果才看出端倪：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]#nslookup www.baidu.com
Server:    127.0.0.1
Address 1: 127.0.0.1 localhost

Name:      www.baidu.com
Address 1: 180.97.33.108
Address 2: 180.97.33.107

[root@PandoraBox:/root]#nslookup www.ip138.com
Server:    127.0.0.1
Address 1: 127.0.0.1 localhost

Name:      www.ip138.com
Address 1: ::ffff:172.30.1.23

[root@PandoraBox:/root]#nslookup www.dasai8.com
Server:    127.0.0.1
Address 1: 127.0.0.1 localhost

Name:      www.dasai8.com
Address 1: ::ffff:172.30.0.44
Address 2: 172.30.0.44
</pre>
<p>可以看到百度域名可以返回正确的结果，因此能正常访问。</p>
<p>无法访问的 www.ip138.com 和 www.dasai8.com 域名返回的则是诡异的 IPv6 和 IPv4 地址，实际上这两个网站从目前来看是不太可能部署了 IPv6 支持的，而且返回的结果中 172.30.1.23 和 172.30.0.44 也是明显的本地局域网地址。</p>
<p>到此我也大概了解原因了：</p>
<p>广电宽带不知道出于节省成本还是什么的考虑，对某些国内网站内容做了缓存，用户解析这些网站域名时直接返回广电网内缓存服务器的地址，这样访问起来也比较快。但不巧的是这些解析到的局域网服务器地址没有通过路由器正确返回给我使用的电脑，导致无法正常访问这些网站。</p>
<h2 id="dns-fix">问题原因</h2>
<p>目前的问题看起来出在路由器上了，为此需要检查路由器的 DNS 服务器设置。最后终于在 PandoraBox 的 “DHCP/DNS” 界面中找到的相关的 “重绑定保护” 设置，把默认选中的 “丢弃RFC1918上行响应数据” 勾去掉之后保存并应用就可以了。</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737370814/dns_rebind_protection.png" alt="DNS 重绑定保护" title="DNS 重绑定保护"></p>
<p>这样修改之后，路由器就不会忽略内网地址的解析结果了。</p>
<p>现在再来看看修改之后 ping 这些网站的结果（广电宽带对于非广电内部网络的地址一般都是不允许 ping 的）：</p>
<pre class="brush: bash; title: ; notranslate">
(trusty)zzm@localhost:~$ ping -c 4 www.dasai8.com
PING www.dasai8.com (172.30.0.44) 56(84) bytes of data.
64 bytes from 172.30.0.44: icmp_seq=1 ttl=58 time=7.94 ms
64 bytes from 172.30.0.44: icmp_seq=2 ttl=58 time=9.74 ms
64 bytes from 172.30.0.44: icmp_seq=3 ttl=58 time=7.40 ms
64 bytes from 172.30.0.44: icmp_seq=4 ttl=58 time=9.97 ms

--- www.dasai8.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3037ms
rtt min/avg/max/mdev = 7.402/8.766/9.975/1.115 ms

(trusty)zzm@localhost:~$ ping -c 4 www.chinaz.com
PING www.chinaz.com (172.30.1.22) 56(84) bytes of data.
64 bytes from 172.30.1.22: icmp_seq=1 ttl=57 time=7.57 ms
64 bytes from 172.30.1.22: icmp_seq=2 ttl=57 time=9.66 ms
64 bytes from 172.30.1.22: icmp_seq=3 ttl=57 time=8.59 ms
64 bytes from 172.30.1.22: icmp_seq=4 ttl=57 time=10.8 ms

--- www.chinaz.com ping statistics ---
4 packets transmitted, 4 received, 0% packet loss, time 3004ms
rtt min/avg/max/mdev = 7.573/9.177/10.870/1.230 ms

(trusty)zzm@localhost:~$ ping -c 4 www.baidu.com
PING www.a.shifen.com (180.97.33.107) 56(84) bytes of data.

--- www.a.shifen.com ping statistics ---
4 packets transmitted, 0 received, 100% packet loss, time 2999ms
</pre>
<p>可以看到前面两个域名的 ping 值显然是局域网内的结果，而 ping 百度则是 <strong>“正常”</strong> 地返回超时了 -_-#。</p>
<h2 id="dns-solve">解决方法</h2>
<p>经过后续测试我发现广电宽带甚至对土豆网这种级别的网站都做了缓存，解析时会返回 172.30.1.23 之类的局域网地址。</p>
<p>尽管可以忽略路由器 DNS 的重绑定保护机制，但访问这些网站完全使用广电缓存的话，很可能会出现网页不正确甚至被插广告的风险，为此我还是在路由器上开启了 pdnsd 服务，修改了 dnsmasq 配置文件，将这些可能被广电缓存的网站域名单独发给本地的 pdnsd 服务进行解析。</p>
<p>dnsmasq 配置文件类似这样：</p>
<pre class="brush: plain; title: dnsmasq.conf; notranslate">
server=/.google.com/127.0.0.1#5353
ipset=/.google.com/gfwlist
server=/.twitter.com/127.0.0.1#5353
ipset=/.twitter.com/gfwlist
server=/.facebook.com/127.0.0.1#5353
ipset=/.facebook.com/gfwlist
server=/.dasai8.com/127.0.0.1#5353
server=/.ip138.com/127.0.0.1#5353
server=/.chinaz.com/127.0.0.1#5353
</pre>
<p>前面几个是必须爬墙的域名，通过 pdnsd 解析并加入到名为 gfwlist 的 ipset 中，这样可以自动走 Shadowsocks ss-redir 线路，后面的几个常规情况下被缓存的域名则只是通过 pdnsd 解析。</p>
<p>pdnsd 服务器的配置是以 TCP 协议通过第三方的 DNS 服务器进行域名解析，考虑到 TCP 的 DNS 协议仍然会被广电给劫持的问题，还需要将 pdnsd 配置中的 DNS 服务器加入到 ipset 中，这样就可以让 pdnsd 的解析请求完全走 Shadowsocks 或者 OpenVPN 来避免污染了。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/bcnet-dns/feed/</wfw:commentRss>
		<slash:comments>0</slash:comments>
		</item>
		<item>
		<title>WordPress 3.8开启Google AMP的问题</title>
		<link>https://zohead.com/archives/wordpress-3-amp/</link>
		<comments>https://zohead.com/archives/wordpress-3-amp/#comments</comments>
		<pubDate>Tue, 01 Aug 2017 17:37:56 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Google]]></category>
		<category><![CDATA[WordPress]]></category>
		<category><![CDATA[AMP]]></category>
		<category><![CDATA[AMP for WP]]></category>
		<category><![CDATA[PHP]]></category>
		<category><![CDATA[qTranslate]]></category>
		<category><![CDATA[插件]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1487</guid>
		<description><![CDATA[关于 AMP Accelerated Mobile Pages（简称 AMP）是 Google 带领开发的开源项目，主要为了提升移动设备对网站的访问速度，大概包括 AMP HTML、AMP JS 和 AMP Cache 三部分，非常适合博客及新闻展示类的静态网站。 有关 AMP 的详细介绍可以参考其官方网站： https://www.ampproject.org/zh_cn/ AMP 网页只能使用 AMP HTML 中允许的有限的标签，不允许使用 AMP Runtime、AMP Components 之外的 JS，而且 AMP Runtime、Components 都必须从 cdn.amppr [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="about-amp">关于 AMP</h2>
<p><a href="https://en.wikipedia.org/wiki/Accelerated_Mobile_Pages" target="_blank">Accelerated Mobile Pages</a>（简称 AMP）是 Google 带领开发的开源项目，主要为了提升移动设备对网站的访问速度，大概包括 <strong>AMP HTML</strong>、<strong>AMP JS</strong> 和 <strong>AMP Cache</strong> 三部分，非常适合博客及新闻展示类的静态网站。</p>
<p>有关 AMP 的详细介绍可以参考其官方网站：</p>
<p><a href="https://www.ampproject.org/zh_cn/" target="_blank">https://www.ampproject.org/zh_cn/</a></p>
<p>AMP 网页只能使用 AMP HTML 中允许的有限的标签，不允许使用 AMP Runtime、AMP Components 之外的 JS，而且 AMP Runtime、Components 都必须从 <code>cdn.ampproject.org</code> 加载，因此目前 AMP 网页都必须在翻墙状态下才能正常浏览。</p>
<p>AMP Cache 是负责缓存并传输 AMP 页面的 CDN 服务器，用户在 Google 移动端中点击 AMP 网站时，实际访问的是缓存过的页面。</p>
<h2 id="wordpress-amp-problem">WordPress 启用 AMP 的问题</h2>
<p>WordPress 官方提供了 <a href="https://wordpress.org/plugins/amp/" target="_blank">AMP</a> 插件以支持直接为博客开启 AMP 加速，只是官方插件要求 WordPress 最低为 4.4 版本。</p>
<p>由于我的博客安装了 <a href="http://www.qianqin.de/qtranslate/" target="_blank">qTranslate</a> 这款多语言插件，而该插件却只支持到 WordPress 3.8.1 版本，如果升级 WordPress 到最新版本，qTranslate 插件就会自动禁用。然而 qTranslate 插件是对 WordPress 数据库直接进行修改的，禁用之后博客文章就可能会同时显示多种语言的内容，这样显然是不可接受的。</p>
<p>虽然网上已经有人继承 qTranslate 原作发布了例如 qTranslate X 之类的支持新版本 WordPress 的插件，但为了数据安全（其实是懒）考虑我暂时还是不打算直接升级 WordPress 了。</p>
<p>不过还好我在 WordPress 插件库里找到一款看起来支持 WordPress 3.8 的 AMP 插件：<a href="https://wordpress.org/plugins/accelerated-mobile-pages/" target="_blank">AMP for WP</a>，毕竟看此插件的介绍和评分都比官方的 AMP 插件要强哦，而且最低只要求 WordPress 3.0 版本。</p>
<p>AMP for WP 安装起来还是非常顺利的，插件选项里目前基本只提供了 Google Analytics UID 的设置选项，启用之后访问 AMP 版网站的方法是在地址后面加上 <code>?wpamp</code> 后缀。</p>
<p>不过我刚开始测试访问 AMP 首页和文章就碰到问题了，直接没有任何显示了，看网页源代码输出信息不全，显然是 AMP for WP 插件对老版本 WordPress 兼容性还是有点问题。</p>
<h2 id="mod-amp-for-wp">修改 AMP for WP</h2>
<p>首先修改 AMP for WP 插件的 <code>wp-amp-ninja/admin/common.php</code> 文件，打开 PHP 报错开关：</p>
<pre class="brush: php; title: wp-amp-ninja/admin/common.php; notranslate">
error_reporting(1);
</pre>
<p>这下访问博客首页和文章页面就能看到详细报错了：</p>
<pre class="brush: plain; title: ; notranslate">
Fatal error: Call to undefined function get_the_permalink() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-front.php on line 24

Fatal error: Call to undefined function the_posts_pagination() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/template/wpamp-content.php on line 53


Fatal error: Call to undefined function the_archive_title() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-functions.php on line 600

Fatal error: Call to undefined function the_archive_description() in /www/zohead.com/wp-content/plugins/wp-amp-ninja/includes/wpamp-functions.php on line 601
</pre>
<p>经过查阅 WordPress 官方文档发现：</p>
<ol>
<li><a href="https://developer.wordpress.org/reference/functions/get_the_permalink/" target="_blank">get_the_permalink</a> 函数在 WordPress 3.9.0 版本开始引入，其实就是 1.0.0 版本就已经有的 <a href="https://developer.wordpress.org/reference/functions/get_permalink/" target="_blank">get_permalink</a> 函数；</li>
<li><a href="https://developer.wordpress.org/reference/functions/the_posts_pagination/" target="_blank">the_posts_pagination</a> 函数在 WordPress 4.1.0 版本开始引入，一同引入的还有 <code>the_posts_navigation</code> 函数，与 <code>get_the_permalink</code> 函数一样都位于 WordPress 代码库的 <code>wp-includes/link-template.php</code> 文件；</li>
<li>至于 <a href="https://developer.wordpress.org/reference/functions/the_archive_title/" target="_blank">the_archive_title</a> 和 <a href="https://developer.wordpress.org/reference/functions/the_archive_description" target="_blank">the_archive_description</a> 函数的功能比较类似，支持显示文章的标题和描述并在前后插入自定义代码，同样也在 WordPress 4.1.0 版本开始引入，位于 WordPress 代码库的 <code>wp-includes/general-template.php</code> 文件。</li>
</ol>
<p>由此可见，AMP for WP 实际上应该至少要求 WordPress 4.1.0 版本，只是作者并没有测试过是否兼容较低版本的 WordPress。</p>
<p>不过还好我看了下 WordPress 最新 4.8 版本的代码，上面缺少的几个 WordPress 内置函数都是功能比较独立的。</p>
<p>因此我稍微修改了一下博客目录下的 <code>link-template.php</code> 和 <code>general-template.php</code> 文件，将最新版本的 <code>get_the_permalink</code>、<code>the_posts_pagination</code>、<code>the_posts_navigation</code>、<code>the_archive_title</code>、<code>the_archive_description</code> 函数实现分别 Backport 到 WordPress 3.8 版本。Backport 完成之后再访问博客首页和文章，就没有 PHP 报错了。</p>
<p>不过初步试用下来，我还是发现 AMP for WP 插件的一些小问题：</p>
<ol>
<li>如果通过 qTranslate 插件访问博客的英文版本（通过增加 <code>?lang=en</code> 地址后缀），对应的 AMP 版页面地址会不正确，AMP for WP 插件在转换地址时并没有考虑地址中会带有其它后缀的情况；</li>
<li>AMP for WP 对于带有多种语言标题的文章直接显示数据库中多种语言合并在一起的标题效果，而并不是 qTranslate 插件根据客户端语言自动处理后的效果，这个问题在我使用的几个 WordPress 主题中都不会出现；</li>
<li>文章中插入的多行代码被合并成一行显示了，这是明显不能接受的；</li>
<li>文章的中文发表时间无法正确显示，统一显示为当前日期。</li>
</ol>
<p>第一个问题需要修改 AMP for WP 插件的 <code>wpamp-front.php</code>、<code>wpamp-functions.php</code>、<code>wpamp-header.php</code> 这几个文件中转换地址的代码，例如 <code>wpamp-front.php</code> 文件的修改：</p>
<pre class="brush: diff; title: wpamp-front.php; notranslate">
 		$the_permalink = get_the_permalink( $post-&gt;ID );
 	}
 	
-	$the_permalink = rtrim( $the_permalink, '/' ) . '/';
+	$the_permalink = rtrim( $the_permalink, '/' );
 	$perma = strpos( $the_permalink, &quot;?&quot; );
 	if ( $perma === false ) {
+		$the_permalink .= '/';
 		$sConnector = &quot;?&quot;;
 	} else {
 		$sConnector = &quot;&amp;&quot;;
</pre>
<p>第二个问题需要修改 <code>wpamp-content.php</code> 文件，文章标题要做 <code>apply_filters</code> 处理：</p>
<pre class="brush: diff; title: wpamp-content.php; notranslate">
                 &lt;div id=&quot;amp-pagination&quot;&gt;
                 	&lt;?php $prev_post = get_previous_post(); if (!empty( $prev_post )): ?&gt;
-                    	&lt;div class=&quot;prev&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($prev_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt; &amp;laquo; &lt;?php echo $prev_post-&gt;post_title ?&gt;&lt;/a&gt;&lt;/div&gt;
+                    	&lt;div class=&quot;prev&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($prev_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt; &amp;laquo; &lt;?php echo apply_filters( 'the_title', $prev_post-&gt;post_title, $prev_post-&gt;ID ); ?&gt;&lt;/a&gt;&lt;/div&gt;
 					&lt;?php endif ?&gt;
 					&lt;?php  $next_post = get_next_post(); if (!empty( $next_post )): ?&gt;
-                        &lt;div class=&quot;next&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($next_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt;&lt;?php echo $next_post-&gt;post_title ?&gt; &amp;raquo; &lt;/a&gt;&lt;/div&gt;
+                        &lt;div class=&quot;next&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink($next_post-&gt;ID, AMP_CONSTANT); ?&gt;&quot;&gt;&lt;?php echo apply_filters( 'the_title', $next_post-&gt;post_title, $next_post-&gt;ID ); ?&gt; &amp;raquo; &lt;/a&gt;&lt;/div&gt;
 					&lt;?php endif ?&gt;
                     &lt;div class=&quot;clearfix&quot;&gt;&lt;/div&gt;
                 &lt;/div&gt;
</pre>
<p>第三个问题就比较简单了，将 <code>simple_html_dom.php</code> 文件中替换回车和换行符的处理去掉就可以了。</p>
<p>第四个文章发表时间的问题也可以修改 <code>wpamp-content.php</code> 文件简化处理：</p>
<pre class="brush: diff; title: wpamp-content.php; notranslate">
                     &lt;?php endif; ?&gt;
                     By &lt;span class=&quot;amp-wp-author&quot;&gt;&lt;a href=&quot;&lt;?php echo wp_amp_permalink( NULL, AMP_CONSTANT, get_author_posts_url( get_the_author_meta( 'ID' ) ) ); ?&gt;&quot;&gt;&lt;?php echo esc_html( get_the_author() ); ?&gt;&lt;/a&gt;&lt;/span&gt;
-                    &lt;?php $the_time = date_i18n( get_option( 'date_format' ), strtotime( get_the_time('F jS, Y') ) ); ?&gt;
-                    on &lt;time datetime=&quot;&lt;?php echo $the_time; ?&gt;&quot;&gt;&lt;?php echo $the_time; ?&gt;&lt;/time&gt;
+                    on &lt;time datetime=&quot;&lt;?php echo get_the_date('c'); ?&gt;&quot;&gt;&lt;?php echo get_the_date('c'); ?&gt;&lt;/time&gt;
                 &lt;/li&gt;
</pre>
<p>另外我还对 AMP for WP 插件的页脚处理做了点小修改，将页脚上切换到博客首页桌面版本的链接改为切换到当前文章的桌面版本，方便访问者使用。</p>
<h2 id="summary">总结</h2>
<p>对 AMP for WP 插件修改完成之后就可以访问博客的 AMP 版进行验证了，例如我的博客的 AMP 版首页地址就是：</p>
<p><a href="https://zohead.com/?wpamp" target="_blank">https://zohead.com/?wpamp</a></p>
<p>普通用户可以通过安装 Google 推出的 <a href="https://chrome.google.com/webstore/detail/amp-validator/nmoffdblmcmgeicmolmhobpoocbbmknc" target="_blank">AMP Validator</a> 官方 Chrome 扩展检测所访问的 AMP 站点是否配置正确。</p>
<p>网站所有者可以用 Google 搜索的 AMP 在线测试工具进行检测：</p>
<p><a href="https://search.google.com/test/amp" target="_blank">https://search.google.com/test/amp</a></p>
<p>输入要测试的 AMP 版网址就可以开始检测，另外这个测试工具的另一个好处就是检测通过之后可以直接把你的 AMP 站点提交给 Google，让 Google 搜索蜘蛛尽快收录并进行 CDN 缓存。</p>
<p>现在通过 Google 移动端（例如 Android Chrome 浏览器）搜索我的博客，应该就能在搜索结果里看到下面的 AMP 闪电标志了：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737371102/google-search-amp.jpg" alt="Google 搜索结果 AMP 标志" title="Google 搜索结果 AMP 标志"></p>
<p>点击搜索结果，你会发现访问的其实是 Google 缓存过的 AMP 地址，下面地址只有移动端浏览器才会显示 AMP 网页：</p>
<p><a href="https://www.google.com/amp/s/zohead.com/%3fwpamp" target="_blank">https://www.google.com/amp/s/zohead.com/%3fwpamp</a></p>
<p>初步启用 AMP 的大体感受就是如果你的梯子还可以，那访问 Google 缓存过的 AMP 网站速度还是非常快的，我这里估计访问 AMP 版网站所需要的流量大概为桌面版本的 1/3。</p>
<p>后面有时间的话还是希望能对 AMP for WP 插件继续改进，例如支持其它的 AMP 后缀或者使用专门的 AMP 子域名方便自己的服务器进行缓存之类的，最后祝大家玩的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/wordpress-3-amp/feed/</wfw:commentRss>
		<slash:comments>2</slash:comments>
		</item>
		<item>
		<title>OpenWRT实现OpenVPN按ipset自动分流</title>
		<link>https://zohead.com/archives/openwrt-openvpn-ipset/</link>
		<comments>https://zohead.com/archives/openwrt-openvpn-ipset/#comments</comments>
		<pubDate>Sun, 16 Jul 2017 04:35:35 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[网络]]></category>
		<category><![CDATA[dnsmasq]]></category>
		<category><![CDATA[gfwlist]]></category>
		<category><![CDATA[ipset]]></category>
		<category><![CDATA[iptables]]></category>
		<category><![CDATA[newifi mini]]></category>
		<category><![CDATA[OpenVPN]]></category>
		<category><![CDATA[OpenWRT]]></category>
		<category><![CDATA[PandoraBox]]></category>
		<category><![CDATA[TUN]]></category>
		<category><![CDATA[Windscribe]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1476</guid>
		<description><![CDATA[接着上面一篇介绍 Windscribe 免费 VPN 的文章，住处的网络通过 OpenVPN 连接 Windscribe 之后虽然速度不快，但好歹广电宽带下没有之前用的几个 VPS 经常超时的问题了。因此想着最好能部署到现在用的 newifi mini 路由器上（毕竟已经刷了 PandoraBox 固件），目标就是能在路由器上用 OpenVPN 连接 Windscribe 并自动分流翻墙访问某些特殊的网站。 OpenWRT 安装使用 OpenVPN 首先在路由器上安装 OpenVPN 客户端： 把上篇文章中生成的 Windscribe OpenVPN 配置文件上传到 /etc/openvpn  [&#8230;]]]></description>
				<content:encoded><![CDATA[<p>接着上面一篇介绍 <a href="https://zohead.com/archives/windscribe-openvpn/">Windscribe 免费 VPN</a> 的文章，住处的网络通过 OpenVPN 连接 Windscribe 之后虽然速度不快，但好歹广电宽带下没有之前用的几个 VPS 经常超时的问题了。因此想着最好能部署到现在用的 newifi mini 路由器上（毕竟已经刷了 PandoraBox 固件），目标就是能在路由器上用 OpenVPN 连接 Windscribe 并自动分流翻墙访问某些特殊的网站。</p>
<h2 id="openwrt-安装使用-openvpn">OpenWRT 安装使用 OpenVPN</h2>
<p>首先在路由器上安装 OpenVPN 客户端：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]# opkg update
[root@PandoraBox:/root]# opkg install openvpn-openssl
</pre>
<p>把上篇文章中生成的 Windscribe OpenVPN 配置文件上传到 <code>/etc/openvpn</code> 目录，假设配置文件路径为 <code>/etc/openvpn/windscribe.ovpn</code>。</p>
<p>这里需要注意 OpenWRT 的 OpenVPN 客户端并不能像 Windows 等客户端那样提示用户输入 Windscribe VPN 连接用户名和密码，只能通过用户密码文件指定。我们需要手工生成用户密码文件 <code>/etc/openvpn/windscribe.txt</code>，文件格式为第一行用户名，第二行密码。</p>
<p>接着修改 OpenVPN 配置文件，增加一行指定用户密码文件：</p>
<pre class="brush: plain; title: ; notranslate">
auth-user-pass windscribe.txt
</pre>
<blockquote>
<p><strong>提示</strong></p>
<p>如果你使用的 OpenVPN 客户端版本比较老（比如我的 PandoraBox 系统里安装的是 2.3.6-2 版本），可能不支持 Windscribe OpenVPN 配置文件里的 <code>block-outside-dns</code> 选项，如果 OpenVPN 运行报错的话可以注释掉这个选项。</p>
</blockquote>
<p>然后修改 <code>/etc/config/openvpn</code> 配置文件增加一个新的 OpenVPN instance，新的配置名称不要与现有的重复即可：</p>
<pre class="brush: plain; title: ; notranslate">
config openvpn 'windscribe'
	option config '/etc/openvpn/windscribe.ovpn'
	option enabled '1'
</pre>
<p>剩下就是激活并启动 OpenVPN 客户端服务了：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]# /etc/init.d/openvpn enable
[root@PandoraBox:/root]# /etc/init.d/openvpn start
</pre>
<p>稍等一会，如果一切正常的话，用 <code>logread</code> 命令应该能看到 OpenVPN 的连接日志：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]# logread -f
Fri Jul  7 00:02:13 2017 daemon.notice openvpn(windscribe)[5618]: TUN/TAP device tun0 opened
Fri Jul  7 00:02:13 2017 daemon.notice openvpn(windscribe)[5618]: do_ifconfig, tt-&gt;ipv6=0, tt-&gt;did_ifconfig_ipv6_setup=0
Fri Jul  7 00:02:13 2017 daemon.notice openvpn(windscribe)[5618]: /sbin/ifconfig tun0 10.110.34.41 netmask 255.255.254.0 mtu 1500 broadcast 10.110.35.255
Fri Jul  7 00:02:13 2017 daemon.notice openvpn(windscribe)[5618]: Initialization Sequence Completed
</pre>
<p>连接上服务器之后可以看看 OpenVPN tun 设备路由信息：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]# route -n
Kernel IP routing table
Destination     Gateway         Genmask         Flags Metric Ref    Use Iface
0.0.0.0         10.110.34.1     128.0.0.0       UG    0      0        0 tun0
0.0.0.0         10.58.71.1      0.0.0.0         UG    0      0        0 eth0.2
10.58.71.0      0.0.0.0         255.255.255.0   U     0      0        0 eth0.2
10.110.34.0     0.0.0.0         255.255.254.0   U     0      0        0 tun0
103.10.197.3    10.58.71.1      255.255.255.255 UGH   0      0        0 eth0.2
128.0.0.0       10.110.34.1     128.0.0.0       UG    0      0        0 tun0
192.168.1.0     0.0.0.0         255.255.255.0   U     0      0        0 br-lan
</pre>
<h2 id="dnsmasq-配置修改">dnsmasq 配置修改</h2>
<p>与之前使用的 Shadowsocks 通过 ipset 自动分流类似，我们首先需要在 OpenWRT 上安装 <code>dnsmasq-full</code> 和 <code>ipset</code> 包。</p>
<p>基本原理也很简单，OpenWRT 上的 dnsmasq 服务器将 gfwlist 中的域名通过 OpenVPN 解析防止域名污染并将解析结果添加到 ipset，然后设置 ipset 中的所有 IP 地址都走 OpenVPN 翻墙，其它地址仍然走默认的宽带线路。</p>
<p>dnsmasq 使用 gfwlist 和 gfwlist 自动更新的方法可以参考我之前写的 <a href="https://zohead.com/archives/newifi-mini-openwrt/">newifi mini路由器OpenWRT初步体验</a> 文章。</p>
<p>我的服务器上基于 gfwlist 自动生成的 dnsmasq 配置文件地址没有变：</p>
<p><a href="https://zohead.com/downloads/dnsmasq.tar.gz">https://zohead.com/downloads/dnsmasq.tar.gz</a></p>
<p>只是自动更新 gfwlist 的 crontab 配置文件要修改一下了，因为上面的 dnsmasq 配置文件是为 Shadowsocks 本地转发解析域名准备的，这里换成 Google 提供的 <code>8.8.8.8</code> DNS 解析服务器：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]#cat /etc/crontabs/root
10 5 * * * curl -k -o /tmp/dnsmasq.tar.gz https://zohead.com/downloads/dnsmasq.tar.gz &amp;&amp; tar -C /tmp -xzf /tmp/dnsmasq.tar.gz &amp;&amp; sed -i 's/127\.0\.0\.1#5353$/8.8.8.8/g' /tmp/dnsmasq_list.conf &amp;&amp; cat /tmp/dnsmasq_list.conf &gt; /etc/dnsmasq.d/dnsmasq_list.conf &amp;&amp; rm -f /tmp/dnsmasq.tar.gz /tmp/dnsmasq_list.conf
</pre>
<h2 id="配置-ipset-自动分流">配置 ipset 自动分流</h2>
<p>首先修改 <code>/etc/iproute2/rt_tables</code> 配置文件，为 OpenVPN 专门增加一个名字为 <code>gfwtable</code> 的路由表（数字不和现有的表重复即可）：</p>
<pre class="brush: plain; title: ; notranslate">
99	gfwtable
</pre>
<p>需要注意的是我们可以从上面的 OpenVPN tun 设备路由信息中看到 OpenVPN 客户端连接上服务器之后自动添加了默认路由，而为了使默认流量都走宽带线路，需要修改 OpenVPN 配置文件禁用默认路由：</p>
<pre class="brush: plain; title: ; notranslate">
route-nopull
</pre>
<p>编辑 <code>/etc/firewall.user</code> 文件增加自定义的防火墙规则：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]# cat /etc/firewall.user
ipset -N gfwlist iphash
iptables -t mangle -N fwmark
iptables -t mangle -C OUTPUT -j fwmark || iptables -t mangle -A OUTPUT -j fwmark
iptables -t mangle -C PREROUTING -j fwmark || iptables -t mangle -A PREROUTING -j fwmark
</pre>
<p>分别简单解释一下：</p>
<ul>
<li>第一行增加新的 iphash 类型的名为 <code>gfwlist</code> 的 ipset；</li>
<li>第二行在 iptables 的 <code>mangle</code> 表中新增 <code>fwmark</code> 链；</li>
<li>第三和第四行分别在 iptables 的 <code>mangle</code> 表的 <code>OUTPUT</code> 和 <code>PREROUTING</code> 链中增加 <code>fwmark</code> target，为了避免重复，增加之前都用了 iptables 命令判断原有规则是否已经存在；</li>
<li>后面三条规则有些 OpenWRT 系统里已经自带了，这里为了保险还是加上了。</li>
</ul>
<p>接着还要再修改 Windscribe OpenVPN 配置文件，增加 VPN 的启动和停止脚本设置，因为我们要在脚本中 添加 / 删除 路由和 iptables 规则：</p>
<pre class="brush: plain; title: ; notranslate">
script-security 2
up /etc/openvpn/openvpn-up.sh
down /etc/openvpn/openvpn-down.sh
</pre>
<p>当然别忘了给 OpenVPN 启动和停止脚本增加执行权限：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]#chmod +x /etc/openvpn/openvpn-up.sh /etc/openvpn/openvpn-down.sh
</pre>
<p>OpenVPN 调用启动和停止脚本的参数格式会区分 tun 和 tap 设备，对于 tun 设备脚本调用参数是这样的：</p>
<pre class="brush: bash; title: ; notranslate">
cmd tun_dev tun_mtu link_mtu ifconfig_local_ip ifconfig_remote_ip [ init | restart ]
</pre>
<p>tap 设备则是：</p>
<pre class="brush: bash; title: ; notranslate">
cmd tap_dev tap_mtu link_mtu ifconfig_local_ip ifconfig_netmask [ init | restart ]
</pre>
<p>这里我们只需要关心第一个 tun /tap 设备名参数，我的 OpenVPN 启动脚本如下：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]#cat /etc/openvpn/openvpn-up.sh
#!/bin/sh
ip route add 8.8.8.8 dev $1
iptables -t mangle -A fwmark -m set --match-set gfwlist dst -j MARK --set-mark 0xffff
ip rule add fwmark 0xffff table gfwtable
ip route add default dev $1 table gfwtable
iptables -I FORWARD -o $1 -j ACCEPT
iptables -t nat -I POSTROUTING -o $1 -j MASQUERADE
</pre>
<p>同样简单说明一下：</p>
<ul>
<li>首先将 <code>8.8.8.8</code> DNS 解析服务器设置为从 OpenVPN 走防止域名污染；</li>
<li>使用 iptables <code>mangle</code> 表中的 <code>fwmark</code> 链为所有目标为 gfwlist ipset 中 IP 地址的数据包打标记，这里标记号用的是 0xffff；</li>
<li>所有标记号为 0xffff 的数据包都使用上面新增的 <code>gfwtable</code> 路由表；</li>
<li><code>gfwtable</code> 路由表固定使用 OpenVPN 线路；</li>
<li>最后两条 iptables 规则也非常重要，允许路由器下的其它设备访问被封锁域名时走 OpenVPN 线路。</li>
</ul>
<p>类似的 OpenVPN 停止脚本就比较简单了：</p>
<pre class="brush: bash; title: ; notranslate">
[root@PandoraBox:/root]#cat /etc/openvpn/openvpn-down.sh
#!/bin/sh
ip rule del table gfwtable
iptables -t mangle -D fwmark -m set --match-set gfwlist dst -j MARK --set-mark 0xffff
iptables -D FORWARD -o $1 -j ACCEPT
iptables -t nat -D POSTROUTING -o $1 -j MASQUERADE
</pre>
<p>都是清理启动脚本中增加的规则，ip route 项会在 tun 设备停止时自动删除，不需要手工进行清理了。</p>
<h2 id="总结">总结</h2>
<p>经过这番对 OpenWRT 的配置折腾，现在住处的手机和电脑就都能通过 Windscribe OpenVPN 自动翻墙了。</p>
<p>最后贴上我的 newifi mini 路由器上的 Windscribe 完整 OpenVPN 配置文件给大家参考，由于文件比较长我放到 Pastebin 上了，最后祝大家炎炎夏日也能玩的开心：</p>
<p><a href="http://pastebin.com/raw.php?i=TWbaMXdg" target="_blank">http://pastebin.com/raw.php?i=TWbaMXdg</a></p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/openwrt-openvpn-ipset/feed/</wfw:commentRss>
		<slash:comments>36</slash:comments>
		</item>
		<item>
		<title>使用OpenVPN连接Windscribe免费VPN</title>
		<link>https://zohead.com/archives/windscribe-openvpn/</link>
		<comments>https://zohead.com/archives/windscribe-openvpn/#comments</comments>
		<pubDate>Fri, 07 Jul 2017 16:59:16 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[网络]]></category>
		<category><![CDATA[OpenVPN]]></category>
		<category><![CDATA[VPN]]></category>
		<category><![CDATA[Windscribe]]></category>
		<category><![CDATA[广电]]></category>
		<category><![CDATA[翻墙]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1466</guid>
		<description><![CDATA[前言 最近换了住处之后，我还是没想到平时上网的宽带问题会成为一大痛点：现在住的地方基本上只能办理南京的广电宽带。广电宽带不但有着臭名昭著的速度慢游戏卡以及墙中墙问题，而且由于其 IP 地址资源有限，访问一些网站经常出现 IP 全国各地乱飞的情况，最要命的是其出国线路与我之前用的移动宽带完全没法比。 我观察到的南京广电宽带基本出国都是走联通线路，使用的是内蒙古包头之类的奇葩 IP 地址。之前在住处用于翻墙的 AlphaRacks VPS 和 Arukas 容器搭建的 Shadowsocks 服务器现在基本都处于不可用的状态，Google 搜索勉强能打开，Gmail 经常卡的不要不要的，YouTu [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="前言">前言</h2>
<p>最近换了住处之后，我还是没想到平时上网的宽带问题会成为一大痛点：现在住的地方基本上只能办理南京的广电宽带。广电宽带不但有着臭名昭著的速度慢游戏卡以及墙中墙问题，而且由于其 IP 地址资源有限，访问一些网站经常出现 IP 全国各地乱飞的情况，最要命的是其出国线路与我之前用的移动宽带完全没法比。</p>
<p>我观察到的南京广电宽带基本出国都是走联通线路，使用的是内蒙古包头之类的奇葩 IP 地址。之前在住处用于翻墙的 AlphaRacks VPS 和 Arukas 容器搭建的 Shadowsocks 服务器现在基本都处于不可用的状态，Google 搜索勉强能打开，Gmail 经常卡的不要不要的，YouTube 视频则基本不用想了。</p>
<p>更恶心的是广电宽带还直接屏蔽了 ICMP ping 外网的请求，只能 ping 广电内网的地址，至于普通的 <code>traceroute</code> 路由跟踪就更别想了。</p>
<p>下面贴出来的是我在 Linux 下使用专用的 TCP 路由跟踪 <code>tcptraceroute</code> 命令看到的惨不忍睹的结果，目的地址是移动宽带下用的无比顺畅的日本免费 Arukas 容器：</p>
<pre class="brush: bash; title: ; notranslate">
(trusty)zzm@localhost:~$ tcptraceroute -n 153.125.238.173 31626
Selected device wlan0, address 192.168.1.243, port 50713 for outgoing packets
Tracing the path to 153.125.238.173 on TCP port 31626, 30 hops max
 1  192.168.1.1  1.321 ms  1.567 ms  3.853 ms
 2  10.58.71.1  9.688 ms  14.964 ms  11.497 ms
 3  192.168.104.57  8.138 ms  20.722 ms  9.597 ms
 4  111.208.1.141  10.785 ms  11.364 ms  8.861 ms
 5  111.208.1.190  9.602 ms  10.524 ms  11.136 ms
 6  192.168.3.225  8.822 ms  9.481 ms  8.833 ms
 7  * * *
 8  172.16.116.13  70.035 ms  71.014 ms  68.664 ms
 9  * * *
10  * * *
11  * * *
12  * * *
13  * * *
14  * * *
15  * * *
16  * * *
17  * * *
18  * * *
19  * * *
20  * * *
21  * * *
22  * * *
23  * * *
24  * * *
25  * * *
26  * * *
27  * * *
28  * * *
29  * * *
30  * * *
Destination not reached
</pre>
<p>由于我平常也使用 Chromebook 设备，特别依赖 Google 服务，Gmail 自不必说，经常要用 Google Drive 同步文件，另外也使用 Google Photos 备份照片，这样必须无法忍受需要找其它翻墙方案。</p>
<h2 id="关于-windscribe-vpn">关于 Windscribe VPN</h2>
<p><a href="https://windscribe.com/?friend=uxavdz64">Windscribe</a> 还是从我一个同事那里了解到的免费 VPN 服务，默认提供每个月 10GB 的流量，免费账户也有多国服务器可选，通过代金券可以增加到每月 50GB 或者 60GB。</p>
<p>需要的朋友可以通过下面的链接注册（没错，带了我的推荐小尾巴 ^_^），需要注意 Windscribe 网站必须翻墙才能打开：</p>
<p><a href="https://windscribe.com/?friend=uxavdz64" target="_blank">https://windscribe.com/?friend=uxavdz64</a></p>
<p>Windscribe 的付费账户则是无限流量每月 $7.50 美元起，最近他们在搞 Lobster Lover 优惠活动，现在付费账户限时 3 折促销每年 $29.99 美元，有需要的朋友可以注册之后用 <a href="https://windscribe.com/upgrade?promo=LOBSTER1&amp;pcpid=lobster_july_2017" target="_blank">Lobster Lover</a> 链接优惠升级哦。</p>
<p>账户注册完成之后登录，在 <code>My Account</code> 页面中点击 <code>Claim Voucher</code> 按钮输入代金券代码：</p>
<ul>
<li><code>SOS60GBS</code>，流量增加到每个月 60 GB，暂不确定什么时候过期；</li>
<li><code>50GBFREE</code>，流量增加到每个月 50 GB。</li>
</ul>
<p>Windscribe 提供了 Windows、Mac OS X、iPhone 下的客户端，而且还有官方的 Chrome、Firefox、Opera 浏览器下的 VPN 扩展程序，客户端下载链接在此：</p>
<p><a href="https://chn.windscribe.com/download" target="_blank">https://chn.windscribe.com/download</a></p>
<p>从下载页面可以看到 Linux、Android 客户端都只有收费账户才支持，而且 Windscribe 并没有直接提供 Linux 和 Android 下的官方客户端，而是通过 OpenVPN、IKEv2、SOCKS5 等配置文件的方式让用户使用其它工具来连接 Windscribe VPN 服务器。</p>
<h2 id="openvpn-连接-windscribe">OpenVPN 连接 Windscribe</h2>
<p>如此看来 Windscribe 是直接支持以 OpenVPN 方式来连接的，当然收费账户可以从下面的链接直接下载 OpenVPN 配置文件和证书：</p>
<p><a href="https://chn.windscribe.com/getconfig/openvpn" target="_blank">https://chn.windscribe.com/getconfig/openvpn</a></p>
<p>虽然免费账户无法下载 OpenVPN 配置，但我估计 Windows 等系统下的客户端很有可能还是以 OpenVPN 方式实现的，马上下载安装 Windows 客户端来确认。</p>
<p>客户端安装的时候会自动提示安装 OpenVPN 的 TAP 驱动，完成之后使用 Windscribe 账户登录，默认会选择离我们最近的香港服务器。连接成功之后就能在进程列表看到 Windscribe 的 <code>windscribeopenvpn.exe</code> 程序，而且在命令行参数中还能看到 OpenVPN 配置文件路径：</p>
<pre class="brush: plain; title: ; notranslate">
&quot;C:\Program Files (x86)\Windscribe\windscribeopenvpn.exe&quot; --config &quot;C:/Users/xxx/AppData/Local/Windscribe/Windscribe/config.ovpn&quot; --management 127.0.0.1 57593 --management-query-passwords --management-hold
</pre>
<p>首先从下面的路径把 OpenVPN 配置文件拷贝出来：</p>
<pre class="brush: plain; title: ; notranslate">
C:/Users/xxx/AppData/Local/Windscribe/Windscribe/config.ovpn
</pre>
<p>配置文件内容大概是这样的：</p>
<pre class="brush: plain; title: config.ovpn; notranslate">
client
dev tun

nobind
auth-user-pass
reneg-sec 432000
resolv-retry infinite

auth SHA512
cipher AES-256-CBC
keysize 256
comp-lzo
verb 2
mute-replay-warnings
ns-cert-type server
persist-key
persist-tun

key-direction 1
&lt;ca&gt;
-----BEGIN CERTIFICATE-----
xxxxxx
-----END CERTIFICATE-----
&lt;/ca&gt;
&lt;tls-auth&gt;
-----BEGIN OpenVPN Static key V1-----
xxxxxx
-----END OpenVPN Static key V1-----
&lt;/tls-auth&gt;
block-outside-dns

remote 103.10.197.3
port 443
proto udp
</pre>
<p>中间的 CA 证书和 TLS 认证 key 太长就没有全部贴出来了，<code>remote</code> 明显就是 Windscribe OpenVPN 服务器的地址，这里的 <code>103.10.197.3</code> 就是 Windscribe 的香港服务器。</p>
<p>现在剩下的问题就是 OpenVPN 的登录用户名和密码了，Windscribe 的 <a href="https://chn.windscribe.com/guides/ubuntu" target="_blank">Linux 客户端说明</a> 中明确提醒用户需要注意的就是 OpenVPN 用户名和密码并不是 Windscribe 账户名和密码。</p>
<p>Windscribe 的 Windows 客户端里并没有直接提供用户名和密码，而且 Windscribe 网站上也只有付费账户才能得到，但这并不妨碍我们从 Windscribe 客户端的日志文件中找出端倪。</p>
<p>打开 Windscribe 客户端的日志文件：</p>
<pre class="brush: plain; title: ; notranslate">
C:\Users\xxx\AppData\Local\Windscribe\Windscribe\log.txt
</pre>
<p>不出意外的话你应该能在其中找到类似下面的输出：</p>
<pre class="brush: plain; title: ; notranslate">
[0607 03:18     36.573] [basic]	 state = CONNECT_BUTTON_CONNECTING
[0607 03:18     36.574] [basic]	 radiusUsername:  &quot;nocwat_xxx&quot;
[0607 03:18     36.574] [basic]	 radiusPassword:  &quot;pppppp&quot;
[0607 03:18     36.574] [basic]	 Connecting to &quot;最佳位置&quot;
[0607 03:18     36.574] [connection]	 Use latest successfully connection protocol: &quot;UDP&quot;
[0607 03:18     36.574] [connection]	 Connection settings: automatic
[0607 03:18     36.574] [connection]	 Location nodes: &quot;node1 = {ip1 = 103.10.197.2, ip2 = 103.10.197.3, ip3 = 103.10.197.4}; &quot;
[0607 03:18     36.575] [connection]	 OVPN-config path: &quot;C:/Users/xxx/AppData/Local/Windscribe/Windscribe/config.ovpn&quot;
[0607 03:18     36.575] [connection]	 Connecting to IP: &quot;103.10.197.3&quot;  protocol: &quot;UDP&quot;  port: 443
</pre>
<p>上面日志里的 <code>radiusUsername</code> 和 <code>radiusPassword</code> 就是 Windscribe 的 OpenVPN 服务器登录用户名和密码了。</p>
<p>接着就是打开 OpenVPN 软件使用刚才拷贝出来的 <code>config.ovpn</code> 配置文件，然后用上面的 OpenVPN 用户名和密码登录了，我的免费账户使用这种绕过 Windscribe 官方客户端的方式登录在测试中并没有发现什么问题。</p>
<h2 id="windscribe-服务器列表">Windscribe 服务器列表</h2>
<p>到这里你应该能使用泛用型 OpenVPN 客户端来连接 Windscribe VPN 了，只是 Windscribe 多个地区的 VPN 服务器地址稍微麻烦点，毕竟使用过程中总会遇到某些地区的服务器比较慢需要切换的。</p>
<p>不过还好网上已经有人整理好了 Windscribe 的各地区 VPN 服务器地址了，大家直接从下面的地址下载 UDP 或者 TCP 协议的各地区 OpenVPN 配置文件：</p>
<p><a href="https://github.com/haugene/docker-transmission-openvpn/files/502948/Windscribe-OVPN-UDP.zip" target="_blank">Windscribe-OVPN-UDP.zip</a> <br />
<a href="https://github.com/haugene/docker-transmission-openvpn/files/502949/Windscribe-OVPN-TCP.zip" target="_blank">Windscribe-OVPN-TCP.zip</a></p>
<p>解压缩之后使用其中某个地区的 OpenVPN 配置文件即可，登录时仍然使用前面日志文件中找到的用户名和密码。</p>
<p>当然后面很可能会碰到配置文件中的服务器地址不正确或者 Windscribe 修改了证书之类的情况，不过大家还是可以从 Windscribe 客户端的服务日志中找到正确的服务器地址，例如：</p>
<pre class="brush: plain; title: ; notranslate">
[04-07 12:11:06]	Service started
[04-07 12:15:14]	AA_COMMAND_FIREWALL_CHANGE, AllowLocalTraffic=1, Ips=38.95.108.xxx;xxxxxx;104.18.56.xxx
[04-07 12:15:14]	AA_COMMAND_FIREWALL_IPV6_ENABLE
[04-07 12:15:14]	Error 13
[04-07 12:15:14]	AA_COMMAND_EXECUTE, blocking=0, cmd=&quot;C:\Program Files (x86)\Windscribe\windscribeopenvpn.exe&quot; --config &quot;C:/Users/xxx/AppData/Local/Windscribe/Windscribe/config.ovpn&quot; --management 127.0.0.1 57593 --management-query-passwords --management-hold
</pre>
<p>上面日志输出中的 <code>Ips</code>（并没有全部列出来） 就是客户端获取到的所有 Windscribe VPN 服务器的地址了。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/windscribe-openvpn/feed/</wfw:commentRss>
		<slash:comments>7</slash:comments>
		</item>
		<item>
		<title>移动宽带丧心病狂的流量劫持</title>
		<link>https://zohead.com/archives/cmcc-network-temper/</link>
		<comments>https://zohead.com/archives/cmcc-network-temper/#comments</comments>
		<pubDate>Tue, 30 May 2017 04:26:42 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[生活]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[HTTP]]></category>
		<category><![CDATA[https]]></category>
		<category><![CDATA[中国移动]]></category>
		<category><![CDATA[劫持]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1447</guid>
		<description><![CDATA[流量劫持情况 最近我发现在住处的江苏移动宽带网络环境下用手机浏览一些 HTTP 网站很容易出现和网站内容明显不符的抢红包广告，有时候页面会显示错乱，而在 PC 端打开同样的网址又没有问题。这种情况只在 HTTP 网站上碰到过，初步判断这就是移动宽带一贯使用的流量劫持把戏。 被劫持的网页在手机端显示起来是这样的： 页面中间的浮标和页面下方的开红包图标都明显不是原始网站投放的广告。这种劫持行为一般在手机浏览器上刷新一下就暂时没有了，但很多情况下会碰到运营商插入的广告导致移动端网页布局出现异常，无法正常使用。 劫持情况分析 由于直接在 PC 端打开被劫持的网址很可能不会出现被插入广告的情况，模拟手机 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="mobile-temper">流量劫持情况</h2>
<p>最近我发现在住处的江苏移动宽带网络环境下用手机浏览一些 HTTP 网站很容易出现和网站内容明显不符的抢红包广告，有时候页面会显示错乱，而在 PC 端打开同样的网址又没有问题。这种情况只在 HTTP 网站上碰到过，初步判断这就是移动宽带一贯使用的流量劫持把戏。</p>
<p>被劫持的网页在手机端显示起来是这样的：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442856/mobile-temper.jpg" alt="手机端网页劫持" title="手机端网页劫持"></p>
<p>页面中间的浮标和页面下方的开红包图标都明显不是原始网站投放的广告。这种劫持行为一般在手机浏览器上刷新一下就暂时没有了，但很多情况下会碰到运营商插入的广告导致移动端网页布局出现异常，无法正常使用。</p>
<h2 id="temper-analysis">劫持情况分析</h2>
<p>由于直接在 PC 端打开被劫持的网址很可能不会出现被插入广告的情况，模拟手机浏览器 user agent 也要碰运气才能出现，因此我直接使用 Android Chrome 浏览器的远程调试功能来进行分析。</p>
<p>打开 Android 的 USB 调试功能，通过数据线连接电脑，在 PC 端 Chrome 浏览器上进入：<code>chrome://inspect/#devices</code> 就能看到连接上的 Android 手机上 Chrome 浏览器打开的标签页，为了方便调试和安利给大家，我使用的是直接基于 Chrome 的 Chromebook 设备：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737369839/android-chrome-debug.png" alt="Android Chrome 远程调试" title="Android Chrome 远程调试"></p>
<p>点击标签页下方的 <code>inspect</code> 按钮就可以远程调试了。</p>
<p>在 Elements 调试界面可以看到运营商在网页 <code>&lt;/body&gt;</code> 结束之前插入了两个 div：<code>tuia-fubiao</code> 和 <code>tuia-customer</code>，更恶心的是下面还加了一个隐藏的 <code>iframe</code>。</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737371494/isp-http-temper.png" alt="流量劫持代码" title="流量劫持代码"></p>
<p>不过看了被劫持之后实际的网页源代码你才能感受到移动宽带的丧心病狂，首先网页 <code>&lt;head&gt;</code> 标签之后就插入了奇奇怪怪的广告代码：</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;html lang=&quot;zh-CN&quot; prefix=&quot;og: http://ogp.me/ns#&quot; class=&quot; js rgba borderradius boxshadow textshadow opacity cssanimations cssgradients csstransitions fontface generatedcontent video audio js&quot;&gt;
&lt;!-- BEGIN head --&gt;
&lt;head&gt;
&lt;script src=&quot;https://engine.tuia.cn/api/v1/activity/spm4web?type=0&amp;amp;adslot_id=1180&amp;amp;app_key=34J8hJmWWs5CArNgfbjAzReG2hRK&amp;amp;activity_id=3000000024%2C3613&amp;amp;ua=Mozilla%2F5.0%20(Linux%3B%20Android%206.0.1%3B%20ASUS_Z00AD%20Build%2FMMB29P)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F57.0.2987.132%20Mobile%20Safari%2F537.36&amp;amp;os_type=&amp;amp;device_id=QjotWKjhRBHLKsYJlCzM1493608315747&amp;amp;token=1493608315732&amp;amp;time=1493608316137&amp;amp;wdata_token=34J8hJmWWs5CArNgfbjAzReG2hRKTJfWvzV0zCtEGT1guzhG1493608315751&amp;amp;spm_id=34J8hJmWWs5CArNgfbjAzReG2hRK1VQvIKrTPbIdBvb0xx871493608316140&amp;amp;callback=jsonp_0q7no0fhvv36mq9&quot; async=&quot;&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://engine.tuia.cn/api/v1/activity/spm4web?type=0&amp;amp;adslot_id=927&amp;amp;app_key=34J8hJmWWs5CArNgfbjAzReG2hRK&amp;amp;activity_id=2000000418&amp;amp;ua=Mozilla%2F5.0%20(Linux%3B%20Android%206.0.1%3B%20ASUS_Z00AD%20Build%2FMMB29P)%20AppleWebKit%2F537.36%20(KHTML%2C%20like%20Gecko)%20Chrome%2F57.0.2987.132%20Mobile%20Safari%2F537.36&amp;amp;os_type=&amp;amp;device_id=QjotWKjhRBHLKsYJlCzM1493608315747&amp;amp;token=1493608315756&amp;amp;time=1493608316119&amp;amp;wdata_token=34J8hJmWWs5CArNgfbjAzReG2hRKTJfWvzV0zCtEGT1guzhG1493608315751&amp;amp;spm_id=34J8hJmWWs5CArNgfbjAzReG2hRKTkxmCuzebbLxiPLAaf0S1493608316129&amp;amp;callback=jsonp_w4rcxsrtl47vpid&quot; async=&quot;&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://engine.tuia.cn/api/v1/activity/get4web?request_id=34J8hJmWWs5CArNgfbjAzReG2hRKKtfJakUIBYbHCqfburmv1493608315757&amp;amp;api_version=1.0.0&amp;amp;app_key=34J8hJmWWs5CArNgfbjAzReG2hRK&amp;amp;app_version=1.0.0&amp;amp;app_package=&amp;amp;adslot_id=927&amp;amp;device_type=&amp;amp;os_type=&amp;amp;os_info=&amp;amp;vendor=&amp;amp;model=&amp;amp;screen_size=360*640&amp;amp;device_id=QjotWKjhRBHLKsYJlCzM1493608315747&amp;amp;connection_type=&amp;amp;operator_type=&amp;amp;cellular_id=&amp;amp;ap_mac=&amp;amp;rssi=&amp;amp;ap_name=&amp;amp;wifi_type=&amp;amp;hotspot_type=&amp;amp;geolocation=true&amp;amp;coordinate_type=&amp;amp;longitude=&amp;amp;latitude=&amp;amp;timestamp=&amp;amp;token=1493608315756&amp;amp;time=1493608315756&amp;amp;wdata_token=34J8hJmWWs5CArNgfbjAzReG2hRKTJfWvzV0zCtEGT1guzhG1493608315751&amp;amp;callback=jsonp_9lyfpalx27d62fk&quot; async=&quot;&quot;&gt;&lt;/script&gt;
&lt;script src=&quot;https://engine.tuia.cn/api/v1/activity/get4web?request_id=34J8hJmWWs5CArNgfbjAzReG2hRKl2K0dtAdcAFOYVPamLi11493608315743&amp;amp;api_version=1.0.0&amp;amp;app_key=34J8hJmWWs5CArNgfbjAzReG2hRK&amp;amp;app_version=1.0.0&amp;amp;app_package=&amp;amp;adslot_id=1180&amp;amp;device_type=&amp;amp;os_type=&amp;amp;os_info=&amp;amp;vendor=&amp;amp;model=&amp;amp;screen_size=360*640&amp;amp;device_id=QjotWKjhRBHLKsYJlCzM1493608315747&amp;amp;connection_type=&amp;amp;operator_type=&amp;amp;cellular_id=&amp;amp;ap_mac=&amp;amp;rssi=&amp;amp;ap_name=&amp;amp;wifi_type=&amp;amp;hotspot_type=&amp;amp;geolocation=true&amp;amp;coordinate_type=&amp;amp;longitude=&amp;amp;latitude=&amp;amp;timestamp=&amp;amp;token=1493608315732&amp;amp;time=1493608315737&amp;amp;wdata_token=34J8hJmWWs5CArNgfbjAzReG2hRKTJfWvzV0zCtEGT1guzhG1493608315751&amp;amp;callback=jsonp_5jm97edzjaj18j0&quot; async=&quot;&quot;&gt;&lt;/script&gt;
</pre>
<p>移动宽带在 <code>&lt;head&gt;</code> 的网站原有 script 脚本中间还硬插了一段：</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;script src=&quot;http://112.4.23.122:8848/a_zdyjs.js?aorlu=aHR0cDovL3d3dy5jbGI2LmNvbS5jbi94bWxrZXkvaHRtbC9keXNqL28tdHQtdGFqcy5qcw==&amp;amp;adid=360523&amp;amp;tcca=MTM5NTE3NzE2NjU=&amp;amp;urip=100.65.241.248&amp;amp;stpt=0&amp;amp;edpt=0&amp;amp;orlu=aHR0cDovL2Jsb2cuam9iYm9sZS5jb20vMTExMDM4Lw==&amp;amp;spid=176150497705350&amp;amp;area=0&amp;amp;motn=1477554323&amp;amp;saas=134352896&amp;amp;p7arm=1&amp;amp;p8arm=0&amp;amp;psad=3232268039&amp;amp;atid=1&amp;amp;paat=0&amp;amp;aaid=0&amp;amp;isaa=0&amp;amp;envs=0&amp;amp;ckts=1493608314&amp;amp;type=2&amp;amp;teid=65459&amp;amp;acst=1&amp;amp;swvi=5277681751310447&quot; type=&quot;text/javascript&quot;&gt;&lt;/script&gt;
</pre>
<p>连 CSS 也别想幸免，<code>&lt;/head&gt;</code> 结束也插入了一段，这里的 CSS 代码太长我就不全部贴出来了：</p>
<pre class="brush: css; title: ; notranslate">
&lt;style type=&quot;text/css&quot;&gt;
#tuia-customer{position:fixed;bottom:0;left:0;width:100%;}
#tuia-fubiao{position: fixed;right: 7.5px;top: 250px;overflow: initial;width: 75px; height: 75px; z-index: 2147483647;}
&lt;/style&gt;
&lt;style type=&quot;text/css&quot;&gt;
.tuia-media{position:relative;overflow:hidden;width:100%;max-width:100%}
.tuia-media,.tuia-media *{-webkit-box-sizing:border-box;-moz-box-sizing:border-box;box-sizing:border-box}
.tuia-media .tuia-media-close{position:absolute;top:0;right:0;width:22.5px;height:22.5px;background-image:url(//yun.duiba.com.cn/static/jssdk/e9fa2ce7753ea10e0425f4c7e71d941b.png);background-repeat:no-repeat;background-position:100% 0;-webkit-background-size:15px 15px;background-size:15px 15px}
&lt;/style&gt;
......
</pre>
<p>至于 <code>&lt;/body&gt;</code> 结束之前插入的广告代码是这样的：</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;!-- END html --&gt;
&lt;div id=&quot;tuia-fubiao&quot;&gt;
&lt;div class=&quot;tuia-media&quot; id=&quot;TuiaMediaID_1493608316134&quot;&gt;&lt;div class=&quot;tuia-media-close&quot; style=&quot;background-image:url(https://yun.duiba.com.cn/upload/4UyUC1480924005775.png)&quot;&gt;&lt;/div&gt;
&lt;img class=&quot;tuia-media-pic&quot; src=&quot;https://yun.duiba.com.cn/tuia-media/img/82ejm1th2s.gif&quot;&gt;
&lt;/div&gt;
&lt;/div&gt;
&lt;div id=&quot;tuia-customer&quot;&gt;
&lt;div class=&quot;tuia-media&quot; id=&quot;TuiaMediaID_1493608316116&quot;&gt;&lt;img class=&quot;tuia-media-pic&quot; src=&quot;https://yun.duiba.com.cn/tuia-media/img/qhszjuf9kr.gif&quot;&gt;&lt;/div&gt;
&lt;/div&gt;
&lt;script src=&quot;http://yun.duiba.com.cn/static/jssdk/media-2.2.2.min.js&quot;&gt;&lt;/script&gt;
&lt;div style=&quot;display: none;&quot;&gt;
&lt;iframe src=&quot;http://www.clb6.com.cn/xmlkey/stat.html?zym=s95&amp;amp;sid=1261769958&quot; width=&quot;0&quot; height=&quot;0&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>面对这样被改的面目全非的网页源代码，我简直是无语到极点。移动宽带为了插广告使用这种下作的劫持方式，也难怪手机浏览器上很容易碰到被劫持后一些移动版网站显示错乱的问题了。</p>
<h2 id="temper-iframe">另一种流量劫持</h2>
<p>另外使用移动宽带在手机端上网还可能碰到一种比较常见和看起来稍微「良心」一点的劫持方式。</p>
<p>这是我用 Android Chrome 浏览器访问 <a href="https://sspai.com/" target="_blank">少数派</a> 网站时碰到的劫持情况，被劫持的网页代码变成这样：</p>
<pre class="brush: jscript; title: ; notranslate">
&lt;html&gt;
&lt;head&gt;
&lt;script&gt;var d=&quot;=iunm?=ifbe?=0ifbe?=cpez!je&gt;#c#!tuzmf&gt;#pwfsgmpx.z;!ijeefo&lt;#!sjhiuNbshjo&gt;1!upqNbshjo&gt;1!mfguNbshjo&gt;1!tdspmm&gt;op?=0cpez?=tdsjqu!tsd&gt;#iuuq;00223/5/34/233;99590b`ig`cpuupn/kt@beje&gt;471494'uddb&gt;NUN6OUF4O{F3OkV&gt;'vsjq&gt;211/76/352/359'tuqu&gt;1'fequ&gt;1'psmv&gt;bIS1dEpwM4O{dHGqMnOwcT:1ZXdwZX6ldn:q[B&gt;&gt;'bpsmv&gt;bIS1dEpwM4e4ez6kcHJ3MnOwcT6kcj:5cX&quot;;function i(_,__){_+=__;var $=&quot;&quot;;for(var u=0;u&lt;_.length;u++){var r=_.charCodeAt(u);$+=String.fromCharCode(r-1);}return $;} var c=&quot;ys[YlwbISucD:lfYOrM39ueIRuNT6peH2t'tqje&gt;287275596954112'bsfb&gt;1'q2bsn&gt;86'q3bsn&gt;1'q4bsn&gt;1'q5bsn&gt;6'q6bsn&gt;4'q7bsn&gt;2'bqqe&gt;1'ibtDpvou&gt;1'ibtXijufVtfs&gt;1'npuo&gt;2588665434'tbbt&gt;2454639:7'q8bsn&gt;2'q9bsn&gt;1'qtbe&gt;434337914:'buje&gt;2'qbbu&gt;1'bbje&gt;1'jtbb&gt;1'fowt&gt;1'dlut&gt;25:4745::6'uzqf&gt;3'ufje&gt;7656:'bdtu&gt;2'txwj&gt;6388792862421558#?=0tdsjqu?=0iunm?&quot;;document.write(i(d,c));&lt;/script&gt;
&lt;/head&gt;
&lt;body id=&quot;b&quot; style=&quot;overflow-y: hidden;&quot; rightmargin=&quot;0&quot; topmargin=&quot;0&quot; leftmargin=&quot;0&quot; scroll=&quot;no&quot;&gt;
&lt;div id=&quot;a&quot; style=&quot;border:0px;overflow:hidden;position:absolute;bottom:0px;width:100%;height:75&quot;&gt;
&lt;iframe src=&quot;http://www.clb6.com.cn/xmlkey/html/dysj/o-tt-1.html?spid=176164485843001&quot; width=&quot;100%&quot; height=&quot;100%&quot; frameborder=&quot;0&quot; scrolling=&quot;no&quot;&gt;&lt;/iframe&gt;
&lt;iframe src=&quot;http://112.4.23.122:8848/a/spd?adid=360383&amp;amp;tcca=MTM5NTE3NzE2NjU=&amp;amp;urip=100.65.241.248&amp;amp;stpt=0&amp;amp;edpt=0&amp;amp;orlu=aHR0cDovL3NzcGFpLmNvbS90YWcvYW5kcm9pZA==&amp;amp;aorlu=aHR0cDovL3d3dy5jbGI2LmNvbS5jbi94bWxrZXkvaHRtbC9keXNqL28tdHQtMS5odG1s&amp;amp;spid=176164485843001&amp;amp;area=0&amp;amp;p1arm=75&amp;amp;p2arm=0&amp;amp;p3arm=0&amp;amp;p4arm=5&amp;amp;p5arm=3&amp;amp;p6arm=1&amp;amp;appd=0&amp;amp;hasCount=0&amp;amp;hasWhiteUser=0&amp;amp;motn=1477554323&amp;amp;saas=134352896&amp;amp;p7arm=1&amp;amp;p8arm=0&amp;amp;psad=3232268039&amp;amp;atid=1&amp;amp;paat=0&amp;amp;aaid=0&amp;amp;isaa=0&amp;amp;envs=0&amp;amp;ckts=1493634995&amp;amp;type=2&amp;amp;teid=65459&amp;amp;acst=1&amp;amp;swvi=5277681751310447&amp;amp;usgt=TW96aWxsYS81LjAgKExpbnV4OyBBbmRyb2lkIDYuMC4xOyBBU1VTX1owMEFEIEJ1aWxkL01NQjI5UCkgQXBwbGVXZWJLaXQvNTM3LjM2IChLSFRNTCUyQyBsaWtlIEdlY2tvKSBDaHJvbWUvNTcuMC4yOTg3LjEzMiBNb2JpbGUgU2FmYXJpLzUzNy4zNg==&amp;amp;pushFlag=1&quot; style=&quot;display:none&quot;&gt;&lt;/iframe&gt;
&lt;img id=&quot;close&quot; onclick=&quot;closeAd()&quot; alt=&quot;Close&quot; src=&quot;http://112.4.23.122:8848/close.gif&quot; style=&quot;position:absolute;right:5px;top:5px;overflow:hidden;border:1px solid;border-color:white;background-color:#EFF7FE;width:12px;height:10px;font-family:System;cursor:hand;z-index:9999;&quot;&gt;
&lt;/div&gt;
&lt;div id=&quot;c&quot; style=&quot;border:0px;overflow:hidden;width:100%;height:100%&quot;&gt;
&lt;iframe name=&quot;cn&quot; src=&quot;http://sspai.com/tag/android?t=1493634994258&quot; frameborder=&quot;0&quot; width=&quot;100%&quot; height=&quot;100%&quot; scrolling=&quot;auto&quot;&gt;&lt;/iframe&gt;
&lt;/div&gt;
&lt;/body&gt;
&lt;/html&gt;
</pre>
<p>这是最常见的 iframe 劫持方式，外面的广告代码套上源网站，只能说好歹还没有直接魔改源网站的代码，另外插入的广告代码同样来自 <code>112.4.23.122</code> 这个 IP 地址。</p>
<p>查询之后发现该 IP 地址是：江苏省南京市 全省共用出口 移动，很明显这些流量劫持行为是南京移动宽带内部人员为利益驱使而做的。</p>
<h2 id="process-temper">后续处理</h2>
<p>发现移动宽带的流量劫持行为之后，我首先与南京移动联系进行了投诉，不出所料移动客服又是一番先坚决不承认然后让提供技术证明的节奏，直到我威胁要投诉到工信部，移动才表态愿意处理此问题。</p>
<p>投诉之后的十几天手机访问一些 HTTP 的网站确实没见到广告劫持了，然而好景不长，前些天又在手机上看到了插入的广告，无奈我先在路由器上直接屏蔽了劫持代码中的 IP 地址和网站域名，而且最近马上要搬家换住处了，可能也不会继续用移动宽带了，因此就没有兴趣继续跟进此事咯。</p>
<p>当然目前最好的应对方式还是希望众多网站能尽快切换到全站 HTTPS 了，文章开头截图里被劫持的 伯乐在线 网站仍然在用 HTTP，国内移动互联网流量的大头 微信公众号 也没有切换到 HTTPS（我也碰到过公众号文章被劫持插入代码的情况）。</p>
<p>比较欣慰的是我写这篇文章的时候，少数派 网站看起来也已经使用 HTTPS 了，最后祝大家儿童节快乐 ^_^。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/cmcc-network-temper/feed/</wfw:commentRss>
		<slash:comments>12</slash:comments>
		</item>
		<item>
		<title>小内存OpenVZ VPS使用UML开启BBR</title>
		<link>https://zohead.com/archives/openvz-uml-bbr/</link>
		<comments>https://zohead.com/archives/openvz-uml-bbr/#comments</comments>
		<pubDate>Mon, 06 Mar 2017 18:39:55 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[Linux]]></category>
		<category><![CDATA[User-mode Linux]]></category>
		<category><![CDATA[技术]]></category>
		<category><![CDATA[网络]]></category>
		<category><![CDATA[BBR]]></category>
		<category><![CDATA[busybox]]></category>
		<category><![CDATA[kernel]]></category>
		<category><![CDATA[OpenVZ]]></category>
		<category><![CDATA[Shadowsocks]]></category>
		<category><![CDATA[ShadowsocksR]]></category>
		<category><![CDATA[TAP]]></category>
		<category><![CDATA[UML]]></category>
		<category><![CDATA[VPS]]></category>
		<category><![CDATA[翻墙]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1365</guid>
		<description><![CDATA[前言 Bottleneck Bandwidth and RTT（BBR）是 Google 最近提交到 Linux 4.9 版本内核的新 TCP 拥塞控制算法，BBR 相对于 Linux 中已经用了好多年的默认 CUBIC 算法的主要改进是在有一定丢包率的网络链路上充分利用带宽，另外也能有效降低延迟。这对于很多使用美帝 VPS + Shadowsocks 爬墙方案的人来说应该还是比较有用的，目前从一些更新了内核开启 BBR 的 KVM VPS 用户的反馈来看效果也还是不错的。 我目前使用的爬墙服务器是 AlphaRacks 的低配 OpenVZ VPS，内存只有 96 MB，到国内的线路质量倒还 [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="preface">前言</h2>
<p><a href="https://github.com/google/bbr">Bottleneck Bandwidth and RTT（BBR）</a>是 Google 最近提交到 Linux 4.9 版本内核的新 TCP 拥塞控制算法，BBR 相对于 Linux 中已经用了好多年的默认 CUBIC 算法的主要改进是在有一定丢包率的网络链路上充分利用带宽，另外也能有效降低延迟。这对于很多使用美帝 VPS + Shadowsocks 爬墙方案的人来说应该还是比较有用的，目前从一些更新了内核开启 BBR 的 KVM VPS 用户的反馈来看效果也还是不错的。</p>
<p>我目前使用的爬墙服务器是 AlphaRacks 的低配 OpenVZ VPS，内存只有 96 MB，到国内的线路质量倒还凑合，OpenVZ 虽然没办法直接升级 kernel ，但看到 AlphaRacks 控制面板里能开启 TUN/TAP，那可以考虑捣鼓使用 User-mode Linux（UML）来开启 BBR 了。</p>
<p>User-mode Linux 和 QEMU 这种虚拟机稍微有点类似，但 UML 是直接将 Linux 内核编译成可执行的 ELF 应用层程序，这样可以直接在普通 Linux 环境中运行及调试其它版本 Linux 内核的功能，有关 UML 的详细信息请参考其<a href="http://user-mode-linux.sourceforge.net/">官方网站</a>。</p>
<blockquote>
<p><strong>提示</strong></p>
<p>不想自己编译 UML 内核和构建 UML rootfs 的朋友可以直接拉到「<a href="#use-uml-ss-system">使用 UML Shadowsocks 系统</a>」这部分哦。</p>
</blockquote>
<h2 id="compile-uml-kernel">编译 User-mode Linux 内核</h2>
<h3 id="compile-prepare">准备编译环境</h3>
<p>我是直接在 Windows 10 RS2 64 位系统上编译 UML 内核的，使用 Win10 自带的 Bash on Ubuntu 14.04 环境编译还是非常方便的，而且编译速度相比使用虚拟机也是快了很多。</p>
<p>首先安装编译需要的软件包：</p>
<blockquote>
<p><strong>备注</strong></p>
<p>由于我使用的 OpenVZ VPS 系统是 32 位的，所以这里安装 <code>libc-dev</code> 和 <code>libvdeplug-dev</code> 开发包时都指定了使用 32 位版本；如果你需要编译 64 位版本的 UML 内核，那把下面的 <code>-i386</code> 去掉即可。</p>
</blockquote>
<pre class="brush: bash; title: ; notranslate">
zzm@ZZM-P238:~$ sudo apt-get install build-essential libncurses5-dev libc6-dev-i386 libvdeplug-dev-i386
</pre>
<p>这里安装 <code>libvdeplug-dev</code> 开发包是为了支持 UML 的 <a href="http://wiki.virtualsquare.org/wiki/index.php/VDE_Basic_Networking#Step_3:_run_a_User-Mode_Linux">Virtual Distributed Ethernet（VDE）</a>模式网卡设备，VDE 主要是为了让 UML 的网络功能在类似 Docker 这种连 TUN/TAP 都不支持的系统上也能工作起来。</p>
<p>接着可以下载最新 Linux 4.10.1 版本内核源代码，并解压缩准备配置内核选项，4.10.1 版本源代码解压之后不到 800 MB。</p>
<blockquote>
<p><strong>提示</strong></p>
<p>如果像我一样直接在 Win10 Bash 环境中编译，那么最好将内核源代码解压到 Win10 Bash 的 VolFs 文件系统中（也就是 Ubuntu rootfs 目录，一般直接 cd 到 <code>HOME</code> 主目录即可）。</p>
</blockquote>
<h3 id="uml-kernel-config">UML 内核配置</h3>
<p>如果使用默认的 UML 内核配置是比较简单的，直接下面两步即可，第二步内核配置界面里可以手工开启 BBR 功能：</p>
<pre class="brush: bash; title: ; notranslate">
zzm@ZZM-P238:~/linux-4.10.1$ cp arch/um/configs/i386_defconfig .config
zzm@ZZM-P238:~/linux-4.10.1$ make menuconfig ARCH=um
</pre>
<p>不过为了能编译出体积最小又能满足 BBR 爬墙需要的 kernel，我还是使用自己修改的最小配置，首先将下面的内容保存为 <code>mini.config</code> 文件（如果需要编译 64 位 kernel，那直接把开头的 <code>CONFIG_64BIT=n</code> 这一行去掉即可）：</p>
<pre class="brush: bash; title: ; notranslate">
zzm@ZZM-P238:~/linux-4.10.1$ cat mini.config
CONFIG_64BIT=n
CONFIG_BINFMT_ELF=y
CONFIG_BINFMT_SCRIPT=y
CONFIG_CORE_DUMP_DEFAULT_ELF_HEADERS=n
CONFIG_HOSTFS=y
CONFIG_MCONSOLE=y
CONFIG_MAGIC_SYSRQ=y
CONFIG_KERNEL_STACK_ORDER=1
CONFIG_SWAP=n
CONFIG_SYSVIPC=y
CONFIG_EXPERT=n
CONFIG_EMBEDDED=n
CONFIG_SLUB_DEBUG=n
CONFIG_BLOCK=y
CONFIG_LBDAF=y
CONFIG_DEVTMPFS=y
CONFIG_DEVTMPFS_MOUNT=y
CONFIG_BLK_DEV_BSG=n
CONFIG_BLK_DEV=y
CONFIG_BLK_DEV_UBD=y
CONFIG_BLK_DEV_LOOP=y
CONFIG_IOSCHED_DEADLINE=y
CONFIG_IOSCHED_CFQ=n
CONFIG_DEFAULT_IOSCHED=&quot;deadline&quot;
CONFIG_NETDEVICES=n
CONFIG_STDERR_CONSOLE=y
CONFIG_SSL=y
CONFIG_NULL_CHAN=y
CONFIG_PORT_CHAN=y
CONFIG_PTY_CHAN=y
CONFIG_TTY_CHAN=y
CONFIG_XTERM_CHAN=y
CONFIG_UNIX98_PTYS=y
CONFIG_EXT2_FS=y
CONFIG_PROC_FS=y
CONFIG_PROC_SYSCTL=y
CONFIG_TMPFS=y
CONFIG_SYSFS=y
CONFIG_SCHED_DEBUG=n
CONFIG_NET=y
CONFIG_UNIX=y
CONFIG_INET=y
CONFIG_TCP_CONG_ADVANCED=y
CONFIG_TCP_CONG_CUBIC=y
CONFIG_TCP_CONG_BBR=y
CONFIG_DEFAULT_BBR=y
CONFIG_DEFAULT_TCP_CONG=&quot;bbr&quot;
CONFIG_IPV6=n
CONFIG_SYN_COOKIES=y
CONFIG_NET_SCHED=y
CONFIG_NET_SCH_QFQ=y
CONFIG_NET_SCH_CODEL=y
CONFIG_NET_SCH_FQ_CODEL=y
CONFIG_NET_SCH_FQ=y
CONFIG_NET_SCH_FIFO=y
CONFIG_UML_NET=y
CONFIG_UML_NET_TUNTAP=y
CONFIG_UML_NET_VDE=y
CONFIG_DEBUG_KERNEL=n
CONFIG_MAGIC_SYSRQ_DEFAULT_ENABLE=0x1
</pre>
<p>简单说明一下上面的内核配置选项：</p>
<ul>
<li>启用了 UML 的 hostfs 及 mconsole 等很实用的功能；</li>
<li>支持 UML 的 ubd 块设备，也开启了 loop 设备支持，去掉了 ramdisk 等没什么用的其它设备支持；</li>
<li>支持 proc、sysfs、tmpfs 等虚拟文件系统，真实的文件系统只保留了 ext2 支持，需要 ext3 或者 ext4 支持的朋友请自行修改；</li>
<li>开启 BBR 并设置为默认拥塞控制算法，另外需要为 BBR 启用 Fair Queue 包调度器；</li>
<li>去掉了 IPv6 支持，去掉了所有的网卡设备驱动；</li>
<li>去掉了几乎所有的内核调试信息。</li>
</ul>
<p>然后使用 <code>mini.config</code> 生成新的内核配置文件：</p>
<pre class="brush: bash; title: ; notranslate">
zzm@ZZM-P238:~/linux-4.10.1$ make ARCH=um allnoconfig KCONFIG_ALLCONFIG=mini.config
</pre>
<h3 id="compile-kernel">编译内核</h3>
<p>内核选项配置完毕之后，编译就非常简单了：</p>
<pre class="brush: bash; title: ; notranslate">
zzm@ZZM-P238:~/linux-4.10.1$ make ARCH=um vmlinux -j4
</pre>
<p>这里我开启了 4 个并发编译（make 的 <code>-j4</code> 参数）支持，UML 的 vmlinux 可执行程序在我的笔记本上不到 4 分钟就编译完成了，最终编译出来的 vmlinux 文件大小大概为 3 - 4 MB。</p>
<p>你可以试着运行编译出来的 vmlinux 可执行程序查看编译时使用的内核配置：</p>
<pre class="brush: bash; title: ; notranslate">
[root@localhost ~]# ./vmlinux --showconfig
</pre>
<h2 id="prepare-uml-rootfs">准备 UML rootfs</h2>
<h3 id="prepare-rootfs-ss-libev">准备 rootfs 和 shadowsocks-libev</h3>
<p>既然 UML 内核我都是按最小化编译的，那运行的 rootfs 自然不能用像 Ubuntu、CentOS 那种「庞大」的系统了，这里我直接使用最小化的 busybox rootfs + Shadowsocks 服务端程序和运行库的方式，除了 busybox 基础环境和 Shadowsocks 服务端程序基本没有添加任何其它东西。</p>
<p>最终我将 UML vmlinux 内核文件和 rootfs 目录一起压缩打包起来大小也不过才 3 MB，这样能非常方便地上传到 VPS 上和分享给其他人。当然缺点就是如果需要安装其它的软件那只能手工拷贝到 rootfs 目录中了。</p>
<p>具体 busybox rootfs 的制作方法这里我就不做详细说明了，感兴趣的朋友可以参考相关的文档了解一下，我分别制作了 32 位和 64 位的 busybox rootfs 目录。</p>
<p>另外为了减少 UML 系统的程序依赖和内存占用，Shadowsocks 服务端我选择的是 <a href="https://github.com/shadowsocks/shadowsocks-libev">shadowsocks-libev</a>，这里我也分别编译了最新 3.0.3 版本 32 位和 64 位的服务端程序。</p>
<p>32 位 shadowsocks-libev 我是在 32 位 Ubuntu 14.04 系统下编译的，依赖的动态库也是使用的 Ubuntu 14.04 自带的库文件；64 位 shadowsocks-libev 则是在 64 位 CentOS 6 系统下编译的，所以 64 位运行库版本和 32 位的不同。你问我为什么不用同一个系统？因为我刚好有这两个系统的 VPS 能用来编译，实在是懒的换了 ^_^。</p>
<h3 id="test-uml-rootfs">测试 UML rootfs</h3>
<p>由于 OpenVZ 系统内核不支持 loop 设备，不能挂载文件系统映像进行修改，这里我直接使用 UML 的 hostfs 将 OpenVZ 主机系统的一个目录设为 UML 系统的 rootfs。</p>
<p>现在 UML hostfs 并没有某些网友说的存在只读的限制，而且相比使用 loop 设备或者 ubd 文件系统这种方式，hostfs 并不需要预先产生一个很大的文件，主机也能直接修改 UML rootfs 目录内容，UML 内核也根本不需要支持 ext3、ext4 这种真实的文件系统，综合比较下来实在是没有什么理由不用 hostfs。</p>
<p>首先安装 UML 工具 <code>uml-utilities</code> 软件包，后面的 <code>tunctl</code> 和 <code>uml_mconsole</code> 等命令会用到：</p>
<pre class="brush: bash; title: ; notranslate">
root@zohead:~# apt-get install uml-utilities
</pre>
<p>接着可以配置 OpenVZ 系统上的 TUN/TAP 虚拟网卡和开启端口转发：</p>
<pre class="brush: bash; title: ; notranslate">
root@zohead:~# tunctl -u root
Set 'tap0' persistent and owned by uid 0
root@zohead:~# ifconfig tap0 192.168.0.3 up
root@zohead:~# echo 1 &gt; /proc/sys/net/ipv4/ip_forward
root@zohead:~# iptables -t nat -I POSTROUTING -o venet0 -j MASQUERADE
root@zohead:~# iptables -t nat -A PREROUTING -i venet0 -p tcp --dport 9443 -j DNAT --to-destination 192.168.0.4
root@zohead:~# iptables -t nat -A PREROUTING -i venet0 -p udp --dport 9443 -j DNAT --to-destination 192.168.0.4
</pre>
<blockquote>
<p><strong>备注</strong></p>
<p>上面的命令中假设 TUN/TAP 虚拟网卡 IP 地址为 <code>192.168.0.3</code>（可以自行修改），UML 系统网卡 IP 地址为 <code>192.168.0.4</code>（需要和 TUN/TAP 虚拟网卡地址在同一网段），只将 OpenVZ 主机系统上 <code>9443</code> 端口的 TCP 和 UDP 数据转发到 UML 系统网卡上。</p>
</blockquote>
<p>最后是启动 UML 系统的例子：</p>
<pre class="brush: bash; title: ; notranslate">
root@zohead:~# ./vmlinux-i686 umid=shadowsocks root=/dev/root rootfstype=hostfs rootflags=/root/umlfs-i686 rw mem=48M init=/sbin/init eth0=tuntap,tap0
</pre>
<p>简单说明一下 UML vmlinux 程序的参数：</p>
<ul>
<li><code>umid</code> 参数指定 UML 系统 ID，建议每个 UML 系统都使用的固定的 ID，不然每次运行都会在 <code>~/.uml</code> 目录下产生新的临时目录；</li>
<li><code>rootflags</code> 参数指定 UML rootfs 路径，这里 <strong>必须</strong> 使用绝对路径；</li>
<li><code>mem</code> 参数指定 UML 系统的内存大小，经过我的测试，只运行 shadowsocks-libev 服务端的话就算分配 32 MB 内存看起来也没什么压力；</li>
<li><code>init</code> 参数指定 UML 系统的 init 进程，不建议修改；</li>
<li><code>eth0=tuntap,tap0</code> 则是指定 UML 的 tuntap 模式网卡，使用 OpenVZ 主机系统的 <code>tap0</code> 虚拟网卡设备。</li>
</ul>
<h2 id="use-uml-ss-system">使用 UML Shadowsocks 系统</h2>
<h3 id="uml-linux-sh">uml-linux.sh 脚本</h3>
<p>为了使用起来方便，我把启动 UML 系统和设置端口转发的操作写成了一个 <code>uml-linux.sh</code> 脚本，这样 OpenVZ 系统启动之后可以根据配置自动运行并配置端口转发：</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh
UML_ID=&quot;shadowsocks&quot;
TAP_DEV=&quot;tap0&quot;
ROUTER_DEV=&quot;venet0&quot;
TAP_ADDR=&quot;192.168.0.3&quot;
UML_ADDR=&quot;192.168.0.4&quot;
REV_TCP_PORTS=&quot;&quot;
REV_UDP_PORTS=&quot;&quot;
FWD_TCP_PORTS=&quot;9443&quot;
FWD_UDP_PORTS=&quot;9443&quot;

DIR=&quot;$( cd &quot;$( dirname &quot;$0&quot; )&quot; &amp;&amp; pwd )&quot;

[ ! -d /sys/class/net/$TAP_DEV ] &amp;&amp; tunctl -t $TAP_DEV
ifconfig $TAP_DEV $TAP_ADDR up

echo 1 &gt; /proc/sys/net/ipv4/ip_forward

iptables -t nat -I POSTROUTING -o $ROUTER_DEV -j MASQUERADE

for i in $REV_TCP_PORTS; do
	if [ &quot;x$i&quot; = &quot;x*&quot; ]; then
		P_TMP=&quot;&quot;
	else
		P_TMP=&quot;--dport $i &quot;
	fi
	iptables -t nat -A PREROUTING -p tcp $P_TMP-j RETURN
done
for i in $REV_UDP_PORTS; do
	if [ &quot;x$i&quot; = &quot;x*&quot; ]; then
		P_TMP=&quot;&quot;
	else
		P_TMP=&quot;--dport $i &quot;
	fi
	iptables -t nat -A PREROUTING -p udp $P_TMP-j RETURN
done

for i in $FWD_TCP_PORTS; do
	if [ &quot;x$i&quot; = &quot;x*&quot; ]; then
		P_TMP=&quot;&quot;
	else
		P_TMP=&quot;--dport $i &quot;
	fi
	iptables -t nat -A PREROUTING -i $ROUTER_DEV -p tcp $P_TMP-j DNAT --to-destination $UML_ADDR
done
for i in $FWD_UDP_PORTS; do
	if [ &quot;x$i&quot; = &quot;x*&quot; ]; then
		P_TMP=&quot;&quot;
	else
		P_TMP=&quot;--dport $i &quot;
	fi
	iptables -t nat -A PREROUTING -i $ROUTER_DEV -p udp $P_TMP-j DNAT --to-destination $UML_ADDR
done

nohup $DIR/vmlinux-i686 umid=$UML_ID root=/dev/root rootfstype=hostfs rootflags=$DIR/umlfs-i686 rw mem=48M init=/sbin/init con=pts eth0=tuntap,$TAP_DEV,,$UML_ADDR &amp;
</pre>
<p>一般只要修改脚本最开始的几行配置即可（最后一行 vmlinux 程序和 UML rootfs 路径默认使用脚本所在路径，如果不同请自行修改）：</p>
<ul>
<li><code>TAP_ADDR</code> 为 TUN/TAP 虚拟网卡地址，<code>UML_ADDR</code> 为 UML 系统内网卡地址；</li>
<li><code>REV_TCP_PORTS</code> 和 <code>REV_UDP_PORTS</code> 分别指定 OpenVZ 主机系统需要保留哪些 TCP 和 UDP 端口不转发到 UML 系统（多个以空格隔开），一般如果 UML 系统使用固定的一些端口，那么默认留空即可；</li>
<li><code>FWD_TCP_PORTS</code> 和 <code>FWD_UDP_PORTS</code> 分别指定哪些 TCP 和 UDP 端口需要转发到 UML 系统（默认只写了一个 <code>9443</code>，实际如果需要多个则以空格隔开），如果需要指定端口范围也可以写成 <code>15000:20000</code>，如果需要所有端口都转发到 UML 系统那可以直接写成 <code>*</code>（此时 <code>REV_TCP_PORTS</code> 一般最少要留一个端口用于 SSH 远程登录）；</li>
<li>需要分配给 UML 系统的内存大小请自行修改 vmlinux 的 <code>mem</code> 参数。</li>
</ul>
<h3 id="uml-ss-config">UML Shadowsocks 系统配置</h3>
<p>另外 UML 系统内部的网卡地址配置及启动 shadowsocks-libev 服务端的操作都在 <code>/etc/rc.local</code> 脚本中：</p>
<pre class="brush: bash; title: ; notranslate">
#!/bin/sh
if [ -d /sys/class/net/eth0 ]; then
	ifconfig eth0 192.168.0.4 up
	route add default gw 192.168.0.3 dev eth0
	sleep 2
fi

SS_DNS=&quot;&quot;

[ -f /etc/default/pdnsd ] &amp;&amp; . /etc/default/pdnsd

# start local DNS server if needed
if [ &quot;x$START_DAEMON&quot; = &quot;xyes&quot; -o &quot;x$START_DAEMON&quot; = &quot;xYES&quot; ]; then
	pdnsd -d
	[ $? -eq 0 ] &amp;&amp; SS_DNS=&quot;-d 127.0.0.1 &quot;
fi

for i in `ls /etc/shadowsocks-libev/*.json 2&gt;/dev/null`; do
	SS_NAME=`basename $i .json 2&gt;/dev/null`
	start-stop-daemon -n shadowsocks-$SS_NAME -x ss-server -b -S -- -c $i -u $SS_DNS--fast-open
done

exit 0
</pre>
<p>简单说明一下：</p>
<ul>
<li>这里的 <code>192.168.0.4</code> 网卡 IP 地址就对应上面的 <code>UML_ADDR</code>，<code>192.168.0.3</code> 网关地址就是 <code>TAP_ADDR</code>，因此如果上面脚本中的地址修改了，那么 UML rootfs 的 <code>/etc/rc.local</code> 中的地址也需要修改；</li>
<li>你可以将 shadowsocks-libev 配置文件放到 <code>/etc/shadowsocks-libev</code> 目录中，此脚本会自动遍历并一一启动 <code>ss-server</code> 服务器，同时默认也开启了 TCP Fast Open 和 UDP 转发；</li>
<li>另外 rootfs 里集成了 <code>pdnsd</code> DNS 服务器，如果需要实现 DNS 缓存加速或者 UML 系统的 UDP DNS 解析存在问题，都可以启用 <code>pdnsd</code> 本地 DNS 服务器。</li>
</ul>
<p>配置修改完成之后，运行 <code>uml-linux.sh</code> 脚本就会在后台启动 UML 系统，并根据需要自动启动 shadowsocks-libev 服务器。</p>
<h3 id="control-uml-system">控制 UML 系统</h3>
<p>如果你需要登录到 UML 系统，可以先用 <code>uml_mconsole</code> 命令得到 UML 系统分配到的虚拟终端（第二个参数就是 UML 系统 ID）：</p>
<pre class="brush: bash; title: ; notranslate">
root@zohead:~# uml_mconsole shadowsocks config con0
OK pts:/dev/pts/2
</pre>
<p>然后使用 <code>screen</code> 命令就可以连接到该虚拟终端上（默认什么都不显示，需要按回车键终端才会出来）：</p>
<pre class="brush: bash; title: ; notranslate">
root@zohead:~# screen /dev/pts/2
</pre>
<p>如果想在 OpenVZ 主机系统里直接关闭整个 UML 系统，那也非常简单：</p>
<pre class="brush: bash; title: ; notranslate">
root@zohead:~# uml_mconsole shadowsocks halt
</pre>
<h3 id="uml-ss-download">UML Shadowsocks 系统下载</h3>
<p>为了方便大家使用，我把 32 位和 64 位的 UML 4.10.1 版本 vmlinux 内核程序及配置和 Shadowsocks 服务端 rootfs 目录、<code>uml-linux.sh</code> 脚本一起打包分享给大家。</p>
<p>32 位的 UML Shadowsocks 系统（百度网盘备用）：</p>
<p><a href="https://zohead.com/downloads/uml-shadowsocks-i686.tar.xz">https://zohead.com/downloads/uml-shadowsocks-i686.tar.xz</a> <br />
<a href="https://pan.baidu.com/s/1kVdoWcB" target="_blank">https://pan.baidu.com/s/1kVdoWcB</a></p>
<p>64 位的 UML Shadowsocks 系统：</p>
<p><a href="https://zohead.com/downloads/uml-shadowsocks-x64.tar.xz">https://zohead.com/downloads/uml-shadowsocks-x64.tar.xz</a> <br />
<a href="https://pan.baidu.com/s/1dFDta9N" target="_blank">https://pan.baidu.com/s/1dFDta9N</a></p>
<p>将上面的文件下载到 VPS 某个目录并解压缩，修改 <code>uml-linux.sh</code> 文件中的转发端口，将 <a href="https://wiki.archlinux.org/index.php/Shadowsocks" target="_blank">Shadowsocks 服务端配置文件</a>放到 rootfs 的 <code>/etc/shadowsocks-libev</code> 目录，之后以 root 身份运行 <code>uml-linux.sh</code> 脚本即可。</p>
<blockquote>
<p><strong>提示</strong></p>
<p>如果需要让 ShadowsocksR 服务器使用 TCP 等方式进行域名解析，可以修改 <code>/etc/default/pdnsd</code> 文件将其中的 <code>START_DAEMON</code> 改为 <code>yes</code> 来启用 <code>pdnsd</code> 本地 DNS 服务器。</p>
</blockquote>
<h3 id="uml-ssr-download">UML ShadowsocksR 系统</h3>
<p>考虑到某些网友的需要，我还生成了 32 和 64 位的 UML ShadowsocksR 系统，都是使用的最新支持混淆的 Python 版本 ShadowsocksR 服务器，有需要的朋友可以下载测试（百度网盘为备用下载地址）。</p>
<p>32 位的 UML ShadowsocksR 系统：</p>
<p><a href="https://zohead.com/downloads/uml-shadowsocksr-i686.tar.xz">https://zohead.com/downloads/uml-shadowsocksr-i686.tar.xz</a> <br />
<a href="https://pan.baidu.com/s/1eSDrWye">https://pan.baidu.com/s/1eSDrWye</a></p>
<p>64 位的 UML ShadowsocksR 系统：</p>
<p><a href="https://zohead.com/downloads/uml-shadowsocksr-x64.tar.xz">https://zohead.com/downloads/uml-shadowsocksr-x64.tar.xz</a> <br />
<a href="https://pan.baidu.com/s/1o7F3qpc">https://pan.baidu.com/s/1o7F3qpc</a></p>
<p>ShadowsocksR 系统的 rootfs 只包含了基础 Python 环境和 ShadowsocksR 服务器程序，同样下载并解压缩，由于包含了 Python 环境，该 rootfs 解压缩之后接近 30 MB。</p>
<p>使用前可根据需要修改 <code>uml-linux.sh</code> 文件中的转发端口，将 <a href="https://github.com/breakwa11/shadowsocks-rss/wiki/config.json" target="_blank">ShadowsocksR 服务器 JSON 格式配置文件</a>放到 rootfs 的 <code>/etc/shadowsocks</code> 目录，之后以 root 身份运行 <code>uml-linux.sh</code> 脚本即可（启用 <code>pdnsd</code> 本地 DNS 服务器的方法和上面的相同）。</p>
<h2 id="uml-bbr-compare">UML 系统 BBR 效果</h2>
<p>最后对比一下我的 AlphaRacks OpenVZ VPS 上启用 BBR 前后的对比速度，这里我就直接观看同一个 1080p 的 YouTube 视频来对比统计信息了。</p>
<p>在我的江苏移动宽带环境下，启用 BBR 之前 YouTube 视频连接速度一般只能跑到 1Mbps 左右：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442863/openvz-ss-speed.png" alt="OpenVZ 未启用 BBR 的 YouTube 速度" title="OpenVZ 未启用 BBR 的 YouTube 速度"></p>
<p>而在使用 UML Shadowsocks 系统开启 BBR 之后能跑到 2Mbps，不过有的时候速度还是不太稳定：</p>
<p><img src="http://res.cloudinary.com/digwht2y0/image/upload/v1737442867/openvz-ss-speed-bbr.png" alt="OpenVZ 启用 UML BBR 的 YouTube 速度" title="OpenVZ 启用 UML BBR 的 YouTube 速度"></p>
<p>UML 目前也是主要用于调试验证 Linux 内核功能的，总之 OpenVZ 使用 UML 开启 BBR 的实际使用效果还是需要长期观察测试的，本文也主要关注 UML 系统下使用 Shadowsocks 的问题，并没有考虑通用的情况，如果文章中有任何问题还请提出指正，祝大家玩的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/openvz-uml-bbr/feed/</wfw:commentRss>
		<slash:comments>40</slash:comments>
		</item>
		<item>
		<title>暂时迁移被爬虫扒得内存不足的VPS</title>
		<link>https://zohead.com/archives/vps-anti-spider/</link>
		<comments>https://zohead.com/archives/vps-anti-spider/#comments</comments>
		<pubDate>Sat, 11 Feb 2017 14:44:57 +0000</pubDate>
		<dc:creator><![CDATA[Uranus Zhou]]></dc:creator>
				<category><![CDATA[主机空间]]></category>
		<category><![CDATA[360Spider]]></category>
		<category><![CDATA[Bluemix]]></category>
		<category><![CDATA[HighSpeedWeb]]></category>
		<category><![CDATA[nginx]]></category>
		<category><![CDATA[robots]]></category>
		<category><![CDATA[VPS]]></category>
		<category><![CDATA[内存不足]]></category>
		<category><![CDATA[容器]]></category>
		<category><![CDATA[爬虫]]></category>

		<guid isPermaLink="false">https://zohead.com/?p=1356</guid>
		<description><![CDATA[VPS 内存不足问题 最近一两个月我在查看 VPS 运行日志的时候，经常发现 kernel 日志中会有 Out of memory 内存不足报错，而且报错基本都是 php-fpm 引起的： 从日志里可以看到每个 php-fpm 进程的 rss 内存占用都接近 30 MB，我之前就已经将 LNMP 环境里的 php-fpm.conf 配置文件中的 pm.max_children 改为 8，这样如果碰到同时请求数较多的情况，php-fpm 就可能会占用 240 MB 内存。再加上 MySQL、BTSync 等其它程序也要占用内存，我这个在 HighSpeedWeb 上购买的 256 MB 内存的  [&#8230;]]]></description>
				<content:encoded><![CDATA[<h2 id="vps-out-of-memory">VPS 内存不足问题</h2>
<p>最近一两个月我在查看 VPS 运行日志的时候，经常发现 kernel 日志中会有 Out of memory 内存不足报错，而且报错基本都是 <code>php-fpm</code> 引起的：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# cat /var/log/kern.log
Dec 15 20:11:43 zoserver kernel: [55751339.090508] Out of memory in UB 1253: OOM killed process 32239 (php-fpm) score 0 vm:56336kB, rss:29832kB, swap:0kB
Dec 15 20:11:56 zoserver kernel: [55751352.643620] Out of memory in UB 1253: OOM killed process 32238 (php-fpm) score 0 vm:55580kB, rss:29444kB, swap:0kB
Dec 15 20:11:57 zoserver kernel: [55751353.609602] Out of memory in UB 1253: OOM killed process 32242 (php-fpm) score 0 vm:56088kB, rss:29800kB, swap:0kB
Dec 15 20:12:23 zoserver kernel: [55751379.072308] Out of memory in UB 1253: OOM killed process 32240 (php-fpm) score 0 vm:55496kB, rss:29520kB, swap:0kB
Dec 15 20:12:45 zoserver kernel: [55751401.084746] Out of memory in UB 1253: OOM killed process 32225 (php-fpm) score 0 vm:55848kB, rss:29564kB, swap:0kB
Dec 15 20:13:22 zoserver kernel: [55751438.326072] Out of memory in UB 1253: OOM killed process 32266 (php-fpm) score 0 vm:56008kB, rss:29880kB, swap:0kB
Dec 15 20:13:36 zoserver kernel: [55751452.087637] Out of memory in UB 1253: OOM killed process 32278 (php-fpm) score 0 vm:55328kB, rss:29356kB, swap:0kB
Dec 15 20:13:37 zoserver kernel: [55751453.035146] Out of memory in UB 1253: OOM killed process 32241 (php-fpm) score 0 vm:55752kB, rss:29784kB, swap:0kB
</pre>
<p>从日志里可以看到每个 <code>php-fpm</code> 进程的 rss 内存占用都接近 30 MB，我之前就已经将 LNMP 环境里的 <code>php-fpm.conf</code> 配置文件中的 <code>pm.max_children</code> 改为 8，这样如果碰到同时请求数较多的情况，<code>php-fpm</code> 就可能会占用 240 MB 内存。再加上 MySQL、BTSync 等其它程序也要占用内存，我这个在 <a href="https://zohead.com/archives/blog-hswvps/">HighSpeedWeb</a> 上购买的 256 MB 内存的 VPS 应该就撑不住了，出现 Out of memory 错误也就不足为怪了。</p>
<p>为了找到原因，我决定检查一下出现内存不足时候的 nginx 请求日志：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# more /home/wwwlogs/zohead.log
64.79.85.205 - - [15/Dec/2016:20:11:43 +0800] &quot;GET /archives/tcpkill-nfs/ HTTP/1.1&quot; 200
13304 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:43 +0800] &quot;GET /archives/newifi-mini-openwrt/ HTTP/1.1&quot; 200
18841 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:43 +0800] &quot;GET /archives/category/technology/linux/ubuntu/ HTTP/1.1&quot; 200
11921 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:43 +0800] &quot;GET /archives/category/technology/phone/ HTTP/1.1&quot; 200
12800 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:43 +0800] &quot;GET /archives/category/technology/ HTTP/1.1&quot; 200
14862 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:44 +0800] &quot;GET /archives/category/technology/android/ HTTP/1.1&quot; 200
15127 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:44 +0800] &quot;GET /archives/zerotier-container/ HTTP/1.1&quot; 200
16323 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:44 +0800] &quot;GET /archives/tag/bash/ HTTP/1.1&quot; 200
11221 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
-
64.79.85.205 - - [15/Dec/2016:20:11:44 +0800] &quot;GET /archives/tag/ssh/ HTTP/1.1&quot; 200
11266 - &quot;-&quot; &quot;Mozilla/5.0 (compatible; SMTBot/1.0; +http://www.similartech.com/smtbot)&quot;
</pre>
<p>这就明显是一个不太友善的爬虫干的好事了，由于请求日志太多这里就不列出来了，统计之后可以发现这个 SMTBot 在十几秒钟的时间里请求了几百次，明显超出了 VPS 能处理的范围了。</p>
<p>另外我在检查日志之后还发现经常有各种初步练习用的爬虫也在不断访问 WordPress 博客数据，这种爬虫的特征就是使用各种不同的 User agent：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# more /home/wwwlogs/zohead.log
138.197.19.145 - - [17/Dec/2016:08:28:49 +0800] &quot;GET /robots.txt HTTP/1.1&quot; 200
145 - &quot;-&quot; &quot;Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:00 +0800] &quot;GET /wp-login.php HTTP/1.1&quot; 200
2464 - &quot;http://zohead.com&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:01 +0800] &quot;GET /archives/category/technology/network-tech/https-ssl/ HTTP/1.1&quot; 200
8604 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Windows NT 6.3; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:03 +0800] &quot;GET /archives/category/travel/ HTTP/1.1&quot; 502
166 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Windows NT 6.1; WOW64; rv:28.0) Gecko/20100101 Firefox/28.0&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:03 +0800] &quot;GET /archives/tag/video/ HTTP/1.1&quot; 200
11459 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.131 Safari/537.36&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:03 +0800] &quot;GET /guestbook/ HTTP/1.1&quot; 200
9962 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:03 +0800] &quot;GET /archives/tasker-shell/ HTTP/1.1&quot; 200
13094 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:04 +0800] &quot;GET /archives/category/technology/ HTTP/1.1&quot; 200
13717 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_2) AppleWebKit/537.75.14 (KHTML, like Gecko) Version/7.0.3 Safari/537.75.14&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:04 +0800] &quot;GET /archives/tag/android/ HTTP/1.1&quot; 200
13879 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Macintosh; Intel Mac OS X 10_9_3) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/35.0.1916.114 Safari/537.36&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:04 +0800] &quot;GET /archives/category/technology/android/ HTTP/1.1&quot; 200
13842 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/34.0.1847.137 Safari/537.36&quot;
-
138.197.19.145 - - [17/Dec/2016:08:29:05 +0800] &quot;GET /archives/author/admin/ HTTP/1.1&quot; 200
13716 - &quot;https://zohead.com&quot; &quot;Mozilla/5.0 (Windows NT 6.1; WOW64; rv:21.0) Gecko/20100101 Firefox/21.0&quot;
</pre>
<p>然而这些小爬虫发起请求来也是毫不手软，基本没有在多个请求之间加什么延时的。不过还好看起来爬虫还是读了 <code>robots.txt</code> 文件的，因此可以考虑在 <code>robots.txt</code> 和 nginx 配置里做一些限制。</p>
<h2 id="treatment">防治措施</h2>
<h3 id="mod-robots-txt">修改 robots.txt</h3>
<p>首先把原来不太重视的 <code>robots.txt</code> 文件完善一下，增加了一些限制，大概如下：</p>
<pre class="brush: plain; title: ; notranslate">
User-agent: *
Disallow: /wp-admin/
Disallow: /wp-content/
Disallow: /wp-includes/
Disallow: /*?replytocom=*
Crawl-delay: 30
Sitemap: https://zohead.com/sitemap.xml
</pre>
<p>禁止所有爬虫访问一些 WordPress 内部目录，增加了 <code>Crawl-delay</code> 参数，并设置为 30 秒，防止产生过多的请求。</p>
<h3 id="mod-nginx-config">修改 nginx 配置</h3>
<p>由于并不是所有爬虫都会读取并遵守 robots 协议，特别是 Google 和百度这样的搜索巨头也明确表态不支持上面增加的 <code>Crawl-delay</code> 参数，为此还是需要修改 nginx 配置直接限制并发连接数：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# more /usr/local/nginx/conf/nginx.conf
http {
	limit_req_zone $anti_spider zone=anti_spider:60m rate=200r/m;
}

server {
	limit_req zone=anti_spider burst=5 nodelay;
	set $anti_spider $http_user_agent;
}
</pre>
<p>上面只是简单节选列出了 nginx 服务器配置的修改，使用 <code>limit_req_zone</code> 限制每分钟 200 个请求，最大并发为 5。</p>
<p>经过上面两步修改之后，VPS 日志里的内存不足错误看起来是减少了，但是好景不长，直到过几天我再去检查内核日志和 nginx 请求日志时发现来了一个臭名昭著的家伙，其频繁的请求仍然导致 VPS 出现 Out of memory 问题：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# more /home/wwwlogs/zohead.log
42.236.99.242 - - [09/Jan/2017:05:41:44 +0800] &quot;GET /archives/tag/keepassdroid/?wpmp_switcher=mobile HTTP/1.1&quot; 503
608 - &quot;https://m.zohead.com/archives/tag/keepassdroid/?wpmp_switcher=mobile&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
-
42.236.99.178 - - [09/Jan/2017:05:41:44 +0800] &quot;GET /archives/easymoney-to-feidee/?lang=en&amp;replytocom=641replytocom=641replytocom=641replytocom=640replytocom=641replytocom=641replytocom=640replytocom=640&amp;wpmp_switcher=desktop HTTP/1.1&quot; 503
608 - &quot;https://zohead.com/archives/easymoney-to-feidee/?lang=en&amp;replytocom=641replytocom=641replytocom=641replytocom=640replytocom=641replytocom=641replytocom=640replytocom=640&amp;wpmp_switcher=desktop&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
-
42.236.99.230 - - [09/Jan/2017:05:41:45 +0800] &quot;GET / HTTP/1.1&quot; 301
178 - &quot;http://www.zohead.com/&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
-
42.236.99.194 - - [09/Jan/2017:05:41:47 +0800] &quot;GET /archives/qiniu-https-tamper/?lang=en&amp;replytocom=2190 HTTP/1.1&quot; 200
12300 - &quot;https://zohead.com/archives/qiniu-https-tamper/?lang=en&amp;replytocom=2190&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
-
42.236.99.206 - - [09/Jan/2017:05:41:48 +0800] &quot;GET /archives/category/technology/linux/page/3/?wpmp_switcher=true HTTP/1.1&quot; 503  
608 - &quot;https://m.zohead.com/archives/category/technology/linux/page/3/?wpmp_switcher=true&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
-
180.153.236.19 - - [09/Jan/2017:05:41:48 +0800] &quot;GET /archives/category/technology/cplusplus/ HTTP/1.1&quot; 503
608 - &quot;https://m.zohead.com/archives/category/technology/cplusplus/&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
-
42.236.99.154 - - [09/Jan/2017:05:41:48 +0800] &quot;GET /comments/feed/?lang=en HTTP/1.1&quot; 503
608 - &quot;http://zohead.com/comments/feed/?lang=en&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
-
180.153.236.165 - - [09/Jan/2017:05:41:49 +0800] &quot;GET /archives/tag/start-stop-daemon/?lang=en&amp;wpmp_switcher=mobile HTTP/1.1&quot; 200
8502 - &quot;http://zohead.com/archives/tag/start-stop-daemon/?lang=en&amp;wpmp_switcher=mobile&quot; &quot;Mozilla/5.0 (compatible; MSIE 9.0; Windows NT 6.1; Trident/5.0); 360Spider&quot;
</pre>
<p>上面只是同一时段博客访问日志的很小一部分，360 搜索的 360Spider 爬虫在不断访问博客，而且看起来 360 服务器集群机器也是相当多，360 蜘蛛的 IP 地址列表可以在其官网查看：</p>
<p><a href="https://www.so.com/help/spider_ip.html">https://www.so.com/help/spider_ip.html</a></p>
<p>经过分析日志我发现最要命的是 360 爬虫根本就没有读取 <code>robots.txt</code> 文件，这样根本谈不上让 <code>Crawl-delay</code> 之类的参数发挥作用。</p>
<h2 id="migrate-server">迁移服务器</h2>
<p>经过我差不多一个月的观察，现在 VPS 遇到的内存不足问题基本都是由 360 爬虫引起的，另外偶尔也有一些小爬虫不按规矩狂发请求。只是考虑到现在这个 256 MB 内存的 VPS 始终不是长久之计，因此还是想把博客迁移到其它服务器上。</p>
<p>首先看了看 HighSpeedWeb 现有的<a href="https://billing.highspeedweb.net/cart.php?gid=19">套餐</a>，512 MB 内存以上的 OpenVZ 或 KVM 套餐现在价格也都不太便宜。一番参考之后我准备先将博客迁移到 IBM <a href="https://zohead.com/archives/ibm-bluemix-docker/">Bluemix</a> 容器平台顶着，因为看起来 Bluemix 容器系统里能使用的突发内存量还是比较多的，而且毕竟目前 Bluemix 平台在我这几个月的使用感受来看除了计费不太清晰之外其它方面还算比较稳定的。</p>
<p>现在博客域名的 A 记录已经修改，你现在看到的页面就是运行在 Bluemix 容器上的了。另外最近碰到好几次 HTTP 的博客网站老是被运营商插入广告代码，于是我也直接禁用了 HTTP 支持，现在必须以 HTTPS 方式访问本博客了。这么一来只是略微可惜了原来 HighSpeedWeb 相当稳定的服务器了：</p>
<pre class="brush: bash; title: ; notranslate">
root@zoserver:~# uptime
 21:29:27 up 325 days,  6:16,  1 user,  load average: 0.00, 0.00, 0.00
</pre>
<p>HighSpeedWeb VPS 服务器已经稳定运行了将近一年时间了，基本上自从上次续费时不小心重启了一下服务器之后 DNSPod 的监控就没有再报过警了。因此这段时间如果 Bluemix 容器万一出什么幺蛾子还能尽快切换回 HighSpeedWeb，最后还是希望现在的 Bluemix 容器能尽量稳定运行了，祝大家元宵节玩的开心。</p>
]]></content:encoded>
			<wfw:commentRss>https://zohead.com/archives/vps-anti-spider/feed/</wfw:commentRss>
		<slash:comments>16</slash:comments>
		</item>
	</channel>
</rss>
