Nginx学习笔记

安装

下面提供两种安装方式,喜欢折腾的推荐使用第一种。
第二种比较简单方便,适合小白(我)。

源码包安装

https://nginx.org/en/download.html

1.下载源码包

1
2
3
4
# 源码包一般放在src里
wget https://nginx.org/download/nginx-1.21.3.tar.gz -P /usr/src
cd /usr/src
tar xf nginx-1.21.3.tar.gz

2.配置(检查环境依赖,安装方式,指定安装路径)

进入解压后的文件,可以--help命令看到如何指定安装目录

1
2
3
4
5
6
7
8
9
10
11
# 安装依赖(gcc编译器,url重写,解压软件)
yum -y install gcc pcre-devel zlib zlib-devel

# 配置
./configure --prefix=/usr/local/nginx

# 编译
make

# 安装
make install

使用rpm包安装

1
2
3
4
5
# centos
yum install nginx

# ubuntu
apt-get install nginx

相关目录

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
# nginx总目录
/usr/local/nginx

# nginx可执行文件
/usr/local/nginx/sbin/nginx

# nginx自身所需的模块
/usr/local/nginx/modules

# 配置文件目录
/usr/local/nginx/conf

# 配置文件
/usr/local/nginx/conf/nginx.conf

# nginx进程id号
/usr/local/nginx/logs/nginx.pid

# 日志
/usr/local/nginx/logs/error.log
/usr/local/nginx/logs/access.log

启动Nginx

1
2
3
4
/usr/local/nginx/sbin/nginx

# 在此之前可以查看80端口是否被占用
lsof -i:80

在linux系统可以用elinks来查看。

1
elinks http://192.168.10.42 --dump

杀死并重启进程

1
killall -s HUP nginx

配置

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
#启动子进程程序默认用户
#user nobody;
#一个主进程和多个工作进程。工作进程是单进程的,且不需要特殊授权即可运行;这里定义的是工作进程数量
worker_processes 1;

#全局错误日志的位置及日志格式
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;

#pid logs/nginx.pid;

events {
#每个工作进程最大的并发数
worker_connections 1024;
}

#http服务器设置
http {
#设定mime类型,类型由mime.type文件定义
include mime.types;

#
default_type application/octet-stream;

#日志格式
#log_format main '$remote_addr - $remote_user [$time_local] "$request" '
# '$status $body_bytes_sent "$http_referer" '
# '"$http_user_agent" "$http_x_forwarded_for"';
#$remote_addr与$http_x_forwarded_for用以记录客户端的ip地址;
#$remote_user:用来记录客户端用户名称;
#$time_local: 用来记录访问时间与时区;
#$request: 用来记录请求的url与http协议;
#$status: 用来记录请求状态;成功是200,
#$body_bytes_sent :记录发送给客户端文件主体内容大小;
#$http_referer:用来记录从那个页面链接访问过来的;
#$http_user_agent:记录客户浏览器的相关信息;

#全局访问日志路径
#access_log logs/access.log main;
#sendfile指令指定 nginx 是否调用sendfile 函数(zero copy 方式)来输出文件,
# 对于普通应用,必须设为on。如果用来进行下载等应用磁盘IO重负载应用,可设置为off,
# 以平衡磁盘与网络IO处理速度,降低系统uptime。
sendfile on;

#此选项允许或禁止使用socke的TCP_CORK的选项,此选项仅在使用sendfile的时候使用
#tcp_nopush on;

#长连接超时时间
#keepalive_timeout 0;
keepalive_timeout 65;

#开启压缩
#gzip on;

#配置虚拟主机
server {
#虚拟主机使用的端口
listen 80;
#虚拟主机域名
server_name localhost;

#虚拟主机支持的字符集
#charset koi8-r;

#虚拟主机的访问日志路径
#access_log logs/host.access.log main;

#定义web根路径
location / {
#根目录路径
root html;
#索引页
index index.html index.htm;
}

#error_page 404 /404.html;

# redirect server error pages to the static page /50x.html
#

#根据错误码 返回对应的页面
error_page 500 502 503 504 /50x.html;

#定义页面路径
location = /50x.html {
root html;
}

#定义反向代理服务器 数据服务器是lamp模型
# proxy the PHP scripts to Apache listening on 127.0.0.1:80
#
#location ~ \.php$ {
# proxy_pass http://127.0.0.1;
#}

#定义PHP为本机服务的模型
# pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
#
#location ~ \.php$ {
# root html;
# fastcgi_pass 127.0.0.1:9000;
# fastcgi_index index.php;
# fastcgi_param SCRIPT_FILENAME /scripts$fastcgi_script_name;
# include fastcgi_params;
#}

# deny access to .htaccess files, if Apache's document root
# concurs with nginx's one
#
#拒绝apache DR目录及子目录下的.htaccess文件访问
#location ~ /\.ht {
# deny all;
#}
}

# another virtual host using mix of IP-, name-, and port-based configuration
#
#server {
# listen 8000;
# listen somename:8080;
# server_name somename alias another.alias;

# location / {
# root html;
# index index.html index.htm;
# }
#}

#https的配置方案
# HTTPS server
#
#server {
# listen 443 ssl;
# server_name localhost;

# ssl_certificate cert.pem;
# ssl_certificate_key cert.key;

# ssl_session_cache shared:SSL:1m;
# ssl_session_timeout 5m;

# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

# location / {
# root html;
# index index.html index.htm;
# }
#}

}

默认网站概念

当Nginx配置文件中有且只有一个Server的时候,该Server就被Nginx认为是默认网站,所有发给Nginx服务器80端口的数据都会默认给该Server。

1
2
3
4
5
6
7
8
9
10
server {
listen 80;
server_name localhost; location / {
root html;
index index.html index.htm;}
error_page 500 502 503 504 /50x.html; location = /50x.html
{
root html;
}
}

Nginx目录访问控制

1
2
3
4
5
6
7
cd html/
mkdir a
mkdir b
mkdir c
echo aaa > a/index.html
echo bbb > b/index.html
echo ccc > c/index.html

访问一下试试http://ip/a

限制ip访问

如果想控制访问,只允许本机访问a

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
server_name localhost; location / {
root html;
index index.html index.htm;
}
# 添加这里
location /a {
allow 127.0.0.1; # 允许本机访问
deny all; # 拒绝所有
return 404; # 返回404代码
}
error_page 500 502 503 504 /50x.html; location = /50x.html
{
root html;
}
}

return 后也可以跟一个网页:

1
return http://www.jd.com;

密码登陆验证

访问b时,需要密码验证

auth_basic: 参数可以是字符,显示在对话框标题。也可以是on|off

auth_basic_user_file: 账号密码的文件

1
2
3
4
location /b {
auth_basic "凌云登陆验证";
auth_basic_user_file /etc/nginx/htpasswd;
}

先安装一个包,用于生成密码

1
2
3
4
5
6
# 安装
yum install httpd-tools

# 生成(如果没有这个文件则可以用 -c 参数)
# 这里创建一个sky用户,根据提示输入密码
htpasswd -m /etc/nginx/htpasswd sky

日志管理

Nginx访问⽇日志主要有两个参数控制:

  • log_format 用来定义记录日志的格式(可以定义多种⽇志格式,取不同名字即可)

    log_format log_name string

  • access_log 用来指定日志⽂件的路径,及使⽤的哪种日志格式记录日志

    access_log logs/access.log main;

log_format格式变量:

1
2
3
4
5
6
7
8
9
$remote_addr #记录访问⽹网站的客户端地址
$remote_user #远程客户端⽤用户名
$time_local #记录访问时间与时区
$request #⽤用户的http请求起始⾏行行信息
$status #http状态码,记录请求返回的状态码,例例如:200、301、404等
$body_bytes_sent #服务器器发送给客户端的响应body字节数
$http_referer #记录此次请求是从哪个连接访问过来的,可以根据该参数进⾏行行防盗链设置。
$http_user_agent #记录客户端访问信息,例例如:浏览器器、⼿手机客户端等
$http_x_forwarded_for #当前端有代理理服务器器时,设置web节点记录客户端地址的配置,此参数⽣生效的前提是代理理服务器器也要进⾏行行相关的x_forwarded_for设置

举个例子,自定义一个log文件与格式:

1
2
log_format lingyun '[$remote_local] $remote_addr "request" $status';
access_log logs/lingyun.log lingyun;

防盗链

如何判断盗链?开发者工具可以看到多出的referer字段。

1
2
3
4
5
6
7
8
location /c {
# 这里限制了三种情况是允许访问/c的
# referer字段为空,满足防火墙策略,匹配到对应域名
valid_referers none blocked *.ayitula.com;
if ($invalid_referer) {
return 403;
}
}

可以根据格式来使用宽泛匹配

1
2
3
location ~* \.(png|gif|bmp)$ {
....
}

虚拟主机

一个web服务器软件发布多个web。

基于IP

缺点:需要多个IP,公网IP是要付费的。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 192.168.10.42:80;
location / {
root html/web1;
index index.html index.htm index.php;
}
}

server {
listen 192.168.10.52:80;
location / {
root html/web2;
index index.html index.htm index.php;
}
}

基于端口

缺点:无法将端口告诉公网用户。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
server {
listen 80;
location / {
root html/web1;
index index.html index.htm index.php;
}
}

server {
listen 8080;
location / {
root html/web1;
index index.html index.htm index.php;
}
}

基于域名

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 80;
server_name www.cbd.com;
location / {
root html/web1;
index index.html index.htm index.php;
}
}

server {
listen 8080;
server_name www.abc.com;
location / {
root html/web1;
index index.html index.htm index.php;
}
}

反向代理服务器

配置解释:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
location / {
index index.php index.html index.htm; # 定义⾸首⻚页索引⽂文件的名称
proxy_pass http://mysvr ;# 请求转向mysvr 定义的服务器器列列表
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
client_max_body_size 10m; # 允许客户端请求的最⼤大单⽂文件字节数
client_body_buffer_size 128k; #缓冲区代理理缓冲⽤用户端请求的最⼤大字节数
proxy_connect_timeout 90; # nginx跟后端服务器器连接超时时间(代理理连接超时)
proxy_send_timeout 90; # 后端服务器器数据回传时间(代理理发送超时)
proxy_read_timeout 90; # 连接成功后,后端服务器器响应时间(代理理接收超时)
proxy_buffer_size 4k; # 设置代理理服务器器(nginx)保存⽤用户头信息的缓冲区⼤大⼩小
proxy_buffers 4 32k; # proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_busy_buffers_size 64k; #⾼高负荷下缓冲⼤大⼩小(proxy_buffers*2)
proxy_temp_file_write_size 64k; #设定缓存⽂文件夹⼤大⼩小,⼤大于这个值,将从upstream服务器器传
}

限速

  • 限速该特性可以限制某个用户在⼀个给定时间段内能够产生的HTTP请求数。请求可以简单到就是⼀个对于主页的GET请求或者⼀个登陆表格的POST请求。
  • 限速也可以用于安全目的上,比如暴力密码破解攻击。通过限制进来的请求速率,并且(结合日志)标记出目标URLs来帮助防范DDoS攻击。⼀般地说,限流是用在保护上游应用服务器不被在同⼀时刻的大量用户请求淹没。

Nginx官⽅版本限制IP的连接和并发分别有两个模块:
limit_req_zone ⽤来限制单位时间内的请求数,即速率限制。
limit_req_conn ⽤来限制同⼀时间连接数,即并发限制。

案例一

基于IP对下载速率做限制 限制每秒处理1次请求,对突发超过5个以后的请求放⼊缓存区。

1
2
3
4
5
6
7
http {
limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s;
server {
location /search/ {
limit_req zone=baism burst=5 nodelay;
}
}

limit_req_zone $binary_remote_addr zone=baism:10m rate=1r/s;
第⼀个参数:$binary_remote_addr 表示通过remote_addr这个标识来做限制,
“binary_”的⽬的是缩写内存占⽤量,是限制同⼀客户端ip地址。
第⼆个参数:zone=baism:10m表示⽣成⼀个大小为10M,名字为one的内存区域,用来存储访问的频次信息。
第三个参数:rate=1r/s表示允许相同标识的客户端的访问频次,这里限制的是每秒1次,还可以有比如30r/m的。

limit_req zone=baism burst=5 nodelay;
第⼀个参数:zone=baism 设置使⽤哪个配置区域来做限制,与上⾯limit_req_zone ⾥的name对应。
第⼆个参数:burst=5,重点说明⼀下这个配置,burst爆发的意思,这个配置的意思是设置⼀个大小为5的缓冲区当有⼤量请求(爆发)过来时,超过了访问频次限制的请求可以先放到这个缓冲区内。
第三个参数:nodelay,如果设置,超过访问频次而且缓冲区也满了的时候就会直接返回503,如果没有设置,则所有请求会等待排队。

案例二

基于IP做连接限制,限制同⼀IP并发为1 下载速度为100K。

(弊端是别人可以用多次请求来进行并发下载)

1
2
3
4
5
6
7
8
9
10
11
12
13
limit_conn_zone $binary_remote_addr zone=addr:10m;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /abc {
limit_conn addr 1;
limit_rate 100k;
}
}

综合案例

限制并发的连接数 + 下载速率。

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
http {
include mime.types;
default_type application/octet-stream;
sendfile on;
keepalive_timeout 65;
# 基于IP做连接限制 限制同⼀IP并发为1 下载速度为100K
limit_conn_zone $binary_remote_addr zone=addr:10m;
# 基于IP对下载速率做限制 限制每秒处理1次请求,对突发超过5个以后的请求放⼊缓存区
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;
server {
listen 80;
server_name localhost;
location / {
root html;
index index.html index.htm;
}
location /abc {
limit_req zone=one burst=5 nodelay;
limit_conn addr 1;
limit_rate 100k;
}
}

URL重写

主要使用rewrite模块(ngx_http_rewrite_module

  • Rewrite功功能是Nginx服务器提供的⼀个重要功能。几乎是所有的web产品必备技能,用于实现URL重写。URL重写是非常有用的功能,比如它可以在我们在改变网站结构后,不需要客户端修改原来的书签,也不需要其他网站修改对我们网站的友情链接,还可以在⼀定程度上提高网站的安全性。
  • Nginx服务器Rewrite功能的实现是依赖于PCRE(Perl Compatible Regular Expression。Perl兼容的正则表达式)的支持,所以在编译安装Nginx之前,需要安装PCRE库。

URL模块语法

1
2
3
4
5
6
7
8
set 设置变量
if 负责语句的判断
retuen 返回返回值或URL
break 终止后续的rewrite规则
rewrite 重定向URL

模糊匹配 ~匹配 !~模糊匹配 ~*不区分大小写的匹配
精确匹配 = !=

例子1:使用变量将http://www.lingyunfx.com 重写为 http://www.lingyunfx.com/abc

1
2
3
4
location / {
set $name abc;
rewrite ^(.*)$ http://www.lingyunfx.com/$name;
}

例子2:使用判断不允许谷歌浏览器访问

1
2
3
4
5
location / {
if ($http_user_agent ~* 'chrome') {
return 403;
}
}

URL rewrite语法

1
2
3
4
5
6
7
8
rewrite <regex> <replacement> [flag];
关键字 正则 替代内容 flag标记

flag有:
last 本条规则匹配完成后,继续向下匹配新的location URL规则
break 本条规则匹配完成即终⽌,不再匹配后⾯的任何规则
redirect 返回302临时重定向
permanent 返回301永久重定向

例子1:将http://www.lingyunfx.com 重定向为http://www.jd.com

1
2
3
4
5
6
7
server {
listen 80;
server_name www.lingyunfx.com;
location / {
rewrite ^/$ http://www.jd.com permanent ;
}
}

例子2:

判断如果是chrome浏览器,就将 http://www.lingyunfx.com/aaa重写为http://www.lingyunfx.com/chrome/aaa

1
2
3
4
5
6
7
8
9
10
location / {
.....
if ($http_user_agent ~* 'chrome'){
rewrite ^(.*)$ /chrome/$1 last;
}
location /chrome {
root html;
index index.html;
}
}