专栏首页FreeBuf使用Go和Let's Encrypt证书部署HTTPS

使用Go和Let's Encrypt证书部署HTTPS

为什么要使用HTTPS?使用HTTPS的途径有哪些?如何用Go来部署HTTPS?拿出你的小本本,你要的干货都在这儿!

HTTPS 的好处我们已在之前的文章中提高好多。它加密浏览器和服务器之间的流量,保障你密码传输的安全,让你的页面加载速度飞快,有助于网站的SEO优化还有对HTTP网站百般嫌弃的浏览器厂商……这些都是使用HTTPS的理由。那么问题来了,怎样可以又快又好地部署HTTPS呢?

使用第三方提供的HTTPS

比如说CloudFlare,他们的免费方案为你那仅支持HTTP的网站提供仿HTTPS代理服务。

要使用CloudFlare:

配置你的域,使用CloudFlare的DNS服务器 在CloudFlare的DNS设置中,将域指向你的服务器,并通将“状态”设为“DNS和HTTP代理服务器(CDN)” 在CloudFlare的加密设置中,将SSL设为“灵活”(该选项使浏览器通过HTTPS与CloudFlare对话,CloudFlare通过HTTP与浏览器对话) 在web管理界面配置CloudFlare的HTTPS代理,提供你的服务器的IP地址。 除此之外,还要启用“总是使用HTTPS”选项

浏览器与CloudFlare对话,CloudFlare负责提供SSL证书,并代理通向你的服务器的通信。由于额外的通信量,这可能会减慢网络速度,也可能由于CloudFlare服务器比你的服务器要快(变得更快是他们的工作),所以导致网络速度变快。

AWS、谷歌云以及其它一些主机服务提供商也为托管在他们那里的服务器提供免费HTTPS服务。

另一个选项是在支持HTTPS的反向代理服务器(如Caddy)后面运行你的服务器。

直接支持HTTPS

很久很久以前,想要一张ssl证书就必须每年为一个域名花很多钱。而现在,Let’s Encrypt改变了这一切。

这是一个非营利性机构,它提供免费证书,并且提供HTTP API来获得证书。API允许自动化处理这一过程。

在Let’s Encrypt出现之前,你可能会购买一个证书,而这仅仅是一串字节而已。你会把证书存放在一个文件中,并配置你的网络服务器来使用它。

有了Let’s Encrypt以后,你就能够使用他们的API来免费获得证书了,而且这一过程是在你的服务器启动后自动完成的。

值得庆幸的是,所有与API进行对话的艰苦工作都已由其他人做完了。我们只需要安装插件就可以了。

有两个Go库可以实现Let’s Encrypt支持。

我一直在使用golang.org/x/crypto/acme/autocert,它是由Go的核心开发人员开发的。

现在已经有几个月了,它运行一切正常。

下面是怎样启动一个使用Let’s Encrypt提供的免费SSL证书的HTTPS网络服务器的方法。

完整的例子请看:free-ssl-certificates/main.go。

const (htmlIndex = `Welcome!`inProduction = true)func handleIndex(w http.ResponseWriter, r *http.Request) {io.WriteString(w, htmlIndex)}func makeHTTPServer() *http.Server {mux := &http.ServeMux{}mux.HandleFunc("/", handleIndex)// set timeouts so that a slow or malicious client doesn't// hold resources foreverreturn &http.Server{ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,IdleTimeout: 120 * time.Second,Handler: mux,}}func main() {var httpsSrv *http.Server// when testing locally it doesn't make sense to start// HTTPS server, so only do it in production.// In real code, I control this with -production cmd-line flagif inProduction {// Note: use a sensible value for data directory// this is where cached certificates are storeddataDir := "."hostPolicy := func(ctx context.Context, host string) error {// Note: change to your real domainallowedHost := "www.mydomain.com"if host == allowedHost {return nil}return fmt.Errorf("acme/autocert: only %s host is allowed", allowedHost)}httpsSrv = makeHTTPServer()m := autocert.Manager{Prompt: autocert.AcceptTOS,HostPolicy: hostPolicy,Cache: autocert.DirCache(dataDir),}httpsSrv.Addr = ":443"httpsSrv.TLSConfig = &tls.Config{GetCertificate: m.GetCertificate}go func() {err := httpsSrv.ListenAndServeTLS("", "")if err != nil {log.Fatalf("httpsSrv.ListendAndServeTLS() failed with %s", err)}}()}httpSrv := makeHTTPServer()httpSrv.Addr = ":80"err := httpSrv.ListenAndServe()if err != nil {log.Fatalf("httpSrv.ListenAndServe() failed with %s", err)}}

需要注意的是:

HTTPS的标准端口是443; 你可以只运行HTTP、只运行HTTPS或两者都运行; 如果服务器没有证书,那么它将会使用HTTP API向Let’s Encrypt服务器请求证书。

这些请求被限制到每周处理20个,以避免Let’s Encrypt服务器过载。

因此,在某个地方缓存证书是非常重要的。在我们的例子中,我们将证书缓存到磁盘上,使用的是autocert.DirCache命令。

缓存只是一个界面,所以你可以在一个SQL数据库或Redis中执行你所存储的。

你必须正确安装DNS

为核实你确实是你所申请证书的域的所有者,Let’s Encrypt服务器会回叫你的服务器。

为了正常工作,DNS名必须解析到你的服务器的IP地址。

这意味着,HTTPS代码-路径的本地测试是很难的。我通常不这么做。

如果你真的想这么做,你可以使用ngrok来将你的本地端口暴露给互联网,设置DNS来将你的域名解析到ngrok创建的公共DNS上,然后等待确认DNS信息传给Let’s Encrypt的计算机。

你可能会好奇:这个HostPolicy业务是什么?

正如我提到的, Let’s Encrypt限制了证书供应,所以你需要确保服务器不会向其请求你不关心的域的证书。Autocert的文档很好地解释了这一点。

我们的例子假设的是最常见的情况:一个服务器仅响应一个域。你可以很容易地改变这一点。

在本地测试时,我们不运行HTTPS

当在你的笔记本电脑上进行本地测试时,运行HTTPS版本是毫无意义的。

你的计算机很可能没有可见公用IP地址,所以Let’s Encrypt服务器无法达到你那里,所以你将不会得到证书。

我们也不能绑定到HTTPS端口443(只有根进程可以绑定到1024以下的端口)。

在这个例子中,我使用inProduction标记来决定是否应该启动HTTPS服务器。

在实际代码中,我会加入检查-production命令行标志的代码,并使用它。

从HTTP重定向到HTTPS

如果你能够使用HTTPS了,那么提供纯HTTP就毫无意义了。

我们可以将所有HTTP请求重定向到同样的HTTPS上,以获得更好的安全性和搜索引擎优化效果。

func makeServerFromMux(mux *http.ServeMux) *http.Server {// set timeouts so that a slow or malicious client doesn't// hold resources foreverreturn &http.Server{ReadTimeout: 5 * time.Second,WriteTimeout: 5 * time.Second,IdleTimeout: 120 * time.Second,Handler: mux,}}func makeHTTPToHTTPSRedirectServer() *http.Server {handleRedirect := func(w http.ResponseWriter, r *http.Request) {newURI := "https://" + r.Host + r.URL.String()http.Redirect(w, r, newURI, http.StatusFound)}mux := &http.ServeMux{}mux.HandleFunc("/", handleRedirect)return makeServerFromMux(mux)}func main() {httpSrv := makeHTTPToHTTPSRedirectServer()httpSrv.Addr = ":80"fmt.Printf("Starting HTTP server on %s\n", httpSrv.Addr)err := httpSrv.ListenAndServe()if err != nil {log.Fatalf("httpSrv.ListenAndServe() failed with %s", err)}}

技术部分到此为止了。

免费证书从何而来?

有种意见认为,由于一个设计错误,SSL协议不仅进行加密,还会向浏览器证明网站的身份。它担负着责任,使得我们可以追踪google.com网站的所有者,并且看到该网站的确是由美国谷歌公司,而不是由莫斯科的黑客伊万所有。

我们只信任极少数公司(证书颁发机构)会颁发能够证明网站所有者身份的证书。

当你申请一个证书时,证书颁发机构必须核实你的身份。他们通过查看你的文件来做这项工作。

核实文件需要人力。保证证书安全也需要人力。证书颁发机构为颁发证书而收费是合理的。

信任并不是成比例的。浏览器和操作系统销售商可以信任10家公司不会颁发无效证书,但他们不可能信任1000家。

我们不想让随便一家公司变成骗子证书颁发机构,然后为黑客伊万颁发google.com域的证书。

为了得到仅有的几个理想结果而连续审核数千家证书颁发机构,将会花费太多的精力。

由少数几家公司控制市场很可能导致垄断,这样,由于缺乏竞争,价格将居高不下。

这正是SSL证书市场当前的行情。你每年只花60美元就可以拥有一台低端服务器,但一个证书却比这要昂贵。

这是一个问题,因为SSL证书的成本是所有网站采用加密技术的明显障碍。

少数几家公司决定共享他们的资源来解决这一问题,从而更有利于整个互联网。于是他们资助了Let’s Encrypt这样一家证书颁发机构,然后编制一些必要的软件并运营着颁发证书的服务器。

这就是免费证书的来历。

本文分享自微信公众号 - FreeBuf(freebuf),作者:SSLChina

原文出处及转载信息见文内详细说明,如有侵权,请联系 yunjia_community@tencent.com 删除。

原始发表时间:2017-07-23

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 什么是SSL预证书?

    预验证是用作证书透明度(CT)一部分的特殊类型的SSL证书。 预先证书与常规SSL证书不同,因为它们不是(也不可以)用于验证服务器或形成经过身份验证的连接(例如...

    FB客服
  • 代码签名证书买卖黑市的真实情况

    代码签名证书 根据研究人员的调查发现,目前地下网络犯罪市场买卖代码签名证书的情况越来越频繁了,而这些伪造的代码签名证书可以帮助攻击者让自己的恶意软件绕过安全防护...

    FB客服
  • 一款使用PowerShell和证书来加密文件的工具

    在之前的两篇文章中,我已经教大家如何使用证书加解密文件,但总的来说操作过程还是有些繁杂。今天我将为你们提供一个文件加密工具,来自动化的帮我们完成这些过程。关于证...

    FB客服
  • 要让Fiddler能够监控加密过后的HTTPS请求,需要执行哪些步骤?

    打开Options菜单的HTTPS,勾上Capture HTTPS Connects和Decrypt HTTPS traffic,会弹出一个对话框,询问是否信任...

    Jerry Wang
  • 如何创建自签名证书

    TLS/SSL是用于将正常流量包装在受保护的加密包装中的Web协议。得益于此技术,服务器可以在服务器和客户端之间安全地发送流量,而不会被外部各方拦截。证书系统还...

    小铁匠米兰的v
  • 【案例分析】如何实现企业SSL证书有效管理和监控?

    2020年3月20日晚间,许多苹果用户看到系统不断地弹窗无法验证服务器身份,包括iOS、iPadOS以及 macOS系统全部如此。

    嘉为科技
  • Pycharm远程调试服务器代码(使用P

    1.随便准备一个项目工程,在本地用Pipenv创建一个虚拟环境并生成Pipfile和pipfile.lock文件,如下:

    py3study
  • 如何构建可伸缩的Web应用?

    想象一下,你的营销活动吸引了很多用户,在某个时候,应用必须同时为成千上万的用户提供服务,这么大的并发量,服务器的负载会很大,如果设计不当,系统将无法处理。

    dys
  • 9 百万用户级游戏服务器架构设计

    所谓服务器结构,也就是如何将服务器各部分合理地安排,以实现最初的功能需求。所以,结构本无所谓正确与错误;当然,优秀的结构更有助于系统的搭建,对系统的可扩展性及可...

    范蠡
  • 正向代理、负载均衡、反向代理

    假设我们需要使用自己的笔记本(A)访问国外的站点(B),由于网络限制,我们无法访问国外的站点.但是此时我们有一台服务器(C)跳出了网络限制可以访问国外站点,那么...

    郑小超.

扫码关注云+社区

领取腾讯云代金券