Nginx《一》——I/O模型以及web服务介绍Nginx《二》——Nginx基础服务介绍以及编译安装、配置Nginx《三》——Nginx基础配置介绍

NginxNginx 高级配置

Nginx 状态页

基于nginx模块ngx_http_auth_basic_module实现,在编译安装nginx的时候需要添加编译参数
–withhttp_stub_status_module,否则配置完成之后监测会是提⽰语法错误。

配置⽰例:
location /nginx_status {
stub_status;
allow 192.168.0.0/16;
allow 127.0.0.1;
deny all;
}
状态⻚⽤于输出nginx的基本状态信息:
输出信息⽰例:
Active connections: 291
server accepts handled requests
16630948 16630948 31070465
上⾯三个数字分别对应accepts,handled,requests三个值
Reading: 6 Writing: 179 Waiting: 106
Active connections: 当前处于活动状态的客⼾端连接数,包括连接等待空闲连接数。
accepts:统计总值,Nginx⾃启动后已经接受的客⼾端请求的总数。
handled:统计总值,Nginx⾃启动后已经处理完成的客⼾端请求的总数,通常等于accepts,除⾮有因
worker_connections限制等被拒绝的连接。
requests:统计总值,Nginx⾃启动后客⼾端发来的总的请求数。
Reading:当前状态,正在读取客⼾端请求报⽂⾸部的连接的连接数。
Writing:当前状态,正在向客⼾端发送响应报⽂过程中的连接数。
Waiting:当前状态,正在等待客⼾端发出请求的空闲连接数,开启 keep-alive的情况下,这个值等于 active –
(reading+writing)

Nginx 第三方模块

第三模块是对nginx 的功能扩展,第三⽅模块需要在编译安装Nginx 的时候使⽤参数–add-module=PATH指定路径添加,有的模块是由公司的开发⼈员针对业务需求定制开发的,有的模块是开源爱好者开发好之后上传到github进⾏开源的模块,nginx⽀持第三⽅模块需要从源码重新编译⽀持,⽐如开源的echo模块 https://github.com/openresty/echo-nginx-module:

cd /usr/local/src/
git clone https://github.com/openresty/echo-nginx-module.git
/apps/nginx/sbin/nginx -s stop
cd /usr/local/src/nginx-1.16.1/
./configure --prefix=/apps/nginx --with-http_ssl_module --with-http_v2_module --with-http_realip_module 
--with-http_addition_module --with-http_image_filter_module --with-http_geoip_module --with-
http_gunzip_module --with-http_stub_status_module --with-http_gzip_static_module --with-pcre --with-stream
 --with-stream_ssl_module --with-stream_realip_module 
 --add-module=/usr/local/src/echo-nginx-module
 make && make install
~]# vim /apps/nginx/conf/conf.d/pc.conf
location /main {
index index.html;
default_type text/html;
echo "hello world,main-->";
echo_reset_timer;
echo_location /sub1;
echo_location /sub2;
echo "took $echo_timer_elapsed sec for total.";  #花费的总时间
}
location /sub1 {
echo_sleep 1;
echo sub1;
}
location /sub2 {
echo_sleep 1;
echo sub2;
}

nginx echo没效果 nginx writing很高_nginx echo没效果

内置变量

内置变量官网参考 内置变量用于日志记录 取值判断

$remote_addr;
#存放了客⼾端的地址,注意是客⼾端的公⽹IP,也就是⼀家⼈访问⼀个⽹站,则会显⽰为路由器的公⽹IP。
$args;
#变量中存放了URL中的指令,例如http://www.magedu.net/main/index.do?id=20190221&partner=search
中的id=20190221&partner=search
$document_root;
#保存了针对当前资源的请求的系统根⽬录,如/apps/nginx/html。
$document_uri;
#保存了当前请求中不包含指令的URI,注意是不包含请求的指令,⽐如http://www.magedu.net/main/index.do?
id=20190221&partner=search会被定义为/main/index.do
$host;
#存放了请求的host名称。
$http_user_agent;
#客⼾端浏览器的详细信息
$http_cookie;
#客⼾端的cookie信息。
limit_rate 10240;
echo $limit_rate;
#如果nginx服务器使⽤limit_rate配置了显⽰⽹络速率,则会显⽰,如果没有设置, 则显⽰0。
$remote_port;
#客⼾端请求Nginx服务器时随机打开的端⼝,这是每个客⼾端⾃⼰的端⼝。
$remote_user;
#已经经过Auth Basic Module验证的⽤⼾名。
$request_body_file;
#做反向代理时发给后端服务器的本地资源的名称。
$request_method;
#请求资源的⽅式,GET/PUT/DELETE等
$request_filename;
#当前请求的资源⽂件的路径名称,由root或alias指令与URI请求⽣成的⽂件绝对路径,
如/apps/nginx/html/main/index.html
$request_uri;
#包含请求参数的原始URI,不包含主机名,如:/main/index.do?id=20190221&partner=search 。
$scheme;
#请求的协议,如ftp,https,http等。
$server_protocol;
#保存了客⼾端请求资源使⽤的协议的版本,如HTTP/1.0,HTTP/1.1,HTTP/2.0等。
$server_addr;
#保存了服务器的IP地址。
$server_name;
#请求的服务器的主机名。
$server_port;
#请求的服务器的端⼝号。

实例操作

root@make-install:~# vim /apps/nginx/conf/conf.d/pc.conf
 location / {
    root  /data/nginx/html/pc;
#    index  index.html index.htm;
     default_type text/html;
     echo 1-->hello world;
     echo 2-->$remote_addr;
   # echo 3-->$args;
     echo 4-->$document_root;
     echo 5-->$document_uri;
     echo 6-->$host;
     echo 7-->$http_user_agent;
   # echo 8-->$http_cookie;
     echo 9-->$remote_port;
   # echo 10-->$remote_user;
   # echo 11-->$request_body_file;
     echo 12-->$request_method;
     echo 13-->$request_filename;
   # echo 14-->$request_uri;
     echo 15-->$scheme;
     echo 16-->$server_protocol;
     echo 17-->$server_addr;
     echo 18-->$server_name;
        }

访问:

root@apt-install:~# curl pc.likai.tech/
1-->hello world
2-->172.20.32.120
4-->/data/nginx/html/pc
5-->/
6-->pc.likai.tech
7-->curl/7.58.0
9-->38567
12-->GET
13-->/data/nginx/html/pc/
15-->http
16-->HTTP/1.1
17-->172.20.32.110
18-->pc.likai.tech
root@apt-install:~#

ubantu-desktop中访问

nginx echo没效果 nginx writing很高_html_02

自定义变量

假如需要⾃定义变量名称和值,使⽤指令set $variable value;,则⽅法如下:
Syntax: set $variable value; Default: — Context: server, location, if

set $name kaivi;
echo $name;
set $my_port $server_port;  #引用内置变量也可以
echo $my_port;
echo "$server_name:$server_port";

Nginx 自定义访问⽇志

访问⽇志是记录客⼾端即⽤⼾的具体请求内容信息,全局配置模块中的error_log是记录nginx服务器运⾏时的⽇志保存路径和记录⽇志的level,因此有着本质的区别,⽽且Nginx的错误⽇志⼀般只有⼀个,但是访问⽇志可以在不同server中定义多个,定义⼀个⽇志需要使⽤access_log指定⽇志的保存路径,使⽤log_format指定⽇志的格式,格式中定义要保存的具体⽇志内容。

自定义默认格式⽇志

如果是要保留⽇志的源格式,只是添加相应的⽇志内容,则配置如下:

log_format nginx_format1 '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"'
'$server_name:$server_port';

access_log logs/access.log nginx_format1;
#重启nginx并访问测试⽇志格式
==> /apps/nginx/logs/access.log <==
192.168.0.1 - - [22/Feb/2019:08:44:14 +0800] "GET /favicon.ico HTTP/1.1" 404 162 "-"
"Mozilla/5.0 (Windows NT 6.1; Win64; x64; rv:65.0) Gecko/20100101 Firefox/65.0" "-"pc.likai.tech:80

自定义json格式⽇志

log_format access_json '{"@timestamp":"$time_iso8601",' #时间戳
'"host":"$server_addr",'
'"clientip":"$remote_addr",'
'"size":$body_bytes_sent,'
'"responsetime":$request_time,'
'"upstreamtime":"$upstream_response_time",'    
'"upstreamhost":"$upstream_addr",'
'"http_host":"$host",'
'"uri":"$uri",'
'"domain":"$host",'
'"xff":"$http_x_forwarded_for",'       #负载均衡地址
'"referer":"$http_referer",'            #上一跳地址 
'"tcp_xff":"$proxy_protocol_addr",'     #Tcp的负载均衡
'"http_user_agent":"$http_user_agent",'
'"status":"$status"}';
access_log /apps/nginx/logs/access_json.log access_json;


#重启Nginx并访问测试⽇志格式
{"@timestamp":"2019-02-
22T08:55:32+08:00","host":"192.168.7.102","clientip":"192.168.0.1","size":162,"response
time":0.000,"upstreamtime":"-","upstreamhost":"-
","http_host":"www.magedu.net","uri":"/favicon.ico","domain":"www.magedu.net","xff":"-
","referer":"-","tcp_xff":"","http_user_agent":"Mozilla/5.0 (Windows NT 6.1; Win64;
x64; rv:65.0) Gecko/20100101 Firefox/65.0","status":"404"}

如何验证是否jeon格式
JSON解析

json格式的⽇志访问统计

#!/usr/bin/env python
#coding:utf-8
#Author:Zhang ShiJie
status_200= []
status_404= []
with open("access_json.log") as f:
for line in f.readlines():
line = eval(line)
if line.get("status") == "200":
status_200.append(line.get)
elif line.get("status") == "404":
status_404.append(line.get)
else:
print("状态码 ERROR")
f.close()
print "状态码200的有--:",len(status_200)
print "状态码404的有--:",len(status_404)

#保存⽇志⽂件到指定路径并进测试:
~]# python nginx_json.py
状态码200的有--: 1910
状态码404的有--: 13

Nginx 压缩功能

Nginx⽀持对指定类型的⽂件进⾏压缩然后再传输给客⼾端,⽽且压缩还可以设置压缩⽐例,压缩后的⽂件大小将⽐源⽂件显著变⼩,这样有助于降低出⼝带宽的利⽤率,降低企业的IT⽀出,不过会占⽤相应的CPU资源。
Nginx对⽂件的压缩功能是依赖于模块ngx_http_gzip_module,官⽅⽂档: https://nginx.org/en/docs/http/ngx_http_gzip_module.html, 配置指令如下:

#启⽤或禁⽤gzip压缩,默认关闭
gzip on | off;
#压缩⽐由低到⾼从1到9,默认为1
gzip_comp_level level;
#禁⽤IE6 gzip功能
gzip_disable "MSIE [1-6]\.";
#gzip压缩的最⼩⽂件,⼩于设置值的⽂件将不会压缩
gzip_min_length 1k;
#启⽤压缩功能时,协议的最⼩版本,默认HTTP/1.1
gzip_http_version 1.0 | 1.1;
#指定Nginx服务需要向服务器申请的缓存空间的个数*⼤⼩,默认32 4k|16 8k;
gzip_buffers number size;
#指明仅对哪些类型的资源执⾏压缩操作;默认为gzip_types text/html,不⽤显⽰指定,否则出错
gzip_types mime-type ...;
#如果启⽤压缩,是否在响应报⽂⾸部插⼊“Vary: Accept-Encoding”
gzip_vary on | off;
#重启nginx并进⾏访问测试压缩功能
 pc]# cp /apps/nginx/logs/access.log /data/nginx/html/pc/test.html
 pc]# echo "test1" > /data/nginx/html/pc/test1.html #⼩于1k的⽂件测试是否会压缩
 pc]# vim /apps/nginx/conf/nginx.conf
gzip on;
gzip_comp_level 5;
gzip_min_length 1k;
gzip_types text/plain application/javascript application/x-javascript
text/cssapplication/xml text/javascript application/x-httpd-php image/jpeg image/gif
image/png;
gzip_vary on;
重启Nginx并访问测试:
curl --head --compressed http://pc.likai.tech/test.html

https 功能

Web网站的登录页面都是使用https加密传输的,加密数据以保障数据的安全,HTTPS能够加密信息,以免敏感信
息被第三方获取,所以很多银行网站或电子邮箱等等安全级别较高的服务都会采用HTTPS协议,HTTPS其实是有两
部分组成:HTTP + SSL / TLS,也就是在HTTP上又加了一层处理加密信息的模块。服务端和客户端的信息传输都会
通过TLS进行加密,所以传输的数据都是加密后的数据。

nginx echo没效果 nginx writing很高_Nginx_03

https 实现过程如下:
1.客户端发起HTTPS请求:
客户端访问某个web端的https地址,一般都是443端口

2.服务端的配置:
采用https协议的服务器必须要有一套证书,可以通过一些组织申请,也可以自己制作,目前国内很多网站都自己做的,
当你访问一个网站的时候提示证书不可信任就表示证书是自己做的,证书就是一个公钥和私钥匙,就像一把锁和钥匙,正
常情况下只有你的钥匙可以打开你的锁,你可以把这个送给别人让他锁住一个箱子,里面放满了钱或秘密,别人不知道里
面放了什么而且别人也打不开,只有你的钥匙是可以打开的。

3.传送证书:
服务端给客户端传递证书,其实就是公钥,里面包含了很多信息,例如证书得到颁发机构、过期时间等等。

4.客户端解析证书:
这部分工作是有客户端完成的,首先回验证公钥的有效性,比如颁发机构、过期时间等等,如果发现异常则会弹出一个警
告框提示证书可能存在问题,如果证书没有问题就生成一个随机值,然后用证书对该随机值进行加密,就像2步骤所说把随
机值锁起来,不让别人看到。

5.传送4步骤的加密数据:
就是将用证书加密后的随机值传递给服务器,目的就是为了让服务器得到这个随机值,以后客户端和服务端的通信就可以
通过这个随机值进行加密解密了。

6.服务端解密信息:
服务端用私钥解密5步骤加密后的随机值之后,得到了客户端传过来的随机值(私钥),然后把内容通过该值进行对称加
密,对称加密就是将信息和私钥通过算法混合在一起,这样除非你知道私钥,不然是无法获取其内部的内容,而正好客户
端和服务端都知道这个私钥,所以只要机密算法够复杂就可以保证数据的安全性。

7.传输加密后的信息:
服务端将用私钥加密后的数据传递给客户端,在客户端可以被还原出原数据内容。

8.客户端解密信息:
客户端用之前生成的私钥获解密服务端传递过来的数据,由于数据一直是加密的,因此即使第三方获取到数据也无法知道
其详细内容。

ssl 配置参数

nginx 的https 功能基于模块ngx_http_ssl_module实现,因此如果是编译安装的nginx要使用参数
ngx_http_ssl_module开启ssl功能,但是作为nginx的核心功能,yum安装的nginx默认就是开启的,编译安装的
nginx需要指定编译参数–with-http_ssl_module开启,官方文档:
https://nginx.org/en/docs/http/ngx_http_ssl_module.html,配置参数如下:

ssl on | off;
#为指定的虚拟主机配置是否启用ssl功能,此功能在1.15.0废弃,使用listen [ssl]替代。

ssl_certificate /path/to/file;
#当前虚拟主机使用使用的公钥文件,一般是crt文件

ssl_certificate_key /path/to/file;
#当前虚拟主机使用的私钥文件,一般是key文件

ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];
#支持ssl协议版本,早期为ssl,现在是TSL,默认为后三个

ssl_session_cache off | none | [builtin[:size]] [shared:name:size];
#配置ssl缓存
	off: 关闭缓存
	none: 通知客户端支持ssl session cache,但实际不支持
	builtin[:size]:使用OpenSSL内建缓存,为每worker进程私有
	[shared:name:size]:在各worker之间使用一个共享的缓存,需要定义一个缓存名称和缓存空间大小,一兆
可以存储4000个会话信息,多个虚拟主机可以使用相同的缓存名称。

ssl_session_timeout time;#客户端连接可以复用ssl session cache中缓存的有效时长,默认5m

自签名 证书

#自签名CA证书
[root@s2 ~]# cd /apps/nginx/
[root@s2 nginx]# mkdir certs
[root@s2 nginx]# cd certs/
[root@s2 nginx]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout ca.key -x509 -
days 3650 -out ca.crt #自签名CA证书
Generating a 4096 bit RSA private key
.................++
.....
Country Name (2 letter code) [XX]:CN #国家代码,https://country-code.cl/
State or Province Name (full name) []:BeiJing #省份
Locality Name (eg, city) [Default City]:Beijing #城市名称
Organization Name (eg, company) [Default Company Ltd]:magedu.Ltd #公司名称
Organizational Unit Name (eg, section) []:magedu #部门
Common Name (eg, your name or your server's hostname) []:magedu.ca #通用名称
Email Address []:[root@s2 certs]# ll ca.crt
-rw-r--r-- 1 root root 2118 Feb 22 12:10 ca.crt
#自制key和csr文件
[root@s2 certs]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout
www.magedu.net.key -out www.magedu.net.csr
Generating a 4096 bit RSA private key
........................................................................++
......
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:BeiJing
Locality Name (eg, city) [Default City]:BeiJing
Organization Name (eg, company) [Default Company Ltd]:magedu.net
Organizational Unit Name (eg, section) []:magedu.net
Common Name (eg, your name or your server's hostname) []:www.magedu.net
Email Address []:
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
[root@s2 certs]# ll
total 16
-rw-r--r-- 1 root root 2118 Feb 22 12:10 ca.crt
-rw-r--r-- 1 root root 3272 Feb 22 12:10 ca.key
-rw-r--r-- 1 root root 1760 Feb 22 12:18 www.magedu.net.csr
-rw-r--r-- 1 root root 3272 Feb 22 12:18 www.magedu.net.key
#
#签发证书
[root@s2 certs]# openssl x509 -req -days 3650 -in www.magedu.net.csr -CA ca.crt -CAkey
ca.key -CAcreateserial -out www.magedu.net.crt
Signature ok
subject=/C=CN/ST=BeiJing/L=BeiJing/O=magedu.net/OU=magedu.net/CN=www.magedu.net/emailAd
dress=
Getting CA Private Key
#验证证书内容
[root@s2 certs]# openssl x509 -in www.magedu.net.crt -noout -text

只能配置到http和server中

listen 80;
listen 443 ssl;
ssl_certificate /apps/nginx/certs/www.magedu.net.crt;
ssl_certificate_key /apps/nginx/certs/www.magedu.net.key;
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
#重启Nginx并访问验证

实现多域名HTTPS

Nginx支持基于单个IP实现多域名的功能,并且还支持单IP多域名的基础之上实现HTTPS,其实是基于Nginx的SNI(Server Name Indication)功能实现,SNI是为了解决一个Nginx服务器内使用一个IP绑定多个域名和证书的功能,其具体功能是客户端在连接到服务器建立SSL链接之前先发送要访问站点的域(Hostname),这样服务器再根据这个域名返回给客户端一个合适的证书。

#制作key和csr文件
[root@s2 certs]# openssl req -newkey rsa:4096 -nodes -sha256 -keyout
mobile.magedu.net.key -out mobile.magedu.net.csr
Generating a 4096 bit RSA private key
..........
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:BeiJing
Locality Name (eg, city) [Default City]:BeiJing
Organization Name (eg, company) [Default Company Ltd]:magedu
Organizational Unit Name (eg, section) []:magedu
Common Name (eg, your name or your server's hostname) []:mobile.magedu.net
Email Address 
Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:
An optional company name []:
#签名证书
[root@s2 certs]# openssl x509 -req -days 3650 -in mobile.magedu.net.csr -CA ca.crt -
CAkey ca.key -CAcreateserial -out mobile.magedu.net.crt
Signature ok
subject=/C=CN/ST=BeiJing/L=BeiJing/O=magedu/OU=magedu/CN=mobile.magedu.net/emailAddress
Getting CA Private Key
#验证证书内容
[root@s2 certs]# openssl x509 -in mobile.magedu.net.crt -noout -text
#Nginx 配置
[root@s2 certs]# cat /apps/nginx/conf/conf.d/mobile.conf
server {
listen 443 ssl;
server_name mobile.magedu.net;
ssl_certificate /apps/nginx/certs/mobile.magedu.net.crt;  #指定公钥路径
ssl_certificate_key /apps/nginx/certs/mobile.magedu.net.key; #指定私钥路径
ssl_session_cache shared:sslcache:20m;
ssl_session_timeout 10m;
location / {
root html;
index index.html index.htm;
}
location /linux39 {
root /data/nginx/mobile/html;
index index.html index.htm;
}
location /python {
root /data/nginx/mobile/html;
index index.html index.htm;
}
}

关于favicon.ico

favicon.ico 文件是浏览器收藏网址时显示的图标,当客户端使用浏览器问页面时,浏览器会自己主动发起请求获取页面的favicon.ico文件,但是当浏览器请求的favicon.ico文件不存在时,服务器会记录404日志,而且浏览器也会显示404报错。
解决办法:

#一:服务器不记录访问日志:
#location = /favicon.ico {
#log_not_found off;
#access_log off;
#}
#二:将图标保存到指定目录访问:
#location ~ ^/favicon\.ico$ {
location = /favicon.ico {
root /data/nginx/html/pc/images;
expires 90d; #设置文件过期时间
}

安全选项

隐藏Nginx版本号

更改nginx源码信息并重新编译Nginx

# vim src/http/ngx_http_header_filter_module.c
49: static u_char ngx_http_server_string[] = "Server: linux39" CRLF;  #定义响应报文中的server字段信息

升级OpenSSL版本

心脏出血(英语:Heartbleed),也简称为心血漏洞,是一个出现在加密程序库OpenSSL的安全漏洞,该程序库广泛用于实现互联网的传输层安全(TLS)协议。它于2012年被引入了软件中,2014年4月首次向公众披露。只要使用的是存在缺陷的OpenSSL实例,无论是服务器还是客户端,都可能因此而受到攻击。此问题的原因是在实现TLS的心跳扩展时没有对输入进行适当验证(缺少边界检查),因此漏洞的名称来源于“心跳”(heartbeat)。该程序错误属于缓冲区过读,即可以读取的数据比应该允许读取的还多。
openssl-1.1.1d下载

准备OpenSSL源码包:
# pwd
/usr/local/src
# tar xvf openssl-1.1.1d
编译安装Nginx并制定新版本OpenSSL路径:
# cd /usr/local/src/nginx-1.16.1/
#./configure --prefix=/apps/nginx --user=nginx --group=nginx --with-http_ssl_module --
with-http_v2_module --with-http_realip_module --with-http_stub_status_module --withhttp_
gzip_static_module --with-pcre --with-stream --with-stream_ssl_module --withstream_
realip_module --with-select_module --with-file-aio --addmodule=/
usr/local/src/echo-nginx-module --with-openssl=/usr/local/src/openssl-1.1.1d
# make && make install
验证并启动Nginx:
# /apps/nginx/sbin/nginx -t
nginx: the configuration file /apps/nginx/conf/nginx.conf syntax is ok
nginx: configuration file /apps/nginx/conf/nginx.conf test is successful
# /apps/nginx/sbin/nginx