Apache-技巧积累

SetHandler

SetHandler xxx 是指定 url, 文件, 或目录由 xxx handler 来处理, 如:

1
2
3
4
<Directory "/var/www/cgi-bin">
Options +ExecCGI
SetHandler cgi-script
</Directory>

如果此时访问 /var/www/cgi-bin/test.pl, 那么:

  1. 识别请求路径: Apache 服务器会识别到你请求的是位于 /var/www/cgi-bin 目录下的 test.pl 文件
  2. 应用目录配置: 根据配置文件中的 <Directory "/var/www/cgi-bin"> 指令,Apache 会应用该目录的配置
  3. 启用 CGI 执行: 由于 Options +ExecCGI 指令的存在,Apache 允许在该目录下执行 CGI 脚本
  4. 设置处理程序: SetHandler cgi-script 指令告诉 Apache,所有在该目录下的请求都应该通过 cgi-script 处理程序处理
  5. 执行 CGI 脚本: Apache 会将请求传递给 cgi-script 处理程序, 该处理程序会执行 test.pl 脚本. test.pl 脚本需要具有执行权限, 并且应该正确输出 HTTP 头和内容

也就是说 cgi-script 这个 handler 能执行访问的脚本.

另一个例子:

1
2
3
4
<Location "/server-status">
SetHandler server-status
Require ip 192.168.1.0/24
</Location>

该请求会传递给 server-status 这个 handler 处理, 其返回服务器的状态.

以服务器任意地址访问

Listen 指定端口时, 不指定地址即可:

1
Listen 80

而非:

1
Listen 192.168.177.1:80

设置基于用户的访问

需要用 htpasswd 来创建用户和对应的密码文件:

1
htpasswd -cb .passwd test Huawei@123
  • -c, “create”, 为覆盖原有文件并创建一个新文件
  • -b, “batch mode”, 表示从命令行接受密码而不是交互式
  • test 指定用户名
  • Huawei@123 指定密码

然后在资源目录下的 .htaccess 中写入 (也可以写入一个配置文件):

1
2
3
4
AuthType Basic
AuthName "http test"
AuthUserFile "/home/source/test/.passwd"
Require user test

(要让 .htaccess 文件起作用, 需要对 Directory 做 AllowOverride All 的配置)

MPM 工作模式

Apache 有三种 MPM (Multi-Processing Module):

  • prefork
  • worker
  • event

prefork

使用多个独立的进程来处理请求, 每个进程都有自己的内存空间. 每个进程可以处理一个请求, 因此适用于处理短期请求或对线程安全性要求不高的环境.

启用:

1
LoadModule mpm_prefork_module modules/mod_mpm_prefork.so

worker

个进程可以有多个线程, 每个线程可以处理一个请求.

启用:

1
LoadModule mpm_worker_module modules/mod_mpm_worker.so

event

一种改进版本的 worker 模块. 它在处理请求时使用了更高级的事件机制, 可以更好地处理大量并发连接.

启用:

1
LoadModule mpm_event_module modules/mod_mpm_event.so

在 Web 查看所有 module 的状态

启用 mod_status, 然后在 conf.d/ 目录下新建一个配置文件如 module.conf, 内容为:

1
2
3
4
5
6
<Location /server-status>
Sethandler server-status
Require ip 192.168.177.1
Require all denied
</Location>
ExtendedStatus On

然后重新加载配置.

正向代理

启用 mod_proxymod_proxy_http 模块, 然后使用 ProxyPass 指令:

1
2
3
<Location "/mirror/foo/">
ProxyPass "http://backend.example.com/"
</Location>

等价于:

1
ProxyPass "/mirror/foo/" "http://backend.example.com/"

Require 关键字的理解

Require 用于控制访问权限, 理解为 “Require 怎样的权限”, 语法为:

1
Require entity [entity] [...]

可选的 entity 有:

  • all: 所有用户都满足访问要求
  • none: 没有用户满足访问要求
  • valid-user: 任何通过身份验证的用户都满足访问要求
  • user username: 指定用户名的用户满足访问要求
  • group groupname: 属于指定用户组的用户满足访问要求
  • host host: 来自指定主机的请求满足访问要求
  • ip IP-address: 来自指定 IP 地址的请求满足访问要求 (注意这里不加子网掩码)
  • method http-method: 指定可以访问的特定 HTTP 方法
  • expr expression: 定义复杂访问要求

这些 entity 之后都可以添加:

  • granted, 表示允许访问
  • denied, 表示拒绝访问

<RequireAll> section 中, 可以列出多个 Require 指令, 且只有当所有 require 都满足时, 才会允许访问资源:

1
2
3
4
5
6
<Directory /var/www/html>
<RequireAll>
Require ip 192.168.0.0/24
Require valid-user
</RequireAll>
</Directory>

定义变量使用以及测试变量是否定义

1
2
3
4
5
6
7
8
9
<IfDefine TEST>
Define servername test.example.com
</IfDefine>
<IfDefine !TEST>
Define servername www.example.com
Define SSL
</IfDefine>

DocumentRoot "/var/www/${servername}/htdocs"

重新加载配置文件

可用:

1
httpd -k graceful

或:

1
apachectl graceful

(都是热加载, 不会中断当前服务)

检查配置文件语法是否正确

1
httpd -t

配置 virtual host

1
2
3
4
5
6
7
8
9
10
11
12
13
14
<VirtualHost *:81>
ServerName localhost
ServerAlias www.dummy-host.example.com
ServerAdmin webmaster@dummy-host.example.com
DocumentRoot "/srv/http/webpage/"
ErrorLog "/var/log/httpd/dummy-host.example.com-error_log"
CustomLog "/var/log/httpd/dummy-host.example.com-access_log" common

<Directory /srv/http/webpage>
DirectoryIndex index.html
AllowOverride All
Require all granted
</Directory>
</VirtualHost>

注意这里使用本地的 81 端口, 需要在 /etc/http/conf/httpd.conf 中添加:

1
Listen 81

然后重新加载配置, 此时 81 端口才会被监听.

配置访问黑白名单

基于客户端地址访问

默认拒绝所有访问.

设置允许所有地址, 并 block 一些 ip (设置黑名单):

1
2
Require all granted
Require not ip xx.xx.xx.xx

设置拒绝所有地址, 并允许一些 ip (设置白名单):

1
2
Require all denied
Require not ip xx.xx.xx.xx

基于账户访问

默认无账户认证.

设置认证类型:

1
Authtype Basic

还可开启 Digest 等认证. 开启 Basic 时, 需同时启用 auth_basic_module 模块.

设置认证提示框内容:

1
AuthName "Restricted Area"

设置密码文件路径:

1
AuthUserFile /path/to/passwords/file

设置用于认证的账户:

1
Require user name1 name2

或者允许所有 valid-user:

1
Require valid-user

设置 KeepAlive

1
2
3
KeepAlive On
KeepAliveTimeout 15 # default is 5s
MaxKeepAliveRequests 200 # default is 100

指定默认页面

1
DirectoryIndex index.html

handler() 子例程

handler() 会在接收到 requests 时自动调用, 在一个 module 中定义了 handler() 后, 可以通过:

1
PerlHandler Apache::Foo

来使用, 但其不会预加载 Apache::Foo.

若想预加载, 可以:

1
PerlModule Apache::Foo

或者在 startup.pl 中加入:

1
use Apache::Foo ();

或者写为:

1
PerlHandler +Apache::Foo

其相当于:

1
2
3
4
5
PerlModule Apache::Foo
<Location ..>
...
PerlHandler Apache::Foo
</Location>

的 alias.

对同一个目录下的 cgi 脚本应用不同的 handler

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
# Typical for plain cgi scripts:
ScriptAlias /cgi-bin/ /home/httpd/perl/

# Typical for Apache::Registry scripts:
Alias /perl/ /home/httpd/perl/

# Typical for Apache::PerlRun scripts:
Alias /cgi-perl/ /home/httpd/perl/

<Location /perl/>
SetHandler perl-script
PerlHandler Apache::Registry
Options +ExecCGI
</Location>

<Location /cgi-perl/>
SetHandler perl-script
PerlHandler Apache::PerlRun
Options +ExecCGI
</Location>

到未定位到资源位置时跳转到一个页面

1
2
RewriteEngine On
ErrorDocument 404 /index.html

关于 Options 之后的符号

Options 指令用于设置特定目录的选项。Options指令后面可以跟一个或多个选项,这些选项之间可以用空格分隔。每个选项可以是以下形式之一:

以+号开头,表示启用该选项。
以-号开头,表示禁用该选项。
不带+或-号,表示仅设置指定的选项,而不启用或禁用它。

如果在 Options 指令后面没有明确使用 +- 号,那么该指令所列出的选项将被视为要设置的选项,而不是启用或禁用的选项。这意味着默认情况下,这些选项将被启用。

查看配置文件语法错误

1
apachectl configtest

查看加载的模块

1
httpd -M

查看编译进 httpd 的模块

1
httpd -l

Apache-技巧积累
http://example.com/2023/10/11/Apache-技巧积累/
作者
Jie
发布于
2023年10月11日
许可协议