编译自:
[users-guide][1]
[1]:https://www.varnish-cache.org/docs/4.0/users-guide
目录:
- 1.安全第一
- 1.1 命令行选项
- 1.1.1 访问命令行接口
- 1.1.2 命令行接口认证
- 1.1.3 参数
- 1.2 命令行接口
- 1.3 VCL 程序
- 1.4 HTTP 请求
- 1.1 命令行选项
- 2.重要的命令行参数
- 2.1 '-a' listen_address
- 2.2 '-f' VCL-file or '-b' backend
- 2.3 其他选项
- 3.CLI - 使用命令行控制 Varnish 的行为
- 3.1 通过 CLI 接口,我们可以做什么
- 3.1.1 加载/使用/丢弃 VCL 程序
- 3.1.2 清除缓存内容(使其失效)
- 3.1.3 修改参数
- 3.1.4 启动/停止 子进程
- 3.1 通过 CLI 接口,我们可以做什么
- 4.后端存储
- 5.Transient Storage
- 6.参数
- 7.决定缓存的大小
1. 安全第一
这是关于安全性的小节。
我们尽了最大的努力使 Varnish 可防御来自 HTTP socket (接受 HTTP 请求的监听 socket)的攻击。
Varnish 提供了四个层次的权限,基本上是关于:命令是如何进入 Varnish 的?命令是从哪里来的?
- 命令行选项
- 访问命令行接口
- VCL 程序
- HTTP 请求
1.1 命令行选项
最顶层的安全策略,是由启动 varnishd 时的命令行参数所定义。
这时,通过 varnishd 的命令行参数要进行如下的定义:
- 谁可以访问命令行接口?
- 通过命令行接口他们可以修改哪些参数?
- 允许使用 inline-C 代码吗?
- VMODs 是否会被限制,VMODs 如何被限制?
1.1.1 访问命令行接口
访问命令行接口有三种方式:
1.可让 Varnishd 进程监听于一个 TCP socket,可以将该 socket 绑定到如下地址上,Varnishd 进程通过该地址接受 CLI 连接:
-T 127.0.0.1:631
-T localhost:9999
-T 192.168.1.1:34
-T '[fe80::1]:8082'
默认地址是 -T localhost:0
,这时会随机选择一个端口号,varnishadm 可从共享内存中获知该端口号。
使用 "localhost",表示将 CLI 访问限制只能在本机访问。
你可以将 CLI 端口绑定到一个 IP 地址上,使我们可远程访问 CLI 接口。
通过远程访问 CLI 接口,命令不会加密,是明文的,但是 -S/PSK 认证要求远程终端知道 shared secret 是什么。
另外,你也可以就把 CLI 接口的访问限制在本地,让远程用户通过 ssh/VPN 等手段连接到本地主机,然后再访问命令行接口。
如果你使用 ssh,你可以将每个用户可使的命令限制为,仅可以使用 varnishadm 命令。甚至可以用脚本封装 varnishadm 命令,通过编写脚本,仅允许使用 varnishadm 执行特定的 CLI 命令,这样也可以达到限制的目的。
2.也可通过 -M 参数将 varnishd 配置为 "反向模式"。这时 varnishd 会尝试打开一个 TCP 连接到一个指定的地址,并对你的中心 Varnish 管理设置发起一个 CLI 连接。这时命令也不会加密,是明文的,但是 -S/PSK 认证要求远程终端知道 shared secret 是什么。
3.最后,可通过 -d 选项运行 varnishd,你可在 stdin/stdout 输入 CLI 命令。
1.1.2 命令行接口认证
CLI 接口在默认情况下,使用 "Pre Shared Key" 认证的方式工作,这种方式在通信时是以明文的方式通信,CLI 命令和响应都是明文的,所以没有保密性。
-S/PSK 认证的工作方式很简单:varnishd 进程在启动时会创建一个文件,其中包含有随机的内容,该文件仅允许启动 varnishd 的用户或者超级用户访问。
要使用命令行接口连接 varnishd 进程,必须通过认证,你必须知道该文件的内容,因为 varnishd 会要求你提供密码。
(XXX: xref to algo in refman) .. XXX:Dunno what this is? benc
varnishadm 必须能访问密码文件才能工作。
如果你想让其他用户,通过本地或远程的方式访问 CLI 接口,你必须创建自己的密码文件,并且是该文件仅对该用户开放可读权限。
下面是创建密码文件的一种很好的方式:
dd if=/dev/random of=/etc/varnish_secret count=1
当你启动 varnishd,使用 -S 选项指定该文件。varnishd 进程也需要读取该文件。
你可以改变密码文件的内容,因为每当 CLI 对一个连接进行认证时,varnishd 进程都会读一次密码文件。
varnishadm 命令仅可在本地从“共享内存”中获取密码文件的文件名,在远程系统上执行 varnishadm,你必须复制一份密码文件提供给 varnishadm 使用,varnishadm 使用 -S 选项指定该文件。
如果要关闭 -S/PSK 认证,在启动 varnishd 进程时,使用 —S 选项指定 “空字符串” 即可:
varnishd [...] -S "" [...]
1.1.3 参数
从命令行中可以对参数进行设置(-p param=value),然后使它们 “只读”(使用 -r),这样设置以后,通过 CLI 接口连接到 varnishd 进程时,不可对这些“只读”参数进行修改。
基本上任何参数都可以将你的 HTTP 服务搞得一塌糊涂,但其中有一些比其他参数更具破坏力:
user and group
通过 VCL 访问本地系统,子进程的权限切换这里设置的 user 和 group ,然后开始接受连接
listen_address
Trojan other TCP sockets, like ssh
cc_command
Execute arbitrary programs
vcc_allow_inline_c
允许在 VCL 中使用 inline C 代码,VCL 中的任何C代码都将被 Varnish 执行
这些参数你也应该将其锁定:
syslog_cli_traffic
将所有 CLI 命令记录当 syslog,你知道这意味着什么
vcc_unsafe_path
Restrict VCL/VMODS to vcl_dir and vmod_dir
vmod_dir
Varnish 在此目录中寻找 modules。
1.2 命令行接口
Varnish 的 CLI 接口功能很强大,通过 CLI 接口,几乎可以对 Varnish 进程做任何操作。
如上一小节所讲述的,通过对某些参数进行锁定,可以减少 CLI 接口可能带来的破坏,但这种保护也仅限于保护你的本地文件系统和操作系统,不能保护你的 HTTP 服务。
目前还不能对 CLI 命令进行限制,让其仅对指定的连接生效。要达到这个效果,你可以使用脚本封装 varnishadm 命令。
使用 sshd 的配置,可以限制远程用户仅能使用这些脚本。
1.3 VCL 程序
VCL 有两种危险的机制:VMODs 和 inline-C
这两种机制运行执行任意的代码,因此可以允许使用子进程的权限访问本地系统。
如果 varnishd 进程以 root/superuser 权限启动,我们使用系统上的任何可用的设施将子进程放入 sandbox 之中,如果 varnishd 进程的权限不是 root/superuser,这样做是不可能的。
Varnish 4 默认在启动时关闭了 inlinde-C,所以除非你主动开启了 inline-C,不必担心它造成什么问题。
上面所提及的参数可以限制 VMODs 的加载,限制其仅能从指定的目录中加载,在该目录中,是你信任的 VMODs。
如果做了这些工作,我们相信你的本地系统不会因为 VCL 受到损害。
1.4 HTTP 请求
为了让 Varnish 能够抵抗来自监听 socket (就是接受 HTTP 请求的 socket)的攻击,我们已经竭尽全力。所以一般来说,你无需对此再做什么。
我们的告诫是,VCL 是一个编程语言,你可以使用它编写规则,决定对 HTTP 请求进行什么样的处理,而你也可以使用它做一些愚蠢的事情,或存在潜在危险的事情,包括使自己暴露在各种攻击之下,或是一些颠覆性的危险动作。
如果你有一些 “管理类” 的 HTTP 请求,比如 PURGE 请求,我们强烈建议你使用 VCL's Access control lists (ACLs),即访问控制,限制这类请求仅能从指定的 IP地址 或网段发出。
2. 重要的命令行参数
启动 varnishd 进程时,有两个命令行参数是必须设置的,它们是:
- '-a' listen_address,使用哪个端口接受 HTTP 请求
- '-f' VCL-file or '-b' backend,后端服务器的访问地址
如果使用软件包安装 Varnish,设置启动选项的配置文件是:
Debian, Ubuntu: /etc/default/varnish
Red Hat, Centos: /etc/sysconfig/varnish
FreeBSD: /etc/rc.conf (See also: /usr/local/etc/rc.d/varnishd)
2.1 '-a' listen_address
-a 参数定义了 Varnish 使用哪个端口地址接受 HTTP 请求,一般设置为 ":80" 。也可以使用逗号分隔,设置多个端口地址,监听地址可使用主机名或 IP 地址。如果设置了多个监听地址,而其中一个无法打开,Varnish 是不能启动的。
示例如下:
-a :80
-a localhost:80
-a 192.168.1.100:8080
-a '[fe80::1]:80'
-a '0.0.0.0:8080,[::]:8081'
要注意的是,如果你的 web 服务器跑在同一台机器上,你只能让它们监听于不同的端口地址上了。
2.2 '-f' VCL-file or '-b' backend
Varnish 需要知道后端服务器的地址,你可以使用 -b 选项指定,或者可以将设置放入 VCL 文件中,然后以 -f 选项指定该文件。
使用 -b 选项指定后端服务器:
-b localhost:81
-b thatotherserver.example.com:80
-b 192.168.1.2:80
要注意,如果使用主机名,它们只能被解析为一个 IPv4 或一个 IPv6 地址。
使用 VCL 文件设置:
backend default {
.host = "localhost:81";
}
In both cases the built-in VCL code is appended.
2.3 Other options
Varnish 有很多命令行参数,我们建议你学习它们,但不需要使用所有的参数,对于刚开始学习的你来说,了解以上的参数就足够了。
Varnish 默认使用 100MB 的 malloc 内存用来缓存对象,如果你希望设置更大的内存,使用 -s 参数。
如果你的网站是一个大型网站,你可能需要调整 worker 线程的个数,以及一些其他的参数,使用 -p 参数进行调整,但我们建议一般不要去修改它们,除非必要的时候。
在上线之前,你可能要再复习一下“安全第一”小节,看是否需要对管理权限进行划分。
完整的命令行参数列表,请求参考 OPTIONS
3. CLI - 使用命令行控制 Varnish 的行为
启动 varnishd 进程滞后,你就可以通过命令行对其进行控制。最简单的方式,是在本地系统上,执行如下命令:
varnishadm help
如果要从远程执行 varnishadm,有两种方式可以选择:
1.通过 ssh 连接到本机,执行 varnishadm
ssh $http_front_end varnishadm help
2.你可以配置 varnish ,让它可以接受远程 CLI 连接 (using the '-T' and '-S' arguments):
varnishd -T :6082 -S /etc/varnish_secret
然后在远程机器上执行 varnishadm :
varnishadm -T $http_front_end -S /etc/copy_of_varnish_secret help
可看到,ssh 方式显然更为方便。
如果不带参数地执行 varnishadm,它会从 stdin 读取 CLI 命令,如果给了参数,它会将其当做一条单独的 CLI 命令,并执行它。
CLI 接口总是会返回状态码:200 表示 OK,其他的状态码表示有错误发生。
如果 varnishadm 收到的状态码不是 200,varnishadm 退出后,返回 1,并且打印收到的状态码。
3.1 通过 CLI 接口,我们可以做什么
使用 CLI 接口几乎可以对 varnishd 进程进行完全的控制。其中一种重要的任务是:
- 加载/使用/丢弃 VCL 程序
- 清除缓存内容(使其失效)
- 修改参数
- 启动/停止 子进程
下面分别讨论这些主题
3.1.1 加载,使用,或者丢弃 VCL 程序
所有的缓存策略和其他决策,由 VCL 程序所决定。
你可以加载多个 VCL 程序,但其中只有一个是 “激活” 的 VCL 程序。
加载一个新的 VCL 程序:
varnish> vcl.load some_name some_filename
在加载时,会从 VCL 文件中读取 VCL 程序,对其进行编译。如果编译失败,会收到如下信息:
.../mask is not numeric.
('input' Line 4 Pos 17)
"192.168.2.0/24x",
----------------#################-
Running VCC-compiler failed, exit 1
VCL compilation failed
如果编译成功,VCL 程序就被加载了,然后你可以激活它:
varnish> vcl.use some_name
切换回原来的 VCL 程序:
varnish> vcl.use old_name
切换是即时发生的,所有新的请求会使用刚才激活的 VCL 程序。正在处理的请求使用原来的 VCL 程序完成处理工作。
设计一个 “应急VCL 程序” 是一个很好的想法,你可以将其加载,在发生紧急情况时切换过去。
3.1.2 清除缓存内容(使其失效)
Varnish 提供 "purges" 操作从缓存中禁止指定的内容。可以使用正则表达式。
设想一个场景,公司的 logo 已经改变了,你需要让 Varnish 不再从缓存中提供旧的 logo,这样做:
varnish> ban req.url ~ "logo.*[.]png"
我们之所以称之为 "banning",即禁止,而不是清除(也可以这样说),是因为缓存对象仍然在缓存中,没有被删除,只是禁止从缓存中发送该对象而已。
我们这样设置之后,Varnish 并不会去检查每一个缓存对象是否匹配,只是当我们收到一个请求该对象的 HTTP 请求时,才会对其进行匹配测试,如果匹配上了,就不直接从缓存中响应,而是转发请求给后端服务器获取响应。
当我们要清除错误的缓存内容,相比于重新启动 Varnish,ban 指令的开销小得多,
3.1.3 修改参数
从 varnishd 的命令行可以使用 -p 选项对参数进行设置,我们也可以通过 CLI 接口在运行时修改参数:
varnish> param.show prefer_ipv6
200
prefer_ipv6 off [bool]
Default is off
Prefer IPv6 address when connecting to backends
which have both IPv4 and IPv6 addresses.
varnish> param.set prefer_ipv6 true
200
一般而言,不建议修改参数,除非你真的有很好的理由修改它,比如为了性能调优或者安全配置的原因.
大部分参数修改会立即生效,有一些需要一些延迟时间。但有一些参数需要重启子进程才能生效,这些在参数的说明中会注明,可以通过 man varnishd 进行查看。
3.1.4 启动、停止子进程
一般你应该让子进程一直运行,不要干扰它,但如果需要停止或启动它,使用如下的命令:
varnish> stop
and:
varnish> start
如果启动 varnishd 时,带了 -d(debugging)选项,你总是需要显式地启动子进程。
当子进程死去,管理进程会自动重启子进程,对此行为,你可以进行调整,相关参数为 auto_restart。
4. Storage backends
Varnish 支持即插即用式的后端存储,包括:malloc,file,persistent(实验版) 三种,它们各有不同的性能特点。默认的配置是使用 malloc 后端存储,并且限制了大小。对于生产环境,你需要调整后端存储的大小。
malloc
syntax: malloc[,size]
Malloc 是一种基于内存的后端,每个缓存对象从内存中获得分配的存储空间。如果你的系统内存太小,可能会用到 swap 内存交换。
size 对实际可用的内存上限进行设置,默认是无限制的。内存参数的单位默认是 bytes,可使用如下的单位:
K, k The size is expressed in kibibytes.
M, m The size is expressed in mebibytes.
G, g The size is expressed in gibibytes.
T, t The size is expressed in tebibytes.
malloc 的性能基于内存的速度,所以是非常快的。如果数据集的大小超过了上限值,此时的性能依赖于操作系统内存分页的效率。
file
syntax: file[,path[,size[,granularity]]]
file 类型的后端,仍然将缓存对象存储在内存,但这个内存空间是通过 mmap 技术将磁盘上的一个 文件(不能是符号链接文件)映射过来的。这个文件可被称为 backing 文件。
path 参数指定 backing 文件的路径,或者指定一个目录,Varnish 将在其中创建 backing 文件。默认的路径是 /tmp。
size 参数指定 backing 文件的大小。内存参数的单位默认是 bytes,可使用如下的单位:
K, k The size is expressed in kibibytes.
M, m The size is expressed in mebibytes.
G, g The size is expressed in gibibytes.
T, t The size is expressed in tebibytes.
如果 path 参数指向一个已经存在的文件,而且没有指定 size 参数,将使用该文件的大小作为 size 参数的值。如果 path 参数指向一个不存在的文件,且没有指定 size 参数,将会因为无法决定 size 参数的值而报告一个错误。
如果 backing 文件已经存在,它将被 truncated,并扩展到指定的 size 大小。
注意,如果 varnishd 需要创建或者扩展 backing 文件,它不会预分配(pre-allocate)增加的空间,这会导致磁盘碎片的产生,对于普通的机械磁盘,这会影响 I/O 性能。最好使用 dd 命令预先创建 backing 文件,这样可以最小化磁盘碎片的产生。
granularity 参数用于指定空间分配的粒度。所有的空间分配会按照这个粒度进行分配。粒度的单位默认是 bytes,可以使其他的单位。
默认的粒度,是 VM page 的大小。如果缓存对象是很多小对象,你需要减少粒度的值。
file 类型的后端存储,其性能受到磁盘设备的写速度的限制,而且受到磁盘寻道时间的影响。
persistent (experimental)
syntax: persistent,path,size {experimental}
persistent 存储。
Varnish 将缓存对象存储在一个文件上,这样可以在 Varnish 关闭后(意外的关闭或者主动的关闭),仍能保存大部分的缓存对象信息。
path 参数指定 backing file 的路径,如果文件不存在,Varnish 会创建文件。
size 参数指定 backing 文件的大小。内存参数的单位默认是 bytes,可使用如下的单位:
K, k The size is expressed in kibibytes.
M, m The size is expressed in mebibytes.
G, g The size is expressed in gibibytes.
T, t The size is expressed in tebibytes.
Varnish will split the file into logical silos and write to the silos in the manner of a circular buffer. Only one silo will be kept open at any given point in time. Full silos are sealed. When Varnish starts after a shutdown it will discard the content of any silo that isn't sealed.
Note that taking persistent silos offline and at the same time using bans can cause problems. This is due to the fact that bans added while the silo was offline will not be applied to the silo when it reenters the cache. Consequently enabling previously banned objects to reappear.
5. Transient Storage
瞬时的存储。
如果你将任何一个后端存储命名为 "Transient" ,这个后端存储只会被用作存储 transient object (shot lived)。默认情况下,Varnish 会使用一个没有上限的 malloc 后端存储来做这个事情。
当一个缓存对象的 TTL 低于 shortlived 参数的值,这个对象被认为是 transient object 。
6. Parameters
Varnish 有很多参数能够影响其行为和性能。大部分的参数可通过 CLI 接口进行设置(使用 varnishadm 命令),使用 param.set
关键字。
通过 varnishd 的命令行参数,在启动时指定 -r 选项,可以将一些参数设置为 “只读”。
我们不建议你调整参数,除非真的知道你在做什么。我们为了使默认参数值能够处理大部分的工作负载付出了很大的努力。所以一般不建议你修改它们。
可在 CLI 中查看所有的参数,使用 param.show
,如果要查看指定的参数的描述,执行:
varnish> param.show shortlived
200
shortlived 10.000000 [s]
Default is 10.0
Objects created with TTL shorter than this are
always put in transient storage.
7. Sizing your cache
要决定使用多大的缓存,是很难的。你可以考虑如几个方面:
-
你的热区数据集有多大?对于一个门户网站,或者一个新的站点,热区数据集是首页上所有资源,加上首页上链接出去的所有页面和对象的总和。
-
生成一个缓存对象的开销是多少?对于图片资源,如果你的内存资源有限,或者直接从后端服务器提供图片服务的性能可以接受,那就可以直接从后端服务器提供图片内容,或者只缓存一小段时间。
-
使用 varnishstat 对
n_lru_nuked
计数器参数进行监控,如果你的 LRU 活动太过频繁,这说明缓存空间太小了,你应该考虑增加缓存的大小。
必须要注意一点,每一个缓存对象所需要的空间不止是其本身的大小,如果你指定了 -s malloc,16G
,Varnish 实际需要的内存可能是其两倍。因为对于每个缓存对象,Varnish 需要 1KB 左右的额外空间,所以如果你有很多的小尺寸的缓存对象,这部分额外的空间需要认真考虑。
网友评论