kubernetes 配置 https 证书

上周在做主站从 http 迁移 https 的过程中发生了严重了事故,明明只设置了主域名生效 https 证书,但是最后问题是所有的子域名也都自动发起 https 请求,导致多个业务子域名无法正常访问。

先整理回忆一下整个迁移过程:

申请 https 证书

我们的域名是在阿里云上采购的,也托管在阿里云上,对比了几个渠道的 https 的证书,价格也差不多,索引就在阿里云 上采购了,购买证书找个最便宜的就可以了,免费证书只能针对单域名,我们买了一个通配符域名,通配符域名有个小小的小坑,域名只能到子域名级,不能再到下一级,如果确实有需求,那要继续采购子域名的通配符域名。

例如:.aliyun.com的通配符证书只能对a.aliyun.com、b.aliyun.com域名进行保护。如果存在a.b.aliyun.com的域名需要购买.b.aliyun.com的通配符证书

托管服务就是可以在证书过期之前,自动更新证书,目前我也不清楚是下发一个新的证书,还是给老的证书续费,可以暂时不购买,意义不是特别大,我们选择成本最低的形式。

还有一点 https 证书有效期都只有一年,如果有骗子说两年三年或者更多那骗术就毫无技术含量。

采购成功需要填写申请的域名,这里有个域名所有权的问题,现在流行且方便的方法是添加一条 TXT 的 DNS 解析,如果是阿里云上采购的域名这里都是一键操作的很方便,申请成功后一般五分钟就能拿到证书。我们选择下载适配 nginx 的证书,后面备用。

配置 ingress

前面已经下载到 https 证书,在正式配置 ingress 之前,我们需要将证书的内容配置到配置到 kubernetes 的 secret 里面,当然有很多方法,我们选择最简单的方式,kubectl create secret tls secret名字 --key key的路径 --cert pem路径

这里我的一个习惯是在给 secret 命名上,如果是单域名 example-com-ingress-secret,如果是多域名前面加上一个 x,后面 ingress 配置上需要用到这个自己命名的 key。

$ kubectl create secret tls xxxx-com-ingress-secret --key xxx.com.key   --cert xxx.com.pem

接下来就是配置 ingress 部分,我这里用的是 helm,直接修改 value 即可:

ingress:
  enabled: true
  annotations: {}
    # kubernetes.io/ingress.class: nginx
    # kubernetes.io/tls-acme: "true"
  hosts:
    - host: xxx.com
      paths:
        - /
  tls:
    - secretName: xxxx-com-ingress-secret
      hosts:
        - xxx.com

如果是直接使用 ingress,那么 spec 如下

spec:
  rules:
    - host: xxx.com
      http:
        paths:
          - backend:
              serviceName: xxx-svc
              servicePort: 80
            path: /
  tls:
    - hosts:
        - xxx.com
      secretName: xxxx-com-ingress-secret

面临两个问题

所有 http 协议的请求都无法正常访问,会 308 重定向到 https 协议上

因为有很多项目都是跑在 http 协议上,直接重定向到 https 会导致很多 api 不可用,所以我们需要保留 http 和 https 协议并行的方式,然后逐步将 http 协议替换成 https

所有子域名也都被 307 重定向到 https 协议上

这里也想纠正一下域名的称呼,com 为一级域名,xxx.com 为二级域名,yyy.xxx.com 为xxx.com 的子域名,xxx.com 为 yyy.xxx.com 父域名。

其实这里是最奇怪的一块,阿里云的 dns 解析只配置了 @.xxx.com 解析到 ingress 关联的 slb 的 ip,其他的子域名我都没有处理,难道 yy.xxx.com 的 dns 解析会先经过 xxx.com 的解析,去查了一些资料,这是不可能的情况。

解决问题

http 和 https 协议并行

这里我联系了阿里云的技术,找到 nginx-ingress-controller 所关联的 configmap ,找到 key 为 nginx-configuration 的 configmap,添加两行 force-ssl-redirect: 'falsessl-redirect: 'false'

apiVersion: v1
data:
  proxy-body-size: 20m
  force-ssl-redirect: 'false'
  ssl-redirect: 'false'
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: ''
  labels:
    app: ingress-nginx
  name: nginx-configuration
  namespace: kube-system

子域名不跳转 https

image.png
image.png

重新打开 Chrome,仔细分析发起的请求,看到一个关键词 HSTS,顺藤摸瓜看到了一个新的安全协议。这套协议让全站 https 变为了更为严格的模式 。

为什么是 HSTS?

在浏览器请求域名的时候,是会发起一个 http 请求,服务端接受到 http 请求再重定向到 https 协议上,后面的请求都建立于 https 协议上所以是安全的,但是问题在于发起的第一次 http 请求可能会被劫持,如果第一次请求被劫持了后面的内容也可能就不是从主站发过来的了。

为此 IETF 规定,在第一次成功发起 https 请求之后会在 response header 中添加一行 strict-transport-security: max-age=15724800; includeSubDomains,这就表明接下来浏览器如果访问 http 请求的时候不再向服务端发起而直接在本地重定向到 https 上,max-age 表示这个本地重定向的有效期,过期之后仍然会向服务端发起请求。includeSubDomains 这也是本次出问题的主凶,表明接下来这个域名的子域名也同样服从父域名的规则,http://yyy.xxx.com 也会本地直接重定向到 https://yyy.xxx.com ,所以就是这个原因感觉影响到了子域名的解析。

这里有杠精肯定想说我要是一次没有访问过 xxx.com,就拿不到第一次成功访问 https 的header,所以访问一个特别陌生网站还是可能被攻击,对!所以 IETF 又提供了一招,在浏览器里面内置了一系列 https 的网站的名单,如果访问这些网址是不需要像服务器发起一个 http 请求的,我们也可以向 https://hstspreload.org/ 提供自己的域名,hstspreload 上面的域名最终会被 Chrome、火狐等浏览器内置到内核当中。

回头解决子域名不跳转 https

根据 ingress-nginx 官网提供的解决方案,可以添加 hsts-include-subdomains 字段,这样在第一次成功发起 https 请求之后会在 response header 中添加 strict-transport-security: max-age=15724800,没有 includeSubDomains,这样子域名就可以走自己的 dns 逻辑。

apiVersion: v1
data:
  proxy-body-size: 20m
  force-ssl-redirect: 'false'
  ssl-redirect: 'false'
  hsts-include-subdomains: 'false'
kind: ConfigMap
metadata:
  annotations:
    kubectl.kubernetes.io/last-applied-configuration: ''
  labels:
    app: ingress-nginx
  name: nginx-configuration
  namespace: kube-system

小结

  • 互联网领域是绝对的错综复杂,各种协议交互穿插,都是为了维护这个不安全不可信的网络
  • 个人觉得对于 ingress-nginx 这个扩展还是很多改进的地方,不可以在单路的一个地方配置 https 证书,而是把证书配置分散在各个 ingress 文件中,从而不好管理证书
  • HSTS 协议简洁且强大,当然这些也都需要浏览器的配合,一个先进的浏览器本身就带着安全的光芒。

参考文档

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 219,039评论 6 508
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 93,426评论 3 395
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 165,417评论 0 356
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 58,868评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 67,892评论 6 392
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 51,692评论 1 305
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,416评论 3 419
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,326评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 45,782评论 1 316
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 37,957评论 3 337
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,102评论 1 350
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,790评论 5 346
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,442评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 31,996评论 0 22
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,113评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,332评论 3 373
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,044评论 2 355