网站建设

由电信宽带封堵443端口引发的一系列折腾

Jager · 2月4日 · 2020年 · 21221次已读

很久木有搭理博客了,最近冠状病毒肆虐也只能窝在家里,要么带娃要么刷新闻。最近折腾 KONG 网关正好有一些心得,就想到博客整理下,结果发现后台打不开。检查一看,原来我部署在群晖上的源站早就挂 B 了,只剩 CloudFlare 的 CDN 缓存在勉强支撑。进一步诊断了下,根因就是电信宽带 443 端口被封了,因此 CloudFlare 回源吃了个闭门羹。

心里默默的问候了一下(河蟹),然后快速想了多个方案:

  1. 研究 CloudFlare 能否指定源站端口,然后在路由器上加一个端口映射就可以解决问题;
  2. 搬迁博客到国外云主机,比如 AWS 的 lightsail,和群晖分手快乐;
  3. 在腾讯云主机上搭建一个反向代理,代理 NAS 上的源站,然后将 CloudFlare 的源站指向腾讯;
  4. 在路由器上装一个花生壳内网穿透来解决端口映射问题;
  5. 投诉电信,让其放通 443 端口;
  6. 寻求支持自定义端口的 CDN 服务,而且只能是海外 CDN 加速,因为无法备案;
  7. 利用 CF 的 Workers 来做反向代理(最新补充于文末);
  8. 最终落地方案(最新补充于文末)。

本文纯属折腾口水文,不感兴趣的就别浪费时间了。

最简单最快速的肯定是第 1 个方案,因此先看了下 CF 的面板发现不支持,然后搜了资料发现 CF 很久之前有个 Proxy anything 的功能内测,做的就是这种任意端口的代理,可惜现在已经是商业化了,需要最贵的企业版才支持,只好作罢!

第 2、3 种方案:都需要买一个云主机,既然都买云主机了,我干嘛要放到群晖呢?

第 4 种方案:看了下需要备案域名而且收费 300 多一年,当我没说好吧!

第 5 种方案:试着找了下微信电信客服,客服给我分配了一个错误的电信故障案例,说是疫情期间宽带故障检修会慢一些,要我耐心等下工程师过来(后面电话确认才发现错误分配到了一个宽带故障的小区),然后搜了下电信封堵 443,发现一片哀嚎,看来管控又收紧了不少,还是算了吧。

看来只有第 6 种方案了,已知腾讯云是支持自定义回源端口的,而且我也是腾讯云海外加速的内测用户,但是腾讯云海外 CDN 节点在国内访问真的慢出翔,ping 探测全面飘红:

由电信宽带封堵443端口引发的一系列折腾
图 1:腾讯云海外 CDN 测试

继续爬了多家 CDN,只有阿里云支持自定义回源端口,因此接入试了下。结果发现经常 504 或 503 错误,提工单让客服看了下,和预想的差不多,阿里云海外 CDN 节点到国内的源站并不稳定(功夫王立了大功),所以断断续续的。实际测试发现阿里云的海外加速节点从国内过去的延迟很低,基本在 100ms 以内,比 CF 强,真是可惜了!

由电信宽带封堵443端口引发的一系列折腾
图 2:阿里云海外 CDN 测试

看来暂时还是只能用腾讯云海外加速了,但是直接到腾讯云海外 CDN 节点延迟太高,这里继续套了一层 CF 来缓解下,因此临时方案为:

CloudFlare-->腾讯云海外 CDN-->NAS 源站。

很快就搞定了,效果当然比之前直接 CF 套 NAS 要慢不少,不过总算是可以正常访问了,回头弄个预缓存脚本定刷一下,前台打开速度基本也就凑合了:

由电信宽带封堵443端口引发的一系列折腾
图 3:腾讯云 CDN 源站及回源设
经验:在腾讯云 CDN 添加一个备过案的二级域名,源站指定为 DDNS 的 CNAME 地址+路由器的自定义端口,然后回源 host 自定义为主站,这样我们的源站就不需要做任何配置。

搞定之后,打算继续花点时间写个 KONG 网关相关经验的草稿(没办法有娃之后时间真的靠挤),结果发现后台卡到吐血,基本没法写文章。之前 CF 直接套源站实际上后台也比较卡,但是家里宽带的 443 端口是正常的,所以我自己访问博客都是用 host 直接回源来解决卡的问题。

继续 YY 了几个方案:

  1. 后台通过自定义端口访问,然后用 hosts 绑定到源站 IP;
  2. 只能在家里用 hosts 绑定 192.168.x.x 来访问博客后台;
  3. 独立博客后台域名,绑定一个备案过的域名。

第 1,2 种方案不够优雅,果断放弃。很明显第 3 种方案还是不错的,因此开始折腾。

更换后台域名的步骤如下:

1、在 wp-config.php 增加如下配置:

//定义前台地址(可选优化)
define('WP_HOME', 'https://zhang.ge');
//定义后台地址
define('WP_SITEURL', 'https://admin.xxoo.com');
//后台开启 https 访问
define('FORCE_SSL_ADMIN', true);
if (strpos($_SERVER['HTTP_X_FORWARDED_PROTO'], 'https') !== false){
       $_SERVER['HTTPS']='on';
}
//定义静态文件地址,不指定会输出 admin 地址
define('WP_CONTENT_URL', '//res.zgboke.com/wp-content');
//define('WP_CONTENT_URL', '/wp-content'); //如果没有二级静态域名可以使用这个配置

2、在主题 functions.php 添加如下功能函数,解决上传图片地址变成 admin 这个域名的问题:

/**
* 小松博客 www.phpsong.com
* 添加的图片还是用前台的地址
**/
add_filter( 'upload_dir', 'wpabcd_custom_upload_dir' );
function wpabcd_custom_upload_dir( $uploads ) {
    $uploads['baseurl'] = str_replace(get_option('siteurl'),get_option('home'),$uploads['baseurl']);
    return $uploads;
}

3、如果主题用到了 RESTful API 功能,则推荐在主题 functions.php 添加函数,将后台 RESTful 地址指向 admin 域名,否则无穷无尽的跨域问题烦死人,当然也是为了加速后台:

/**
* WordPress 修改后台 RESTful API 域名 by zhang.ge
**/
if (is_admin()) {
    add_filter("rest_url",function($url){
        $url = parse_url($url);
        return get_option('siteurl').$url["path"].$url["query"];
    });
}

添加完以上配置之后,后台基本就可以使用 admin 这个域名来访问了,走国内 CDN 线路,速度自然不可同日而语也。

4、修改了后台域名之后,CloudFlare 插件会不能工作,定位发现是因为 CF 拿到的域名变成了 admin 这个了,修复方法:

找到文件:网站根目录/wp-content/plugins/cloudflare/src/WordPress/WordPressWrapper.php
将代码里面的 get_site_url 改为 get_home_url 即可。

5、如果后面发现还有前台还有个别输出为 admin 域名的链接,这里可以继续在 functions.php 加一段终极替换代码:

/**
* WordPress 替换前台静态地址
* 1. 修改 admin\.xxoo\.com 为后台独立域名地址,小数点需要反斜杠
* 2. 如果是有自己的静态文件域名,将 res.foo.com 改为自己的静态域名,如果没有直接删除 //res.foo.com 即可。
**/
if (!is_admin()) {
    ob_start("rewrite_static_domain");
}
function rewrite_static_domain($buffer_out) {
    $buffer_out = preg_replace('/http(s|):\/\/admin\.xxoo\.com\/wp-([^"\']*?)\.(jpg|png|gif|bmp|jepg|jpeg|css|js|woff|woff2|ttf|svg|eot|wo|otf|sv|eo)/i','//res.foo.com/wp-$2.$3',$buffer_out);
    return $buffer_out;
}

6、最后,如果不想让网站的任意资源能够通过 admin 访问到,那么还是在源站加一个虚拟主机配置,如下所示:

server {
        listen 80;
        server_name admin.foo.com;
        index index.html index.htm index.php default.html default.htm default.php;
        root  /data/wwwroot/zhang.ge;
        # 禁止搜索引擎收录
        if ($http_user_agent ~* "spider|bot|baiduboxapp") {
            return 403;
        }
        # admin 这个域名仅允许访问 WP 后台和内核资源,防止其他页面通过 admin 这个域名访问到
        if ($request_uri !~* "^/wp-(admin|json|includes)" ) {
            rewrite ^/(.*)$ $scheme://zhang.ge/$1 permanent;
        }
        # 以下配置保持和源站一致即可:
        location ~ [^/]\.php(/|$) {
            try_files $uri =404;
            fastcgi_pass  unix:/dev/shm/php-cgi.sock;
            fastcgi_index index.php;
            include fastcgi.conf;
        }
        location / {
            try_files $uri $uri/ /index.php?$args;
            rewrite /wp-admin$ $scheme://$host$uri/ permanent;
        }    
        location ~ /\. { deny  all; access_log off; log_not_found off; }
        access_log /data/wwwlogs/admin.foo.com.log access;
}

最后在 CDN 设置 admin 的回源域名使用默认的回源域名即可:

由电信宽带封堵443端口引发的一系列折腾
图 4:腾讯云 CDN 回源设置为默认

全部搞完,后台就可以非常顺畅的用 admin 独立域名访问了,顺便把这篇文章一写,之前计划的 KONG 网关的相关经验就没时间整理了,后面有空再说吧...

第二天补充:想了一晚上,感觉上面的方案在动态内容的访问上比过去慢太多了,很不爽还要继续改造下。

方案 1:利用 CF 的 Workers 来做 JS 反向代理,这个在之前的文章也提到过。

在网上找了下就找到了 2 个开源项目:jsproxyWorkers-Proxy

都试了下,前者其实就是一个写好的动态代理,指哪打哪,比如 google、Youtube 等(嘘...你懂的),不改造的话不适合我这个需求。后者就是一个固定代理到某个源站的脚本,但是目前不支持自定义端口,但是从我这个源站指向上文提到的腾讯云 admin 二级域名是可以成功的:

由电信宽带封堵443端口引发的一系列折腾
图 5:CF Workers 代理自定义源站

所以这个方案其实是行得通的:

CF Workers --> 腾讯云国内 CDN --> DDNS+Port --> NAS

但是有个问题,Workers 每次都是实时拉取然后返回内容,没做缓存。当然,CF Workers 肯定是可以写缓存逻辑的,但是太折腾了,到时候一堆缓存规则需要自己写,还是算了。不过从上面的方案让我想到另一个可行方案:

CF(全缓存) --> 阿里云海外 CDN(回源腾讯 CNAME,缓存静态文件) --> 腾讯云国内 CDN(缓存静态文件) --> DDNS+Port --> NAS

说干就干,当我把阿里云海外 CDN 的回源地址改为腾讯云国内 CDN 的 CNAME 记录之后,发现可以了,没有之前的断断续续 50x 错误了!!看来还是阿里云到自定义的端口有点坑啊。

简单总结:最终的方案相当于是利用阿里云海外 CDN、腾讯云国内 CDN 做了 2 层中转代理,解决了 CF 免费版不支持设置回源 HOST、不支持回源到自定义端口的问题。

第三天补充:当前最终方案

想了又想,其实没必要弄个 admin 二级域名,直接启用 zhangge.net 这个备案域名不就好了。。。所以,博客的最终架构如下图所示:

由电信宽带封堵443端口引发的一系列折腾
图 6. 张戈博客部署架构图

确实搞的无比复杂,想用 NAS 搭建站点朋友可以参考下。

12 条回应
  1. 心灵博客 2020-2-4 · 16:15

    直接把站放国外vps上吧

    • avatar
      Jager 2020-2-4 · 16:53

      后面再考虑找个VPS,主要还是想放到自己的NAS上。

      • Sam.Z 2020-2-9 · 14:22

        赞同放NAS,还是放在自己的NAS上最稳当,不过就是必须要再多一套数据数据备份方案。

  2. 缙哥哥 2020-2-5 · 8:05

    好思路,参考借鉴下!

  3. 3I6N 2020-2-7 · 12:27

    请教一下,有没有啥不需要域名备案的云存储呀!,托管一下照片就行的!

    • avatar
      Jager 2020-2-8 · 0:01

      貌似云存储都有一个自带的域名给你用吧,只是又臭又长,但是是备案过的。阿里云OSS、腾讯云COS、又拍云、七牛什么的。

  4. 边缘Z 2020-2-10 · 16:50

    老哥,其实第一个方案应该可行。Cloudflare有个插件叫Portzilla,可以指定端口回源。
    顺便问问博客字体是什么啊,挺好看的

    • avatar
      Jager 2020-2-10 · 17:01

      嗯,那个插件前几天有朋友推荐过,我试了下貌似免费版只能加一条路由,然后试了半天没成功,老外写的文档真心难懂,你有什么教程的话分享分享~~
      字体啊,我都没注意,查看元素看了下是这样的:

          font-family: Play,"微软雅黑","Microsoft YaHei UI","Microsoft YaHei","PingFang SC","Helvetica Neue",Helvetica,Arial,sans-serif !important;
      
      • 边缘Z 2020-2-11 · 10:12

        我只是,路过的一个小白~~原来折腾过也没成功,等有其他老哥分享喽~
        谢谢字体

    • avatar
      Jager 2020-2-10 · 17:04

      Portzilla 这玩意和文章中提到的 Workers-Proxy 基本是一个原理,Workers-Proxy这个我是调成功了,不过这玩意没加缓存逻辑,所以放弃了。

  5. 方寸 2020-2-17 · 11:07

    可以,参考一下

  6. 技术宅小明 2020-2-20 · 13:27

    我电脑打开你的网站 电脑就变得非常卡,赶紧就像在挖矿一样

  7. NNDS 2020-2-24 · 14:10

    思路很好,就是海外CDN貌似也要收费来的。

    • avatar
      Jager 2020-2-28 · 18:14

      前面做了一层缓存,基本没什么流量,而且做了动静分离,静态文件用备案域名走了免费的百度云加速。

  8. 烧饼博客 2020-2-25 · 11:14

    Workers-Proxy虽然不能缓存,但是接入Cloudflare域名可以绑定Workers,然后使用Page Rules来设置缓存。

  9. noco 2020-2-27 · 20:46

    完成了折腾的成就感,貌似忽略了实际的成本付出呀!VPS不香吗?

  10. 一同学习 2020-3-9 · 23:04

    我也一直用的自家的宽带,域名是备案的,80,443去年就不能用了,我一直是腾讯国内CDN反代自定义端口,最近好像被发现了,老是把http流量给断开,要重启才行,只要继续有http流量又会断开,而且是只断http不断网,最终只能投降,现在用内网穿透,这个老哥自己做的免费的内网穿透www.natfrp.com,香港CN2,速度还行,偶尔会被它的同行蹦掉,和别人合用,只能将就着用了,我用的树莓派4,不知道性能和你那个群辉怎么样

    • avatar
      jager 2020-3-10 · 22:55

      1、可以换https试下,我目前都没什么问题;
      2、树莓派应该差不少,我这款4核8G16TB硬盘,一万多大洋呢,树莓派应该几百块就可以搞定吧,而且群晖最大的区别是长时间运行的,我这个除了更新,基本没关机过,一切正常。

  11. 一同学习 2020-3-9 · 23:06

    顺便问下,你这个主题是什么名字呀

  12. 星光 2020-3-11 · 14:55

    大佬现在用的是群晖建站我在群晖也建立了个,向大佬学习一下

  13. 王光卫博客 2020-3-16 · 13:14

    这个是按照规范型站点标准搞得啊

  14. 菜鸟之志 2020-3-24 · 15:47

    看了你的文章,我说下我自己的想法,我想用我的软路由,再上个虚拟机,做个图床,我听说现在电信宽带不允许有web服务,加端口无所谓,能用即可,只是做图床嘛,根据你的经验,电信宽带,做web服务器不会被封吧。

    • avatar
      Jager 2020-4-13 · 8:00

      如果是直接提供访问基本都会被封,套了CDN应该还好。

  15. xc 2020-4-8 · 2:27

    博主你好!
    我想问一下:腾讯cdn到你的源站是通过HTTP还是HTTPS来回源的?
    我使用腾讯cdn的时候发现HTTPS回源的话无法自定义端口。而阿里云则支持自定义端口的HTTPS回源,不过需要提交工单来申请。

    • avatar
      Jager 2020-4-13 · 8:02

      嗯,这里没描述清楚,腾讯CDN回源是HTTP协议。

  16. 呼啦小棒 2020-4-22 · 19:24

    大神你好,我按你的方法配置好了,现在有个问题是,腾讯云开启https的时候css文件无法加载,这个怎么解决呀?

    • avatar
      Jager 2020-8-2 · 17:07

      要看具体是什么错误

  17. lsqxxx00 2020-5-23 · 10:29

    大佬你好,我自己也是电信宽带在家用群晖搭建了WordPress博客,但是由于443端口被封,必须改成别的端口,现在遇到的问题是带端口号的网址在微信里面分享很受限制,你有什么好的办法帮帮我吗?

    • avatar
      Jager 2020-8-2 · 17:04

      其实这篇文章就是解决这个问题的呀,仔细看看。

  18. Alliot 2020-5-26 · 20:04

    打开你的博客。。。GPU跑了40%。。。 GTX1050。。。 是不是动画太多了。。

    • avatar
      Jager 2020-8-2 · 17:02

      最近花时间定位,基本解决了,有空可以帮忙试下。应该要好不少。

  19. 2020-6-4 · 16:03

    那这样的话,站长是不是要时不时去更新那个回源cdn里面的ip咯?

    • avatar
      Jager 2020-6-4 · 16:42

      NAS支持DDNS,CDN设置的源站是一个DDNS的别名,能够根据宽带拨号公网变化动态更新。

      • 2020-6-5 · 10:03

        站长能说的再详细一点吗,我如果用域名回源就进不去,ip地址如果家里换了,我要手动换,好难过= =

        • 都督 2020-6-24 · 12:17

          把你的DDNS域名填到CDN的源站域名那里就可以了。源站域名用来解析网站ip的,可以是二级域名或其他的解析到你网站的域名。

  20. terry 2020-8-21 · 19:46

    来自 1.0.0.1 的回复: 字节=32 时间=188ms TTL=52

  21. Cyberzyh 2020-9-2 · 1:35

    老哥我想问下,我用的北京联通的宽带,在我的ESXi上虚拟了一个Centos,搭建了一个Web服务,用ROS软路由通过DDNS以及端口转发 转发出去,我本来想的是内网Web的80端口转发到外网80端口,然后域名访问的话就不需要带端口号了,事实上我也转发成功了,但是问题就很奇怪,我转发成功之后,我的内网所有机器都没法上国内的网,国外的网是通过OpenClash上的,当时我不仅占用了我的公网ip的80端口,还占用了443端口,两个端口一占,国内网完全没法上,我的公网ip就跟消失了一样,但是我的web服务却可以通过域名访问。然后我删了443端口转发,然后国内部分网可以上。。。我人晕了都。

  22. michaelchen644 2021-4-13 · 13:38

    看了你的套娃经历,我这个“国家一级套娃表演大师”也汗颜了,真是自愧不如。一个端口封禁引发的血案!!

  23. 逗逗 2021-5-21 · 23:18

    你这个网站真的非常快

  24. MiTu 2021-6-21 · 8:55

    大佬,Cloudflare免费版不支持自定义证书,这个怎么解决的

    • 墨风 2021-11-7 · 10:38

      用lets encrypt的免费证书了。。

  25. zizdog 2021-11-29 · 19:27

    其实就加上端口不就行了。毕竟也没有谁访问那个网站每次都输入网址吧。就像我留言用的网址就是家里路由器上整了个网站,用的88端口。你点一下同样可以访问啊,是不是默认端口无所谓了。又没事多重要的事儿。

    • avatar
      Jager 2021-11-30 · 18:29

      你说的有理,不过作为开放到互联网的博客来说,带个非80或443的非标端口,感觉还是不够自然,输入也麻烦。毕竟不只是给自己用的,如果只是一个个人笔记服务,那就无所谓端口了。

  26. Michael 2022-2-19 · 10:53

    可以试试CF的Tunnel,甚至可以部署在docker里。速度勉强能接受吧

  27. couper 2022-3-12 · 18:57

    不太明白,腾讯CDN流量不要钱的吗?我现在是routeos DDNS 到cloudflare,访问家里的NAS都要加个端口,才看到楼主的文章,可是还不太明白这个逻辑,比如加速a.com,源写成a.com:1234,host写成a.com,用户访问a.com会到a.com:1234去拉内容返回用户,那无论如何也用到腾讯的流量了啊,这是加速还仅仅是cname指向?

    • avatar
      Jager 2022-3-18 · 14:26

      确实要钱,不过腾讯云CDN老用户每个月有50G免费流量。。。

      • couper 2022-3-21 · 4:57

        试用了一下,目前你的方案对于知识分享http是可行的,流量也有限,不过https它已经不支持指定端口了

  28. rong 2022-4-22 · 11:19

    哈哈,从头看到未,很牛叉

  29. Jonty 2022-5-8 · 16:00

    也就是说即使有公网ip,但是80和443被封了,也不建议当主机搞博客呗。。这也太麻烦了

  30. 电器网 2022-7-25 · 9:50

    折腾了半天,还是没弄明白