普通视图

发现新文章,点击刷新页面。
昨天以前gd1214b's blog

【主机测评】——蓝易云——1C1G 10M香港CN2 服务器 29元/月起

2022年10月10日 20:08

一、商家简介

“蓝易云”2020-2022年成都天上云网络科技有限公司旗下运营,是旗下的云计算服务品牌,专注为个人开发者用户、中小型企业用户、大型企业用户提供一站式核心网络云端部署服务,促使用户云端部署化简为零,轻松快速运用云计算。

云服务器、云虚拟主机、云数据库、云存储、域名、SSL证书、服务器租用托管等服务。

蓝易云创建于2020年,致力于个人及企业上云服务,在数据安全方面提供三层存储技术,保障数据安全及可用性;在网络连接方面使用BGP线路,解决了南北互联互通的问题。同时自身具有容灾性,保障线路安全稳定;在硬件配置方面,搭建纯SSD架构的高性能企业级云服务器,同时采用Intel Haswell CPU、高频DDR4内存、高速Sas3 SSD闪存作为底层硬件配置,分钟级响应速度;在售后保障方面,提供100倍故障相关赔偿方案,并且提供除传统域名业务PUSH转让以外的云服务器、云虚拟主机等服务也支持在线PUSH转让功能。

购买链接:https://tsyvps.com/cart?action=configureproduct&pid=37

香港云标准型和增强型都选择VPC网络的话,还可以组内网。

二、硬件测评

  1. 概览
  1. CPU
    1核E5-2678 V3,经过特别优化,分数接近物理核心:

  2. 硬盘
    SSD固态硬盘,4K读写2000+IOPS,读写速度和IO基本达标:

三、网络测评

  1. 网络延迟
    三网优化线路,全国ping值优秀

去程:

回程:

增强型网络得到进一步优化,相比标准型低10%左右延迟。
2. 网络抖动
网络带宽充足,抖动较小,基本不丢包:

  1. 去程路由
    电信、联通走CN2:

移动走CMI->Telstra->HKBN

  1. 回程路由
    三网回程CN2:
  1. ip质量检测
    IP很干净,没有滥用记录:

流媒体解锁Netflix,Disney+, Spotify, 等

三、服务条款(TOS)

禁止行为:

1.禁止放置木马、病毒、骇客、色情、诈骗、私服、外挂、博彩、赌博用品、仿品站、窃听类、弓弩枪支、仿牌网站、暴力威胁、骚扰内容、煽动仇恨/暴力、以及其他任何违反中国及当地国家法律的内容;

2.禁止使用V-P-N/SS或其他任何网络中转代理服务用于销售或者共享或搭建个人使用;

3.除非您已经获得作者或法律许可,否则您不能以其他任何管道复制受版权保护的音乐,软件,书籍,或其他;

4.禁止发送未经接收方许可的电子邮件(垃圾邮件);

5.禁止在非防御型机器上运行包括但不限于:容易受DDoS流量攻击的网站或程式;

6.禁止各种非正当的机器测试行为(包括但不限于:求攻击、求压力测试等);

7.禁止运行包括但不限于:挖流量矿、各类虚拟币、视频挂机、集羣计算、流量互刷等,对CPU、频宽、硬碟资源消耗极大的软件;

经核实确认,如果用户出现以上行为,我们将有权进行包括但不限于以下处理:要求删除、暂停服务、中止服务、提交给相关执法部门等。

资源使用公约:

1.不得长时间占用大量带宽,使用影响网络效能的软件(包括但不限于:PT下载、BT下载、迅雷、电驴、挖矿等)。

2.不得长时间占用大量磁片I/O,使用影响服务器稳定性的软件(包括但不限于:磁片DD测试、磁片扫描和杀毒软体等)。

3.不得长时间占用大量CPU,使用影响服务器效能的软件(包括但不限于:集群计算、比特币、挖矿等)。

4.非独立服务器的频宽为峰值频宽(非独享频宽),请不要长期占满,否则将被限速峰值频宽的30%-50%。

5.云产品谢绝长时间、大流量纯代理性质连接。(包括服务商节点、多人代理、反向代理)以及使用Windows系统访问海外网站等。

6.基于蓝易云服务运行和交易安全的需要,如您发生或可能发生破坏或试图破坏蓝易云或蓝易云关联公司公平交易环境或正常交易秩序的,或任何使用含有蓝易云或蓝易云关联公司名称、品牌且对他人有误导嫌疑或任何使用某种中英文(全称或简称)、数字、域名等意图表示或映射与蓝易云或其关联公司具有某种关联的,您将有可能被冻结账号。

在VirtualBox上安装macOS虚拟机

2022年10月2日 17:03

零、前言

本篇文章是一篇详细完整的VirtualBox安装macOS Monterey教程,如果你有测试或是学习的需求,但是没有足够的财力可以负担一台苹果电脑,通过虚拟机也是一个不错的选择!

如果在阅读文章的过程中有任何问题,欢迎随时在底下留言,或者联系博主,让我开始介绍今天的主角吧!

一、准备工作

在正式开始今天的教程之前,有几件事情是必须先准备好的,建议完整遵守并做到本章节,确保后续教程顺利。

本篇文章会以Intel CPU 的Windows 11 的电脑来示范教程,如果你是使用Windows 10 也可以,但是因为macOS 所需执行的资源较大,所以建议至少有以下的系统规格:

  • Windows 10 或Windows 11
  • 8GB 内存
  • 100GB 未使用SSD 空间
  • Intel 4 核心以上CPU
    目前经过测试下来,虚拟机器如果配置8GB 内存与2 CPU 核心,运作macOS Monterey 会较为顺畅。

二、安装与配置VirtualBox

  1. 安装
    这边我就不赘述下载与安装的细节,请点我前往VirtualBox 下载页面,并选择Windows 版本下载与安装。
  1. 配置
    在VirtualBox 安装完成后,也必须下载「功能扩充包」安装,详细步骤如下:
  • 点击这里下载扩展包

  • 打开下载的扩展包并进行安装

  • 最后,你应该会看到类似于下面的屏幕截图的内容。

三、安装macOS虚拟机


1. 下载macOS系统镜像

点击下面的链接来下载:
https://drive.gd1214b.icu/onedrive/系统镜像/macOS_Catalina_10.15.5_19F101.iso

2. 创建虚拟机

  • 打开你的 VirtualBox 应用程序并单击新建。
  • 单击专家模式并选择以下选项,然后单击创建。
    • 键入合适的虚拟机名称。
    • 虚拟机位置(建议使用单独的驱动器)。
    • 类型(Mac OS X)。
    • 版本(Mac OS X 64 位)。
    • 内存4 GB(推荐 8 GB 或更高)。
    • 硬盘:选择立即创建虚拟磁盘。
    • 在创建虚拟硬盘窗口中,选择以下选项。
      • 磁盘位置:除非你想更改为新位置,否则默认位置应该没问题。
      • 文件大小:你可以在此处指定磁盘大小。
      • 硬盘文件类型:选择 VHD(虚拟硬盘)格式。
      • 存储在物理硬盘上:选择动态分配选项。但是,如果你想拥有性能更好的磁盘,请选择固定磁盘。固定磁盘,将立即从你的主机分配指定的大小。

3. 编辑虚拟机配置

  • 在System>Motherboard下,将Base Memory增加到12281MB。但是,如果你的系统没有这么多 RAM,你可以使用更低的内存。
  • 从引导顺序部分取消选中软盘。
  • 在处理器选项卡下,将处理器增加到4 个或更高。
  • 在显示窗口中,将视频内存增加到128MB。
  • 在存储部分,单击空>DVD 图标。单击选择磁盘文件。你应该选择从本文下载的macOS Catalina ISO。最后,单击“确定”关闭 macOS Catalina 设置窗口。
  • 把USB控制器调整成「USB 3.0 (xHCI) 控制器,如下图。

4. 通过命令提示符运行 VirtualBox 代码

首先关闭VirtualBox,然后按win+R键,打开“运行窗口”,输入“cmd”并回车,打开命令提示符窗口:

依次输入以下代码并回车:(把VM Name 换成你自己的虚拟机的名字)

cd "C:\Program Files\Oracle\VirtualBox\"
VBoxManage.exe modifyvm "VM Name" --cpuidset 00000001 000106e5 00100800 0098e3fd bfebfbff
VBoxManage setextradata "VM Name" "VBoxInternal/Devices/efi/0/Config/DmiSystemProduct" "iMac19,1"
VBoxManage setextradata "VM Name" "VBoxInternal/Devices/efi/0/Config/DmiSystemVersion" "1.0"
VBoxManage setextradata "VM Name" "VBoxInternal/Devices/efi/0/Config/DmiBoardProduct" "Mac-AA95B1DDAB278B95"
VBoxManage setextradata "VM Name" "VBoxInternal/Devices/smc/0/Config/DeviceKey" "ourhardworkbythesewordsguardedpleasedontsteal(c)AppleComputerInc"
VBoxManage setextradata "VM Name" "VBoxInternal/Devices/smc/0/Config/GetKeyFromRealSMC" 1

如果是使用AMD CPU 的电脑,请多加入下面这一行:

VBoxManage modifyvm "VM Name" --cpu-profile "Intel Core i7-6700K"

(可选)调整虚拟机分辨率(把 HxV 换成你要调整的分辨率,比如 1920x1080):

VBoxManage setextradata "VM Name" VBoxInternal2/EfiGraphicsResolution HxV

5.启动macOS虚拟机

打开 VirtualBox 应用程序,然后单击开始按钮。屏幕上将出现带有一些白色文本的黑色屏幕。

等待几分钟,你应该会看到 macOS Catalina 语言窗口。选择你的语言,然后单击继续箭头。

安装macOS系统

现在,你将看到macOS 实用程序窗口。从列表中选择磁盘工具并单击继续。

选择你的主VHD 磁盘,然后单击擦除按钮。选择以下选项并再次单击擦除。

选择以下选项并再次单击擦除。

  • 名称:Catalina Disk(你可以输入任何你想要的名称)
  • 格式:APFS(如果出现错误,请选择 Mac OS X Extended Journaled)
  • 方案: GUID 分区 MAP

看到以下画面就代表已经成功,接下来退出工具回到上一个画面。

选择「安装macOS Monterey」选项,并点击右下角的「继续」按钮。

按一下「继续」按钮来设置安装的选项,如下图。

接下来请同意软件使用授权条款,如下图。

选择安装的目标硬盘,并点击继续

接下来就会正式开始安装,大约要30 分钟

最终配置

一旦你通过了上一步。你将看到 macOS Catalina 欢迎窗口。选择以下选项。你可以稍后更改大部分设置,所以暂时不用担心。

  • 选择你的 国家 并点击 继续。
  • 选择 键盘布局并单击继续。如果你对默认设置不满意,可以自定义设置。
  • 在“数据和隐私”窗口中,单击继续。
  • 选择现在不传输任何信息。

  • 单击 稍后设置, 然后 单击不登录。单击跳过。你可以稍后添加你的 Apple ID。

  • 点击同意条款和条件 , 然后点击继续。

  • 填写 全名、帐户名、密码和提示,然后单击继续。

  • 如果你想自定义快速设置,你可以点击自定义设置,否则点击 继续。
  • 在分析窗口中,单击继续。
  • 在屏幕时间,单击稍后设置。
  • 暂时不要设置 Siri。跳过它。
  • 选择一个外观主题并单击继续。你可以在暗模式或亮模式和自动模式之间进行选择。
  • 等待几秒钟,你的 macOS 应该已设置完毕。
  • 暂时关闭反馈助手并关闭鼠标和键盘窗口。

现在你已经使用 ISO 镜像在 VirtualBox 上成功安装了 macOS Catalina。

五、结语

苹果官方是不允许在「非苹果」的硬件上安装macOS,本文章纯粹为学术研究与教学目的,请各位在学习完毕后自行把相关文件删除,且不要拿来做任何商用行为。

参考资料

国内至国际骨干 ISP 线路整理

2022年7月27日 14:03

前言

本文主要探讨的是IPv4网络,对于IPv6网络,那就是另一个故事了~ 我想在整理完此文后,对几条重要的线路单独拿出来说一说,我会直接拿接入该线路的VPS来做测试,来最大化给读者可视化线路质量。

此文采用CC BY-NC-SA 4.0协议,可自由摘取片段用于非商业用途分享。

国内几大骨干网介绍

目前国内有三大ISP,电信、联通、移动,电信有2大骨干网——163和CN2,联通有2大骨干网——169和A网,移动只有1个骨干网CMNET,一共有5大骨干网,这些骨干网都有自己的独立国际出口,和国外ISP有直接Peer或Transit。

另外有用于科研和教育用途的2个小型骨干网,CERNET(教育网,主用于高校)和CSTNET(科技网),这2个骨干网也有自己的独立国际出口,但是总体规模远小于电信、联通、移动,故能承载的出国带宽有限。

电信的163骨干网自治系统编号 AS4134

电信的CN2骨干网自治系统编号 AS4809

联通的169骨干网自治系统编号 AS4837

联通的A网骨干网自治系统编号 AS9929

移动的CMNET境内骨干网自治系统编号 AS9808

移动的CMI境外骨干网自治系统编号 AS58453

CERNET骨干网自治系统编号 AS4538

CSTNET骨干网自治系统编号 AS7497

要注意一点的是,CMNET并没有和国外ISP有直接的互联,而是借助其境外骨干网CMI进行互联的。

显然,如果我们只是了解到这里,对于后文的很多内容,读者还是无法理解,所以我们还需要知道这些骨干网更详细的信息,让我们一个个来看。

以下的各AS BGP互联图来自 bgp.he.net ,版权归Hurricane Electric所有。

如果对此已经完全熟悉的朋友建议直接跳过下面这段介绍

AS4134 CHINANET 中国电信163骨干网

宽带业务范围:普通家用宽带、商用宽带、政企宽带

海外加速的专有业务:163精品网套餐(上海地区)

已知出口:北京、上海、广州

全国规模最大的骨干网,享有最大的国际出口,如果读者办理的是一般性的电信宽带又或者是商宽,访问境外网站,如果对方ISP没有购买电信的CN2 Transit,那么就走这个骨干网。

img

AS4809 CNCN(CN2) 中国电信第二代骨干网

宽带业务范围:家用游戏及海外加速宽带、商用跨国优化宽带、政企宽带

海外加速的专有业务:CN2国际精品网套餐(覆盖几乎全国)

已知出口:北京、上海、广州、乌鲁木齐

技术先进,一般到一个ISP有不止一个Policy可以到达,灵活性非常高,因此可以提供稳定快速的国际互联服务,一般对海外聊天、游戏有较高需求的都会使用该网。目前该网是国内到国际网络高峰期能提供最好速率和体验的骨干网之一。

img

AS4837 China Unicom BackBone 中国联通骨干网

宽带业务范围:家宽、商宽、政企宽带

海外加速业务:尚不明确,或当前未推出

已知出口:北京、上海、广州

如果是联通用户,除非访问的对方ISP购买了电信CN2 Transit/联通的CU Premiun,否则一律走169骨干网。该网目前出国拥堵程度小于电信163,但是总体速度和延时可靠性不如CN2。因价格便宜实惠,一般被很多游戏爱好者(国际服玩家)以及对普通外教课程有需求的首选宽带。

通常我们这些Player也会更多倾向的考虑联通宽带,因为目前到国际网络普遍较好的就是联通的169骨干网。

img

AS9929 CHINA UNICOM Industrial Internet Backbone 中国联通工业互联骨干网

宽带业务范围:商业宽带、政企宽带

海外加速服务:本网专做海外加速服务

已知出口:北京、上海、广州

本网前身为网通的骨干网,后与联通合并后改为联通A网,联通将该骨干网用于国际互联加速服务,价格昂贵,主要是跨国企业在使用,该网已无家宽业务。

img

AS9808 China Mobile 中国移动骨干网

img

宽带业务范围:家宽、商宽、政企宽带

海外加速业务:尚不明确,或为高Qos商宽/机房宽带

已知出口:北京、上海、广州

AS9808为移动境内的骨干网,未设与国际ISP Peer,故所有出境流量通过AS58453(CMI)与外网互联。

img

AS58453又被称之为CMI,是移动的国际段骨干网,最早只在香港建网,并接入HKIX,后逐渐扩大至全球。

移动骨干网现如今已经不再具有国际出口优势,目前三网中只略好于电信163。只有高Qos的宽带才可以体验到17年前移动最初的乐趣。

AS4538 CERNET China Education and Research Network 中国教育研究网络

宽带业务范围:各大高校的校园网和部分大型国内云服务提供商

已知出口:北京清华大学

该网不服务于家宽、商宽、政企,一般来说,只有大学生和大学教授才会经常接触到这个网络。

img

国内ISP与国际ISP的互联详情

亚太地区

中国香港

常见ISP:CMI、CUG、NTT、PCCW、Telia、Telstra、CHT、HKBN、HKT、WTT、HGC、GTT、TaTa、HE、Cogentco、SingTel

常见IX:HKIX、EIEHKG(Equinix Internet Exchange HongKong)

常见下游:Cloudflare、Amazon、Azure、Google、CDN77、Cera Network

该地区ISP连接质量排名(仅供参考,有些线路走不同的汇聚层会有不同的质量):

AS4134:CUG > CMI > Telstra >Others(对于163来说,只有CMI、CUG、CN2才可以不被严格的Qos限速,其他163直连的ISP在高峰几乎都一致性地失速,再往后比较就没有意义了)

AS4837:CUG > CMI > PCCW > CHT > HKBN/WTT > HKT > Others

AS58453:CMI > CUG > SingTel > HKIX > NTT > HKBN/WTT > Others

我相信对于很多南方地区的用户来说,对于需要访问一些全球类的网站,离得最近的CDN网络都是在香港(延时最低)。香港机房一直都是很多面向亚太地区服务器托管商的兵家必争之地,所以也涌现出了大量的IDC商家,可惜虽然鱼目混杂,但是能做到价格便宜且到国内直连的却少之又少,直连高昂的宽带单价也劝退了大部分商家。

截至目前,只有国内大厂如阿里云、腾讯云敢大规模对外提供到国内直连的低价的香港轻量云服务,把价格从千元价位瞬间杀至2位数,但是因为需求量极大,而不得不严重超售宽带——极大的延时抖动,随机不确定的丢包,这使得对于托管在腾讯云、阿里云香港的网站的访客来说体验并不好。

CMI - 移动自己的国际骨干网

由于CMI自己也在卖香港资源,所以有些下游会选择直接购买CMI的Transit,来获得高Qos的CMI体验,这样国内用户到这些下游提供商就可以全部走移动的骨干网,来获得高性价比且高质量的访问体验。

境内连接质量:非常高,只要对方下游接入了足够的CMI Transit宽带,峰值宽带基本是移动保证的。无论是电信、联通还是移动(当然移动用户访问过去,优先级是最高的)。虽然高性价比,但是毕竟是香港地区,流量单价依旧远超美欧Transit的单价。

CUG - 联通自己的国际骨干网

  • 感谢知友@Mushroom Kinoko提醒,已经修正。

同移动的CMI,联通也卖香港资源(自治系统编号AS10099),很多下游也选择接入了CUG的资源,这对于联通用户来说,等于获得了很好的质量保证。

境内连接质量:非常高,只要对方下游接入了足够的CUG Transit宽带,峰值宽带基本是联通保证的。无论是电信、联通还是移动(当然联通用户访问过去,优先级是最高的)。

NTT(香港)

可直连的国内骨干网:AS4809、AS58453

在香港地区,只有电信CN2、移动可以直连,其中电信CN2买了NTT Transit 。其余电信163和联通169都会绕路日本和美国,详见NTT(日本)和NTT(美国)。

连接质量:需要注意的是,CN2很多时候不是万能的,特别是香港地区。CN2到香港NTT不可靠,有时候会爆炸,延时会呈现剧烈的抖动,如果需要追求高稳定性,不推荐CN2用户使用接入香港NTT的网络。

移动如果不买他们的商业高Qos宽带,在高峰时期直连NTT会被Qos,丢包和延时都会显著增加,速度一般无法超过10Mbps。对于高Qos的移动用户也并不乐观,高峰时期,因为上海和广州地区汇聚层拥堵显著,所以最高速率往往也无法超过200Mbps

特殊CM2精品网大客户除外,此类客户购买了移动的国际加速业务,移动优先保证此类 VIP 付费客户的宽带,Qos等级仅次于移动内网业务的必要控制流量,是所有运营类宽带里最高的,故除非PoP塞爆,否则在CMI和各大ISP的Peer下都会极力保证合同签约速率,哪怕是NTT、Cogent这些平时流量极大的网络都可以做到插队绿色通道。

PCCW(香港)/HKT

可直连的国内骨干网:AS4134、AS4809、AS4837、AS9929、AS58453

我们平时接触PCCW的机会很多,PCCW也有一个负责国际优化的网络PCCWG (G=Global),我们平时遇到的商家一般接入的都是PCCW(非含G的网)。其实PCCW的效果在平时是被夸大的,就算是线路可以直连实际综合连接效果也仅仅是一个平均水平。

电信163(AS4134)到香港PCCW是否直连看本地电信网络是否有自己的AS号,比如北京电信的AS4847城域网,上海电信的AS4812城域网等。一般来说,如果该地网络有自己的城域网AS号专门管辖,除非商家有特别优化,那么一般到香港PCCW不直连,否则如果是直接位于AS4134上一般会直连。电信网络到PCCW一般只有北京和广州两个汇聚层可达,上海汇聚层不可达,高峰丢包较高,速度不理想。

联通169(AS4837)联通到香港PCCW可能绕美,原因和电信部分相同,不再赘述。直连的情况下,联通到PCCW效果要远远好于电信,处于可用的状态。

联通A网(AS9929) 网络质量基本是这么多网络里面连接到PCCW最好的,延时抖动也是最低的。但是9929的价格比CN2都要贵上好多倍,一般没有点钞能力是用不上的...

移动的CMI(AS58453),如果没有商家优化,移动会随机把路由发往美国、日本、香港三地,以实现流量平衡,在用户看来,这就导致延时时高时低,非常不稳定,不推荐移动使用。

同时,HKT隶属于PCCW,所有的国际出口都是走PCCW/PCCWG的。HKT因为可以走上PCCWG和德国地区直连,所以也被称之为打机神线。但是普通的HKT家宽/静态根据段不一样,联通169可能绕韩国KT,也有可能直连;
联通9929通过PCCW与HKT互联。

Telstra Global(香港)

可直连的国内骨干网:AS4134、AS4837、AS4538、AS9929、AS58453

这个网络我相信教育网用户会比较熟悉,Pacnet就是Telstra的,Telstra 承担了教育网的亚太地区的主要出口。

Telstra是为数不多三网都可以直连香港,对我们很友好的ISP。哪怕是电信163也可以在香港地区直连Telstra,高峰速度也算是电信163网络中顶级的了,我一向非常推荐Telstra,于是在此反复安利了。另外,Telstra也是电信163到亚太地区(特别是印度、澳大利亚、新加坡)低延时的性价比解决方案。

img

Traceroute to India Telstra Global

联通的169网络到Telstra也不差,在香港的直连宽带很大,高峰情况,据近一年的SmokePing数据来看很稳定,如果想要搞一个新加坡的VPS,选Telstra线路的也不差哦~(香港的Telstra线路的VPS很少)

AS9929与Telstra Global有Peer,高峰速度非常可观。

香港Telstra和移动CMI的互联就比较拉垮了.... 整体互联宽带相比与NTT、HKIX而言相形见绌,这也为高峰的延时猛涨买下了伏笔(互联宽带一旦打满,数据包需要排队等待,延时立即升高)。较小的宽带会影响线路的稳定性,如遇DDOS塞满PoP,延时和丢包也会使得网络瞬间不可用。

所以移动用户决定要用Telstra线路的服务器来搞事情之前最好深思熟虑一下 - -

CHT(香港)

可直连国内骨干网:AS4134、AS4837、AS58453

CHT即中华电信,为中国台湾的第一大ISP,拥有2大骨干网(CHW「 HINET」、TWGATE),我们通常说的Hinet即为CHW网络,CHW与TWGATE的关系可以参照电信163和CN2的关系。

事与愿违,从几天前开始,电信163骨干网到CHW网络的效果急转直下,无论是低峰还是高峰的下载速度都只能用惨淡来形容。所以除非你有业务需求,否则我不推荐你把个人网站放在CHW下,高昂的成本价格现在无法匹配上其延时和速度,是个性价比很低的选择。

相比于电信163的拉垮表现,联通169的表现就漂亮的多,差不多的延时却有着更低的丢包,更高的峰值速度。但是鉴于该地区很高的主机售价,如果你是一个联通用户,CHW也未必是最佳的选择。

也别对移动CMI抱有太大的期望,在低峰和高峰表现截然不同,高峰常常极度拉垮,上面的Telstra好歹还是有速度,这个是真的一点速度都跑不出来,不推荐。

HKBN/WTT

可直连国内骨干网:AS4134、AS4837、AS58453

HKBN都主要服务于香港宽带,故一起讨论了,目前没有看到亚太其他有接入它们的案例。一般只有在流媒体解锁用途的时候会用到它。

HKBN三网可以直连,由于没有资料表明HKBN拥有强大的国际骨干网,这两家也没有什么特殊的地方,故点到为止。

HE(香港)

可直连国内骨干网:AS58453(Through HKIX)、AS9929(via HKIX)

移动可以通过HKIX直连HE香港,但是该操作需要IDC调整路由表,否则移动默认连接香港HE会绕美。

联通9929同样也是通过HKIX直连HE香港。曾经是走CUG的HKIX互联,如今是走联通9929自己与HKIX的互联。

爆炸绕路三幻神之一,所以对于电信、联通169和教育网来说,都会绕美,故详见HE(美国)。

TaTa(香港)

可直连国内骨干网:AS4837、AS9929

电信163网络原先和Tata在香港有Peer,但现在基本不走了,具体原因未知。联通和Tata在香港直连,大部分情况下回程绕美,安徽联通商宽到香港GCP/台湾GCP(标准ip)回程走Tata直连。此线路出现的概率极小,联通4837和香港Tata存在带宽大约为600mbps的peer。

在特殊优化下,联通9929可以经过TATA与CUG的Peer来得到直连。但是非优化线路哪怕跟CUG有Peer也绕美。不愧是爆炸绕路三幻神之首...

Cogentco(香港)

可直连国内骨干网:无

爆炸绕路三幻神之一。Cogentco在香港地区没有国内的ISP可以直连。电信、联通9929、移动和教育网会绕美,联通169则绕新加坡,详见Cogentco(美国)、Cogentco(新加坡)

GTT(香港)

可直连国内骨干网:无

GTT在香港地区没有国内的ISP可以直连。三网均会绕美,详见GTT(美国)

中国澳门

常见ISP:中国电信(澳门分公司)、CTM、MTel

中国电信(澳门)

中国电信自己在澳门经营的分公司,国内全部网络都可直连,走AS4134或AS4809(GIA)。

CTM

可直连国内骨干网:AS4134*、AS4837*、AS58453

并非所有IP都直连,非大陆优化的国际网络都不直连

CTM是澳门最早成立的电信公司,在澳门地区提供上网服务,目前仍旧是当地规模最大的ISP。

CTM很早就和电信163、联通169互联,网络质量可靠,但是CTM的机房托管业务把网络分为了2类,一类是国内优化,即提供国内直连路由,一类是更加便宜的国际路由,这类路由不提供国内直连。目前市场上比较平民的澳门VPS都是国际路由,并未针对国内优化。

移动则是在后期不断扩张中涉及澳门移动上网业务,后在澳门建设PoP,但澳门PoP只和香港PoP相连接,所以移动用户如需访问澳门CTM需要先经过香港方可到达,延时自然就不如前者低(大约多了6ms)。

MTel

可直连国内骨干网:AS4134、AS58453

MTel于2011年成立,是所有澳门经营的电信公司里资历最浅的。MTel和中国电信163目前已经实现互联,但因容量很小,导致互联效果不佳——澳门MTel和中国电信163的互联经常打满,延时波动很大,晚高峰受限于整体互联宽带大小,速度也无法令人满意。

联通绕日本NTT,主要取决于联通到日本NTT的表现,移动走自家的澳门PoP,主要取决于CMI是否给力。

中国台湾

常见ISP:HiNet、TFN(台湾固网)、SeedNet、TaNet(台湾学术网络)、HomePlus(中嘉宽频)

常见IX:TWIX

HINET

可直连国内骨干网:AS4134、AS58453、AS4837

其中 AS4134 和 AS4837 延迟都明显要比 AS58453 高一些。广州移动延迟大约 40ms,武汉电信家宽环境中延迟大约 50ms~60ms,北京电信商宽大约 70ms,上海联通商宽延迟大约170ms,长沙联通商宽延迟大约140ms。

HiNet是中华电信(CHT)的一个品牌,也是全台湾最大的宽带提供商。目前台湾地区的主流流媒体解锁都是用了HiNet动态IP(家宽)以及静态IP(商宽、IDC)来解锁的。HiNet拥有整个台湾地区最大的电信骨干网,也是国内出口流量最大的ISP。CHT另拥有一张TWGate的网络,专注国际互联,其性质相当于中国电信的CN2。

TFN

台湾固网

SeedNet

TaNet

HomePlus

日本

常见ISP:NTT、IIJ、KDDI、BBTEC、Telstra、PCCW、BGP.NET

常见IX:JPIX、BBIX、EIEHND(Equinix Internet Exchange Tokyo)

常见下游:Cloudflare、Amazon、Azure、Google、M427、xTom

日本的宽带业务竞争激烈,导致ISP提供商不得不杀出更低的价格来吸引客户,但是往往事与愿违——用户的口碑却更糟糕了。比如,和阿里巴巴合资的SoftBank(软银)公司创立的ISP服务商——BBTEC,看起来是一个不错的选择,实际晚高峰网络拥堵,体验很差劲,试想如果发条消息都要卡半天的话,真的是一件很让人抓狂的事情呢。

不仅是家宽,商宽乃至服务器机房,接入一条ISP线路的成本价格都不菲,况且很多日本IDC只对日本本国居民提供服务,所以催生了很多代办业务,最有名的就是樱花机房的服务器代办服务。往往只有这些对本土开放的IDC才有可能是原生IP(可以解锁当地的众多流媒体、游戏和网站,很有意义),所以哪怕要被代办收取高额的代办费,也会有很多有需求的人士会前去购买。

NTT

可直连国内骨干网:AS4134、AS4809、AS4837、AS9929、AS58423

日本作为NTT的大本营,几乎全国的宽带服务提供商都有NTT的踪迹。因为NTT的骨干网覆盖了日本几乎所有能够覆盖到的地区。

关于日本NTT,我想在文中说明的实在太多了,限于篇幅,我还是精简一下 - -...

NTT和国内ISP互联时间很早,在2000年后,NTT和当时的网通互联,互联出口设在上海和北京,并在上海和北京分别建设NTT的PoP节点(少数国外ISP将PoP设在国内的案例)。

值得一提的是,但是这是目前国内直连日本NTT延时很低且很稳定的渠道,CN2到日本NTT都干不过它,根据实测,目前NTT-9929的速度基本取决于用户接入的9929的带宽速度。

中国电信163和日本NTT之间的扩容就勤快多了,电信还在日本东京设立了PoP方便和日本本土ISP快速互联。听起来很美好是吗?但是这不妨碍电信163和日本NTT之间日常大爆炸(里面大部分都是被巨量的DDOS流量打崩的)。

绝大多数情况下,163-东京NTT、163-新加坡NTT两线是163网络所有互联线路中质量最差的网络,没有之一

根据近一个月的监测记录,上海电信到东京NTT之间的平均延时(周期为半小时)在48~295ms之间抖动,高峰一小时平均丢包率峰值可达40%,高峰一分钟平均丢包率极限情况下达到了惊人的99%,这就导致了高峰哪怕绕美的体验都要强于直连。

联通的169网络早期有2条路线可以前往日本NTT,一条是从北京-大阪,另外一条是上海-东京。虽然联通169一直普遍被用户认为国际出口质量很高,但是这2条NTT的线路也并非各位读者想的那么美好。

北京联通169 - 日本大阪NTT该线其实最早是网通搭建的。联通收购网通后,便把网通的PoP拨给自己使用,直至今日,我们都可以在NTT在北京PoP IP的rDNS上找到来自历史的证明——

129.250.8.26(xe-0.cnc-g.osakjp02.jp.bb.gin.ntt.net)

这里的CNC,就是曾经的China NetCom(中国网通)的缩写,osakjp,指的就是日本大阪。xe是指骨干网路由使用的是Juniper公司研发的路由,每条线为10Gbps端口 。

但是到了现在,由于联通也在不断开拓自己的国际市场,目前联通也在东京和大阪分别设立了PoP,只是目前往北京方向回程依旧在走NTT的北京PoP,往上海直接走的是联通在日本自己的PoP了。

经过了最近的一番扩容和优化,北方联通169往日本NTT方向也有很大的改善(目前暂时停止北京-大阪该线路由,走上海),延时显著降低。虽然去程多绕了一点,但是延时下降了很多,还是可以接受的。

移动作为后来者,前往日本NTT最早都是借助香港CMI出国,近两年才开通了日本东京的PoP,并用上了全新的NCP海缆才得以能够不绕港直连。

但是目前移动到日本NTT都不走NCP,而是继续绕香港CMI,估计在不久的未来直连后会有更低的延时体验。

IIJ

可直连骨干网:AS4134、AS4837、AS58423

中国电信的163与IIJ的互联是通过电信在东京的PoP实现的,国内可以通过三大汇聚层轻松访问PoP节点。互联的网络质量远好于和NTT的质量。IIJ是电信163用户造访日本网站最好的线路之一,目前已经胜过软银,不考虑高峰丢包和延时抖动,是性价比之选。

中国联通169与IIJ的互联方式和电信几乎一样,但是综合来看要好于163与IIJ互联的质量。提供IIJ接入的IDC价格比较亲民的很多,如果不愿意接受软银的高价位的话,不妨试试IIJ。另外,教育网前往IIJ也会走联通169骨干网出国。

目前移动和IIJ的互联已经通过东京移动的PoP来完成,故移动到日本IIJ不再绕香港而是通过NCP海缆直连东京的PoP后与IIJ完成互联,上海移动到东京IIJ参考延时为45ms(实际上可以做到32ms)。

综上,IIJ是日本地区对我们比较友好的,也是价格相较于其他三家比较实惠的一家ISP,如果没有太小众化的需求,上国内走IIJ的VPS是很省心的选择。

BBTEC

可直连骨干网:AS4134、AS4837、AS9929、AS58423

BBTEC(软银)其实是近几年才被我们注意到的一家ISP,在上海地区设有PoP并与电信163和联通169/9929互联。该线路一直被称之为联通到日本最好的线路之一。

想要补充一点的是,9929早期和软银并没有直连Peer,而是借助4837(联通169)作为跳板实现的。而近期在路由测试中,我们可以清楚地看到软银和9929已经在上海PoP实现互联,但是在BGP ToolKit上都未显示2者有任何形式的互联,基本可以判断是Private Peer。

电信163到软银延时相比于NTT属实较低,但是却同样跑不出什么速度来,延时最初是日本御四家里最低的,但是后来因为使用人数的增加,延时逐渐不如IIJ。

联通169到软银的延时则相对不稳定,取决于去程走上海口和北京口,通常BBTEC回程经由自己的上海POP与联通互联。尽管联通和软银互联的优势已经不如以前,但是目前仍旧是联通到日本最好的线路之一。

联通9929到软银的延时稳定,互联速度也取决于用户接入的9929带宽速度。

如今,移动已经在日本的东京设立了PoP,所以从回程看,除了广州移动还是继续走香港CMI,其余均在日本就Peer,并由移动自己的骨干网负责流量回国承载。目前去程依旧全部绕香港CMI,这也导致北方移动延时的升高。总体来说,软银对北方移动不友好。

KDDI

可直连国内骨干网:AS9929

曾经活在传说中的线路,价格昂贵,唯一的优势就是低负载,延迟一般40ms上下抖动。联通9929速度单线程只能跑到100Mbps左右。

新加坡

常见ISP:NTT、Singtel、Telstra、StarHub、MyRepublic、PCCW(G)、Cogentco、HE、Tata、CMI、CUG、BGP.NET、SG.GS

常见IX:SGIX、EIESG(Equinix Internet Exchange Singapore)

下游:OVH、Cloudflare、Google、Amazon

NTT(新加坡)

可直连国内骨干网:AS4134、AS58453

正如你所见,NTT在亚太地区无处不在~ 所以我们一般把NTT视作亚太地区ISP的标杆,这已经成为了事实上公认的标准。

在新加坡,NTT也拥有巨量的骨干资源,轻松连接新加坡所有的本地ISP。NTT也有多条新加坡至日本的海底光缆所有权/使用权,所以NTT可以借新加坡作为跳板,以此连接马来西亚、菲律宾、印度尼西亚、泰国、越南、缅甸、柬埔寨、印度等国,在其后我们也会讨论到这些地区的本地网络情况。

中国电信163与2020年和NTT在新加坡正式建立互联,即意味着新加坡NTT从即日起无需绕行日本再与163骨干网互联,但是情况变得更加糟糕,因为新加坡地区的中国电信163和NTT互联宽带很小,所以几乎全天都处于被塞满的状态,延时异常偏高,丢包率极大,因此非常不推荐使用163连接新加坡地区的NTT。

移动的CMI在新加坡有自己的PoP,同时在当地就可以和NTT互联,因互联宽带很大,所以目前没有看到被塞爆的情况,移动用户目前访问新加坡地区资源的主流渠道就是通过新加坡PoP。

联通9929和联通169目前都不能直连新加坡NTT,请详见日本NTT。

SingTel(新加坡电信)

可直连骨干网:AS4837、AS9929、AS58453

Update: 随着移动CMI Transit在亚太的高性价比的优势被挖掘,我们也可以看到大量走CMI的香港/新加坡VPS出现在市场上。这也是目前最具有性价比的大宽带亚太VPS,但是目前CMI的峰值流量已经达到其容量极限,如果依旧不能大幅度扩容的话,CMI在晚高峰的延时和丢包已经呈现显著增长的趋势。

移动为了减轻自己的跨国骨干网压力,目前已经开始对于第三方ISP收取更高的Transit费用,第三方有些已经采用单向路由的方式来节省成本。对于SingTel来说,大陆->新加坡的这部分流量要远大于新加坡->大陆的流量,而现在拥堵的也主要是新加坡->大陆的这部分流量,所以目前SingTel已经断开了往大陆方向移动在新加坡的直连,改走更加通用的NTT。不过目前移动对自家网络CMI和NTT的质量部署了较为严格的限速策略,导致延时、丢包和速度表现均不佳。

联通的169,在这里把“稳定”两个字表现的淋漓尽致,网络对于亚太的支持绝对可以称为老二,在新加坡地区,联通和SingTel有直接Peer,故整体延时和移动几乎一致,只要回程不绕路,使用SingTel也很棒,目前联通也是唯一SingTel双向新加坡直连的国内ISP。

但是对于中国电信163来说,因163网络和SingTel在世界各地都没有Transit/Peer,这就导致前往新加坡SingTel之前,数据先会被发送至美西Tata/Telia,但是目前电信163和美西的互联早就已经满了(其实不只是163,CN2也满了),所以速度上来说非常糟糕,加上严格的动态Qos策略,使得延时和丢包雪上加霜。

需要补充一下的是,新加坡SingTel是全新加坡最大规模的ISP,在非大陆地区的国际互联上面,SingTel还是有着相当大的优势,如果您在新加坡的话,选择SingTel还是最佳选择。

Telstra Global(新加坡)

可直连骨干网:这都香港直连了,还要什么自行车!

由于接入Telstra的VPS大多在日本、澳大利亚、新加坡,而Telstra和国内御三家主要的Peer在HKG(香港),所以速度肯定差不多的啦~

StarHub

可直连骨干网:AS4134、AS4837、AS58453

StarHub是当地一大本土运营商,提供宽带服务,因为规模较大,常用来解锁新区流媒体的用途。

既然三网都在新加坡和StarHub有Peer,那么是不是就代表着StarHub到我们国内的表现非常优秀呢?实际路由表现并没有读者想象中的那么好。电信163去程是直连但是回程是绕路的,联通169回程是直的但是去程绕了日本NTT。

只有移动比前两者好一些,通过新加坡EIE和Starhub互联,较于前者这种的优势在于IX中心互联非常方便对接IX内的所有网络,但是容量可能有限,难免高峰不爆炸。

MyRepublic

MyRepublic也是当地一大本土运营商,通常被用来解锁新区流媒体的用途。但是MyRepublic没有任何和国内御三家的互联,所以最好使用移动CMI或者CN2中转。

中国电信163、中国联通169网络走NTT,移动走新加坡EIE至StarHub再转MyRepublic。

Cogentco

可直连骨干网:AS4837

近日,中国联通169在新加坡地区和Cogentco开通了新的Peer,使得很多亚太地区Cogent单栈的宽带/服务器都焕发了新的生命,通过联通的169网络,可以做到广州联通到新加坡Cogentco 46ms的延时成绩。

Tata

可直连骨干网:AS4387、AS9929(从AS10099接入)
Tata在新加坡与联通存在peer,可经由AS4837直连广州入口,目前已知经过新加坡Tata到联通的线路几乎都是孟买一带的机器,例如Linode、阿里云、腾讯云等

马来西亚

常见ISP:TMNet (unifi) 、TIMEdotCom (TIME MY)、EBB.MY (Extreme Broadband) 、Allo Technology (City Broadband) 、Maxis Communications Bhd 、Celcom Axiata Berhad 、PCCW(G)、HE、Tata、CMI

常见IX:MYIX (The Malaysia Internet Exchange) 、JBIX (Johor Bahru Internet Exchange (JBIX))

下游:Cloudflare、OVH、MSCHosting (Exabytes)、U Mobile 、DiGi Telecommunications (Telenor)、MYREN (Malaysian Research & Education Network)

马来西亚所有的ISP几乎都对中国移动友好,有些是在 Equinix SG 转一圈后接入 CMI , 有些是接入 NTT 新加坡 后到 NTT HK 再到 CMI HK

TMNet (unifi)

TMNet (unifi) , ASN 为 4788 , 是全马来西亚数一数二的ISP , 几乎垄断马来西亚近70%的固定宽频市场,常用来解锁马区流媒体的用途

可直连骨干网: AS4134 中国电信

中国联通会从新加坡接入 HE.Net 后绕到美国HE.Net 再接入中国大陆

CU

中国电信通过TM接入中国电信日本后接入中国大陆

CTTMNet

CN2 经由Singtel SG 后跳入广州

cn2TMNet

中国移动先是到 Equnix SG 再到 CMI 再到 AS9808
CMCC

和 TIMEdotCom (TIME MY) 的互联很烂,经常出现晚高峰 100ms + 的情况

国际网络质量偶尔抽风

和 OVH 新加坡拥有peering

TIMEdotCom (TIME MY)

TIMEdotCom (TIME MY) , ASN 为 9930 , 是全马来西亚除 TMNet (unifi) 第二大的ISP,提供的家宽配套无论是在速度还是价钱都吊打 TMNet(unifi) , 双向500Mbps带公网IP家宽只需210+人民币,在马来西亚算很便宜了,目前市面上没看见 TIMEdotCom 的VPS,不过可用来解锁马区流媒体

可直连骨干网:

  • IPV4 : N/A

AS9808 会经过:

  1. NTT SG - NTT HK - CMI HK - 9808
  2. HE.NET KL - HE.NET SG - Equinix SG - CMI Guangzhou - 9808

163 骨干网和 TMNet (unifi) 情况类似,会转发到 Tata :
Tata SG - Tata JP - Tata US - 163 骨干网

CN2 会经过 HGC HK 接入大陆 CN2

AS4837 都会经过 Singtel

  • IPV6 : AS4134

仍不确定 TIME 跟 中国电信买了多少容量

可是通过路由可以发现是直接从马来西亚 TIME 骨干网跳入中国电信新加坡 PoP , 后直接到中国大陆电信骨干网

路由

AS4837 : 去程经过 NTT SG - NTT 日本 - 中国大陆
目测回程绕美 ,延迟可达200ms +

路由

其他ISP基本都半斤八两:

  1. Maxis 上 AS4837 同样走 Singtel
  2. Digi / U Mobile 靠AS4788 作为上游所以线路基本和AS4788一致
  3. Allo Technology 最大上游为 Cogent , 也有接入 TMNet , 不排除部分线路走 TMNet 过 , IPV6 最大上游为 HE.Net
  4. EBB.MY 基本靠 HE.Net 做上游,移动/联通/电信都不讨好,不过可以直接接入 CN2

总结:

马来西亚ISP基本都对中国移动友好极少ISP (比如 Maxis / TIMEdotCom) 在连接中国联通时走的是 Singtel 直连,不过延迟90+ , 有可能回程绕日本
市面上目前也就 TMNet (unifi) VPS , 仍未见到类似 TIMEdotCom / Maxis 的VPS

韩国

常见ISP:KT、SKT、LG (绕路的ISP:NTT、PCCW、Telstra Global 绕日绕港绕新加坡 故不测试)

常见IX:KINX

常见下游:Moack、Oracle、Cloudflare、Amazon、Azure

韩国本土网络发达,除了三大ISP以外还有地区性ISP,大陆地区前往韩国主要走TPE、APG、APCN-2、NCP四大海缆。

国际路由差强人意,但靠着CDN也足够应付。但到中国大陆的带宽与路由不尽人意,绕路与直连汇聚层日常性堵塞层出不穷,丢包与抖动比较严重(虽然没有到163-NTT那么夸张)。

同时韩国的互联网管理相对严格,购买上比较麻烦。

KT

可直连骨干网:AS4134、AS4809、AS4837、AS9929、AS58453

KT(Korea Telecom),韩国最大电信运营商,市场占有率排名第一。

目前电信163/CN2和韩国KT之间的互联是通过APG海缆完成的,因为APG海缆只在上海有登陆,所以目前前往韩国KT都是走上海出口。需要注意的是,无论是电信163还是CN2和韩国KT的互联宽带均有限,高峰汇聚层没炸先Peer炸了也是经常发生的事情。

电信163至韩国KT的速度在Peer不被塞满的情况下单线程能跑100-200Mbps,晚高峰受限于汇聚层和Peer宽带的双重因素影响,速度受限比较严重。CN2虽然不用太担心汇聚层的拥塞问题,但是目前的Peer宽带依旧是比较主要的速度和延时等稳定性制约因素。

联通9929与KT有互联,同样也是走上海出口。高峰期几乎无丢包,延迟极低,单看极限最低延迟逼近沪韩IPLC;可惜经常抖动,虽然幅度不超过5ms。速度方面也属于跟日本ISP到9929一样,KT到9929的速度取决于用户接入的9929带宽速度。近期似乎扩容/更新设备了,抖动大幅降低。

根据测试。KT-广州移动(120.197/183.240段)高峰期速度非常不稳定,回程路由绕港。

SK Telecom

可直连骨干网:AS4134、AS4809、AS4837、AS58453

SKT可能从某种意义上知名度比KT高,SK Telecom是韩国最大的移动网络业务运营商。
实际上提供网络服务的是SKT的旗下公司SK Boardband。这一点可以从ASN信息中看出。

SK - 163 答案很简单,走上海出口直连但是会BOOM,包括163+...
SK - CN2 非常稳定,有Peer,任何时段基本没有丢包但看起来绕港,速度不稳定。
SK - CU169(上海)时延会在高峰期会振荡,速度也飘忽不定,但配合单边加速还算可用。
CMI与SK Boardband在香港Peer,移动经香港到CMI可以与其直连,到广东移动的速度飘忽不定。

LG

可直连骨干网: AS4134、AS4809、AS4837、AS9929

韩国第三大ISP,现名LG Uplus,曾用名“Intergrated LG Telecom”。LG的电信发展历史基本上就是一场收购史……
LG Uplus 由三家LG子公司合并而来,分别是LG DACOM,LG Powercom和LG Telecom。其中LG DACOM和LG Powercom又是收购而来。原来的LG Powercom负责运营民用网络,从韩国电力收购而来;LG DACOM负责国际通信业务,也就是LG的国际路由上会出现DACOM的原因。

DACOM全名为DataCommunication,由韩国政府牵头,LG与三星共同投资建设,但拥有独立经营权的ISP,后因为LG额外注资增持股份,LG完全接管DACOM。而LG Telecom则是LG自己独自投资建设的移动网络。

LG到联通169(上海)直连,走上海出口,配合单边加速高峰期速度不错。但ICMP丢包率特别高。

LG到联通9929是直连,同样走上海出口。但奇特的是虽然延迟也很低,速度却非常不稳定,隔三差五就突发性的延时起飞;但是正常的时候又十分平稳,几乎没有抖动,可速度依旧不尽人意。

越南

常见ISP:VNPT、FPT

VNPT

可直连骨干网:AS4134、AS4837、AS58453

作为全越南最大的电信ISP,VNPT拥有着全越南最大的骨干网和国际出口,但是一般很少有人会拿越南的宽带做流媒体解锁服务。

虽然电信163和VNPT互联(广州出口,胡志明市PoP),但VNPT的网络质量本身就不是很可靠,导致高峰没有速度乃是常态。最近VNPT还把回程的163直连路由改成绕路了(到香港后转PCCW,但PCCW到电信现在默认会绕美),使得电信163和VNPT的网络单向互联意义不大。

电信163也和VNPT在香港地区以CTG(中国电信国际)的名义互联,但少有可以走到这条线上的,而且回程依旧绕PCCW,导致目前两条与VNPT互联的线路都是单向路由。

电信163最神奇的地方莫过于,并不是所有的VNPT IP段都会走上述2条互联,也有可能会走美西的Tata亦或是走欧洲的Cogent借助胡志明的BICS接入VNPT。

联通169到VNPT也通过胡志明市的PoP互联,但是和电信163一样,也是单向互联,回程绕PCCW。

移动CMI在香港和VNPT互联,常规操作,感兴趣的可以翻翻香港地区的ISP是怎么和移动互联的就知道了。

FPT

可直连骨干网:AS4134、AS4837、AS58453

如果说VNPT到国内御三家都不怎么友好的话,那么FPT应该是到越南地区非常友好的ISP了。

电信去程163会走联通的网络去和FPT互联,回程走香港CTG回国,但是宽带很小经常爆炸,不爆炸的时候速度很快,期待以后的扩容。

因为FPT接入了CUG,所以联通169到越南FPT走的是AS4837->AS10099->FPT,虽然CUG很可靠,但是依旧受限于FPT接入宽带的容量,晚高峰几乎天天爆炸,这个只能等FPT扩容。

移动CMI和VNPT一样,都是常规互联,晚上也炸的很厉害。

我后期还会在这里添加日本、印度尼西亚、菲律宾、泰国、印度、孟加拉国、柬埔寨、泰国、尼泊尔等国家。

欧洲/北美地区

欧洲/北美的网络情况跟亚太差异比较大。欧美的中小ISP大部分依靠的是IX互联或者机房托管的混合网络接入。
虽然商业网络的价格比亚洲地区便宜,但至少对中国用户来说,很少再回程路由中遇见欧美的Regional T1或者高质量T1 ISP。

比如说在欧洲的Orange(前身法国电信France Télécom,AS Rank 11),Vodafone (总部在英国,AS Rank 12),Deutsche Telekom(德国电信AS Rank 24),北美的ATT(AS Rank 20) ,Verzion(AS Rank 21) ,Sprint(AS Rank 26)。题外话,BT(英国电信)反而是Regional T1,AS Rank比中国电信还低。

欧洲德国

DTAG

可直连骨干网: AS4134、AS4837、AS9929

Deutsche Telekom AG ,德国电信,德国第一大ISP,T1级。旗下移动运营商T-mobile相比于DTAG更加知名。

DTAG于AS4134和AS4837均有peer。同时也是AS9929上游。但延迟均200+起跳。

电信163普通家宽会被强制丢包,而163plus能保证相对稳定延迟与相对较低的丢包

联通169则取决于汇聚层是否拥塞。非拥塞状态则能保证网络质量。但是只限于北方地区的联通(如河南/山东等)。
南方地区的联通(如上海)将会被无慈悲的绕美,由DTAG转发Level3。

AS9929依旧稳定发挥,甚至延迟优于AS4134 AS4837,但速度很勉强,几乎稳定80Mbps。

Cogent Communications

Cogentco由于在Traceroute上的细节写的过于清楚明白,以至于有一部分以为跳数越多越差人觉得Cogentco不行。虽然它也确实不太行...

可直连骨干网:AS4134、AS4837、AS9929、AS58453。

Cogentco,联通9929真正的互联主力……几乎绝大部分的欧美线路到9929都会被Cogentco宣告。以至于在欧洲会出现回程不走DTAG硬是跑Cogentco
外加联通9929的NOC基本不会主动调整欧美路由。速度十分玄学,单线程在50Mbps摇摆,多线程却接近跑满。

美国洛杉矶&圣何塞

洛杉矶和圣何塞是美西重要的面向亚太地区的互联网PoP中心,TPE海缆多从此处2点接入。中美之间的互联占据了出境流量很大的一部分,也是电信163出国的主要路径。

HE

HE,全称为 Hurricane Electric(飓风电气),目前是坐拥全球以Peer数量计算的最大IPv6骨干网的ISP,骨干网自治编号为AS6939。HE也提供免费的IPv6 Tunnel,以方便IPv4单栈的用户能够无障碍地访问IPv6网络。

HE的发展思路一直是竭尽全力和世界上更多的ISP Peer,尽管获得了非常多的本地互联,但是因自身前期在亚太骨干网投入不足,导致和一些ISP对等宽带过小、跨洋传输场景下的宽带传输速率有限,HE也一直在努力扩容,可惜仍旧有较大缺口。

我们看到的亚太地区(香港、新加坡)的低价VPS产品线,几乎都一致地选择了HE作为唯一的互联网接入,而且接入的宽带并不大,平均1Gbps。但是哪怕是HE这样的ISP,在亚太地区的BGP Transit也颇为昂贵,这些商家为了能够有所盈利,在超低的VPS价格上,宽带上面必须大幅超售,这些反而给低端用户群体带来了十分糟糕的用户体验,很多时候,这些VPS访问外网速度慢不是HE的问题,而是IDC没有购买足够的宽带导致。

作为对等节点极多的HE来说,IPv6网络下和中国大三ISP均有直接互联,也是当下国内IPv6网络跨国的主要对等ISP,为推动全球IPv6互联中扮演着非常重要的角色。

可直连骨干网:AS4134、AS4837、AS58453

电信163和HE在洛杉矶有10~20G的互联,平时鲜有出现较大的延时抖动,但是速度限制较为严重。

联通169和HE的洛杉矶互联通常被视为在廉价互联里面很具有性价比的,相比于联通169和GTT的互联,和HE的互联质量就要好很多,很多用户也在尽可能选择更价廉物美的选择。

CMI与美西的互联一向较差,并不具有较好的连通性,再加上HE和CMI的互联本身就炸的比较厉害,此条线路不推荐移动去尝试。

GTT

GTT,前身为Global Telecom and Technology,自1998年成立以来,在跨国电信业务上耕作至今。

可直连骨干网:AS4134、AS4837、AS58453

联通169在美西较大地依赖GTT的互联,导致延时相比正常美西延时高很多,速度并不乐观。

电信163和GTT的互联却是出乎意料的好,根据SmokePing的结果,电信163和GTT的互联全天几乎不丢包,完全受限于汇聚层是否通畅。这就意味着只要使用高Qos的电信宽带就可以获得较好的速度。

Telia

Telia是瑞典最大的电话和电信通讯公司,前身为瑞典电报局及芬兰电讯。现更名为Arelion,但目前在路由上的名称依旧是Telia。

可直连骨干网:AS4134、AS4809、AS4837、AS58453

Telia在美国、欧洲都有和电信163互联,总体来说是很中规中矩的线路,

Cogent Communications

可直连骨干网:AS4134、AS4837、AS9929、AS58453

跟欧洲情况差不多。

电信163在美西较大程度上依赖Cogentco的互联,爆炸的几率较高。

Verizon

可直连骨干网:AS9929

联通9929与Verizon的互联一言难尽,延迟不是最优,单线程速度也不是最优。高峰期单线程速度在50-70Mbps震荡。而多线程速度倒是能跑满,非常的玄学。
有时候其他北美ISP到联通9929需要经Verizon转发,而被转发的速度就很难保证了。

非洲地区

img

肯尼亚

常见ISP:LiquidTelecom

可直连的骨干网:AS4134、AS4809、AS58423

LiquidTelecom在肯尼亚设有非洲国际交换中心,后与中国电信签署合作关系,目前中国电信在肯尼亚设有一处PoP,同时接入了163和CN2网络,和LiquidTelecom都有Peer。

LiquidTelecom也是非洲北部最大的ISP,在非洲拥有100GE的骨干网,可以说是非常强了。电信163前往该PoP需要先在新加坡的163 PoP中转,后前往非洲。在世界各地有自己的骨干网以及PoP,这就是为什么中国电信现在越来越被认可为Tier 1的原因。

虽然听起来特别厉害,但是实际上163网络到肯尼亚直连很差,不过这并不是因为LiquidTelecom导致的,电信的163汇聚层拉垮是主因。

从肯尼亚CN2的表现,严格的来说,是达到及格线的,但是价格昂贵,一般很少有人会去选择那么偏僻的CN2,我也只是找到了没几个段的肯尼亚CN2 IP段,通过SmokePing检测观察许久得出来的结论。

联通和移动都没有和LiquidTelecom直连,所以都绕路。

南非

在南非,一共有三大IX,JINX、CINX、DINX(约翰内斯堡互联网交换中心、开普敦互联网交换中心、德班互联网交换中心) ,这里我们主要讲JINX,别的基本和我们的御三家无关。

我们可以看出电信的非洲地区是下了功夫的,JINX也设有电信的PoP,同时接入AS4134和AS4809,这个网可能听说的人比较多,Misaka的南非约翰内斯堡的服务器网络就是接入了JINX和电信CN2互联的。

说实话,因为联通、移动没有想过在非洲布局,所以这个地区基本没他们什么事...

中东地区

阿联酋

常见ISP:du.ae

可直连的骨干网:AS4134、AS4809

du.ae 是当地一大电信ISP,骨干网覆盖全国,在阿联酋的迪拜电信设有PoP,同时接入电信163和CN2。

电信依旧是通过新加坡的PoP中转以连接阿联酋,根据Ucloud的阿联酋地区长达一个月的TCPPing数据,该地区163网络要比南非肯尼亚LiquidTelecom稳定,CN2可以实现132ms的低延时。

后记

洋洋洒洒写了1万多字,但是发现还有许多地区未能来得及覆盖到,后面继续追更吧~ 虽然很多地方我主观上已经有了结果,但是光靠个人的感受,没有数据的支撑(延时抖动、丢包率、峰值宽带均值),直接写上去未免太不严谨,等我测全了,再一点点补上去也不迟。

如果您喜欢这篇文章的话,也欢迎点赞啦,或许能成为我追更的动力哦。我会尽可能研究一些网上不曾有的ISP资料,并在此呈现给大家~

如果有任何不正确的地方也请指正,我会尽快修改,非常感谢!

参考资料

Telegram 文章排版指南

2022年7月9日 13:48

本文转自:https://japan.typlog.io/tgpaiban

写在前面

赏心悦目的排版会令人舒适,但是小小的文本框需要的注意的地方还挺多的。希望本文能对大家Telegram频道的文本编辑工作和提高字体与排版审美有所帮助。

字体样式的选择

由于Telegram的中文无法改变字体,只能在纯文本的基础上改变字体的样式,目前可供改变的样式有以下几种:

  • 普通字体(Ctrl+Shift+N)
  • 加粗样式(Ctrl+B)
  • 倾斜样式(Ctrl+I)
  • 下划线字(Ctrl+U)
  • 删除线字(Ctrl+Shift+X)
  • 等宽样式(Ctrl+Shift+M)
  • 剧透样式(Ctrl+Shift+P)
  • 链接样式(Ctrl+K)

虽然可供更改的样式选择不多,但是可以满足Telegram的基本排版需求,只要我们善于灵活运用以上这些样式,就可以做出清晰的文章排版,提升订阅者的阅读感。

如何使用字体样式

可以根据内容的变化自由选择字体样式。

一般来说,我会在标题处使用加粗字体,在引用处使用倾斜字体,在有外部链接处使用链接样式。文章后面也会结合具体内容举例说明。

排版的基础原则

无论在任何地方进行中文排版,都应该尽量符合以下的排版原则。

文章分段

文章分段可以使排版更加清晰明了,也能让读者快速找到重要的段落内容进行阅读。在Telegram中,由于消息的推送机制导致一行的文字数量有限,所以文章分段不仅是一个回车符这么简单,空白一行会让段落更加清楚。

可以看出,原文的排版有些拥挤,而过长的内容阅读起来也可能会让读者产生厌倦。故意留空一行,会让字数多的文章更有层次感,阅读起来也会舒服很多。

在英文数字前后插入空格

在中英文交替的情况下,应该在英文单词开头和结尾分别插入一个半角空格,以达到良好的视觉效果。

可以明显看出,在英文较长的情况下,前后加入空格会让内容显得更清晰。

符号的使用

灵活运用一些特殊符号会增加一些内容的醒目性,也可以增加内容的条理性。

比如使用符号 ▎ 来强调标题,使用 - 符号来罗列一些软件的特点。

当然,同时也要控制符号的数量,不然可能适得其反。

使用配图

文字是非常单一的表现形式,如果使用配图就会显得丰富一些。配图尽量和文字内容相关,做到简约简单即可。

关于配图的数量:如果配图只是单纯为了丰富视觉,那使用一张图片即可。如果配图是为了和内容相辅相成,并且补充文字内容,那可以选择多张图。

以上是配图,尽量遵从了相同比例和一致的设计风格。

使用标签

标签是Telegram的一大特点之一,合理利用标签可以将文章进行分类。标签还可以帮助在有配图的情况下调整图文比例。

左侧的排版使用tag将图片和标题分开,会更有层次。右边标题紧贴配图,稍显拥挤。

频道的排版方式

配图

配图简洁醒目,最好能表现文章内容,让读者一眼能看出主题即可。图片的要素不易过多,文字也尽量控制在一两行即可。配图一般只用一张图即可,规格900*400左右。如果多图的话可能会导致要素过多,反而显得混乱。当然多图的优势是能展示的更全面,还是要对不同的内容进行自我判断。

标签

围绕频道主题,固定下来一些标签,可以更好的给文章分类,同时也可以让新订阅的用户更快地阅读到之前的内容。

标题

这里使用的固定的特殊符号并且对标题文字进行了加粗,标题前后都留白,使得标题更醒目。

超链接

限于Telegram的文字篇幅,有很多内容无法写的非常详尽,所以可以利用超链接把具体内容链接起来,这样方便感兴趣的读者进一步了解,也节省了一部分篇幅显得文章不过于冗余。

留白

段落之间留白会显得层次分明,文字过多的情况下使用效果会更明显。

频道信息

标注自己的频道信息,这样在别人转发的时候也会带上频道信息,方便看到本条消息的人进一步订阅频道。

写在后面

以上内容是博主的一些排版心得体会,仅供大家参考。排版是一种审美,而审美因人而异,所以没有固定的标准。

希望本文对大家有所帮助,也欢迎各位朋友提出各自的见解。

从GFW原理到翻墙实践

2022年6月28日 17:16

引言

GFW具有重大的社会意义。无论是正面的社会意义,还是负面的意义。无论你是讨厌,还是憎恨。它都在那里。在可以预见的将来,墙还会继续存在。我们要学会如何与其共存。

我们把翻墙看成一场我们与GFW之间的博弈,是一个不断对抗升级的动态过程。目前整体的博弈态势来讲是GFW占了绝对的上风。我们花费了大量的金钱(买VPS买VPN),花费大量时间(学习各种翻墙技术),而GFW只需要简单发几个包,配几个路由规则就可以让你的心血都白费。

GFW并不需要检查所有的上下行流量中是不是有不和谐的内容,很多时候只需要检查连接的前几个包就可以判断出是否要阻断这个连接。为了规避这种检查,我们就需要把所有的流量都通过第三方代理,还要忍受不稳定,速度慢等各种各样的问题。花费的是大量的研究的时间,切换线路的时间,找出是什么导致不能用的时间,当然还有服务器的租用费用和带宽费用。我的感觉是,这就像太极里的四两拨千斤。GFW只需要付出很小的成本,就迫使了我们去付出很大的反封锁成本,而且这种成本好像是越来越高了。

这场博弈的不公平之处在于,GFW拥有国家的资源和专业的团队。而我们做为个体,愿意花费在翻墙上的时间与金钱是非常有限的。在竞争激烈的北上广深,每天辛苦忙碌的白领们。翻墙无非是为了方便自己的工作而已。不可能在每天上下班从拥挤的地铁中挤出来之后再去花费已经少得可怜的业余时间去学习自己不是翻墙根本不需要知道的名词到底是什么意思。于是乎,我们得过且过。不用Google也不会死,对不对?。博弈的天平远远不是平衡的,而是一边倒。

全面学习GFW

GFW会是一个长期的存在。要学会与之共存,必须先了解GFW是什么。做为局外人,学习GFW有六个角度。渐进的来看分别是:

首先我们学习到的是what和when。比如说,你经常听到人的议论是“昨天”,“github”被封了。其中的昨天就是when,github就是what。这是学习GFW的最天然,最朴素的角度。在这个方面做得非常极致的是一个叫做 greatfire 的网站。这个网站长期监控成千上万个网站和关键词。通过长期监控,不但可以掌握为什么被封锁了,还可以知道什么时候被封的,什么时候被解封的。

接下来的角度是who。比如说,“方校长”这个人名就经常和GFW同时出现。但是如果仅仅是掌握一个两个人名,然后天天在twitter上骂一遍,除了把这个人名骂成名人之外,没有什么特别的积极意义。我们可以通过网络上的公开信息,掌握GFW的哪些方面与哪些人有关系,这些合作者之间又有什么联系。除了大家猜测的将来可以鞭尸之外,对现在也是有积极的意义的。比如关注这些人的研究动态和思想发展,可以猜测GFW的下一步发展方向。比如阅读过去发表的论文,可以了解GFW的技术演进历史,可以从历史中找到一些技术或者管理体制上的缺陷。

再接下来就是why了。github被封之后就常听人说,github这样的技术网站你封它干啥?是什么原因促成了一个网站的被封与解封的?我们做为局外人,真正的原因当然是无从得知的。但是我们可以猜测。基于猜测,可以把不同网站被封,与网络上的舆情时间做关联和分类。我们知道,方校长对于网路舆情监控是有很深入研究的。有一篇论文(Whiskey, Weed, and Wukan on the World Wide Web: On Measuring Censors’ Resources and Motivations)专门讨论监管者的动机的。观测触发被封的事件与实际被封之间的时间关系,也可以推测出一些有趣的现象。比如有人报告,翻墙触发的封端口和封IP这样的事情一般都发生在中国的白天。也就是说,GFW背后不光是机器,有一些组件是血肉构成的。

剩下的两个角度就是对如何翻墙穿墙最有价值的两个角度了:how和where。how是非常好理解的,就是在服务器和客户端两边抓包,看看一个正常的网络通信,GFW做为中间人,分别给两端在什么时候发了什么包或者过滤掉了什么包。而这些GFW做的动作,无论是过滤还是发伪包又是如何干扰客户端与服务器之间的正常通信的。where是在知道了how之后的进一步发展,不但要了解客户端与服务器这两端的情况,更要了解GFW是挂在两端中间的哪一级路由器上做干扰的。在了解到GFW的关联路由器的IP的基础上,可以根据不同的干扰行为,不同的运营商归属做分组,进一步了解GFW的整体部署情况。

整体上来说,对GFW的研究都是从what和when开始,让偏人文的就去研究who和why,像我们这样偏工程的就会去研究how和where。以上就是全面了解GFW的主体脉络。接下来,我们就要以how和where这两个角度去看一看GFW的原理。

GFW的原理

要与GFW对抗不能仅仅停留在什么不能访问了,什么可以访问之类的表面现象上。知道youtube不能访问了,对于翻墙来说并无帮助。但是知道GFW是如何让我们不能访问youtube的,则对下一步的翻墙方案的选择和实施具有重大意义。所以在讨论如何翻之前,先要深入原理了解GFW是如何封的。

总的来说,GFW是一个分布式的入侵检测系统,并不是一个严格意义上的防火墙。不是说每个出入国境的IP包都需要先经过GFW的首可。做为一个入侵检测系统,GFW把你每一次访问facebook都看做一次入侵,然后在检测到入侵之后采取应对措施,也就是常见的连接重置。整个过程一般话来说就是:

检测有两种方式。一种是人工检测,一种是机器检测。你去国新办网站举报,就是参与了人工检测。在人工检测到不和谐的网站之后,就会采取一些应对方式来防止国内的网民访问该网站。对于这类的封锁,规避检测就不是技术问题了,只能从GFW采取的应对方式上采取反制措施。另外一类检测是机器检测,其检测过程又可以再进一步细分:

重建

重建是指GFW从网络上监听过往的IP包,然后分析其中的TCP协议,最后重建出一个完整的字节流。分析是在这个重建的字节流上分析具体的应用协议,比如HTTP协议。然后在应用协议中查找是不是有不和谐的内容,然后决定采用何种应对方式。

所以,GFW机器检测的第一步就是重建出一个字节流。那么GFW是如何拿到原始的IP包的呢?真正的GFW部署方式,外人根本无从得知。据猜测,GFW是部署在国家的出口路由器的旁路上,用“分光”的方式把IP包复制一份到另外一根光纤上,从而拿到所有进出国境的IP包。

GFW通过配置骨干网的BGP路由规则,是可以让国内机房的流量经过它。一个例子是当我们访问被封的网站触发连接重置的时候,往往收到两个RST包,但是TTL不同。还有一个例子是对于被封的IP,访问的IP包还没有到达国际出口就已经被丢弃。所以GFW应该在其他地方也部署有设备,据推测是在省级骨干路由的位置。

对于GFW到底在哪这个话题,最近又有国外友人表达了兴趣( https://github.com/mothran/mongol)。其原理是基于一个IP协议的特性叫TTL。TTL是Time to Live的简写。IP包在没经过一次路由的时候,路由器都会把IP包的TTL减去1。如果TTL到零了,路由器就不会再把IP包发给下一级路由。然后我们知道GFW会在监听到不和谐的IP包之后发回RST包来重置TCP连接。那么通过设置不同的TTL就可以知道从你的电脑,到GFW之间经过了几个路由器。比如说TTL设置成9不触发RST,但是10就触发RST,那么到GFW就是经过了10个路由器。另外一个IP协议的特性是当TTL耗尽的时候,路由器应该发回一个TTL EXCEEDED的ICMP包,并把自己的IP地址设置成SRC(来源)。结合这两点,就可以探测出IP包是到了IP地址为什么的路由器之后才被GFW检测到。有了IP地址之后,再结合IP地址地理位置的数据库就可以知道其地理位置。据说,得出的位置大概是这样的:

但是这里检测出来的IP到底是GFW的还是骨干路由器的?更有可能的是骨干路由器的IP。GFW做为一个设备用“分光”的方式挂在主干路由器旁边做入侵检测。无论如何,GFW通过某种神奇的方式,可以拿到你和国外服务器之间来往的所有的IP包,这点是肯定的。更严谨的理论研究有: Internet Censorship in China: Where Does the Filtering Occur?

GFW在拥有了这些IP包之后,要做一个艰难的决定,那就是到底要不要让你和服务器之间的通信继续下去。GFW不能太过于激进,毕竟全国性的不能访问国外的网站是违反GFW自身存在价值的。GFW就需要在理解了IP包背后代表的含义之后,再来决定是不是可以安全的阻断你和国外服务器之间的连接。这种理解就要建立了前面说的“重建”这一步的基础上。大概用图表达一下重建是在怎么一回事:

重建这样的字节流有一个难点是如何处理巨大的流量?其原理与网站的负载均衡器一样。对于给定的来源和目标,使用一个HASH算法取得一个节点值,然后把所有符合这个来源和目标的流量都往这个节点发。所以在一个节点上就可以重建一个TCP会话的单向字节流。

最后为了讨论完整,再提两点。虽然GFW的重建发生在旁路上是基于分光来实现的,但并不代表整个GFW的所有设备都在旁路。后面会提到有一些GFW应对形式必须是把一些GFW的设备部署在了主干路由上,也就是GFW是要参与部分IP的路由工作的。另外一点是,重建是单向的TCP流,也就是GFW根本不在乎双向的对话内容,它只根据监听到的一个方向的内容然后做判断。但是监听本身是双向的,也就是无论是从国内发到国外,还是从国外发到国内,都会被重建然后加以分析。所以一个TCP连接对于GFW来说会被重建成两个字节流。具体的证据会在后面谈如何直穿GFW中详细讲解。

分析

分析是GFW在重建出字节流之后要做的第二步。对于重建来说,GFW主要处理IP协议,以及上一层的TCP和UDP协议就可以了。但是对于分析来说,GFW就需要理解各种各样的应用层的稀奇古怪的协议了。甚至,我们也可以自己发明新的协议。

总的来说,GFW做协议分析有两个相似,但是不同的目的。第一个目的是防止不和谐内容的传播,第二个目的是防止使用翻墙工具绕过GFW的审查。下面列举一些已知的GFW能够处理的协议。

对于GFW具体是怎么达到目的一,也就是防止不和谐内容传播的就牵涉到对HTTP协议和DNS协议等几个协议的明文审查。大体的做法是这样的:

像HTTP这样的协议会有非常明显的特征供检测,所以第一步就没什么好说的了。当GFW发现了包是HTTP的包之后就会按照HTTP的协议规则拆包。这个拆包过程是GFW按照它对于协议的理解来做的。比如说,从HTTP的GET请求中取得请求的URL。然后GFW拿到这个请求的URL去与关键字做匹配,比如查找Twitter是否在请求的URL中。为什么有拆包这个过程?首先,拆包之后可以更精确的打击,防止误杀。另外可能预先做拆包,比全文匹配更节省资源。其次,GFW还是先去理解协议,然后才做关键字匹配的。关键字匹配应该就是使用了一些高效的正则表达式算法,没有什么可以讨论的。

HTTP代理和SOCKS代理,这两种明文的代理都可以被GFW识别。之前笔者认为GFW可以在识别到HTTP代理和SOCKS代理之后,再拆解其内部的HTTP协议的正文。也就是做两次拆包。但是分析发现,HTTP代理的关键字列表和HTTP的关键字列表是不一样的,所以笔者现在认为HTTP代理协议和SOCKS代理协议是当作单独的协议来处理的,并不是拆出载荷的HTTP请求再进行分析的。

目前已知的GFW会做的协议分析如下:

DNS 查询

GFW可以分析53端口的UDP协议的DNS查询。如果查询的域名匹配关键字则会被DNS劫持。可以肯定的是,这个匹配过程使用的是类似正则的机制,而不仅仅是一个黑名单,因为子域名实在太多了。证据是:2012年11月9日下午3点半开始,防火长城对Google的泛域名 .google.com 进行了大面积的污染,所有以 google.com 结尾的域名均遭到污染而解析错误不能正常访问,其中甚至包括不存在的域名。

目前为止53端口之外的查询也没有被劫持。但是TCP的DNS查询已经可以被TCP RST切断了,表明了GFW具有这样的能力,只是不屑于大规模部署。而且TCP查询的关键字比UDP劫持的域名要少的多。

HTTP 请求

GFW可以识别出HTTP协议,并且检查GET的URL与HOST。如果匹配了关键字则会触发TCP RST阻断。

HTTP 响应

GFW除了会分析上行的HTTP GET请求,对于HTTP返回的内容也会做全文关键字检查。这种检查与对请求的关键字检查不是由同一设备完成的,而且对GFW的资源消耗也更大。

HTTP代理协议

SOCKS4/5代理协议

SMTP 协议

因为有很多翻墙软件都是以邮件索取下载地址的方式发布的,所以GFW有针对性的封锁了SMTP协议,阻止这样的邮件往来。

封锁有三种表现方式,简单概要的说就是看邮件是不是发往上了黑名单的邮件地址的,如果发现了就立马用TCP RST包切断连接。

  1. 发现发件人在黑名单中,立即重置TCP链接
     from scapy.all import *
     send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='S', seq=0))
     send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1))
     send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1) / 'MAIL FROM: xiazai@upup.info\r\n')
    
    看似普通的三个包其实暗藏玄机。首先,目标地址是1.2.3.4,这显然是我胡写的一个地址,而且TTL设置为9。所以这个包发出去就没有打算让最终的目标机器接到,而只是发给GFW看的。这个TTL值要大于你的机器到GFW的跳数,一般11是一个保险的值。

然后要触发GFW的响应,有以下几个缺一不可的条件:

  • 目标端口是25,我尝试了其他几个端口没有发现触发响应。

  • 第二个包虽然内容是空的,但是必须存在。而且必须是ACK。内容也可以不为空,GFW似乎不care内容是什么,只要有这个包就可以。

  • 第三个包的seq必须为1,哪怕第二包有内容了,这个包的seq也必须为1。而且MAIL FROM: \r\n这个格式必须对,不能替换成FROM MAIL啥的。还有一个条件就是邮件地址必须上了黑名单。这里举的例子是一个翻墙软件的索取地址,所以上了黑名单。

观测到的响应是GFW发一个TCP RST包。而且每次都是一个,从来不多发。如果少了中间那个空的ACK,则是连做两次探测触发一个TCP RST。貌似GFW把两次探测认为是一个连接了。
2. 发现收件人在黑名单中,立即重置TCP链接

 from scapy.all import *
 send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='S', seq=0))
 send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1))
 send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1) / 'RCPT TO: xiazai@upup.info\r\n')

这与上面的MAIL FROM的例子基本上是一样的。不同之处只有一点就是有的时候可以看到两个TCP RST的回包。
3. 发现收件人在黑名单中,发回用户不存在的错误消息

 from scapy.all import *
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='S', seq=0))
send(IP(dst='1.2.3.4', ttl=9) / TCP(dport=25, flags='A', seq=1) / 'EHLO anything-here\nRCPT TO: xiazai@upup.info\n')

得到的错误消息是 “551 User not local; please try \r\n”。有的时候还会伴随有数个连续的TCP RST。同样因为包根本没有到对方的服务器,而且这个服务器压根就不存在,所以这个用户不存在的错误消息只能是GFW做出的响应。

触发的条件是

  • 目标端口必须是25
  • 第二个包的第一个命令必须是EHLO或者HELO,内容没有关系
  • 第二个包的第二个命令必须是RCPT TO,而且邮件地址要在黑名单中。
  • \r\n没有关系,\n也是可以触发的

这次触发的条件是一个合法的SMTP请求过程。而之前的触发过程根本就不是合法的SMTP请求。而且另外一个特征是这样触发的TCP RST,会有三个重叠,ack递加的现象,与HTTP全文关键字的响应非常类似。我推测,两型的响应是两个不同的模块。单独对MAIL FROM和RCPT TO的封锁,与对HTTP关键字的封锁类似,属于看到就封型。而后一种更智能的,还会回答错误消息的是能够真正理解SMTP协议的模块,可能还用于做邮件全文内容的关键字检测。

电驴(ed2k)协议

GFW还会过滤电驴(ed2k)协议中的查询内容。因为ed2k还有一个混淆模式,会加密往来的数据包,GFW会切断所有使用混淆模式的ed2k连接,迫使客户端使用明文与服务器通讯。然后如果客户端发起了搜索请求,查找的关键字中包含敏感词的话就会被用TCP RST包切断连接。

对翻墙流量的分析识别

GFW的第二个目的是封杀翻墙软件。为了达到这个目的GFW采取的手段更加暴力。原因简单,对于HTTP协议的封杀如果做不好会影响互联网的正常运作,GFW与互联网是共生的关系,它不会做威胁自己存在的事情。但是对于TOR这样的几乎纯粹是为翻墙而存在的协议,只要检测出来就是格杀勿论的了。GFW具体是如何封杀各种翻墙协议的,我也不是很清楚,事态仍然在不断更新中。但是举两个例子来证明GFW的高超技术。

第一个例子是GFW对TOR的自动封杀,体现了GFW尽最大努力去理解协议本身。根据这篇博客( <https://blog.torproject.org/blog/knock-knock-knockin-bridges-doors >)。使用中国的IP去连接一个美国的TOR网桥,会被GFW发现。然后GFW回头(15分钟之后)会亲自假装成客户端,用TOR的协议去连接那个网桥。如果确认是TOR的网桥,则会封当时的那个端口。换了端口之后,可以用一段时间,然后又会被封。这表现出了GFW对于协议的高超检测能力,可以从国际出口的流量中敏锐地发现你连接的TOR网桥。据TOR的同志说是因为TOR协议中的握手过程具有太明显的特征了。另外一点就表现了GFW的不辞辛劳,居然会自己伪装成客户端过去连连看。

第二个例子表现了GFW根本不在乎加密的流量中的具体内容是不是有敏感词。只要疑似翻墙,特别是提供商业服务给多个翻墙,就会被封杀。使用ShadowSocks协议, 预先部署密钥,没有明显的握手过程仍然被封。据说是GFW已经升级为能够机器识别出哪些加密的流量是疑似翻墙服务的。

总结起来就是,GFW已经基本上完成了目的一的所有工作。明文的协议从HTTP到SMTP都可以分析然后关键字检测,甚至电驴这样不是那么大众的协议GFW都去搞了。从原理上来说也没有什么好研究的,就是明文,拆包,关键字。GFW显然近期的工作重心在分析网络流量上,从中识别出哪些是翻墙的流量。这方面的研究还比较少,而且一个显著的特征是自己用没关系,大规模部署就容易出问题。我目前没有在GFW是如何封翻墙工具上有太多研究,只能是道听途说了。

应对

GFW的应对措施是三步中最明显的,因为它最直接。GFW的重建过程和协议分析的过程需要耐心的试探才能大概推测出GFW是怎么实现的。但是GFW的应对手段我们每天都可以见到,比如连接重置。GFW的应对目前可以感受到的只有一个目的就是阻断。但是从广义上来说,应对方式应该不限于阻断。比如说记录下日志,然后做统计分析,秋后算账什么的也可以算是一种应对。就阻断方式而言,其实并不多,那么我们一个个来列举吧。

封IP

一般常见于人工检测之后的应对。还没有听说有什么方式可以直接使得GFW的机器检测直接封IP。一般常见的现象是GFW机器检测,然后用TCP RST重置来应对。过了一段时间才会被封IP,而且没有明显的时间规律。所以我的推测是,全局性的封IP应该是一种需要人工介入的。注意我强调了全局性的封IP,与之相对的是部分封IP,比如只对你访问那个IP封个3分钟,但是别人还是可以访问这样的。这是一种完全不同的封锁方式,虽然现象差不多,都是ping也ping不通。要观摩的话ping twitter.com就可以了,都封了好久了。

其实现方式是把无效的路由黑洞加入到主干路由器的路由表中,然后让这些主干网上的路由器去帮GFW把到指定IP的包给丢弃掉。路由器的路由表是动态更新的,使用的协议是BGP协议。GFW只需要维护一个被封的IP列表,然后用BGP协议广播出去就好了。然后国内主干网上的路由器都好像变成了GFW的一份子那样,成为了帮凶。

如果我们使用traceroute去检查这种被全局封锁的IP就可以发现,IP包还没有到GFW所在的国际出口就已经被运营商的路由器给丢弃了。这就是BGP广播的作用了。

DNS劫持

这也是一种常见的人工检测之后的应对。人工发现一个不和谐网站,然后就把这个网站的域名给加到劫持列表中。其原理是基于DNS与IP协议的弱点,DNS与IP这两个协议都不验证服务器的权威性,而且DNS客户端会盲目地相信第一个收到的答案。所以你去查询facebook.com的话,GFW只要在正确的答案被返回之前抢答了,然后伪装成你查询的DNS服务器向你发错误的答案就可以了。

下图为GFW对域名telegram.org的劫持:

可见许多地区的IP被解析到Twitter和Facebook等已被封锁的IP上。

TCP RST阻断

TCP协议规定,只要看到RST包,连接立马被中断。从浏览器里来看就是连接已经被重置。我想对于这个错误大家都不陌生。据我个人观感,这种封锁方式是GFW目前的主要应对手段。大部分的RST是条件触发的,比如URL中包含某些关键字。还有一些网站,会被无条件RST。也就是针对特定的IP和端口,无论包的内容就会触发RST。比较著名的例子是https的wikipedia。GFW在TCP层的应对是利用了IPv4协议的弱点,也就是只要你在网络上,就假装成任何人发包。所以GFW可以很轻易地让你相信RST确实是Google发的,而让Google相信RST是你发的。

封端口

GFW除了自身主体是挂在骨干路由器旁路上的入侵检测设备,利用分光技术从这个骨干路由器抓包下来做入侵检测 (所谓 IDS),除此之外这个路由器还会被用来封端口 (所谓 IPS)。GFW在检测到入侵之后可以不仅仅可以用TCP RST阻断当前这个连接,而且利用骨干路由器还可以对指定的IP或者端口进行从封端口到封IP,设置选择性丢包的各种封禁措施。可以理解为骨干路由器上具有了类似“iptables”的能力(网络层和传输层的实时拆包,匹配规则的能力)。这个iptables的能力在CISCO路由器上叫做ACL Based Forwarding (ABF)。而且规则的部署是全国同步的,一台路由器封了你的端口,全国的挂了GFW的骨干路由器都会封。一般这种封端口都是针对翻墙服务器的,如果检测到服务器是用SSH或者VPN等方式提供翻墙服务。GFW会在全国的出口骨干路由上部署这样的一条ACL规则,来封你这个服务器+端口的下行数据包。也就是如果包是从国外发向国内的,而且src(源ip)是被封的服务器ip,sport(源端口)是被封的端口,那么这个包就会被过滤掉。这样部署的规则的特点是,上行的数据包是可以被服务器收到的,而下行的数据包会被过滤掉。

如果被封端口之后服务器采取更换端口的应对措施,很快会再次被封。而且多次尝试之后会被封IP。初步推断是,封端口不是GFW的自动应对行为,而是采取黑名单加人工过滤地方式实现的。一个推断的理由就是网友报道,封端口都是发生在白天工作时间。

在进入了封端口阶段之后,还会有继发性的临时性封其他端口的现象,但是这些继发性的封锁具有明显的超时时间,触发了之后(触发条件不是非常明确)会立即被封锁,然后过了一段时间就自动解封。

HTTPS间歇性丢包

对于Github的HTTPS服务,GFW不愿意让其完全不能访问。所以采取的办法是对于Github的某些IP的443端口采取间歇性丢包的措施。其原理应该类似于封端口,是在骨干路由器上做的丢包动作。但是触发条件并不只是看IP和端口,加上了时间间隔这样一个条件。

翻墙原理

前面从原理上讲解了GFW的运作原理。翻墙的原理与之相对应,分为两大类。第一类是大家普遍的使用的绕道的方式。IP包经由第三方中转已加密的形式通过GFW的检查。这样的一种做法更像“翻”墙,是从墙外绕过去的。第二类是找出GFW检测过程的中一些BUG,利用这些BUG让GFW无法知道准确的会话内容从而放行。这种做法更像“穿”墙。曾经引起一时轰动的西厢计划第一季就是基于这种方式的实现。

基于绕道法的翻墙方式无论是VPN还是代理,原理都是类似的。都是以国外有一个代理服务器为前提,然后你与代理服务器通信,代理服务器再与目标服务器通信。

绕道法对于IP封锁来说,因为最终的IP包是由代理服务器在墙外发出的,所以国内骨干路由封IP并不会产生影响。对于TCP重置来说,因为TCP重置是以入侵检测为前提的,客户端与代理之间的加密通信规避了入侵检测,使得TCP重置不会被触发。

但是对于反DNS污染来说,VPN和代理代理却有不同。基于VPN的翻墙方法,得到正确的DNS解析的结果需要设置一个国外的没有被污染的DNS服务器。然后发UDP请求去解析域名的时候,VPN会用绕道的方式让UDP请求不被劫持地通过GFW。

但是SOCKS代理和HTTP代理这些更上层的代理协议则可以选择不同的方式。因为代理与应用之间有更紧密的关系,应用程序比如浏览器可以把要访问的服务器的域名直接告诉本地的代理。然后SOCKS代理可以选择不在本地做解析,直接把请求发给墙外的代理服务器。在代理服务器去与目标服务器做连接的时候再在代理服务器上做DNS解析,从而避开了GFW的DNS劫持。

VPN与代理的另外一个主要区别是应用程序是如何使用上代理去访问国外的服务器的。先来看不加代理的时候,应用程序是如何访问网络的。

应用程序把IP包交给操作系统,操作系统会去决定把包用机器上的哪块网卡发出去。VPN的客户端对于操作系统来说就是一个虚拟出来的网卡。应用程序完全不用知道VPN客户端的存在,操作系统甚至也不需要区分VPN客户端与普通网卡的区别。

VPN客户端在启动之后会把操作系统的缺省路由改成自己。这样所有的IP包都会经由这块虚拟的网卡发出去。这样VPN就能够再打包成加密的流量发出去(当然线路还是之前的线路),发回去的加密流量再解密拆包交还给操作系统。

应用层的代理则不同。其流量走不走代理的线路并不是由操作系统使用路由表选择网卡来决定的,而是在应用程序里自己做的。也就是说,对于操作系统来说,使用代理的TCP连接和不使用代理的TCP连接并没有任何的不同。应用程序自己去选择是直接与目标服务器建立连接,还是与代理服务器建立TCP连接,然后由SOCKS代理服务器去建立第二个TCP连接,两个TCP连接的数据由代理服务器中转。

绕道法的翻墙原理就是这些了,相对来说非常简单。其针对的都是GFW的分析那一步,通过加密使得GFW无法分析出流量的原文从而让GFW放行。但是GFW最近的升级表明,GFW虽然无法解密这些加密的流量,但是GFW可以结合流量与其他协议特征探测出这些流量是不是“翻墙”的,然后就直接暴力的切断。绕道法的下一步发展就是要从原理弄明白,GFW是如何分析出翻墙流量的,从而要么降低自身的流量特征避免上短名单被协议分析,或者通过混淆协议把自己伪装成其他的无害流量。

穿墙原理

DNS劫持观测

我们要做的第一个实验是用python代码观测到DNS劫持的全过程。

应用层观测

dig是DNS的客户端,可以很方便地构造出我们想要的DNS请求。 dig @8.8.8.8 twitter.com 。可以得到相应如下:

; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5494
;; flags: qr rd ra; QUERY: 1, ANSWER: 1, AUTHORITY: 0, ADDITIONAL: 0    

;; QUESTION SECTION:
;twitter.com.                        IN        A    

;; ANSWER SECTION:
twitter.com.                4666        IN        A        59.24.3.173    

;; Query time: 110 msec
;; SERVER: 8.8.8.8#53(8.8.8.8)
;; WHEN: Sun Jan 13 13:22:10 2013
;; MSG SIZE  rcvd: 45

可以很清楚地看到我们得到的错误答案59.24.3.173。

抓包观测

使用iptables我们可以让特定的IP包经过应用层的代码,从而使得我们用python观测DNS查询过程提供了可能。代码如下:

from netfilterqueue import NetfilterQueue
import subprocess
import signal    

def observe_dns_hijacking(nfqueue_element):
   print('packet past through me')
   nfqueue_element.accept()    

nfqueue = NetfilterQueue()
nfqueue.bind(0, observe_dns_hijacking)    

def clean_up(*args):
   subprocess.call('iptables -D OUTPUT -p udp --dst 8.8.8.8 -j QUEUE', shell=True)
   subprocess.call('iptables -D INPUT -p udp --src 8.8.8.8 -j QUEUE', shell=True)    

signal.signal(signal.SIGINT, clean_up)    

try:
   subprocess.call('iptables -I INPUT -p udp --src 8.8.8.8 -j QUEUE', shell=True)
   subprocess.call('iptables -I OUTPUT -p udp --dst 8.8.8.8 -j QUEUE', shell=True)
   print('running..')
   nfqueue.run()
except KeyboardInterrupt:
   print('bye')

执行此脚本,再使用dig @8.8.8.8 twitter.com应该可以看到package past through me。这就说明DNS的请求和答案都经过了python代码了。

上一步主要是验证NetfilterQueue是不是工作正常。这一步则要靠dpkt的了。代码如下:

from netfilterqueue import NetfilterQueue
import subprocess
import signal
import dpkt
import traceback
import socket    

def observe_dns_hijacking(nfqueue_element):
   try:
       ip_packet = dpkt.ip.IP(nfqueue_element.get_payload())
       dns_packet = dpkt.dns.DNS(ip_packet.udp.data)
       print(repr(dns_packet))
       for answer in dns_packet.an:
           print(socket.inet_ntoa(answer['rdata']))
       nfqueue_element.accept()
   except:
       traceback.print_exc()
       nfqueue_element.accept()    

nfqueue = NetfilterQueue()
nfqueue.bind(0, observe_dns_hijacking)    

def clean_up(*args):    

   subprocess.call('iptables -D OUTPUT -p udp --dst 8.8.8.8 -j QUEUE', shell=True)
   subprocess.call('iptables -D INPUT -p udp --src 8.8.8.8 -j QUEUE', shell=True)    

signal.signal(signal.SIGINT, clean_up)    

try:
   subprocess.call('iptables -I INPUT -p udp --src 8.8.8.8 -j QUEUE', shell=True)
   subprocess.call('iptables -I OUTPUT -p udp --dst 8.8.8.8 -j QUEUE', shell=True)
   print('running..')
   nfqueue.run()
except KeyboardInterrupt:
   print('bye')

执行此脚本,再使用dig @8.8.8.8 twitter.com应该可以看到类似如下的输出:

DNS(ar=[RR(type=41, cls=4096)], qd=[Q(name='twitter.com')], id=8613, op=288)
DNS(an=[RR(name='twitter.com', rdata=';\x18\x03\xad', ttl=19150)], qd=[Q(name='twitter.com')], id=8613, op=33152)
.24.3.173
DNS(an=[RR(name='twitter.com', rdata='\xc7;\x95\xe6', ttl=27), RR(name='twitter.com', rdata='\xc7;\x96\x07', ttl=27), RR(name='twitter.com', rdata="\xc7;\x96'", ttl=27)], ar=[RR(type=41, cls=512)], qd=[Q(name='twitter.com')], id=8613, op=33152)
.59.149.230
.59.150.7
.59.150.39

可以看到我们发出去了一个包,收到了两个包。其中第一个收到的包是GFW发回来的错误答案,第二个包才是正确的答案。但是由于dig只取第一个返回的答案,所以我们实际看到的解析结果是错误的。

观测劫持发生的位置

利用IP包的TTL特性,我们可以把TTL值从1开始递增,直到我们收到错误的应答为止。结合TTL EXECEEDED ICMP返回的IP地址,就可以知道DNS请求是在第几跳的路由器分光给GFW的。代码如下:

from netfilterqueue import NetfilterQueue
import subprocess
import signal
import dpkt
import traceback
import socket
import sys    

DNS_IP = '8.8.8.8'    

# source http://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BC%93%E5%AD%98%E6%B1%A1%E6%9F%93
WRONG_ANSWERS = {
   '4.36.66.178',
   '8.7.198.45',
   '37.61.54.158',
   '46.82.174.68',
   '59.24.3.173',
   '64.33.88.161',
   '64.33.99.47',
   '64.66.163.251',
   '65.104.202.252',
   '65.160.219.113',
   '66.45.252.237',
   '72.14.205.99',
   '72.14.205.104',
   '78.16.49.15',
   '93.46.8.89',
   '128.121.126.139',
   '159.106.121.75',
   '169.132.13.103',
   '192.67.198.6',
   '202.106.1.2',
   '202.181.7.85',
   '203.161.230.171',
   '207.12.88.98',
   '208.56.31.43',
   '209.36.73.33',
   '209.145.54.50',
   '209.220.30.174',
   '211.94.66.147',
   '213.169.251.35',
   '216.221.188.182',
   '216.234.179.13'
}    

current_ttl = 1    

def locate_dns_hijacking(nfqueue_element):
   global current_ttl
   try:
       ip_packet = dpkt.ip.IP(nfqueue_element.get_payload())
       if dpkt.ip.IP_PROTO_ICMP == ip_packet['p']:
           print(socket.inet_ntoa(ip_packet.src))
       elif dpkt.ip.IP_PROTO_UDP == ip_packet['p']:
           if DNS_IP == socket.inet_ntoa(ip_packet.dst):
               ip_packet.ttl = current_ttl
               current_ttl += 1
               ip_packet.sum = 0
               nfqueue_element.set_payload(str(ip_packet))
           else:
               if contains_wrong_answer(dpkt.dns.DNS(ip_packet.udp.data)):
                   sys.stdout.write('* ')
                   sys.stdout.flush()
                   nfqueue_element.drop()
                   return
               else:
                   print('END')
       nfqueue_element.accept()
   except:
       traceback.print_exc()
       nfqueue_element.accept()    

def contains_wrong_answer(dns_packet):
   for answer in dns_packet.an:
       if socket.inet_ntoa(answer['rdata']) in WRONG_ANSWERS:
           return True
   return False    

nfqueue = NetfilterQueue()
nfqueue.bind(0, locate_dns_hijacking)    

def clean_up(*args):
   subprocess.call('iptables -D OUTPUT -p udp --dst %s -j QUEUE' % DNS_IP, shell=True)
   subprocess.call('iptables -D INPUT -p udp --src %s -j QUEUE' % DNS_IP, shell=True)
   subprocess.call('iptables -D INPUT -p icmp -m icmp --icmp-type 11 -j QUEUE', shell=True)    

signal.signal(signal.SIGINT, clean_up)    

try:
   subprocess.call('iptables -I INPUT -p icmp -m icmp --icmp-type 11 -j QUEUE', shell=True)
   subprocess.call('iptables -I INPUT -p udp --src %s -j QUEUE' % DNS_IP, shell=True)
   subprocess.call('iptables -I OUTPUT -p udp --dst %s -j QUEUE' % DNS_IP, shell=True)
   print('running..')
   nfqueue.run()
except KeyboardInterrupt:
   print('bye')

执行 dig +tries=30 +time=1 @8.8.8.8 twitter.com 可以得到类似下面的输出:

.158.100.166
.158.11.150
* 219.158.97.30
* * 219.158.27.30
* 72.14.215.130
* 209.85.248.60
* 216.239.43.19
* * END

出现*号前面的那个IP就是挂了GFW的路由了。脚本只能执行一次,第二次需要重启。另外同一个DNS不能被同时查询,把8.8.8.8改成你没有在用的DNS。这个脚本的一个“副作用”就是dig返回的答案是正确的了,因为错误的答案被丢弃了。

反向观测

前面我们已经知道从国内请求国外的DNS服务器大体是怎么一个被劫持的过程了。接下来我们在国内搭建一个服务器,从国外往国内发请求,看看是不是可以观测到被劫持的现象。

把路由器的WAN口的防火墙打开。配置本地的dnsmasq为使用非标准端口代理查询从而保证本地做dig查询的时候可以拿到正确的结果。然后在国外的服务器上执行dig @国内路由器ip twitter.com

可以看到收到的答案是错误的。执行前面的路由跟踪代码,结果如下:

.160.187.13
.248.76.73
.158.33.181
.158.29.129
.158.19.165
* 219.158.96.225
* * * 219.158.101.233
END

可以看到不但有DNS劫持,而且DNS劫持发生在非常靠近国内路由器的位置。这也证实了论文中提出的观测结果。GFW并没有严格地部署在出国境前第一跳的位置,而是更加靠前。并且是双向的,至少DNS劫持是双向经过实验证实了。

反DNS劫持

通过避免GFW重建请求反DNS劫持

使用非标准端口

这个实验就非常简单了。使用53之外的端口查询DNS,观测是否有错误答案被返回。

使用的DNS服务器是OpenDNS,端口为5353端口。使用非标准端口的DNS服务器不多,并不是所有的DNS服务器都会提供非标准端口供查询。结果如下:

; <<>> DiG 9.9.1-P3 <<>> @208.67.222.222 -p 5353 twitter.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 5367
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1    

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 8192
;; QUESTION SECTION:
;twitter.com.                        IN        A    

;; ANSWER SECTION:
twitter.com.                5        IN        A        199.59.150.39
twitter.com.                5        IN        A        199.59.148.82
twitter.com.                5        IN        A        199.59.148.10    

;; Query time: 194 msec
;; SERVER: 208.67.222.222#5353(208.67.222.222)
;; WHEN: Mon Jan 14 11:47:46 2013
;; MSG SIZE  rcvd: 88

可见,非标准端口还是可以得到正确结果的。但是这种穿墙并不能被应用程序直接使用,因为几乎所有的应用程序都不支持使用非标准端口查询。有很多种办法把端口变成53端口能用:

  • 使用本地DNS服务器转发(dnsmasq,pdnsd)
  • 用NetfilterQueue改写IP包
  • 用iptables改写IP包: iptables -t nat -I OUTPUT --dst 208.67.222.222 -p udp --dport 53 -j DNAT --to-destination 208.67.222.222:5353

使用TCP查询

这个实验就更加简单了,也是一条命令:

dig +tcp @8.8.8.8 twitter.com

GFW在日常是不屏蔽TCP的DNS查询的,所以可以得到正确的结果。但是和非标准端口一样,几乎所有的应用程序都不支持使用TCP查询。已知的TCP转UDP方式是使用pdnsd或者unbound转。

但是GFW现在不屏蔽TCP的DNS查询并不代表GFW不能这么干。做一个小实验:

root@OpenWrt:~# dig +tcp @8.8.8.8 dl.dropbox.com
;; communications error to 8.8.8.8#53: connection reset

可以看到GFW是能够知道你在查询什么的。与HTTP关键字过滤一样,一旦发现查询的内容不恰当,立马就发RST包过来切断连接。那么为什么GFW不审查所有的TCP的DNS查询呢?原因很简单,用TCP查询的绝对少数,尚不值得这么去干。而且就算你能查询到正确域名,GFW自认为还有HTTP关键字过滤和封IP等后着守着呢,犯不着在DNS上卡这么死。

使用单向代理

严格来说单向代理并不是穿墙,因为它仍然需要在国外有一个代理服务器。使用代理服务器把DNS查询发出去,但是DNS查询并不经由代理服务器而是直接发回客户端。这样的实现在目前有更好的反劫持的手段(比如非标准端口)的情况下并不是一个有实际意义的做法。但是对于观测GFW的封锁机制还是有帮助的。据报道在敏感时期,对DNS不仅仅是劫持,而是直接丢包。通过单向代理可以观测丢包是针对出境流量的还是入境流量的。

客户端需要使用iptables把DNS请求转给NetfilterQueue,然后用python代码把DNS请求包装之后发给中转代理。对于应用程序来说,这个包装的过程是透明的,它仍然认为请求是直接发给DNS服务器的。

客户端代码如下:

from netfilterqueue import NetfilterQueue
import subprocess
import signal
import traceback
import socket    

IMPERSONATOR_IP = 'x.x.x.x'
IMPERSONATOR_PORT = 19840    

udp_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM, socket.IPPROTO_UDP)    

def smuggle_packet(nfqueue_element):
   try:
       original_packet = nfqueue_element.get_payload()
       print('smuggled')
       udp_socket.sendto(original_packet, (IMPERSONATOR_IP, IMPERSONATOR_PORT))
       nfqueue_element.drop()
   except:
       traceback.print_exc()
       nfqueue_element.accept()    

nfqueue = NetfilterQueue()
nfqueue.bind(0, smuggle_packet)    

def clean_up(*args):
   subprocess.call('iptables -D OUTPUT -p udp --dst 8.8.8.8 --dport 53 -j QUEUE', shell=True)    

signal.signal(signal.SIGINT, clean_up)    

try:
   subprocess.call('iptables -I OUTPUT -p udp --dst 8.8.8.8 --dport 53 -j QUEUE', shell=True)
   print('running..')
   nfqueue.run()
except KeyboardInterrupt:
   print('bye')

服务器端代码如下:

import socket
import dpkt.ip    

def main_loop(server_socket, raw_socket):
    while True:
        packet_bytes, from_ip = server_socket.recvfrom(4096)
        packet = dpkt.ip.IP(packet_bytes)
        dst = socket.inet_ntoa(packet.dst)
        print('%s:%s => %s:%s' % (socket.inet_ntoa(packet.src), packet.data.sport, dst, packet.data.dport))
        raw_socket.sendto(packet_bytes, (dst, 0))    

server_socket = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
try:
    server_socket.bind(('0.0.0.0', 19840))
    raw_socket = socket.socket(socket.AF_INET, socket.SOCK_RAW, socket.IPPROTO_RAW)
    try:
        raw_socket.setsockopt(socket.SOL_IP, socket.IP_HDRINCL, 1)
        main_loop(server_socket, raw_socket)
    finally:
        raw_socket.close()
finally:
    server_socket.close()

在路由器上运行的时候要把WAN的防火墙规则改为接受INPUT,否则进入的UDP包会因为没有对应的出去的UDP包而被过滤掉。这是单向代理的一个缺陷,需要在墙上开洞。把防火墙整个打开是一种开洞的极端方式。后面专门讨论单向代理的时候会有更多关于防火墙凿洞的讨论。

第二个运行的条件是服务器所在的网络没有对IP SPROOFING做过滤。服务器实际上使用了和GFW发错误答案一样的技术,就是伪造SRC地址。通过把SRC地址填成客户端所在的IP地址,使得DNS查询的结果不需要经过代理服务器中装直接到达客户端。

通过丢弃错误答案反DNS劫持

使用iptables过滤

前两种方式都是针对GFW的重建这一步。因为GFW没有在日常的时候监听所有UDP端口以及监听TCP流量,所以非标准端口或者TCP的DNS查询可以被放行。选择性丢包则针对的是GFW的应对措施。既然GFW发错误的答案回来,只要我们不认它给的答案,等正确的答案来就是了。
代码如下:

mport sys
import subprocess    

# source http://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BC%93%E5%AD%98%E6%B1%A1%E6%9F%93
WRONG_ANSWERS = {
    '4.36.66.178',
    '8.7.198.45',
    '37.61.54.158',
    '46.82.174.68',
    '59.24.3.173',
    '64.33.88.161',
    '64.33.99.47',
    '64.66.163.251',
    '65.104.202.252',
    '65.160.219.113',
    '66.45.252.237',
    '72.14.205.99',
    '72.14.205.104',
    '78.16.49.15',
    '93.46.8.89',
    '128.121.126.139',
    '159.106.121.75',
    '169.132.13.103',
    '192.67.198.6',
    '202.106.1.2',
    '202.181.7.85',
    '203.161.230.171',
    '207.12.88.98',
    '208.56.31.43',
    '209.36.73.33',
    '209.145.54.50',
    '209.220.30.174',
    '211.94.66.147',
    '213.169.251.35',
    '216.221.188.182',
    '216.234.179.13'
}    

rules = ['-p udp --sport 53 -m u32 --u32 "4 & 0x1FFF = 0 && 0 >> 22 & 0x3C @ 8 & 0x8000 = 0x8000 && 0 >> 22 & 0x3C @ 14 = 0" -j DROP']
for wrong_answer in WRONG_ANSWERS:
    hex_ip = ' '.join(['%02x' % int(s) for s in wrong_answer.split('.')])
    rules.append('-p udp --sport 53 -m string --algo bm --hex-string "|%s|" --from 60 --to 180  -j DROP' % hex_ip)    

try:
    for rule in rules:
        print(rule)
        subprocess.call('iptables -I INPUT %s' % rule, shell=True)
    print('running..')
    sys.stdin.readline()
except KeyboardInterrupt:
    print('bye')
finally:
    for rule in reversed(rules):
        subprocess.call('iptables -D INPUT %s' % rule, shell=True)

本地有了这些iptables规则之后就可以丢弃掉GFW发回来的错误答案,从而得到正确的解析结果。这个脚本用到了两个iptables模块一个是u32一个是string。这两个内核模块不是所有的linux机器都有的。比如大部分的Android手机都没有这两个内核模块。所以上面的脚本适合内核模块很容易安装的场景,比如你的ubuntu pc。因为linux的内核模块与内核版本(每次编译基本都不同)是一一对应的,所以不同的linux机器是无法共享同样的内核模块的。所以基于内核模块的方案天然地具有安装困难的缺陷。

使用nfqueue过滤

对于没有办法自己安装或者编译内核模块的场景,比如最常见的Android手机,厂家不告诉你内核的具体版本以及编译参数,普通用户是没有办法重新编译linux内核的。对于这样的情况,iptables提供了nfqueue,我们可以把内核模块做的ip过滤的工作交给用户态(也就是普通的应用程序)来完成。

CLEAN_DNS = '8.8.8.8'    

RULES = []
for iface in network_interface.list_data_network_interfaces():
    # this rule make sure we always query from the "CLEAN" dns
    RULE_REDIRECT_TO_CLEAN_DNS = (
        {'target': 'DNAT', 'iface_out': iface, 'extra': 'udp dpt:53 to:%s:53' % CLEAN_DNS},
        ('nat', 'OUTPUT', '-o %s -p udp --dport 53 -j DNAT --to-destination %s:53' % (iface, CLEAN_DNS))
    )
    RULES.append(RULE_REDIRECT_TO_CLEAN_DNS)
    RULE_DROP_PACKET = (
        {'target': 'NFQUEUE', 'iface_in': iface, 'extra': 'udp spt:53 NFQUEUE num 1'},
        ('filter', 'INPUT', '-i %s -p udp --sport 53 -j NFQUEUE --queue-num 1' % iface)
    )
    RULES.append(RULE_DROP_PACKET)    

# source http://zh.wikipedia.org/wiki/%E5%9F%9F%E5%90%8D%E6%9C%8D%E5%8A%A1%E5%99%A8%E7%BC%93%E5%AD%98%E6%B1%A1%E6%9F%93
WRONG_ANSWERS = {
    '4.36.66.178',
    '8.7.198.45',
    '37.61.54.158',
    '46.82.174.68',
    '59.24.3.173',
    '64.33.88.161',
    '64.33.99.47',
    '64.66.163.251',
    '65.104.202.252',
    '65.160.219.113',
    '66.45.252.237',
    '72.14.205.99',
    '72.14.205.104',
    '78.16.49.15',
    '93.46.8.89',
    '128.121.126.139',
    '159.106.121.75',
    '169.132.13.103',
    '192.67.198.6',
    '202.106.1.2',
    '202.181.7.85',
    '203.161.230.171',
    '203.98.7.65',
    '207.12.88.98',
    '208.56.31.43',
    '209.36.73.33',
    '209.145.54.50',
    '209.220.30.174',
    '211.94.66.147',
    '213.169.251.35',
    '216.221.188.182',
    '216.234.179.13',
    '243.185.187.39'
}    

def handle_nfqueue():
    try:
        nfqueue = NetfilterQueue()
        nfqueue.bind(1, handle_packet)
        nfqueue.run()
    except:
        LOGGER.exception('stopped handling nfqueue')
        dns_service_status.error = traceback.format_exc()    

def handle_packet(nfqueue_element):
    try:
        ip_packet = dpkt.ip.IP(nfqueue_element.get_payload())
        dns_packet = dpkt.dns.DNS(ip_packet.udp.data)
        if contains_wrong_answer(dns_packet):
        # after the fake packet dropped, the real answer can be accepted by the client
            LOGGER.debug('drop fake dns packet: %s' % repr(dns_packet))
            nfqueue_element.drop()
            return
        nfqueue_element.accept()
        dns_service_status.last_activity_at = time.time()
    except:
        LOGGER.exception('failed to handle packet')
        nfqueue_element.accept()    

def contains_wrong_answer(dns_packet):
    if dpkt.dns.DNS_A not in [question.type for question in dns_packet.qd]:
        return False # not answer to A question, might be PTR
    for answer in dns_packet.an:
        if dpkt.dns.DNS_A == answer.type:
            resolved_ip = socket.inet_ntoa(answer['rdata'])
            if resolved_ip in WRONG_ANSWERS:
                return True # to find wrong answer
            else:
                LOGGER.info('dns resolve: %s => %s' % (dns_packet.qd[0].name, resolved_ip))
                return False # if the blacklist is incomplete, we will think it is right answer
    return True # to find empty answer

其原理是一样的,过滤所有的DNS应答,如果发现是错误的答案就丢弃。因为是基于nfqueue的,所以只要linux内核支持nfqueue,而且iptables可以添加nfqueue的target,就可以使用以上方式来丢弃DNS错误答案。目前已经成功在主流的android手机上运行该程序,并获得正确的DNS解析结果。另外,上面的实现利用iptables的重定向能力,达到了更换本机dns服务器的目的。无论机器设置的dns服务器是什么,通过上面的iptables规则,统统给你重定向到干净的DNS(8.8.8.8)。

自此DNS穿墙的讨论基本上就完成了。DNS劫持是所有GFW封锁手段中最薄弱的一环,有很多种方法都可以穿过。如果不想写代码,用非标准端口是最容易的部署方式。如果愿意部署代码,用nfqueue丢弃错误答案是最可靠通用的方式,不依赖于特定的服务器。

封IP观测

观测twitter.com

首先使用dig获得twitter.com的ip地址:


; <<>> DiG 9.9.1-P3 <<>> +tcp @8.8.8.8 twitter.com
; (1 server found)
;; global options: +cmd
;; Got answer:
;; ->>HEADER<<- opcode: QUERY, status: NOERROR, id: 8015
;; flags: qr rd ra; QUERY: 1, ANSWER: 3, AUTHORITY: 0, ADDITIONAL: 1    

;; OPT PSEUDOSECTION:
; EDNS: version: 0, flags:; udp: 512
;; QUESTION SECTION:
;twitter.com.                        IN        A    

;; ANSWER SECTION:
twitter.com.                7        IN        A        199.59.149.230
twitter.com.                7        IN        A        199.59.150.39
twitter.com.                7        IN        A        199.59.150.7

根据前面的内容我们知道使用dns over tcp,大部分的域名解析都不会被干扰的。这里得到了三个ip地址。先来测试199.59.149.230

traceroute to 199.59.149.230 (199.59.149.230), 30 hops max, 38 byte packets
  123.114.32.1  19.862 ms  4.267 ms  101.431 ms
  61.148.163.73  920.148 ms  5.108 ms  3.868 ms
  124.65.56.129  7.596 ms  7.742 ms  7.735 ms
  123.126.0.133  5.310 ms  7.745 ms  7.573 ms
  *  *  *
  *  *  *

这个结果是最常见的。在骨干路由器上,针对这个ip丢包了。这种封锁方式就是最传统的封IP方式,BGP路由扩散,现象就是针对上行流量的丢包。再来看199.59.150.39

traceroute to 199.59.150.39 (199.59.150.39), 30 hops max, 38 byte packets
  123.114.32.1  14.046 ms  20.322 ms  19.918 ms
  61.148.163.229  7.461 ms  7.182 ms  7.540 ms
  124.65.56.157  4.491 ms  3.342 ms  7.260 ms
  123.126.0.93  6.715 ms  7.309 ms  7.438 ms
  219.158.4.126  5.326 ms  3.217 ms  3.596 ms
  219.158.98.10  3.508 ms  3.606 ms  4.198 ms
  219.158.33.254  140.965 ms  133.414 ms  136.979 ms
  129.250.4.107  132.847 ms  137.153 ms  134.207 ms
  61.213.145.166  253.193 ms  253.873 ms  258.719 ms
  199.16.159.15  257.592 ms  258.963 ms  256.034 ms
  199.16.159.55  267.503 ms  268.595 ms  267.590 ms
  199.59.150.39  266.584 ms  259.277 ms  263.364 ms

在我撰写的时候,这个ip还没有被封。但是根据经验,twitter.com享受了最高层次的GFW关怀,新的ip基本上最慢也是隔日被封的。不过通过这个traceroute可以看到219.158.4.126其实就是那个之前捣乱的服务器,包是在它手里被丢掉的(严格来说并不一定是219.158.4.126,因为ip包经过的路由对于不同的目标ip设置不同的端口都可能会不一样)。再来看199.59.150.7

traceroute to 199.59.150.7 (199.59.150.7), 30 hops max, 38 byte packets
  123.114.32.1  11.379 ms  10.420 ms  23.008 ms
  61.148.163.229  6.102 ms  6.777 ms  7.373 ms
  61.148.153.61  5.638 ms  3.148 ms  3.235 ms
  123.126.0.9  3.473 ms  3.306 ms  3.216 ms
  219.158.4.198  2.839 ms !H  *  6.136 ms !H

这次同样是封IP,但是现象不同。通过抓包可以观察到是什么问题:

:46:11.355913 IP (tos 0x0, ttl 251, id 0, offset 0, flags [none], proto ICMP (1), length 56)
.158.4.198 > 123.114.40.44: ICMP host r-199-59-150-7.twttr.com unreachable, length 36
        IP (tos 0x0, ttl 1, id 0, offset 0, flags [DF], proto UDP (17), length 38)
.114.40.44.45021 > r-199-59-150-7.twttr.com.33449: UDP, length 10

原来219.158.4.198发回来了一个ICMP包,内容是地址不可到达(unreachable)。于是traceroute就在那里断掉了。

如果把unreachable类型的ICMP包丢弃掉,会发现ip包仍然过不去

traceroute to 199.59.150.7 (199.59.150.7), 30 hops max, 38 byte packets
  123.114.32.1  4.866 ms  3.165 ms  3.212 ms
  61.148.163.229  3.107 ms  3.104 ms  3.270 ms
  61.148.153.61  6.001 ms  7.246 ms  7.398 ms
  123.126.0.9  7.840 ms  7.223 ms  7.443 ms
  *  *  *

这次就和被丢包了是一样的观测现象了。

同时,可以看到我们仍然是收到了icmp地址不可到达的包的,只是被我们drop掉了。

观测被封ip的反向流量

之前的观测中,被封的ip是ip包的dst。如果我们从国外往国内发包,其src是被封的ip,那么ip包是否会被GFW过滤掉呢?登录到一台国外的vps上执行下面的python代码:

from scapy.all import *
send(IP(src="http://drops.wooyun.org/papers/199.59.150.7", dst="123.114.40.44")/ICMP())

然后在国内的路由器上执行抓包程序

tcpdump: listening on pppoe-wan, link-type LINUX_SLL (Linux cooked), capture size 65535 bytes
:41:14.294671 IP (tos 0x0, ttl 50, id 1, offset 0, flags [none], proto ICMP (1), length 28)
    r-199-59-150-7.twttr.com > 123.114.40.44: ICMP echo request, id 0, seq 0, length 8
:41:14.294779 IP (tos 0x0, ttl 64, id 25013, offset 0, flags [none], proto ICMP (1), length 28)
.114.40.44 > r-199-59-150-7.twttr.com: ICMP echo reply, id 0, seq 0, length 8

可以看到,如果该ip是src而不是dst并不会被GFW过滤。这一行为有两种可能:要么GFW认为封dst就可以了,不屑于再封src了。另外一种可能是GFW封twitter的IP用的是路由表扩散技术,而传统的路由表是基于dst做路由判断的(高级的路由器可以根据src甚至端口号做为路由的依据),所以dst路由表导致的路由黑洞并不会影响该ip为src的情况。我相信是后者,但是GFW在封个人翻墙主机上所表现的实力(对大量的ip做精确到端口的全国性丢包)让我们相信,GFW很容易把封锁变成双向的。不过说实话,在这个硬实力的背后,靠的更多的是CISCO下一代骨干网路由器的超强处理能力,而不是GFW自身。

单向代理

因为GFW对IP的封锁是针对上行流量的,所以使得单向代理就可以突破封锁。上行的IP包经过单向代理转发给目标服务器,下行的IP包直接由目标服务器发回给客户端。代码与DNS(UDP协议)的单向代理是一样的。因为单向代理利用的是IP协议,所以TCP与UDP都是一样的。除了单向代理,目前尚没有其他的办法穿过GFW访问被封的IP,只能使用传统的翻墙技术,代理或者VPN这些。

结语

GFW与网民之间已经或者即将形成某种稳态,这种稳态是双方斗争状况下的动态平衡,是需要有意识维护的。一个无法控制的网络是无法被政府所容忍的,当网络无法控制时政府是不吝于切断一切网络的(你一定知道我在说什么),稳态的破坏也就意味着环境的毁灭。一个理想的稳态就是网络处于“看起来”可以控制的状态,让GFW处于不断取得小型封锁成功的虚幻胜利感之中,网民个人各自掌握非中心化的翻墙方法。一个中心化的大众翻墙方法(最典型的例子就是设置hosts静态解析)必定无法避免被当局发现并被GFW封锁。下一代的翻墙方法应该是去中心化的(p2p)、小众的、多样化的、混合型的、动态更新的。

参考资料

jsDelivr域名遭到GFW封锁

2022年6月12日 14:18

前情提要--jsDelivr 备案被吊销

2021年12月20日,jsDelivr 团队主要负责人 Dmitriy Akulov 在 jsDelivr 官方 GitHub 仓库的一条 issue 下发表了以下说明

Thank you all for your tests, feedback and support. I am personally sorry for the issues we had today.
We can consider the issue as resolved, now its a question of DNS propagation getting to everyone.
Our official announcement regarding the problems today:
Unfortunately today jsDelivr unexpectedly lost its ICP license in China. As effect the regional CDN disabled our account.
This resulted in the extended outage we had in mainland China and Taiwan.
Other regions were unaffected.
We understand how difficult it was for our users to experience this unique situation.
From now on all Chinese traffic will be served by "near China" locations provided by global CDN providers.
This will have the additional benefit of better failover logic in the future.

译文:

感谢大家的测试、反馈和支持。我个人对我们今天遇到的问题感到抱歉。
我们可以认为这个问题已经解决,现在它是一个 DNS 传播问题。
我们今天关于问题的官方公告:
不幸的是,今天 jsDelivr 意外失去了在中国的 ICP 牌照。结果,区域 CDN 禁用了我们的帐户。
这导致我们在中国大陆和台湾的停电时间延长。
其他地区不受影响。
我们了解我们的用户体验这种独特的情况是多么困难。
从现在开始,所有中国流量都将由全球 CDN 提供商提供的“中国附近”位置提供服务。
这将在未来获得更好的故障转移逻辑的额外好处。

当天jsDelivr 在国内的故障,并不是偶发的 SSL 证书出现问题导致资源下线,而是域名备案被吊销,导致国内 CDN 提供商网宿移除了 jsDelivr 的账号。当时 jsDelivr 国内线路为 Fastly:

2021年12月20日 - 可喜可贺的一天,jsDelivr 的 ICP 没了。最少在短时间内,jsDelivr 是无法也不会提供基于国内节点的托管服务了。可以想象,也是可能的下一步,就是 jsDelivr 完全被 GFW 阻断,成为连 Google Hosted Libraries 和 cdnjs 都不如的开源 CDN - 最少这两个国内还极其勉强地能用。

封锁历程

DNS 污染

2022.04.28 GFW开始实行dns污染:

可以看到,jsDelivr的域名已经被解析到Twitter,Facebook等被阻断的IP地址上。

2022年4月28日,jsDelivr得到了与Facebook、Twitter等如出一辙的安排,主要的服务域名遭到DNS污染。在正常状态下,当你请求网站域名域名时,你的DNS服务器会逐级向上寻找这个域名的解析记录,并通过这个链条将它指向的服务器返回给你,实现域名与服务器的融合。若你的DNS逐级向上请求记录的过程中,出现了一个中间人提前抢答了错误的记录,而非来自域名权威服务器的正确回复,导致返回的结果并不是指向正确服务器的,连接因此不能建立,这便是DNS污染。

此轮封锁于2022.04.29解除。

SNI阻断

2022.05.17 jsDelivr 的域名再次被污染,同时伴随SNI阻断,即改host的方法不在有效。

此轮封锁于2022.06.11解除。

jsDelivr的命运

惊艳四座的jsDelivr

不知道提到jsDelivr,大家都是从哪一项服务开始接触到它的?由中国最大的传统CDN提供商网宿(QUANTIL)赞助,支持cdnjs和GitHub内容直接加速引用,它的应用可以说是迄今为止所有静态库中最为广泛的了。大到各种门户网站,小到个人博客,乃至去广告规则订阅、图床、插件静态库等等种种衍生场景,都能见到它的身影。

在网宿的协助下,2016年12月jsDelivr挂名在上海幻文信息科技有限公司下完成了企业ICP备案,取得了备案号【沪ICP备15005128号-2】。这是一家网宿用于代理备案的公司,通过天眼查等工具很容易看出来,历史上共有8个网站在这个公司挂名进行备案,目前除了所谓的主页已全部注销。

这是历史上第一个以较为正规的方式进入中国大陆的海外静态资源库项目,在网宿与诸多海外赞助商协同下,5年中jsDelivr提供了非常稳定且出色的服务。jsDelivr官方毫不掩饰对自己能够在中国大陆合法提供服务的喜悦,专门在节点页面中写下了“我们拥有中国政府的ICP许可证,拥有数百个服务节点的巨大中国网络”的字眼。

然而千里之堤溃于蚁穴,纵使拥有网宿这样强有力的支撑,也难抵运营以来遇到的重重阻碍。

一波三折的大陆服务

在网宿负责中国大陆的CDN节点这几年中,因为网宿方面的问题导致了几次SSL证书过期而宕机,博主有印象的在2019、2020年都有出现过。如果说那些都是网宿单方面的失误的话,2019年10月的暂时退出是jsDelivr官方面临的第一次危机。2018年工信部对域名备案政策颁布了新的规定,只有注册局在中国大陆拥有代理公司并完成申报、且域名停放在在中国大陆注册商的情况下才可以进行备案。jsDelivr挂名的公司在2019年需要进行了负责人信息的变更,备案主体信息需要进行修改,这在多个域名中都可以查到记录。

当时,jsDelivr暂时关闭了中国大陆的节点,转而使用网宿位于中国台湾和韩国首尔的节点提供服务,加载速度一落千丈。当时博主还向官方发送了一封邮件进行了咨询,官方也亲切地回应是在更新ICP备案,将在不久之后恢复。较早的issue中,官方人员进行了更详细的解释,他们在更新ICP备案的过程中遇到新规的要求将备案域名转入至中国大陆的服务商的问题,在评估后他们认为没有一种安全的方式能够确保在服务不中断的前提下将域名转移至中国大陆,因此暂时关闭中国大陆的节点等待进一步的探讨。最终在一个月后,jsDelivr恢复了位于中国大陆的节点,这次风波算是告一段落。

接下来的三年中大体相安无事,除了几乎每年一度的网宿忘记更新SSL证书。但是由于支持对GitHub项目的完整加速,对jsDelivr的滥用日趋严重,GitHub+jsDelivr图床、视频床甚至网盘层出不穷。如果说以上只是对免费资源的滥用,在GitHub中储存成人、邪教等文件通过jsDelivr向中国大陆分发,则是将jsDelivr一步步推向万丈深渊。

在2020年的8月15日,jsDelivr在官方GitHub项目中首次更新了使用限制说明,这是官方第一次明确表示禁止多种滥用行为并添加了对中国大陆政策的额外说明。在这之后,官方在网宿方向屏蔽了一系列不符合中国大陆法律内容的项目。但是由于是针对整个GitHub项目的通用加速,官方的封禁显然远远比不过肆意滥用的脚步。

命中注定的结局

jsDelivr对中国大陆的态度一直颇为暧昧,在2019年风波平息后,有不少人提议针对中国大陆的服务中GitHub加速项目应当审核开放或关闭此项以防止滥用,但官方认为将项目推送cdnjs也是很容易的事,单单禁用GitHub并不能解决不合理利用的问题,于是便没有了后文。

于是在2021年12月20日,当项目组成员在另一个半球睡得正香的时候,自上而下的命令压力下网宿直接关闭了jsDelivr的大陆CDN,几个小时后jsDelivr的ICP备案也被注销。当jsDelivr项目工作人员起来时,一脸茫然地发现网宿在未告知原因的情况下关闭了中国大陆的CDN,在愤怒之余将DNS记录切换至了Fastly恢复了jsDelivr的访问,这次的风波暂时告一段落。

但是网宿这次为何突然关闭CDN的原因依然众说纷纭,有内部人士称是因为网安部门发现了通过jsDelivr的链接传播邪教内容,但这些无从考证,官方自始至终也未对此给出任何解释。但无法改变的是,jsDelivr失去了ICP许可证,不再拥有位于中国大陆的CDN节点,加载速度大幅下降,官方也不再通过区域服务商对内容进行过滤。

在这之前有一个同样支持GitHub加速的静态资源库statically.io已被SNI阻断,与曾经的jsDelivr唯一的不同便是没有ICP许可证的保护。它走过的路,冥冥中暗示着jsDelivr注定的结局。

2022年4月28日,jsDelivr在中国大陆确认遭到DNS污染,乐章到此戛然而止。

jsDelivr的替代方案

遭到GFW封锁,基本宣告这个域名面向大众的服务失去价值,因为你无法让每个人学习像极客一样学会修改hosts、使用DoH分流。特别是前端引用这样面向用户的场景,应当更多考虑用户的便利性。以下提供几种可行的方案供大家参考,希望对大家有所帮助。

针对恢复访问主要分为服务和本地两种场景,服务场景修改则是替换jsDelivr资源到可访问的资源上,本地场景修改恢复访问的目的是针对海外引用jsDelivr的站点,这是两种不同的操作和目标。

官方子域

这次的污染只针对cdn.jsdelivr.net这一个域名,jsDelivr有很多的CDN赞助商共同支持,每一个服务商都会有自己的专有子域名,通过替换访问资源到其他的二级域名可以恢复访问。但这些CDN普遍速度一般,而且前途并不明朗,建议仅供临时使用。

CloudFlare:test1.jsdelivr.net
CloudFlare:testingcf.jsdelivr.net
Fastly:fastly.jsdelivr.net
GCORE:gcore.jsdelivr.net

反向代理

如果一定要使用jsDelivr的资源的话,可以考虑通过反代cdn.jsdelivr.net这一个资源库自用。建议通过海外优化线路落地+国内中转缓存,不过要注意添加防盗链以及尽量隐藏反代路径,以防止被其他人滥用。
nginx配置文件:

#针对/gh目录的反代 
location /gh
{
    proxy_pass https://104.16.86.20;
    proxy_set_header Host cdn.jsdelivr.net;
    proxy_ssl_server_name on;
    proxy_ssl_name cdn.jsdelivr.net;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header REMOTE-HOST $remote_addr;
}

Cloudflare Workers 配置文件:

const hostname = "https://cdn.jsdelivr.net"


function handleRequest(request) {
    let url = new URL(request.url);
    return fetch(new Request(hostname + url.pathname,request))
}

addEventListener("fetch", event => {
  event.respondWith(handleRequest(event.request))
})

由于Cloudflare Workers也被GFW封锁了,所以需要绑定一个域名:
如添加cdn.example.com指向8.8.8.8,类型可添加A或CNAME类型,并勾选Cloudflare代理。

(此处ip地址或CNAME可随意填写,因为只是为了让域名走Cloudflare。)

添加路由,配置Route:cdn.example.com/*指向创建的Workesr,到此等待DNS生效即可。

切换国内静态库

推荐一些国内比较稳定、全面的静态资源库吧,其中不乏完全同步cdnjs内容的,可以逐步将静态资源替换过去。

字节静态库:cdn.bytedance.com

  • 完整同步了cdnjs的内容,通过自家CDN加速,缺点是没有海外节点而且链接比较凌乱。

360静态库:cdn.baomitu.com

  • 完整同步了cdnjs的内容,并且有提供Google fonts加速,通过自家CDN加速,前段时间启用了AWS CloudFront的海外节点,是目前国内公共CDN做的比较好的了。

七牛静态库:staticfile.org

  • 通过自家融合CDN加速,海外节点较少不过也表现尚可,缺点就是担心org域名后续备案维护的问题。

修改Hosts(失效)

一般情况下,DNS污染通常伴随着SNI阻断,不过比较幸运的是jsDelivr只是单纯的DNS污染,可以通过本地指定正常的IP恢复访问。这样操作可以解决作为用户本地无法加载页面包含jsDelivr资源的问题。Hosts文件在UNIX系统下位于/etc/hosts,Windows系统下位于C:\Windows\System32\drivers\etc\hosts,在末尾处添加适当的以下条目即可恢复访问。

#CloudFlare(不推荐联通使用)
104.16.85.20     cdn.jsdelivr.net
104.16.86.20     cdn.jsdelivr.net
104.16.87.20     cdn.jsdelivr.net
104.16.88.20     cdn.jsdelivr.net
104.16.89.20     cdn.jsdelivr.net
#Fastly(不推荐电信使用)
151.101.1.229    cdn.jsdelivr.net
151.101.129.229  cdn.jsdelivr.net

使用DoH/DoT(失效)

因为jsDelivr只是单纯的DNS污染可以通过DNS分流走海外加密DNS绕过污染。可以参考:https://blog.gd1214b.icu/post/Zr3HDqj6D/,但是修改DNS一定要做好分流,以免影响DoH/DoT对日常上网导致的CDN分配的问题。

其他可能的思路

目前有通过油猴替换reCAPTCHA使用的API中的google.com为recaptcha.net实现中国大陆加载,理论上也是可以通过这样的方法将jsDelivr替换到大陆可加载的链接上,期待各位大佬的实践。

结语

到底是谁杀死了jsDelivr呢?是jsDelivr审核不够严谨?是网宿的不辞而别?还是是政策的“一刀切”?博主不知道,相信各位看官自己心里都有自己的答案吧。

本来只是想简单讲几句,没想到就说了这么多,一篇文章难免会参杂有个人情感,文中如果有不够严谨的地方请多指点。

最后,晚安jsDelivr,感谢您和诸多的赞助商这么多年来为用户无偿提供这样便捷的服务~

参考资料

公安部门高科技查水表取证的方法

2022年6月8日 22:07

本文转自:https://www.guokr.com/post/565846/

我们来假设一个案例,在一个月黑风高的晚上,小明在某论坛大肆批评政府,第二天小明刚一睡醒就听见咚咚咚,开门查水表,于是乎小明神秘消失了。

好了,再以网监的角度来看看:
一天,网监局的小红看到了一个网民在网上发了个大肆批判政府的帖子,心想,这哥们胆子挺大啊?于是联系了那个网络公司,要求调取发帖人IP地址,IP调取结果为122.224.54.112,IPWHOIS登记的所有人为中国电信,好了,网监局小红联系了中国电信,要求查在2014-01-21 03:30分使用122.224.54.112的人,之后中国电信乖乖的配合网监局,交出了小明的家庭地址,浙江省绍兴市XXXXXX ,然后水表就没了。

再切换会小明的角度:小明心想,老子明明用的是ADSL,动态IP,发完贴就断开了,怎么还tm被查到了,WTF?

老衲的解释:在各级ISP的日志服务器上都有留存日志,日志留存时间大概是6个月左右,在AAA服务器上留有你登录认证的用户名,时间,分配的IP地址。依靠这个就能找到谁在哪个时间段使用过哪个IP地址。


被拘留15天后的小明终于出来了,他心想,老子就要跟你们这群网监局的人干到底,小明就在网上找到了个代理VPN,继续上网发帖,继续在另一个网站上批评政府,这是个小网站啊,日志留存期内肯定查不到了,而且还挂了个VPN,第二天,小明又被查水表了。

以网监局的小红的角度再看看:诶呀?根据“與情控制系统”的报告,有人在某个小型网站发了个反政府的文章,小红又火速要求网站提供发帖人IP地址,结果小红一看 175.45.176.11 这是尼玛是我大朝鲜IP啊,难不成是金三胖子发的帖子么?小红想了想,金三胖子不会说中文啊,于是,小红上报了此次事件,上级表示一定要查到,然后小红就去各大出口运营商调取路由日志了,于是小明发现,在2014年2月8日,122.224.250.38链接到了175.45.176.11的某个端口,于是乎小红查了查122.224.250.38在那个时间段是属于谁的?一查,又是小明干的。

小红第二天火速赶往小明家,把正在看电视的小明抓捕归案。小明又被小红胖揍一顿。

小明心想:老子明明挂了VPN了啊,又在小型网站上发帖,怎么又尼玛被抓了。

老衲的解释:各级公安系统均配备了與情控制系统,能采集几乎所有的国内网站的发帖信息,检测到关键字就被单独列出。而且单层VPN很不保险,查路由日志就查到了。


又是蹲了15天拘留, 小明肯定心里很不爽啊,于是苦修黑阔技术。同时中国电信也拒绝继续向小明提供服务,他换成了广电网络(二级ISP,出口IP都一样,几千人共用一个IP)之后又学会了一招,双层VPN/变换出口IP的VPN(就比如链接用175.45.176.11,但是访问网站的时候出口IP就变成了175.45.179.244,这样就没法靠路由日志查了),于是乎小明又继续批评政府。

网监局的小红看到后,这怎么又有人发帖了,查吧。一看,IP是175.45.179.244,这尼玛又是我大朝鲜的IP,是不是小明干的啊?但是没证据啊,于是又查了查路由日志,这回什么都没有,小红心想,这小明技术提高了啊。于是乎小红要求国内各大网络公司提供175.45.179.244这个IP的访问记录,于是某企鹅公司说了,这个IP登录过我们公司的服务,号码是12345668,小红又要求某企鹅公司提供这个号码的历史登录记录,于是乎小红看到了,看IP是二级ISP的,几千人共用一个ip啊,怎么办呢?小红又要求企鹅公司提供登录端口号,然后又同时根据二级ISP内网审计设备查到了登录该qq的内网IP,于是根据内网记录,查到了网络开户人就是小明。

小红火速赶到了小明的家,又把小明抓走了。这是小明的三进宫了,小红也表示很无奈,渐渐的,单身的小红和小明互相就有了好感(>.<尼玛)

小明想:老子都用二级ISP了,也用双重VPN了,怎么又尼玛被抓了,wr!!

老衲的解释:首先二级ISP有更严格的内网审计功能,你要是直接登录QQ,他们的内网审计就能直接看到你登录的QQ帐号但是看不到你的聊天记录,因为加密的。某局实验室的设备可以直接看到你的聊天记录(老衲见识过这个,有QQ的解密密钥,还能解飞信,YY之类的,毕竟中国的企业必须给网警部门提供方便)。虽然是几千人共用一个IP,但是端口号是唯一的,可以通过端口号查内网路由日志。而且这种VPN甚至IPSecVPN能在某墙的干扰下变成纯明文VPN,因为windows系统中可能有bug,即使开启了必须加密也能链接成功,但是却没加密。这就是为什么有时候你开VPN上网,DNS都设置好了,还是打不开非死不可之类的网站。即使这些情况都没有,你也不能保证VPN服务商跟网警部门没有合作的。而且电脑上有很多国产软件是和网警部门有合作的,比如搜狗拼音,腾讯qq啊之类的,这些软件的特征是 开启时间长,可长时间驻留,每日必备。在你开全局VPN的时候,你的qq,搜狗拼音等也会被代理上,比如qq会断线重链,根据每个人的唯一码,很简单找到你。


又是15天的拘留,小明很不爽啊,出来后苦苦学习黑阔技术,之后又学会了一招:
小明用了个Linux LiveCD,把电脑网卡MAC都改了,然后破解了邻居的一个WiFi,然后用I2P作为前置代理链接上了TOR网络,然后继续发帖。第二天,咚咚咚,小明又被小红带走了。

网监局小红:还是有人发帖批评政府啊,于是小红查了下发帖IP,是个欧洲的TOR出口,小红心想,这怎么办呢,TOR网络,不可能继续追查下去了。小红看了看发帖的用户名:laozishixiaoming,这个用户名。。。

然后百度谷歌搜索了下这个用户名,发现这个用户名注册过很多网站,于是乎联系这些网站要求提供IP,拿到IP后查AAA服务器记录,一看,是小明。于是小红气呼呼的奔向了小明家................

小明心想:又尼玛栽了。

小红说:想见我不要用这种方法吧?

老衲的解释:这是社会工程学的一种手段,小明犯的致命错误就是用了自己的常用用户名发帖。


总结:
首先要做到匿名发帖就要保证自己的电脑没有“后门”,这里的“后门”指不经自己授权就随意发送接受自己不想被发送或接收的数据。在这个条件下,腾讯qq,搜狗拼音,暴风影音,迅雷等就是“后门”。

其次要应用的安全,比如VPN总不能被干扰成明文了你还在网上狂吧? IP藏匿手段要好,最好用I2P+TOR代理。

最重要的也是要保证社会工程学的防御,据老衲的了解,很多发帖人就栽在这上面了。

使用Diceware创建高强度且便于记忆的密码

2022年6月1日 17:30

前言

现在保护您的数字隐私变得越来越容易。iPhone现在加密了大量的个人信息;Mac 和Windows 8.1计算机上的硬盘现在自动锁定;就连Facebook 也在聊天工具 WhatsApp 中提供端到端加密。但是,如果您不知道如何想出一个好的密码短语,那么这些技术都无法提供您想象的那么多保护。

密码短语类似于密码,但更长、更安全。从本质上讲,它是您记住的加密密钥。一旦您开始更深入地关心您的隐私并改善您的计算机安全习惯,您将遇到的第一个障碍就是必须创建密码。

例如,当您对硬盘驱动器、U盘或计算机上的文档进行加密时,磁盘加密的强度通常仅与您的密码一样强。如果您使用密码数据库或 Web 浏览器中的密码保存功能,您需要设置一个强大的主密码来保护它们。如果您想使用 PGP 加密您的电子邮件,您可以使用密码保护您的私钥。爱德华·斯诺登在给 Laura Poitras 的第一封电子邮件中写道:“请确认没有人拥有您的私钥的副本,并且它使用了强密码。假设你的对手每秒能够进行一万亿次猜测。”

在这篇文章中,我们将介绍一种简单的方法来提供易于记忆但非常安全的密码短语。事实证明,通常情况下想出一个好的密码短语是非常困难的。如果你的对手真的有能力每秒猜测一万亿次,那么你的密码将会变得很不安全。如果您使用完全随机的字符序列,它可能非常安全,但记住也很痛苦(老实说,浪费脑力)。

人们经常从流行文化中挑选一些短语——歌曲中最喜欢的歌词或电影或书中最喜欢的台词——然后通过改变一些大小写或添加一些标点符号或修改该短语中每个单词的第一个字母来稍微改变它。其中一些密码短语可能看起来不错并且完全无法猜测,但很容易低估那些投入猜测密码短语的人的能力。

想象一下,你的对手已经从每首歌曲的歌词、每部电影和电视节目的剧本、每本书的数字化文本以及维基百科的每一页中提取了每种语言的文本,并将其用作猜测列表的基础。你的密码还能安全吗?

如果您只是通过出一个好的密码来创建密码,那么很有可能它还不足以抵抗间谍机构的力量。例如,您可能会想出“To be, or not to be, that is the question.” 如果是这样,我可以保证您不是第一个使用这句经典莎士比亚名言作为密码的人,而且攻击者知道这一点。

使用莎士比亚名言作为密码短语糟糕的原因是它缺少称为的东西。您可以将熵视为随机性,它是密码学中最重要的概念之一。事实证明,人类无法以真正随机的方式做任何事情。

即使您不使用引用,而是在脑海中编造一个短语,您的短语仍然远非随机,因为语言是可预测的。正如一篇关于该主题的研究论文所述,“用户无法选择由完全随机的单词组成的短语,但会受到短语在自然语言中出现的概率的影响”,这意味着用户选择的密码短语不包含像你想象的那样多的熵。你的大脑倾向于继续使用减少随机性的常用习语和语法规则。例如,在副词后面加上动词,反之亦然。

来自流行文化、关于你的生活的事实或任何直接来自你脑海的密码短语比从大自然中收集到的充满实际熵的密码短语要弱得多。

但幸运的是,这种可用性与安全性之间的矛盾可以解决。有一种生成密码短语的方法,即使是最强大的攻击者也无法猜测,但人类却很可能记住。该方法称为Diceware,它基于一些简单的数学运算。

什么是Diceware

一旦您承认您的旧密码并不像您想象的那么安全,您就可以使用 Diceware技术了。

Diceware 是一种由 Arnold Reinhold 创造的生成密码短语的方法。使用 Diceware 需要一份词表和至少一个骰子。词表由7776(6^5) 个不同的单词构成,每个单词对应一个5位“骰子序号”(如 "46134"),每掷5个/次骰子便可选中一个随机的单词。掷30个/次骰子就能生成一个高强度的6词密码短语。由于每个单词有明确的意思,这样的密码短语通常比相同强度的由随机字符组成的密码更容易记忆。

如何使用Diceware

最初的 Diceware 词表 是英文的,且生僻词较多,不易于中文母语者使用。之后多种其他版本/语言的 Diceware 词表陆续出现,本文使用的中文词表由Chenfeng Bao制作:https://github.com/cfbao/chinese-diceware

首先,获取一份Diceware 单词表(可以到https://cdn.gd1214b.tk/diceware/diceware_chinese_wordlist.txt上去下载),其中包含 7,776 个单词——大约37 页。您会注意到,每个单词旁边都有一个五位数字,每个数字介于 1 和 6 之间。以下是单词列表的一小段摘录:

11111 aba 阿爸
11112 afuhan 阿富汗
11113 aichou 哀愁
11114 aidai 爱戴
11115 aidao 哀悼
11116 aie 挨饿
11121 aifu 爱抚
11122 aiguo 爱国
11123 aihao 爱好

为了保证安全,您应该将单词表打印下来,而不是使用电子版。然后确保您处于一个安全的环境中(旁边没有其他人和摄像头)

现在拿起一些六面骰子(是的,真正的物理骰子)并掷几次,写下你得到的数字(建议在坚硬的表面上书写,因为这样难以留下痕迹)。您总共需要掷五次骰子才能得出密码短语中的第一个单词。您在这里所做的是生成熵,从自然界中提取真正的随机性并将其转化为数字。

如果您滚动数字五、二、二、五、一,然后在 Diceware 单词列表 52251 中查找,您会看到“shuxue(数学)”这个词。这将是您密码中的第一个单词。现在重复。

使用 Diceware,您最终会得到看起来像“haoshi aosang roucuo lizhan cesuan teshi”、“bang vivo threadductknipple train”和“pichai beichu budebu minyao yecao xingge”的密码短语。如果你想要一个更强的密码,你可以使用更多的单词;如果您可以使用较弱的密码短语,则可以使用更少的单词。

对于像“sanhui beibu fuqiao dongwu yinju guolai (散会-北部-浮桥-动物-隐居-过来)”这样的密码短语来说还不错,大多数人完全有可能记住。将其与“aE6,kP3^fT1"mA5)”这样一个随机密码相比,其熵比七字的 Diceware 密码略少,而且更难记住。

生成密码后,下一步是牢牢地记住它。

我们建议您将新密码写在一张纸上,并随身携带,直到您不再需要它为止。每次需要输入时,请先尝试从记忆中输入,但如果需要,请查看纸张。假设你一天打几次,在你不再需要纸之前不应该超过两三天,这时你应该把它销毁(建议用火烧掉)。

根据对高熵密码短语的研究,定期输入密码短语可以让您通过称为间隔重复的过程记住它。

关于Diceware的安全性

Diceword 密码短语的强度取决于它包含的单词数量。如果您选择一个单词(从 7,776 个单词的列表中),攻击者有 7,776 分之一的机会在第一次尝试时猜出您的单词。要猜出你的密码短语的话,攻击者至少需要尝试一次,最多尝试 7,776 次,平均尝试 3,888 次(因为攻击者有 50% 的机会会在他们完成单词列表的一半时猜出你的单词)。

但是,如果您为密码选择两个单词,则可能的密码列表的大小会呈指数增长。仍然有 7,776 分之一的机会正确猜测您的第一个单词,但对于每个第一个单词,也有 7,776 分之一的机会正确猜测第二个单词,攻击者不会知道第一个单词是否正确而无需猜测整个单词密码。

这意味着对于两个单词,有7,776^2或 60,466,176 个不同的潜在密码短语。平均而言,在前 3000 万次尝试后,可以猜出两个单词的 Diceware 密码。一个五字密码短语,有 7,776^5 个可能的密码短语,可以在平均 14 千亿次尝试后猜出(14 后面有 18 个零)。

密码短语(或加密密钥或任何其他类型的信息)中的不确定性量以熵的位数来衡量。您可以通过包含多少位熵来衡量随机密码的安全性。Diceware 列表中的每个单词都值大约 12.92 位熵(因为 2^12.92 大约是 7,776)。因此,如果您选择七个单词,您最终会得到一个具有大约 90.5 位熵的密码(因为 12.92 乘以 7 大约是 90.5)。

换句话说,如果攻击者知道您使用的是 7 个单词的 Diceware 密码短语,并且他们从 Diceware 单词列表中随机选择 7 个单词进行猜测,那么他们一次猜测成功的概率为 :
1/1,719,070,799,748,422,591,028,658,176。

以每秒一万亿次的猜测——根据爱德华·斯诺登 2013 年 1 月的警告——猜测这个密码短语平均需要 2700 万年。

相比之下,一个五字密码短语将在不到六个月的时间内破解,而一个六字密码短语平均需要 3,505 年(每秒猜测一万亿次)。牢记摩尔定律,计算机将不断变得更强大,不久之后,每秒 1 万亿次猜测可能会开始变得更快,因此最好给您的密码短语留出一些安全的空间。

使用这样的系统,您选择的单词列表是否公开并不重要。列表中的单词是什么甚至都没有关系。重要的是单词列表有多长以及列表中的每个单词都是唯一的。猜测由这些随机选择的单词组成的密码短语的概率随着您添加的每个单词而呈指数级减小,并且使用这个规律可以制作永远无法猜测的密码短语。

我们如何使用 Diceware 保护我们的个人信息

当您将 Diceware 密码短语输入计算机以在本地解密某些内容(例如硬盘驱动器、PGP 密钥或密码数据库)时,它们非常适合。

您不太需要它们来登录网站或互联网上的其他东西。在这些情况下,您从使用高熵密码短语中获得的好处较少。如果每次猜测都需要与互联网上的服务器通信,那么攻击者将永远无法每秒猜测一万亿次。在某些情况下,攻击者将拥有或接管远程服务器——在这种情况下,他们可以在您登录并发送密码后立即获取密码,无论密码强度如何。

要登录网站和其他服务器,请使用密码数据库。推荐使用KeePassX,因为它是免费的、开源的、跨平台的,而且它从不在云中存储任何东西。然后将所有密码锁定在您使用 Diceware 生成的主密码短语后面。使用您的密码管理器为您登录的每个网站生成和存储不同的随机密码。

我真的必须使用骰子吗?

这是一个复杂的问题,但简短的回答是:使用物理骰子会给你一个更强有力的保证,不会出错。但这既费时又乏味,使用计算机生成这些随机数又是会很方便。
这里有一个用于生成Diceware短语的程序(仅适用于Windows):
点击下载

参考资料

Web Feed 倡议书

2022年5月11日 18:18

独立博客应该提供 RSS/Atom 输出,以便读者可以订阅博客。

原文作者:涛叔

为了推动开放 Web 生态的发展,请使用 Web Feed,用户可以在浏览器中方便地订阅独立博客,从而获取类似微信公众号的体验。但目前基于 Web Feed (RSS/Atom) 的订阅方案还有不少问题。今天向广大作者发出倡议,希望能一起解决这些问题。

方便读者快速订阅博客

我们虽然可以在博客上指明 Feed 链接,但不同博客的链接位置却不尽相同,多数在页面的右上角,少数在页面底部,还有一些在左边或者右边。有的网站虽然提供 Feed 链接,却只在首页等特殊页面展示。如果用户只是阅读某篇特定的文章,则不能第一时间发现 Feed 链接。

为了解决这个问题,我建议所有作者都为博客加入 rss-autodiscovery 支持。简单来说就是在每个页面的 <head> 部分都添加特殊的 <link> 标签:

<link rel="alternate"
      type="application/atom+xml"
      title="RSS"
      href="https://example.com/atom.xml">

这里的 type 属性指明 Feed 类型。如果是 RSS 需要写成 application/rss+xml ,Atom 则需要写成 application/atom+xml

有了这样标准化的 <link> 标签,我们才有可能实现自动发现、一键订阅等功能。

选择合适的 Feed 类型

我们知道 Feed 类型分为 RSS 和 Atom,虽然 RSS 历史更久远,兼容性更好,我还是建议大家选用 Atom 格式。这是因为在 RSS 规范里面,每一个 <item> 只有一个<description>字段。有的站长用它输出摘要,有的站长用它输出全文。局面比较混乱。而 Atom 规范则分别定义了 <summary> <content>,在语义上更加清晰,客户端在解析的时候也更加简单。

Feed 文件体积过大

很多作者为了方便读者订阅,不但在 Feed 中输出了全文,而且还把所有的历史文章都加到了 Feed 中。这样会生成一个非常大的 XML 文件。Feed 文件体积过大,一方面会消耗不必要的服务器流量,导致下载时间过长,另一方面还会给客户端解析带来非常大的负担。更重要的是,我们不可能在短时间内写很多文章,所以用户订阅 Feed 的时候大多数情况下下载的 XML 文件内容都只有很少变化或者根本没有变化。

为此,我建议各位作者把 Feed 当成一种更新同步机制,而非内容同步机制。也就是说,大家只需要把最新发布的内容输出到 Feed 中就可以了。比如,我们可以只针对最新的十篇文章生成 Feed 文件。读者只需按照一定的周期来检查是否有新的 Feed 就不会错过新发布的文章。为了进一步减少 Feed 文件的体积,我进一步呼吁大家只在 Feed 中输出文章摘要。如果读者有兴趣,则可以作者的博客上继续阅读。

顺便提一个小细节。有的作者为了让读者回源站阅读全文,不但没有在 Feed 中输出全文,而且在输出的摘要的最后还附加了一个超链接,来引导读者跳转到自己的博客。其实这大可不必。因为 Feed 信息中已经包含了文章链接,阅读器一般也都会再显示一个阅读原文按钮。如果在文章摘要中再输出一个,那就会显示两个原文跳转链接,非常难看。

Feed 信息不完善

这个问题基本不影响用户订阅 Feed。但我还是建议作者能把网站标题、网站图标、主页链接、个人邮箱等信息加现 Feed 文件。

统一内容编码

建议大家统一使用 UTF-8 编码。


以上就是我所想到的 Feed 订阅问题。总结一下就是使用 Atom 格式,加入自动发现的 标签,只输出最新几篇文章的摘要,完善站点信息,比如一使用 UTF-8 编码。欢迎大家留言讨论。也欢迎大家关注Web Feed 项目。

使用instant.page js 脚本提升页面加载速度

2022年4月26日 18:03

简介

instant.page 是一个 JS 库,当用户鼠标悬停在链接上面,就开始预加载网页,从而使得用户真正点击的时候,页面瞬间就能加载完成。

原理

instant.page 利用了 预加载技术,当用户有意向访问某个页面之前,浏览器首先对此页面进行预加载,当用户真正点击链接后,会从预加载的缓存中直接读取页面内容,缩短页面的加载时间。
当用户鼠标放在页面上某个链接上时,该脚本会在页面头部添加一行代码

<link rel="prefetch" href="链接地址">

有了上面的link标记,浏览器就会提前加载这个网址。

注意由于仅仅是提前获取资源,因此浏览器不会对资源进行预处理,并且像 CSS 样式表、JavaScript 脚本这样的资源是不会自动执行并应用于当前文档的。

使用

<script src="//instant.page/5.1.0" type="module" integrity="sha384-by67kQnR+pyfy8yWP4kPO12fHKRLHZPfEsiSXR8u2IKcTdxD805MGUXBzVPnkLHw"></script>

只需要复制这行代码添加到你的网站上即可。注意:将此HTML片段放在</body >标签之前。

对于国内网站最好下载该脚本托管到自己网站上或国内cdn上,这样速度更快。
脚本可以去GitHub上下载,下载地址:
https://raw.githubusercontent.com/instantpage/instant.page/master/instantpage.js

参考资料

Koyeb部署V2ray

2022年3月7日 17:43

准备工作

部署步骤

  1. 打开仓库,并Fork一份;进入“Settings”,输入名称,改名 (随便什么名字都可以,防Koyeb风控):
  1. 编辑文件.github/workflows/docker-image.yml,按照“name: Docker Hub ID/自定义镜像名称”格式修改第13行:(其他地方不要动)
  1. 添加Actions的Secrets变量,变量说明如下;
    DOCKER_USERNAME:Docker Hub 用户名
    DOCKER_PASSWORD:Docker Hub 登录密码
  1. 登录Koyeb,创建一个APP,配置如下:
    Docker Image:Docker Hub镜像地址,格式为“docker.io/Docker Hub 用户名/自定义镜像名称”
    Container size:部署配置,一般默认即可
    Port:80
    Environment variables:Key:PORT,Value:80
    Name:随便填

大概等待1-3分钟,然后出现“Healthy”字样即为部署成功

客户端配置

  • 地址:***-***.koyeb.app (***-***是Koyeb为你分配的名称,如下图中红圈所示)
  • 端口:443
  • 用户ID:24b4b1e1-7a89-45f6-858c-242cf53b5bdb
  • 额外ID:0
  • 加密方式:auto
  • 别名:随便填
  • 传输协议: ws
  • 伪装类型:none
  • 路径:24b4b1e1-7a89-45f6-858c-242cf53b5bdb-vmess
  • 传输层安全: tls
  • 跳过证书认证:false
  • SNI:***-***.koyeb.app (***是Koyeb给你分配的二级域名)

注意事项

  • 不要滥用本服务,否则可能被封号。

深入理解GFW:DNS污染

2021年12月2日 17:48

本文转自:https://gfwrev.blogspot.com/2009/11/gfwdns.html

初识DNS污染

DNS(Domain Name System)污染是GFW的一种让一般用户由于得到虚假目标主机IP而不能与其通信的方法,是一种DNS缓存投毒攻击(DNS cache poisoning)。其工作方式是:对经过GFW的在UDP端口53上的DNS查询进行入侵检测,一经发现与关键词相匹配的请求则立即伪装成目标域名的解析服务器(NS,Name Server)给查询者返回虚假结果。由于通常的DNS查询没有任何认证机制,而且DNS查询通常基于的UDP是无连接不可靠的协议,查询者只能接受最先到达的格式正确结果,并丢弃之后的结果。对于不了解相关知识的网民来说也就是,由于系统默认使用的ISP提供的NS查询国外的权威服务器时被劫持,其缓存受到污染,因而默认情况下查询ISP的服务器就会获得虚假IP;而用户直接查询境外NS(比如OpenDNS)又可能被GFW劫持,从而在没有防范机制的情况下仍然不能获得正确IP。然而对这种攻击有着十分简单有效的应对方法:修改Hosts文件。但是Hosts文件的条目一般不能使用通配符(例如*.blogspot.com),而GFW的DNS污染对域名匹配进行的是部分匹配不是精确匹配,因此Hosts文件也有一定的局限性,网民试图访问这类域名仍会遇到很大麻烦。

观测DNS污染

“知己知彼,百战不殆”。这一节我们需要用到前面提到的报文监听工具,以及参考其DNS劫持诊断一节。在Wireshark的filter一栏输入udp.port eq 53可以方便地过滤掉其他无关报文。为了进一步减少干扰,我们选择一个并没有提供域名解析服务的国外IP作为目标域名解析服务器,例如129.42.17.103。运行命令nslookup -type=A www.youtube.com 129.42.17.103。如果有回答,只能说明这是GFW的伪造回答,也就是我们要观测和研究的对象。

伪包特征

经过一番紧密的查询,我们可以发现GFW返回的IP取自如下列表:

  • 4.36.66.178
  • 203.161.230.171
  • 211.94.66.147
  • 202.181.7.85
  • 202.106.1.2
  • 209.145.54.50
  • 216.234.179.13
  • 64.33.88.161

关于这八个特殊IP,鼓励读者对这样两个问题进行探究:1、为什么是特定的IP而不是随机IP,固定IP和随机IP各自有什么坏处;2、为什么就是这8个IP不是别的IP,这8个IP为什么倒了GFW的霉?关于搜索这类信息,除了www.google.com之外,www.bing.com有专门的搜索IP对应网站的功能,使用方法是输入ip:IP地址搜索。www.robtex.com则是一个专门收集域名解析信息的网站。欢迎读者留下自己的想法和发现。

从Wireshark收集到的结果分析(实际上更好的办法是,将结果保存为pcap文件,或者直接使用tcpdump,由tcpdump显示成文本再自行提取数据得到统计),我们将GFW发送的DNS污染包在IP头部的指纹特征分为两类:

  1. 一型:
  • ip_id == ____(是一个固定的数,具体数值的查找留作习题)。
  • 没有设置“不分片”选项。
  • 没有设置服务类型。
  • 对同一对源IP、目标IP,GFW返回的污染IP在上述8个中按照给出的顺序循环。与源端口无关、与源IP目标IP对相关。
  • TTL返回值比较固定。TTL为IP头部的“Time to Live”值,每经过一层路由器这个值会减1,TTL为1的IP包路由器将不再转发,多数路由器会返回源IP一条“ICMP time to live exceed in transit”消息。
  1. 二型:
  • 每个包重复发送3次。
  • 没有设置“不分片”选项。
  • 设置了“保障高流量”服务类型。
  • (ip_id + ? * 13 + 1) % 65536 == 0,其中?为一个有趣的未知数。ip_id在同一个源IP、目标IP对的连续查询之间以13为单位递减、观测到的ip_id的最小值和最大值分别为65525(即-11,溢出了!)和65535。
  • 对同一对源IP、目标IP,GFW返回的污染IP在上述8个中按照给出的顺序循环。与源端口无关、与源IP目标IP对相关。
  • 对同一对源IP、目标IP,TTL返回值时序以1为单位递增。TTL在GFW发送时的取值有64种。注:源IP接收到的包的TTL被路由修改过,所以用户观测到的TTL不一定只有64种取值,这是由于网络拓扑变化的原因导致的。一型中的“比较固定”的“比较”二字也是考虑到网络拓扑偶尔的变化而添加的,也许可以认为GFW发送时的初始值是恒定的。

(以上结果仅保证真实性,不保证时效性,GFW的特征随时有可能改变,尤其是时序特征与传输层特征相关性方面。最近半年GFW的特征在很多方面的变化越来越频繁,在将来介绍TCP阻断时我们会提到。)

还可以进行的实验有:由于当前二型的TTL变化范围是IP个数的整数倍,通过控制DNS查询的TTL使得恰好有GFW的返回(避免动态路由造成的接收者观察到的TTL不规律变化),观察IP和TTL除以8的余数是否有对应关系,在更改源IP、目标IP对之后这个关系是否仍然成立。这关系到的GFW负载平衡算法及响应计数器(hit counter)的独立性和一致性。事实上对GFW进行穷举给出所有关于GFW的结果也缺乏意义,这里只是提出这样的研究方法,如果读者感兴趣可以继续探究。

每次查询通常会得到一个一型包和三个完全相同的二型包。更换查询命令中type=A为type=MX或者type=AAAA或者其它类型,可以看到nslookup提示收到了损坏的回复包。这是因为GFW的DNS污染模块做得十分粗制滥造。GFW伪造的DNS应答的ANSWER部分通常只有一个RR组成(即一条记录),这个记录的RDATA部分为那8个污染IP之一。对于二型,RR记录的TYPE值是从用户查询之中直接复制的。于是用户就收到了如此奇特的损坏包。DNS响应包的UDP荷载内容特征:

  1. 一型
  • DNS应答包的ANSWER部分的RR记录中的域名部分由0xc00c指代被查询域名。
  • RR记录中的TTL设置为5分钟。
  • 无论用户查询的TYPE是什么,应答包的TYPE总是设置为A(IPv4地址的意思)、CLASS总是设置为IN。
  1. 二型
  • DNS应答包的ANSWER部分的RR记录中的域名部分是被查询域名的全文。
  • RR记录中的TTL设置为1天。
  • RR记录中的TYPE和CLASS值是从源IP发送的查询复制的。

其中的术语解释:RR = Resource Record:dns数据包中的一条记录;RDATA = Resource Data:一条记录的数据部分;TYPE:查询的类型,有A、AAAA、MX、NS等;CLASS:一般为IN[ternet]。

触发条件

实际上DNS还有TCP协议部分,实验发现,GFW还没有对TCP协议上的DNS查询进行劫持和污染。匹配规则方面,GFW进行的是子串匹配而不是精确匹配,并且GFW实际上是先将域名转换为字符串进行匹配的。这一点值得特殊说明的原因是,DNS中域名是这样表示的:一个整数n1代表以“.”作分割最前面的部分的长度,之后n1个字母,之后又是一个数字,若干字母,直到某次的数字为0结束。例如www.youtube.com则是"\x03www\x07youtube\x03com\x00"。因此,事实上就可以观察到,对www.youtube.coma的查询也被劫持了。

现状分析

  • 4.36.66.178,关键词。whois:Level 3 Communications, Inc. 位于Broomfield, CO, U.S.
  • 203.161.230.171,关键词。whois:POWERBASE-HK位于Hong Kong, HK.
  • 211.94.66.147,whois:China United Network Communications Corporation Limited位于Beijing, P.R. China.
  • 202.181.7.85,关键词。whois:First Link Internet Services Pty Ltd.位于North Rocks, AU.
  • 202.106.1.2,whois:China Unicom Beijing province network位于Beijing, CN.
  • 209.145.54.50,反向解析为dns1.gapp.gov.cn,新闻出版总署的域名解析服务器?目前dns1.gapp.gov.cn现在是219.141.187.13在bjtelecom。whois:World Internet Services位于San Marcos, CA, US.
  • 216.234.179.13,关键词。反向解析为IP-216-234-179-13.tera-byte.com。whois:Tera-byte Dot Com Inc.位于Edmonton, AB, CA.
  • 64.33.88.161,反向解析为tonycastro.org.ez-site.net, tonycastro.com, tonycastro.net, thepetclubfl.net。whois:OLM,LLC位于Lisle, IL, U.S.

可见上面的IP大多数并不是中国的。如果有网站架设到了这个IP上,全中国的Twitter、Facebook请求都会被定向到这里——好在GFW还有HTTP URL关键词的TCP阻断——HTTPS的请求才构成对目标IP的实际压力,相当于中国网民对这个IP发起DDoS攻击,不知道受害网站、ISP是否有索赔的打算?

我们尝试用bing.com的ip反向搜索功能搜索上面那些DNS污染专用IP,发现了一些有趣的域名。显然,这些域名都是DNS污染的受害域名。

  • 例如倒霉的edoors.cn.china.cn,宁波中国门业网,其实是因为edoors.cn被dns污染。一起受害的* 还有chasedoors.cn.china.cn,美国蔡斯门业(深圳)有限公司。
  • 还有*.sf520.com,似乎是一个国内的游戏私服网站。www.sf520.com也是一个私服网站。可见国内行政体系官商勾结之严重,一个“国家信息安全基础设施”竟然还会用来保护一些网游公司的利益。
  • 此外还有一些个人blog。www.99tw.net也是一个游戏网站。
  • 还有www.why.com.cn,名字起得好。
  • 还有www.999sw.com 广东上九生物降解塑料有限公司生物降解树脂|增粘母料|高效保水济|防洪 邮编:523128……这又是怎么一回事呢?不像是被什么反动网站连坐的。还有人问怎么回事怎么会有那么多IP结果。
  • www.facebook.comwww.xiaonei.com,怎么回事呢?其实是因为有人不小心把两个地址连起来了,搜索引擎以为这是一个链接,其实这个域名不存在,但是解析的时候遭到了污染,就以为存在这个域名了。
  • 倒霉的www.xinsheng.net.cn——武汉市新胜电脑有限公司,因为www.xinsheng.net被连坐。

DNS劫持的防范和利用

之前我们已经谈到,GFW是一套入侵检测系统,仅对流量进行监控,暂没有能力切断网络传输,其“阻断”也只是利用网络协议容易被会话劫持(Session hijacking)的弱点来进行的。使用无连接UDP的DNS查询只是被GFW抢答了,真正的答案就跟在后面。于是应对GFW这种攻击很自然的想法就是:

根据时序特性判断真伪,忽略过早的回复。
通常情况对于分别处于GFW两端的IP,其RTT(Round-trip time,往返延迟)要大于源IP到GFW的RTT,可以设法统计出这两个RTT的合适的均值作为判断真伪的标准。另外由于GFW对基于TCP的DNS请求没有作处理,于是可以指定使用TCP而不是UDP解析域名。也可以通过没有部署GFW的线路到没有被DNS污染的NS进行查询,例如文章一开始提到的“远程解析”。但黑体字标出的两个条件缺一不可,例如网上广为流传的OpenDNS可以反DNS劫持的说法是以讹传讹,因为到OpenDNS服务器的线路上是经由GFW的。

本质的解决办法是给DNS协议增加验证机制,例如DNSSEC(Domain Name System Security Extensions),客户端进行递归查询(Recursive Query)而不查询已经被污染了的递归解析服务器(Recursive/caching name server)。然而缺点是目前并非所有的权威域名解析服务器(Authoritative name server)都支持了DNSSEC。Unbound提供了一个这样的带DNSSEC验证机制的递归解析程序。

另外GFW的DNS劫持还可能被黑客利用、带来对国际国内互联网的严重破坏。一方面,GFW可能在一些紧急时刻按照“国家安全”的需要对所有DNS查询都进行污染,且可能指定污染后的IP为某个特定IP,使得全球网络流量的一部分直接转移到目标网络,使得目标网络立刻瘫痪。当然我们伟大的祖国郑重承诺“不率先使用核武器”…另一方面,GFW将伪造的DNS返回包要发送给源IP地址的源端口,如果攻击者伪造源IP,会怎样呢?将会导致著名的增幅攻击:十倍于攻击者发送DNS查询的流量将会返回给伪源IP,如果伪源IP的端口上没有开启任何服务,很多安全配置不严的系统就需要返回一条ICMP Port Unreachable消息,并且将收到的信息附加到这条ICMP信息之后;如果伪源IP的端口上开启了服务,大量的非法UDP数据涌入将使得伪源IP该端口提供的服务瘫痪。如果攻击者以1Gbps的速度进行查询,一个小型IDC(DNSpod被攻击事件)甚至一个地域的ISP也会因此瘫痪(暴风影音事件)。攻击者还可能设置TTL使得这些流量恰好通过GFW产生劫持响应,并在到达实际目标之前被路由丢弃,实现流量“空对空不落地”。攻击者还可能将攻击流量的目标IP设置伪造成与伪源IP有正常通信或者其他关联的IP,更难以识别。这样实际上就将一个国家级防火墙变成了一个国家级反射放大式拒绝服务攻击跳板。

最为严重的是,这种攻击入门难度极低,任何一个会使用C语言编程的人只要稍微阅读libnet或者libpcap的文档,就可能在几天之内写出这样的程序。而GFW作为一套入侵防御系统,注定缺乏专门防范这种攻击的能力,因为如果GFW选择性忽略一些DNS查询不进行劫持,网民就有机可乘利用流量掩护来保证真正的DNS通信不被GFW污染。尤其是UDP这样一种无连接的协议,GFW更加难以分析应对。“反者道之动,弱者道之用。”

参考文献

  1. 闫伯儒, 方滨兴, 李斌, 王垚. "DNS欺骗攻击的检测和防范". 计算机工程, 32(21):130-132,135. 2006-11.
  2. Graham Lowe, Patrick Winters, Michael L. Marcus. The Great DNS Wall of China. 注:这篇文章虽然试图通过统计特性了解GFW,但由于实验条件控制不佳、实验结果观察不细致,加上缺乏对GFW的整体观,故没有提供什么有意义的结论。然而美国同学的这种科学态度与实验精神值得我们学习和思考。事实上,这篇文章仍然提供了珍贵的历史资料,读者不妨按照本文逻辑来分析这篇参考文献。阅读过这篇文献的敏感的读者还将在我们后续的文章中看到熟悉的数字。
  3. KLZ毕业. 入侵防御系统的评测和问题. 注:本文对DNS污染包的分类就是从这篇文章的分类继承而来。
❌
❌