散户福利! Nodejs 多站点切换 Htpps 协议 - V2EX
V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
famanoder
V2EX    Node.js

散户福利! Nodejs 多站点切换 Htpps 协议

  •  2
     
  •   famanoder 2017-02-23 00:09:32 +08:00 4448 次点击
    这是一个创建于 3153 天前的主题,其中的信息可能已经有所发展或是发生改变。

    记录一些要点,以便于常记起时有据可循!

    纯属赶个时髦,折腾了两天终于将个人小站的全部服务由 http 协议切换到了 https ,整个过程虽然也不算太麻烦,但也不得不承认,个人对互联网安全这方面的知识确认比较欠缺;

    Letsencrypt 是由 Mozilla 、思科和 EFF 等组织发起的,免费向广大互联网网站提供 SSL 证书,目的在于加速推进互联网由 Http 过渡到 Https ,很高兴周末能够与其不期而遇,这对于一个互联网散户来说,绝对是大大的福利,所以决定乘周末折腾一番:先搞到证书,再改程序;

    获取 letsencrypt 颁发的免费的 SSL 证书也是相对比较简单的,我还是个 windows 服务器,目前没能耐去折腾 Linux ,所以要下载 letsencrypt-win-simple 的安装包,运行 letsencrypt.exe 就开始了:第一步输入邮箱,如果不是第一次申请会跳过前两步,然后有 5 个选项供你选择,一般选 M ,输入 M , Enter 就到了让你输入需要证书的域,接着输入这个域对应的站点的根目录,输入一个线上运行的域即可,指定的根目录需要是能够直接访问的,因为他会访问你输入的域以及根目录下的某个文件,我很纳闷他是怎么在我站点新建的那些目录和验证文件,也就是说,他会在你指定的目录下新建两层目录和一个他需要访问的验证文件,准确的说他要知道这个乱码文件里的一段乱码内容来完成认证;完成认证后就会在 C:\Users\Administrator\AppData\Roaming\letsencrypt-win-simple\httpsacme-v01.api.letsencrypt.org 目录下生成证书文件;接下来的步骤就相对可以随意些了;

    如果你就一个主域和一个站点,那么就可以拿证书去改程序了;

    如果真的这样就完事了,那么是否感觉太快了,以致于没啥体验了;按照上面的步骤一个域下面可以生成一次证书,那么重复这些步骤,生成多个域下面的多个证书自然也是可以的了,问题在于必要性,或许折腾就是在为你的天真弱知买单;

    Ok ,我很天真;我为主域和两个二级域各生成了一次证书,接下来改程序咯!

    我的站点是用 Nodejs 搭建的,内部由 http-proxy 代理来串起来的 3 个小站点,没有使用 Nginx 完全是为了以业余的玩性多去理解一点 Nodejs ;接下来主站监听 443 端口,二级站点由 http-proxy 代理分发;

    var https=require('https'); var http=require('http'); var fs=require('fs'); var server = http.createServer(app); var httpsServer=https.createServer({ key: fs.readFileSync('./privatekey.pem'), cert: fs.readFileSync('./certificate.pem') },app); httpsServer.listen(443); server.listen(80); 

    代理中间件大概的样子:

    app.use(function(req,res,next){ var proxy = httpProxy.createProxyServer({ headers:{ 'x-forward-ip':req.ip.match(/([\w\.]+)/g)[1] } }); proxy.on('error', function (err, req, res) { res.writeHead(500, { 'Content-Type': 'text/plain' }); res.end('Something went wrong.'); }); switch (req.headers.host){ case 'm.famanoder.cn': proxy.web(req, res, { target: 'https://localhost:2333' }); break; case 'cdn.famanoder.cn': proxy.web(req, res, { target: 'https://localhost:3222' }); break; default: next(); } }); 

    这样主域用 https 访问一点问题没有,问题在于二级站点的访问浏览器始终会提示网站的证书不受信任,没办法,只好这样访问二级站点: https://cdn.famanoder.com:4000/,是的,带端口访问当然没问题,这样的话就没走代理了,可始终感觉不太方便,别扭,只能重想办法了;

    又是一个机缘巧合,准备起身下班时看到了一篇文章,除了标题,全英文的,但直觉告诉了我,内容有我想要的东西;一脸懵逼的走马观花的看了一遍,果然豁然开朗了:在命令行里启动 letsencrypt 加--san 参数来申请证书,可以为一个域绑定多个附带的域,也就说多个域可以共用同一套证书,那么代理的问题自然就解开了;输入主域后,再输入多个域用逗号隔开,然后他会依次去每个域验证,最后生成共用的一套证书;于是我决定了:今晚加餐!

    Letsencrypt 的验证方式为访问这个格式的地址:

    http://cdn.famanoder.com/.well-known/acme-challenge/RHha4Dx3YaUzi7tu_C6p9mPk-TNpuLVN5hMQro2N1_Q

    他会依次访问每个域的这个乱码文件,估计这个文件里有他想要的另一段乱码内容,打开看看就知道了;主站用的 Express , cdn 站点使用的原生 Nodejs ,两个站点的访问结果都是直接下载了文件,可能 MIME 头要改改,因为现在是多个域要访问同一个目录下的文件,索性在填写根目录时别填真正的根目录,而是填一个多个根目录共同所属的目录,比如 D:\,修改路由文件如下:

    // www(Express) app.get('/.well-known/acme-challenge/:ids',function(req,res,next){ require('fs').readFile('D:/.well-known/acme-challenge/'+req.params.ids,function(err,data){ err&&console.log(err); res.end(data); }); }); // www(Koa2) router.get('/.well-known/acme-challenge/:ids',async (cx,next)=>{ await next(); let data=await fs.readFileSync('D:'+cx.request.url); cx.response.body=data; }); // cdn if (req.url.indexOf('acme-challenge')!=-1) { var pathname=url.parse(req.url).pathname; fs.readFile('D:'+pathname,function(err,data){ err&&console.log(err); res.writeHead(200,{ 'content-type':'text/html' }); res.end(data); return false; }); } return false; 

    这样,多个域依次验证通过了,生成了同一套证书,有效期 3 个月,有效期内系统正常的话, 3 个月后会自动续期;那么就可以继续走 http-proxy 代理了,二级站点的 https 访问也不需要带端口了;接下来就是替换所有的 http 为 https 了,或者直接去掉协议,//www.famanoder.com 格式也可以,浏览器会自动识别采用相应的协议;

    由于 Letsencrypt 的验证域必须是线上可访问的,所以本地开发要另外配置,比如用 Git 自带的 openssl 生成一套证书作为开发调试时用也是可以的,只是浏览器会提示证书不受信用;

    总之,说复杂也不复杂,说简单也不是那么简单,事情就是那么个事情,折腾就是为天真弱知买单嘛!

    如果你已在路上,就勇敢的向前吧!

    原文来自:花满楼(https://www.famanoder.com

    16 条回复    2017-04-07 00:07:19 +08:00
    t123yh
        1
    t123yh  
       2017-02-3 00:18:22 +08:00 via Android
    感觉将 TLS 交给 Nginx 反代实现要好些。
    isCyan
        2
    isCyan  
       2017-02-23 00:40:19 +08:00 via Android
    用 nginx 多舒服
    ryd994
        3
    ryd994  
       2017-02-23 02:24:12 +08:00 via Android
    san vs sni
    gzlock
        4
    gzlock  
       2017-02-23 06:11:54 +08:00 via Android
    交给 Nginx 处理后你会发现这是只需要花一分钟时间的事
    justyy
        5
    justyy  
       2017-02-23 06:33:26 +08:00
    @gzlock 交给 CloudFlare (Flexible SSL) 你会发现这是 三秒钟的事情。一点不夸张,就是一个开关而已。
    zhuangtongfa
        6
    zhuangtongfa  
       2017-02-23 08:34:49 +08:00
    用 nginx 多舒服
    renyiqiu
        7
    renyiqiu  
       2017-02-23 08:40:07 +08:00 via iPhone
    @justyy CloudFlare 最近慢得可怜,虽然不少功能不错
    icebergSnow
        8
    icebergSnow  
       2017-02-23 08:43:41 +08:00 via Android
    Htpps 是什么
    还有 花满楼=>famanoder.com
    站长是福(hu)建人吗?
    xuezher
        9
    xuezher  
       2017-02-23 09:25:08 +08:00
    楼主撸多了吧, https
    justyy
        10
    justyy  
       2017-02-23 09:58:40 +08:00
    @renyiqiu 嗯 不太清楚,我所有十个域名全是 CloudFlare 其中有几个域名还是 Pro (20 美元每个月)。
    特别好用。 真心喜欢。 每个月花些钱心甘情愿,暂时没发现啥问题,当然也许这个和我在英国有关 -- 肉身翻墙已久,国外的互联网环境没有国内这么多问题。
    asuraa
        11
    asuraa  
       2017-02-23 10:19:17 +08:00
    htpps 是啥协议?
    O3YwA1ENkb7i35XJ
        12
    O3YwA1ENkb7i35XJ  
       2017-02-23 12:44:30 +08:00
    @famanoder 大哥,你的网站有漏洞呀。。。

    看你的文章都被清空了(仅在列表里没显示,实际上文章还存在,请自行恢复)
    https://www.famanoder.com/bokes

    > PS : 大部分玩 nodejs 的前端都没有安全意识, 注意是大部分,请不要对号入座 :P
    famanoder
        13
    famanoder  
    OP
       2017-02-23 14:39:00 +08:00
    @xqin 厉害!
    skyfore
        14
    skyfore  
       2017-02-28 15:13:20 +08:00
    这些直接让后台服务器去处理这些(比如 Nginx , Apache ),然后使用代理到 nodejs ,这样在服务器端就只暴露 80 和 443 接口了~~。
    skyfore
        15
    skyfore  
       2017-02-28 17:18:19 +08:00
    你的网站点赞该修改一下了,我帮你点了 1W 的赞,手都点麻了 [手动滑稽]
    libook
        16
    libook  
       2017-04-07 00:07:19 +08:00
    nginx 一分钟搞定,还能在 nginx 后面挂多个不同的 node 服务,用同一个域名的不同 location ,共用同一个 TLS 证书。。。
    关于     帮助文档     自助推广系统     博客     API     FAQ     Solana     2817 人在线   最高记录 6679       Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 31ms UTC 13:31 PVG 21:31 LAX 06:31 JFK 09:31
    Do have faith in what you're doing.
    ubao snddm index pchome yahoo rakuten mypaper meadowduck bidyahoo youbao zxmzxm asda bnvcg cvbfg dfscv mmhjk xxddc yybgb zznbn ccubao uaitu acv GXCV ET GDG YH FG BCVB FJFH CBRE CBC GDG ET54 WRWR RWER WREW WRWER RWER SDG EW SF DSFSF fbbs ubao fhd dfg ewr dg df ewwr ewwr et ruyut utut dfg fgd gdfgt etg dfgt dfgd ert4 gd fgg wr 235 wer3 we vsdf sdf gdf ert xcv sdf rwer hfd dfg cvb rwf afb dfh jgh bmn lgh rty gfds cxv xcv xcs vdas fdf fgd cv sdf tert sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf sdf shasha9178 shasha9178 shasha9178 shasha9178 shasha9178 liflif2 liflif2 liflif2 liflif2 liflif2 liblib3 liblib3 liblib3 liblib3 liblib3 zhazha444 zhazha444 zhazha444 zhazha444 zhazha444 dende5 dende denden denden2 denden21 fenfen9 fenf619 fen619 fenfe9 fe619 sdf sdf sdf sdf sdf zhazh90 zhazh0 zhaa50 zha90 zh590 zho zhoz zhozh zhozho zhozho2 lislis lls95 lili95 lils5 liss9 sdf0ty987 sdft876 sdft9876 sdf09876 sd0t9876 sdf0ty98 sdf0976 sdf0ty986 sdf0ty96 sdf0t76 sdf0876 df0ty98 sf0t876 sd0ty76 sdy76 sdf76 sdf0t76 sdf0ty9 sdf0ty98 sdf0ty987 sdf0ty98 sdf6676 sdf876 sd876 sd876 sdf6 sdf6 sdf9876 sdf0t sdf06 sdf0ty9776 sdf0ty9776 sdf0ty76 sdf8876 sdf0t sd6 sdf06 s688876 sd688 sdf86