我们如何突破中国防火墙(第 2 部分)

您好!

公司系统工程师Nikita又和你在一起了 SEMrush。 在这篇文章中,我将继续讲述我们如何想出解决方案的故事 中国防火墙 对于我们的服务 semrush.com。

В 上一节 我说:

  • 做出“我们需要在中国开展服务”的决定后会出现哪些问题
  • 中国互联网存在哪些问题?
  • 为什么需要ICP许可证?
  • 我们如何以及为何决定使用 Catchpoint 测试我们的测试平台
  • 我们第一个基于 Cloudflare 中国网络的解决方案的结果是什么
  • 我们如何发现 Cloudflare DNS 中的错误

在我看来,这部分是最有趣的,因为它重点关注分期的具体技术实现。 我们将开始,或者更确切地说继续, 阿里巴巴云.

阿里巴巴云

阿里巴巴云 是一家相当大的云提供商,拥有一切可以让它诚实地称自己为云提供商的服务。 很好的是他们有机会为外国用户注册,而且网站的大部分内容都被翻译成英文(对中国来说这是一种奢侈)。 在这个云中,您可以与全球多个地区、中国大陆、以及大洋洲亚洲(香港、台湾等)合作。

安全协议

我们从地理开始。 由于我们的测试站点位于Google Cloud上,我们需要将阿里云与GCP“链接”,因此我们打开了Google所在位置的列表。 当时他们在香港还没有自己的数据中心。
最近的区域原来是 亚洲-东部1 (台湾)。 阿里原来是中国大陆距离台湾最近的地区 cn-深圳 (深圳)。

terraform 描述并提出了GCP和阿里的整个基础设施。 云层之间的 100 Mbit/s 隧道几乎立即就建立起来了。 深圳和台湾这边,提出了代理虚拟机。 在深圳,用户流量被终止,通过隧道代理到台湾,然后从那里直接到达我们服务的外部IP 美国东部 (美国东海岸)。 通过隧道在虚拟机之间执行 Ping 操作 24ms,这还不错。

与此同时,我们在 阿里云DNS。 将区域委托给 NS Ali 后,解决时间从 470 毫秒减少到 50毫秒。 在此之前,该专区也在 Cloudlfare 上。

与隧道平行 亚洲-东部1 另一条隧道从深圳直达 美国东部4。 他们在那里创建了更多代理虚拟机并开始测试这两种解决方案,使用 Cookie 或 DNS 路由测试流量。 测试台示意图如下图所示:

隧道延迟结果如下:
阿里 cn-深圳 <—> GCP asia-east1 — 24ms
阿里 cn-深圳 <—> GCP us-east4 — 200ms

Catchpoint 浏览器测试报告了出色的改进。

比较两种解决方案的测试结果:


正常运行时间
中位数
75 百分位数
95 百分位数

Cloudflare
86.6
18s
30s
60s

IPsec的
99.79
18s
21s
30s

这是来自使用 IPSEC 隧道的解决方案的数据 亚洲-东部1。 通过us-east4,结果更差,错误也更多,所以我就不给出结果了。

根据对两条隧道的测试结果,其中一条隧道终止于距离中国最近的地区,另一条隧道终止于最终目的地,很明显,尽快从中国防火墙下“出来”非常重要可能的话,然后使用快速网络(CDN 提供商、云提供商等)。 无需试图一举突破防火墙并到达目的地。 这不是最快的方法。

总的来说,结果还不错,但是,semrush.com 的中位数为 8.8 秒,75 百分位数为 9.4 秒(在同一测试中)。
在继续之前,我想做一个简短的抒情题外话。

抒情撤退

用户进入网站后 semrushchina.cn,它通过“快速”的中国 DNS 服务器进行解析,HTTP 请求通过我们的快速解决方案。 响应沿着相同的路径返回,但在所有 JS 脚本、HTML 页面和网页的其他元素中指定了域 我semrush.co 用于渲染页面时必须加载的其他资源。 也就是说,客户端解析“主”A 记录 semrushchina.cn 并进入快速隧道,很快收到响应 - 一个 HTML 页面,其中指出:

  • 从sso.semrush.com下载这样那样的js,
  • 从 cdn.semrush.com 获取 CSS 文件,
  • 还从 dab.semrush.com 拍了一些照片
  • 等。

浏览器开始前往“外部”互联网获取这些资源,每次都会穿过防火墙,从而消耗响应时间。

但之前的测试显示的是页面没有资源时的结果 我semrush.cosemrushchina.cn,*.semrushchina.cn 解析为深圳虚拟机的地址,以便进入隧道。

只有这样,通过您的解决方案将所有可能的流量推到最大,快速通过中国防火墙,您才能获得可接受的速度和网站可用性指标,以及诚实的解决方案测试结果。
我们在团队产品方面没有进行任何代码编辑就做到了这一点。

子过滤器

这个问题一出现,解决方案几乎立刻就诞生了。 我们需要 的PoC (概念证明)我们的防火墙渗透解决方案确实运作良好。 为此,您需要尽可能地将所有站点流量包装到此解决方案中。 我们申请了 子过滤器 在 Nginx 中。

子过滤器 是 nginx 中一个相当简单的模块,允许您将响应正文中的一行更改为另一行。 所以我们改变了所有发生的事情 我semrush.cosemrushchina.cn 在所有答案中。

而且...它不起作用,因为我们从后端收到了压缩内容,因此子过滤器找不到所需的行。 我必须向 nginx 添加另一个本地服务器,它解压缩响应并将其传递到下一个本地服务器,该服务器已经忙于替换字符串、压缩它,并将其发送到链中的下一个代理服务器。

结果,客户端会在哪里收到 .semrush.com, 他收到了 .semrushchina.cn 并乖乖地执行了我们的决定。

然而,仅仅以一种方式更改域是不够的,因为后端仍然期望在来自客户端的后续请求中使用 semrush.com。 因此,在完成单向替换的同一服务器上,使用简单的正则表达式,我们从请求中获取子域,然后我们执行 代理通行证 有变量 $主机,展出于 $subdomain.semrush.com。 这可能看起来令人困惑,但它确实有效。 而且效果很好。 对于需要不同逻辑的各个域,只需创建您自己的服务器块并进行单独的配置即可。 为了清晰和演示该方案,下面是缩短的 nginx 配置。

以下配置处理来自中国的所有请求 .semrushchina.cn:

    listen 80;

    server_name ~^(?<subdomain>[w-]+).semrushchina.cn$;

    sub_filter '.semrush.com' '.semrushchina.cn';
    sub_filter_last_modified on;
    sub_filter_once off;
    sub_filter_types *;

    gzip on;
    gzip_proxied any;
    gzip_types text/plain text/css application/json application/x-javascript text/xml application/xml application/xml+rss text/javascript application/javascript;

    location / {
        proxy_pass http://127.0.0.1:8083;
        proxy_set_header Accept-Encoding "";
        proxy_set_header Host $subdomain.semrush.com;
        proxy_set_header X-Accept-Encoding $http_accept_encoding;
    }
}

此配置代理 本地 到端口 83,以下配置正在等待:

    listen 127.0.0.1:8083;

    server_name *.semrush.com;

    location / {
        resolver 8.8.8.8 ipv6=off;
        gunzip on;
        proxy_pass https://$host;
        proxy_set_header Accept-Encoding gzip;
    }
}

我再说一遍,这些都是经过裁剪的配置。

像那样。 它可能看起来很复杂,但它是在文字中。 事实上,一切都比蒸萝卜简单:)

题外话结束

有一段时间我们很高兴,因为关于 IPSEC 隧道崩溃的神话没有得到证实。 但随后隧道开始塌陷。 每天数次,每次几分钟。 有一点,但这不适合我们。 由于两条隧道都在同一路由器上的阿里侧终止,我们认为这可能是一个区域问题,我们需要提高备份区域。

他们捡起了它。 隧道在不同的时间开始出现故障,但在 nginx 的上游级别,故障转移对我们来说工作得很好。 但随后隧道大约在同一时间开始塌陷:) 502 和 504 又开始塌陷。正常运行时间开始恶化,因此我们开始研究该选项 阿里巴巴中心 (云企业网络)。

- 这是阿里云内不同地域的两个VPC的互通,即可以连接云内任意地域的私网。 最重要的是:这个渠道有相当严格的要求 SLA。 无论是速度还是正常运行时间都非常稳定。 但事情从来没有那么简单:

  • 如果您不是中国公民或法人实体,则很难获得,
  • 您需要为每兆比特的通道带宽付费。

有机会联系 中国大陆 и 海外留学,我们在两个阿里区域之间创建了一个CEN: cn-深圳 и 我们-东-1 (距离 us-east4 最近的点)。 在阿里 我们-东-1 启动另一个虚拟机,这样就多了一个 .

结果是这样的:

浏览器测试结果如下:


正常运行时间
中位数
75 百分位数
95 百分位数

Cloudflare
86.6
18s
30s
60s

IPsec的
99.79
18s
21s
30s


99.75
16s
21s
27s

性能比IPSEC稍好一些。 但通过 IPSEC,您可以以 100 Mbit/s 的速度下载,而通过 CEN 只能以 5 Mbit/s 或更高的速度下载。

听起来像是混合动力,对吧? 结合 IPSEC 速度和 CEN 稳定性。

这就是我们所做的,在 IPSEC 隧道发生故障时允许流量通过 IPSEC 和 CEN。 正常运行时间变得更长,但网站加载速度仍然有很多不足之处。 然后我画出了我们已经使用和测试过的所有电路,并决定尝试在这个电路上添加一点GCP,即 GLB.

GLB

GLB - 全局负载均衡器 (或谷歌云负载均衡器)。 它对我们来说有一个重要的优势:在 CDN 的背景下,它具有 任播IP,它允许您将流量路由到距离客户端最近的数据中心,以便流量快速进入 Google 的快速网络,并减少通过“常规”互联网的流量。

我们不假思索地提出了 HTTP/HTTPS 负载均衡 我们在 GCP 中安装了带有子过滤器的虚拟机并作为后端。

有几种方案:

  • 使用 Cloudflare中国网,但是这次 Origin 应该指定全局 IP GLB.
  • 终止客户 cn-深圳,然后从那里将流量直接代理到 GLB.
  • 从中国直达 GLB.
  • 终止客户 cn-深圳,从那里代理到 亚洲-东部1 通过 IPSEC(在 美国东部4 通过CEN),从那里去GLB(冷静,下面会有图片和解释)

我们测试了所有这些选项以及其他几个混合选项:

  • Cloudflare + GLB

由于正常运行时间和 DNS 错误,该方案不适合我们。 但测试是在CF端修复bug之前进行的,也许现在更好(不过,这不排除HTTP超时)。

  • 阿里+GLB

这种方案在正常运行时间方面也不适合我们,因为 GLB 经常由于无法在可接受的时间或超时内连接而脱离上游,因为对于中国境内的服务器,GLB 地址仍然在外部,因此落后于中国防火墙。 魔法并没有发生。

  • 仅限 GLB

与前一个类似的选项,只是它不使用中国本身的服务器:流量直接进入 GLB(DNS 记录已更改)。 因此,结果并不令人满意,因为使用普通互联网提供商服务的普通中国客户在通过防火墙方面的情况比阿里云差得多。

  • 深圳 -> (CEN/IPSEC) -> 代理 -> GLB

在这里,我们决定使用最好的解决方案:

  • CEN 的稳定性和 SLA 保证
  • IPSEC 的高速
  • 谷歌的“快速”网络及其选播。

该方案看起来像这样:用户流量在虚拟机上终止 ch-深圳。 那里配置了Nginx上游,其中一些上游指向位于IPSEC隧道另一端的私有IP服务器,一些上游指向CEN另一端的服务器的私有地址。 IPSEC 配置为区域 亚洲-东部1 在 GCP(创建解决方案时是距离中国最近的区域。GCP 现在也在香港设有办事处)。 CEN-- 至地区 美国东部1 在阿里云。

然后两端的流量被定向到 任播 IP GLB,即到最近的 Google 存在点,并通过其网络到达该区域 美国东部4 在 GCP 中,其中有替换虚拟机(在 nginx 中带有子过滤器)。

正如我们所期望的,这种混合解决方案利用了每种技术的优点。 一般来说,流量会通过快速 IPSEC,但如果出现问题,我们会在几分钟内迅速将这些服务器从上游踢出,并仅通过 CEN 发送流量,直到隧道稳定为止。

通过实施上面列表中的第四个解决方案,我们及时实现了我们想要的以及业务对我们的要求。

与之前的解决方案相比,新解决方案的浏览器测试结果:


正常运行时间
中位数
75 百分位数
95 百分位数

Cloudflare
86.6
18s
30s
60s

IPsec的
99.79
18s
21s
30s


99.75
16s
21s
27s

CEN/IPsec + GLB
99.79
13s
16s
25s

我们实施的解决方案一切都很好,但没有 CDN 可以加速区域甚至城市级别的流量。 从理论上讲,这应该可以通过使用 CDN 提供商的快速通信渠道来加快最终用户的网站速度。 我们一直在思考这个问题。 现在,该项目的下一次迭代已经到来:在中国搜索和测试 CDN 提供商。

我将在下一个最后部分告诉你这一点:)

来源: habr.com

添加评论