用 HAproxy 实现 HTTPS 反向代理

听闻水果要求 APP 全面开启 HTTPS 协议了,作为微信企业号的使用者,也会连带受到影响。为了解决这一即将到来的问题,需要购买证书,并快速实现实现已有业务的 HTTPS 访问。本文针对这两个问题简要介绍一下。


首先,稍微解释一下加密证书。

有一个最基本的常识就是你自己生成的自签名证书是无效的,譬如 12306.cn 那样自己给自己颁发的证书,大家的浏览器都不能识别,就总会被提示为不安全。(一直想不通铁总那么大的盘子,为啥舍不得花那点买证书的钱。)

自签名加密证书不能使用,原因在于浏览器能够识别的加密证书,其颁发机构的根证书是随着操作系统一起安装到每个用户的 PC 或手机中的,只有这些颁发机构所签名过的加密证书,浏览器才会认。目前,有两种方法获得办法机构签名的证书,其一是花钱购买,其二是申请免费使用。

两种方法都很简单,但还是先说说传统的购买方式。互联网上有专门从事加密证书销售的中介机构,譬如证书巴士。但通常他们的网站上都有各种各样的颁发机构的不同类型证书在叫卖,价格相差也比较大,应该如何选购呢?这就要稍微了解一下数字证书的分类。

从用途上,数字证书分为很多种,比较常用的是用于 WEB 服务器、邮件服务器等与客户端之间进行加密通信的,以及用于应用程序签名的。很显然,为了应对水果的新规定,需要购买前者。

为 WEB 服务器通信提供加密的证书,根据其功能和价格,还可以分成三种:

  1. 仅仅提供加密通信:这类证书中仅仅携带了该证书所对应的网站域名以及证书的有效期,通过证书,不能获知网站由哪个机构管理。
  2. 提供网站管理者识别信息:这类证书在第一类证书的基础上增加了管理机构的信息,但这些信息必须由网站访问者点开证书才能查看到。
  3. 直接在地址栏上显示网站管理者识别信息:这类证书在第二类证书的基础上,直接将网站管理者的信息显示在地址栏上。

最后,还有一个要考虑的问题就是你所拥有的二级域名数量,如果需要启用 HTTPS 访问的二级网站较多,并且已经使用或者准备使用 HAproxy/nginx 或土豪专用的 F5/A10 集中管理应用发布,那么可以考虑购买泛域名证书。

所谓泛域名证书,就是 *.xxx.edu.cn 这种域名的所有二级网站都能用(三级是不能用的)。但需要注意的是,泛域名证书必须集中部署,如果安装在各种应用服务器上并且失窃,就达不到保护传输数据不被窃取的目的了。

购买证书,并不仅仅是一个花钱的过程,而是一个小小的技术活儿:

  1. 为域名生成私钥,这个东西,任何中介机构和证书颁发机构都是不需要的,必须自己保管好;
  2. 用私钥签名 CSR(证书请求)文件,相当于你填了张申请表;
  3. 把 CSR 文件提交给中介机构或颁发机构;
  4. 颁发机构要检验你的身份真实性,越贵的证书检查的内容项就越多,说不定还要填表盖章签字画押,便宜的通常只要用个特定名称的邮箱做验证就行;
  5. 颁发机构经过一番审查,会生成一个证书文件通过邮件发给你,你的数字证书就拿到手了;
  6. 赶快检查一下你第一步生成的私钥还在不在手里,要是搞丢了,就跳转回步骤1。

如果不习惯使用 OpenSSL 的命令行,可以使用 xca 做证书管理。

用 HAproxy 实现 HTTPS 反向代理_第1张图片
XCA界面

免费申请的证书,仅仅提供加密通信,并且必须提供准确域名,一个证书中最多包含 100 个域名。目前比较有名的证书提供组织是 Let's Encrypt,申请很方便,但有效期较短,以后有机会详说。

现在,证书已经到手,该部署了。


后面的工作,假设你手里已经有了私钥文件 edu.key 和含完成签名链的证书文件 edu.pem,两者都为 PEM 格式。所谓完整签名链,就是你的证书通常并非由颁发机构的根证书直接签名,而是由其某个子证书签名的,这时需要把根证书、子证书和你域名的证书放到一个文件里。不会做的话,xca 导出的时候可以直接选择的。

安装一台 Linux 服务器,可以是任何你喜欢的版本,本文以 CentOS 6 为例,这种服务器通常 2C/2G 内存就差不多了,访问量特别大的,可以考虑增加一些资源。

1. 确认服务器上安装了最新版的编译工具和库文件:

# yum install make gcc pcre-devel openssl-devel

2. 下载 haproxy-1.6 的源代码

# cd /usr/local/src
# wget http://www.haproxy.org/download/1.6/src/haproxy-1.6.10.tar.gz
# tar xf  haproxy-1.6.10.tar.gz

3. 编译安装 haproxy-1.6

# cd haproxy-1.6.10
# make TARGET=linux26 USE_PCRE=1 USE_OPENSSL=1
# make install

此时运行 haproxy -v ,应该能看到版本号信息。

4. 安装数字证书

把 edu.key 和 edu.crt 两个文件复制到服务器上,然后执行命令将其合并

# mkdir /etc/certs/private
# cat edu.pem edu.key > /etc/certs/private/edu.pem

5. 创建配置文件

创建配置文件 /etc/haproxy/haproxy.cfg 内容如下:

global
    log /dev/log   local0
    log /dev/log   local1 notice
    pidfile     /var/run/haproxy-http.pid
    user nobody
    group nobody
    #daemon

    # Default SSL material locations
    #ca-base /etc/ssl/certs
    #crt-base /etc/ssl/private

    # Default ciphers to use on SSL-enabled listening sockets.
    # For more information, see ciphers(1SSL). This list is from:
    #  https://hynek.me/articles/hardening-your-web-servers-ssl-ciphers/
    ssl-default-bind-ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS
    ssl-default-bind-options no-sslv3
    tune.ssl.default-dh-param 2048

defaults
    log     global
    mode    http
    option                  httplog
    option                  dontlognull
    option http-server-close
    option httpclose
    option forwardfor       except 127.0.0.0/8
    option                  redispatch
    retries                 3
    timeout http-request    10s
    timeout queue           1m
    timeout connect         10s
    timeout client          1m
    timeout server          60m
    timeout http-keep-alive 10s
    timeout check           10s

frontend http
    # 绑定 80 端口,启动 http
    bind :80
    # 绑定 443 端口,启动 https
    bind :443 ssl crt /etc/certs/private/edu.pem
    # 根据域名生成 acl 规则
    acl is_weixin_bit_edu_cn hdr(host) -i weixin.bit.edu.cn weixin.bit.edu.cn:443
    # 根据 acl 规则选择后端
    use_backend weixin_bit_edu_cn if is_weixin_bit_edu_cn
 
backend weixin_bit_edu_cn
    # 如果未使用 https 则自动跳转,此处未开启
    #redirect scheme https if !{ ssl_fc }
    server weixin 10.0.0.250:8080 maxconn 100 check

6. 启动 haproxy

haproxy -f /etc/haproxy/haproxy.cfg -D

其中 -D 参数是使其进入后台运行

现在,就可以开启浏览器访问网站了,记得地址前缀为 https://


成文匆忙,如有不妥,欢迎指正。

你可能感兴趣的:(用 HAproxy 实现 HTTPS 反向代理)