Nginx 能做的事实在太多,先遇到什么记录下什么吧。
和本博客其他很多汇总性日志一样,本文内容也会不定期更新。
泛域名配置
自动关联子域名到目录名
1 | server { |
如果 nginx 后面是 PHP,只是这样配置会出现 $_SERVER['host']
一字不差的为 ~^(?<subdomain>.+).example.com$
,因此还需要添加一个 fastcgi_param
的 SERVER_NAME
配置:
1 | location ~ [^/]\.php(/|$) { |
安全
IP 访问频率限制
1 | geo $whitelist { |
配置好后可以简单通过命令来测试结果:ab -n 5000 -c 100 http://www.example.com/
,会显示绝大部分请求均返回 503
。
注 ab是做压力测试的一种方法,如果显示没有这个命令,运行
1 | yum install httpd-tools |
配置说明:
geo
定义了白名单$whitelist
:默认值为 0;如果请求 IP 与白名单中的 IP 匹配,则$whitelist
值为 1- map 指令是将
$whitelist
值为 0 的,也就是受限制的 IP,映射为请求 IP。将$whitelist
值为 1 的,也就是白名单 IP,映射为空的字符串。 limit_conn_zone
和limit_req_zone
将忽略键值为空请求 IP,从而实现对白名单中的 IP 不限制而对其他 IP 做限制。
设置 nginx 密码认证
1 | location /path { |
IP 黑/白名单
1 | location /path { |
被 deny
掉的 IP 会得到 403
状态码。可以制定一个拒绝访问的页面:
1 | location / { |
allow
和 deny
的顺序问题
- 先
allow
部分后deny all
,表示只允许部分 IP 访问 - 先
deny all
后allow
部分,表示拒绝全部
禁止指定 IP 或 IP 段
1 | # /path/to/blacklist.ip |
限制特定目录访问
1 | localtion ~ .*(config|cache)/.*\.php$ { |
限制 UA
1 | location / { |
Rewrite 规则
别忘了限制条件
1 | if (!-e $request_filename) { |
如果不在限制条件下使用 rewrite
规则,容易造成死循环。
- HTTP 重定向到 HTTPS
1 | server { |
PHP 项目常用 rewrite 规则
- Laravel
1 | location / { |
- 禅道项目管理系统
1 | server { |
日志配置
关闭对 favicon 和 robot.txt 的日志记录
1 | location = /favicon.ico { |
只记录特定状态的访问日志
1 | http { |
With PHP
nginx
与 fastcgi/php-fpm
之间的关系
- Nginx:Web 服务器。
- FastCGI:同
cgi
一样只是一个协议,负责规范 Web 应用程序和 Web 服务器的连接,规定了传递给 PHP 等动态程序的有哪些参数以及通过什么形式传递。 - php-fpm:PHP 官方采纳并使用的,实现了
FastCGI
协议的进程管理器,负责管理和调度php-cgi
进程。
这里的「Web 应用程序」指的是 PHP 开放的应用程序,虽然我们常说 PHP 服务器后端开发,但是站在 Nginx 角度,PHP 开发的后端程序依然是应用程序的范畴。
HTTP
请求到达服务器之后,首先经过专门的 Web
服务器,然后 Web
服务器会将该请求简单处理后将按照 CGI/FastCGI
规定的标准数据格式交给 PHP-FPM
处理。
php-fpm 的安装,旧版本 PHP 中需要下载对应 PHP 版本的 php-fpm 源码以内核补丁的形式编译到 PHP 中,PHP 5.4 之后 PHP 核心已内置 php-fpm
,只需在安装的时候启用 --enable-fpm
就行了。
nginx+fpm 高并发优化思路
- 启用
opcache
(no zend guard loader) nginx
和fpm
的通信方式使用UNIX socket
替换TCP
端口
1 | fastcgi_pass 127.0.0.1:9000; |
其中,/dev/shm/php-fpm.sock
是在 php-fpm.conf
中配置的。
- 优化 Linux 内核参数
修改 /etc/sysctl.conf(_/proc/sys/net/core/_somaxconn)后使用 sysctl -p
重启:
1 | net.ipv4.tcp_max_syn_backlog = 16384 |
- 优化
php-fpm
参数
1 | listen.backlog = 8192; ; 默认为 -1(由系统决定) |
反向代理
1 | upstream service_a { |
FAQ
客户端获得 403 原因
“403” is actually an HTTP status code that means that the web server has received and understood your request, but that it cannot take any further action.
客户端访问目录而
autoindex
设置成off
。由于安全原因,目录索引默认是关闭的。打开方式:
1
2
3
4location /path {
autoindex on;
autoindex_exact_size_off;
}autoindx
必须出现在location
块中。客户端访问了只能在服务端内部访问的资源。
nginx 无需要的网站路径权限
文件要被能 nginx read
,目录要能被 nginx execute
。
- 目录索引文件未定义
以 PHP 为例,如果只定义 index index.html index.htm
则 nginx 会直接返回 403 而无论是否真实存在 index.php
。
- 索引定义的文件名大小写弄错
index
指令使大小写区分的,如果 index.php
错写成 Index.php
依然会出现 403
.
nginx 屏蔽了指定的客户端/IP
,通常通过 deny 等指令设置。
参考
How to rate-limit in nginx, but including/excluding certain IP addresses?
[How to Secure Nginx Using Fail2ban on Centos-7]](https://hostpresto.com/community/tutorials/how-to-secure-nginx-using-fail2ban-on-centos-7/)