使用清漆和磅允许来自 Drupal 的缓存 HTTPS 流量

Varnish 是一种 Web 应用程序加速器,有助于加快网站速度。它的工作原理是坐在 Web 服务器前面并缓存由它提供服务的网页。

当发出对网页的请求时,Varnish 将此请求传递给 Web 服务器,然后该服务器像往常一样响应该请求。Varnish 然后缓存这个请求的结果,然后将它发送给用户。这意味着下次请求页面时,页面的缓存版本将发送给用户,而 Web 服务器实际上并不是该过程的一部分。由于 Varnish 不运行任何网站代码或访问任何数据库,因此响应比来自 Web 服务器的原始响应快得多。事实上,简单地使用 Varnish 就可以在没有太多配置的情况下大幅提高网站速度。Varnish 非常擅长这项工作,可以显着加快网站速度。

Varnish 不能满足的一件事是 HTTPS 流量。这是设计使然,因此如果您有 Varnish 设置,如果您想使用加密的 HTTPS 流量,则需要完全绕过它。

解决此问题的一种方法是使用称为 Pound 的反向代理系统。Pound 位于 HTTPS 端口上的 Varnish 前面,并在将它们发送到 Varnish 之前解密所有 HTTPS 请求。所有正常的 HTTP 流量都被 Pound 忽略并通过 Varnish 并按正常方式处理。

我不打算在这里安装和设置 Varnish,因为这本身就是一个冗长的操作。如果您有兴趣,那么我已经写了安装和配置 Varnish 的过程的描述,其中还包括配置 Drupal 的描述。

要在基于 Debian 的系统上安装 Pound,只需运行以下命令。

sudo apt-get install pound

基于 RedHat 的系统非常相似,但在这种情况下它们使用 yum。

sudo yum install pound

开箱即用,Pound 不会在系统启动时启动,要设置此编辑文件 /etc/default/pound.conf 中的设置。

startup=1

在编辑主要的 Pound 配置之前,我们需要生成一个 Pound 理解的证书文件,以便它可以解密我们的 HTTPS 传输并将它们转发到 Varnish。如果您已经拥有受信任的 SSL 证书,您可能仍需要完成此步骤才能生成 Pound 满意的证书。出于测试目的,我们将使用 Ubuntu 附带的现有测试 SSL 证书来演示如何执行此操作(保存在 /etc/ssl/certs/ssl-cert-snakeoil.pem)。要为 Pound 生成证书文件,您需要像这样将 pem 和密钥文件组合在一起。

mkdir keys
cp /etc/ssl/certs/ssl-cert-snakeoil.pem keys
sudo openssl rsa -in /etc/ssl/private/ssl-cert-snakeoil.key >> keys/ssl-cert-snakeoil.pem

主要的 Pound 配置文件位于 /etc/pound/pound.cfg,需要对其进行编辑以做两件事。默认情况下,Pound 将侦听端口 80,我们的 Varnish 服务器已经在侦听该端口,因此需要将其删除。然后我们需要添加一个规则,让 Pound 监听 HTTPS 流量并告诉它如何处理请求。

您的 Pound 配置文件应如下所示。

User    "www-data"
Group    "www-data"
RootJail  "/var/pound"
LogLevel    1
 
## check backend every X secs:
Alive    30
 
# poundctl control socket
Control "/var/run/pound/poundctl.socket"
 
ListenHTTPS
    Address 10.0.0.1  # put your server's public IP address here
        Port 443
        Cert "/path/to/ssl-cert-snakeoil.pem"
        HeadRemove "X-Forwarded-Proto"
        AddHeader "X-Forwarded-Proto: https"
        Service
            BackEnd
                Address 127.0.0.1
                Port 80
            End
        End
End

上述选项设置了一些默认设置,然后允许 Pound 侦听传入的 HTTPS 请求。我们告诉 Pound 解密这些请求,然后将它们作为未加密的流量转发到端口 80。X-Forwarded-Proto 标头设置为“https”,以便 Varnish 和 Web 应用程序知道它应该处理 HTTPS 流量。'Cert' 参数引用我们上面生成的 pem 文件,但应更改为您的受信任证书。

另请注意,我们没有在此处添加“ListenHTTP”指令,因为我们根本不希望 Pound 监听 HTTP 流量。

如果您已经设置了您的网络服务器来侦听 HTTPS 流量,那么您需要在启动 Pound 之前将其关闭。在 Apache 中,这通常以 Listen 指令的形式保存。您可以删除它,也可以通过更改以下配置指令来更改端口。

<ifmodule mod_ssl.c="">
    Listen 44300
</ifmodule>

最后,我们只需要在我们的default.vcl文件中添加一个 vcl_hash 回调。这将允许我们在尝试缓存页面时区分 HTTP 和 HTTPS 流量。

sub vcl_hash {
  hash_data(req.url);
  if (req.http.host) {
    hash_data(req.http.host);
  } else {
    hash_data(server.ip);
  }
  # Use special internal SSL hash for https content
  # X-Forwarded-Proto is set to https by Pound
  if (req.http.X-Forwarded-Proto ~ "https") {
    hash_data(req.http.X-Forwarded-Proto);
  }
  return (hash);
}

有了所有这些,您应该能够重新启动 Apache、Varnish 和 Pound 以使所有内容都在一起。

sudo service apache2 restart && sudo service varnish restart && sudo service pound restart

您可以通过运行“netstat -nlp”来仔细检查哪些服务正在侦听哪些端口,这应该会产生如下内容。这假设 Varnish 将流量发送到的后端端口是 8080,这是 Apache 响应的端口。

$ sudo netstat -nlp
Active Internet connections (only servers)
Proto Recv-Q Send-Q Local Address           Foreign Address         State       PID/Program name
.....
tcp        0      0 0.0.0.0:80              0.0.0.0:*               LISTEN      11605/varnishd
tcp        0      0 0.0.0.0:8080            0.0.0.0:*               LISTEN      11554/apache2
.....
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      11647/pound
......

如果您在启动 Pound 时遇到问题,请查看 Pound 日志,该日志将保存在 Debian 系统上的 /var/log/syslog 中。

sudo tail /var/log/syslog

在这里,它会告诉您任何端口冲突或不正确的 SSL 证书文件,因此您应该能够找出问题所在并进行更正。

此处需要牢记一两个安全注意事项。如果您正在解密流量,然后通过网络将此流量发送到不同的服务器,则该流量被拦截的可能性很小。出于这个原因,Pound 必须仅用于私有网络或与 Varnish 实例在同一台机器上。

最后,那些在家里跟随的人可能会意识到这里房间里的大象。尽管 HTTP 和 HTTPS 匿名流量都会被缓存,但不会缓存经过身份验证的流量。因此,如果您的所有用户都登录查看您的网站,那么使用 Pound 通过 Varnish 发送流量不会减少您需要的资源量。主要问题是您并不真的希望向已登录的用户提供缓存页面,因为他们有可能看到另一个用户生成的缓存。您可以做一些事情来允许缓存,包括设置自定义标头和 cookie,甚至 ESI(包括边缘端)。

作为奖励,我想我会创建一个 Ansible playbook,它将在 Ubuntu 设置上与现有的 Varnish 一起安装 Pound。本剧本中使用的两个模板( pound_config.j2 和 pound_initscript.j2 )可以在上面的文章中找到。

---
- hosts: all
  tasks:
    - name: install Pound
      apt: pkg=pound state=installed
      sudo: true
 
    - name: setup Pound initscript
      template: xx_src=pound_initscript.j2 dest=/etc/default/pound
      sudo: true
 
    - name: create snakeoil pem certificate directory
      file: path=/home/{{ user }}/keys state=directory
 
    - name: copy snakeoil certificate pem file
      command: cp /etc/ssl/certs/ssl-cert-snakeoil.pem /home/{{ user }}/keys creates=/home/{{ user }}/keys/ssl-cert-snakeoil.pem
 
    - name: generate pem file with key file
      shell: openssl rsa -in /etc/ssl/private/ssl-cert-snakeoil.key >> ssl-cert-snakeoil.pem chdir=/home/{{ user }}/keys creates=/home/{{ user }}/keys/ssl-cert-snakeoil-pound.pem
      sudo: true
 
    - name: add Pound config file
      template: xx_src=pound_config.j2 dest=/etc/pound/pound.cfg
      sudo: true
      notify:
        - restart pound
 
    - name: ensure pound is started
      service: name=pound state=started
      sudo: true
 
    - name: get iptables rules
      shell: iptables -L
      register: iptablesrules
      sudo: true
      always_run: true
      changed_when: False
 
    - name: add apache iptable rule
      command: iptables -I INPUT 1 -p tcp --dport 443 -j ACCEPT -m comment --comment "pound https port"
      sudo: true
      when: iptablesrules.stdout.find("pound") == -1
      notify:
       - save iptables
 
  handlers:
    - name: restart pound
      service: name=pound state=restarted
      sudo: true
 
    - name: save iptables
      command: iptables-save
      sudo: true
      notify:
       - restart ufw
 
    - name: restart ufw
      service: name=ufw state=restarted
      sudo: true