Nginx部署Hexo的优化(二)
一段时间没看网站, 发现Chrome访问图片都挂了, 然后推送新的笔记发现SSH端口被拒绝, 今天来说一下这两个事, 以及一些个人的心得.
PS: 最近忙别的事去了, 笔记有段时候没推出来更新, 年底前补上数篇
0x00. 问题描述
网站的基本技术组成和配置可以参考上一篇, 这里不再重述. 简单说在 ”Nginx + Hexo + 七牛云” 的组合下, 我们可以安全可控的部署自己的小站点, 但是最近它出现了开头说的两个问题, 这里再带上原因列一下:
- Chrome 81版本后,
HTTPS
页面自动所有静态资源HTTPS
化, 不加载HTTP
资源, 而七牛免费的对象存储(图床)只有HTTP
(重要) - 内部网络安全策略升级, 访问外部主机, 只允许80和443端口, 其它端口直接全部禁止, 导致无法推送更新
上面两个问题中, 第一个 Chrome 最新稳定版V81/84 (最新V86)影响主要是从这几个月开始, 随着新版 Edge 直接使用了最新的Chromium内核, 国内和Firefox等一众浏览器可能也会逐步跟上, 所以解决这个问题迫在眉睫.
至于第二个问题, 可能遇到的同学并不多… 但是总归是让我赶上了, 没有推送SSH的端口权限等于直接狗带, 必须处理.
下面来说说我解决这两个问题的思路, 以及参考的一些资料的想法. 供大家参考
0x01. 问题分析
1. Chrome强制转换HTTP资源为HTTPS
首先, 遇到这个问题, 首先是看到图片挂了, 然后F12打开, 发现 HTML
中 http://xx/xx.jpg
的资源, 都被自动转换为了 https://xx/xx.jpg
, 然后图片/静态库访问的是七牛的对象存储, 访问失败当然就在 console
中提示加载失败了. 我印象中在 Chrome 7x 版本的时候的确从文章里看到过说 V8x 要彻底禁止加载 http 资源和 FTP协议, 所以很快想到是这样的内部机制导致的, 我的思路是:
查阅资料, 确认是Chrome高版本的策略变化导致这个问题, 并尝试使用低版本Chrome对比 (确认原因)
查阅官方文档, 确认是否彻底禁止, 还是默认禁止, 提供了选项给用户自己开启… (寻求官方生机, 结果如下图, V86是所有混合资源的最后期限.)
查阅其他文章/博客, 看看大家的解决办法, 找到了数个思路:
- Chrome 并非禁止了
HTTP
的使用, 只是默认禁止HTTPS
的页面加载HTTP
资源, 那么敌不动我动, 可以把页面整个降级为HTTP
- 通过服务端开启反向代理从而访问七牛的 HTTP 资源. 相当于
User –HTTPS- > Nginx <-HTTP– Qiniu
(具体见[0x03](#0x03.反向代理实现 HTTPS?)) - 个人用户浏览器设置 “允许不安全资源加载”
- …. (基本是随口胡说的, 实际根本不可行, 就略了)
- Chrome 并非禁止了
2. SSH只开放80和443端口的服务器
可能从某一时刻/网络开始, 你会发现不管是 XXR
还是 V2R
等 proxy 软件, 都会秒被 ban 掉端口, 这样导致个人的 Hexo 更新推送就会被禁止 (默认通过SSH推送资源)
但是你稍微测一下会发现, 实际端口检测是通的, 服务器的ping也都是通的, 那再使用 ssh -v
来确认端口存活会发现: (不推荐telnet
)
1 | # 测试远程主机proxy端口, 比如7788, 会直接卡在网络验证出口处失败 |
如果出现上述情况, 你尝试更改 proxy_port
比如21之后, 仍然是秒拒, 就可以推测很可能是内部/防火墙等安全策略, 只开放了 80 & 443 的端口. 那就很容易想到一个思路, 复用/公用 80 和 443端口 (这也是著名的 Trojan 项目的伪装思路), 有两种常见实现方式:
- 使用Linux 自带的防火墙
iptables/firewall
等, 编写多个规则, 允许你期望的IP通过80/443端口访问, 然后禁止其他流量 (复杂. 易变) - 使用开源的sslh方案, 支持全面的代理协议, 以及简单的包部署方式 (apt/yum)
显然, 对大部分同学来说, 写出多个复杂的 iptables
并不是易事, 使用单独针对ssh + ssl
复用的方案是更值得选择的, 当然初除此之外, 还有一些其他优势(支持多种代理模式)
0x02. 具体实践
上面的分析和方案列举选择完之后, 下面来具体说一下实践过程
1. 两种方式访问 HTTP 资源
A. 用户单独设置
(适合服务器端自己无法控制)
这种方案参考 Chrome 文档后尝试可以, 后面写笔记发现也有其他网友发现了, 这个方法是在每个浏览器端生效, 很简单易操作, 具体可参考此文, 我就懒得单独截图了. 缺点自然是普通用户无法自信得知, 后续也可能被 Chrome
移除此选项, 局限性大.
B. 网页视情况跳转为 HTTP (适合服务端可自己控制)
自己控制自然是通用得多, 这里以 Nginx
为例, 说一下我的思路和简单写法:
- 我并不希望所有页面都降级为 HTTP, 那会影响网站入口, 我希望首页/导航页面HTTPS, 内容页面降级
- 文章页面来说, 希望尽可能分多个规则, 按需降级
- Chrome内核 < 80的. 不进行降级
- 文章页面不包含
http
内容的, 不进行降级 (不少文章没有配图, 但 Nginx 如何感知这部分不走它的请求呢? TODO)
可参考的配置如下, 具体规则可调整, 特别要注意别让 https 和 http 进入了死循环的跳转. 确保及时中断:
1 | # vi /etc/nginx/sites-available/default # Ubuntu下默认apt安装路径 |
至于选择仅有带 http
资源的页面才调整, 我的思路大致是在进入文章匹配的loction
中, 直接去读取服务器本地html文件, 判断网页目录下 .html
中是否包含 http
, 如果有, 则降级, 没有就跳出结束. 这个还没加到配置中, 后续补上. 也欢迎大家提供更好的思路和写法.
2. 优雅复用80或443端口
社区给的文档(翻译)已经写得足够好, 安装和启动我都不再重复, 这里单独说一下可以修改的地方 (不与文档一致的配置. 可选):
1 | # 我们的 Nginx 可以不设置监听本机(127.0.0.1)的443端口, 而是其他比如1443 |
其他就暂时没啥可说的了, 等待以后特殊需要再看, 关于用 SSL
来科学上罔的同学, 可以看看最后的提醒.
0x03.反向代理实现 HTTPS?
首先, 结论是完全不建议. 可称之为企业级的开倒车或原地TP
最早遇到这个问题的时候, 大家遵循RSA原则. 自然是想到去搜一下其他人的做法, HTTP免费的情况下, 大家不想被迫上收费的船, 那么很容易可以看到大量的反向代理来让七牛CDN实现全站HTTPS, 例如如下文章:
经过自己实践和思考, 觉得这种思路普遍存在几个问题:
- 没有很好的理解
Nginx
配置 (即使是用反代, 也把简单的问题复杂化了..完全不需要申请那么多域名. 配置也就一行) - 没有很好理解回源/镜像站 (CDN提供的功能), 或混淆了
- 最根本的, 没想明白为什么使用图床 & CDN, 得到了一个似是而非的方案.
首先说最主要的, 反向代理实现全站HTTPS最大的问题在于等于把CDN彻底废了. 使用CDN + 图床我们的主要目的是啥?
不就是为了加速静态资源的访问, 从而提升网站浏览速度么, 如果只是单纯为了HTTPS, 我们直接把所有图片用相对地址放在 ../img/
下, 丢在服务器上不就好了, 这样管理还异常方便, 也不用担心公有云哪天跑路把图弄丢了. 让我们来简单捋一下七牛云CDN + 反代的简单访问路径:
- 客户端从国内浏览器请求网页, 然后请求了一个图片, 假设地址是
https://imbajin.com/img/a.png
- 服务器端
Nginx
收到请求后, 检测到判断, 从而代理请求http://xxx-qiniu.com/a.png
- 关键来了, 这里我们分服务器在海外/国内两个来分析:
- 海外: 那你很可能需要跨国访问国内的七牛CDN节点, 然后返回资源给国内用户.. (海外CDN节点较少的情况下)
- 国内: 你会访问距离你服务器国内最近的CDN节点, 然后再返回给国内所有地区的用户 (国内CDN节点一般充裕)
- 不管是国内还是国外, 你可以发现, 原本分布式的CDN节点, 可以让全世界不同地区的用户就近访问到资源, 结果你这样反代一下, 等于一个360°空转, 让所有的用户都必须从你的龟速服务器去访问资源, 而且比起直接访问CDN节点, 还多了一层代理请求, 速度是慢上加慢
- 而且这样做, 还会让你服务器的流量猛增, 因为所有的请求实际都是走的你的服务器, 且不说主机是否限流量使用, 或者是按流量计费. 一般乞丐云主机都有很严格的带宽限制, 访问的请求一多或者下载资源较大, 那就直接把带宽耗光.
所以, 不管是国内还是国外主机, 你可以看出除了一个自我欺骗的HTTPS, 而且这个做法还不如直接把图片存本地(相对路径)快捷简单.
方案还有非常明显的副作用, 除了彻底废了CDN外, 还包括你需要为一个图床维护两个不同的图片引用地址, 并且还需要修改历史文章里直接使用图床的URL, 到时候如果开启CDN自带的 HTTPS, 还得全部改回来…. 所以仔细想一下, 看似开心撸羊毛的思路其实跟掩耳盗铃差不多滑稽..
这里详细说一下也是为了避免其他同学没细想的时候, 一脚踩了个大坑…
0x04. 一些思考
1. 七牛 HTTPS 的霸王条款
对于今天提到的图片(对象存储) 资源来说, 如果服务商能提供完善廉价的 HTTPS
服务, 其实很多问题都可以解决, 但是仔细阅读了七牛的 HTTPS
总裁文档后, 我选择了拒绝使用它的服务, 原因如下:
- 七牛原本提供每月 10 GB + 的免费 HTTP 流量, 但开启 HTTPS 化后, 所有走 HTTP 的流量, 也全部算为 HTTPS 计费 (参考FAQ)
- 不管何时开通, 当前月之前的 HTTP 流量消耗, 全部按 HTTPS 计算 (比如 29号开通HTTPS, 那之前1~29号所有流量也需要按 HTTPS 付费..)
这两个设定都让人觉得匪夷所思, 且都没明显告知用户, 以至于我开始设想的 “分流选择 HTTP / HTTPS 流量”的方案就彻底流产了, 再加上因为缺乏细致的 HTTPS
限流和暂停访问(自动降级HTTP), 所以如果有人想搞破坏, 可以很轻松一晚上把你的 HTTPS 流量刷爆, 用户为了安全考虑, 还得自己去设定一堆复杂的安全策略 (例如复杂的防盗链设定).
2. HTTPS的安全性
HTTPS 简单来说, 就像一个城堡/房间的大门/入口, 可以基本保障开门进入的过程是安全的. 但是完全不保障房里的内容是否安全..
为何网站/资源要开通 HTTPS
我想大家都能达成一定共识, 但是目前的问题是, 谁来出 HTTPS 的资源服务费, 以及推动所有的 旧资源 更新 (成本?)
目前的 HTTPS
化, 多半是个人去申请一个0门槛的免费证书, 然后部署到自己的服务器上, 因为 HTTPS 本身只能保障连接过程的相对安全性
其可信程度只限于颁发证书的9线机构 —-> 域名提供商之间, 基本等同于 “君子协定”, 而网站本身所有内容的安全性, 都是没有保障的. 所以你仔细看一下 Chrome
或 Firefox
那把看似是安全的小绿锁 (现在可能取消了绿色), 实际写的是 “网站连接是安全的”, 而不是 “网站是安全的”. (但是http会直接显示不安全)
但是, 大部分普通用户根本不会在意这个细节, 也不清楚连接安全仅等于开门这个过程安全, 很容易误以为安全的小锁就代表网站安全, 从而大幅降低安全意识和防范, 截止2020年的欺诈钓鱼网站 60% 以上都已经 HTTPS 化了, 至于其中是否会藏有恶意资源更加难以确定, 是否 HTTPS 化, 和网站本身是否安全几乎没有多少必然联系..
当然, 在 HTTPS
普及的前提下, 全站 HTTPS 自然是利大于弊, 毕竟保障开门进入的过程安全, 也是一种最小信任原则的体现, 只不过还是希望这个过程更加平滑和可靠一些.
3. 端口复用虽好, 也不可贪杯
上文提到的, 通过隐匿在非常常见的网络服务提供端口里, 是一个看起来很不错的注意和选择, 也让很多软件无法精准分别流量类型. 但也要知道, 对方(检测软件)是在暗处, 我们是在明处, 仍有几个需要特别注意的事项:
- 复用80/443来隐匿并不是什么新鲜招式, 方法被被用的越多, 就会越被 “重点关注”
- 80 和 443虽然一般不会被ban, 但是你如果过度使用(比如用来隐藏proxy), 很可能对方直接就把 ip 封了, 那就是搬石砸脚了
- 如果您坚持想用 80 和 443 走代理, 可以考虑加入负载均衡, 让端口流量看起来更均匀一些.
- 如果您所在的网络环境本身足够严格, 认真考虑只复用作
SSH
连接, 然后再走一层跳板 / Float IP.
以上是一些解决这两个安全问题相关的个人实践, 也算是 Hexo 网站部署过程中的一些优化心得吧..
参考资料: