nginx

一.nginx概述

nginx是一款开源的http,web应用服务器,其功能模块化,高性能高可靠。

特性:
功能模块少:源代码仅保留http与核心模块代码,其余不够核心代码会作为插件来安装
代码模块化:易读,便于二次开发
优势:
适合当前主流架构趋势,微服务,云架构,中间层
统一技术栈,降低维护成本,降低技术成本更新成本

Nginx特点是占有内存少,并发能力强,事实上nginx的并发能力确实在同类型的网页服务器中表现较好。

Nginx由内核和模块组成,其中,内核的设计非常微小和简洁,完成的工作也非常简单,仅仅通过查找配置文件将客户端请求映射到一个location block(location是Nginx配置中的一个指令,用于URL匹配),而在这个location中所配置的每个指令将会启动不同的模块去完成相应的工作。

Nginx相对于Apache优点:

  1. 高并发响应性能非常好,官方Nginx处理静态文件并发5w/s
  2. 反向代理性能非常强。(可用于负载均衡)
  3. 内存和cpu占用率低。(为Apache的1/5-1/10)
  4. 对后端服务有健康检查功能。
  5. 支持PHP cgi方式和fastcgi方式。
  6. 配置代码简洁且容易上手。
  7. nginx采用epoll模型(异步非阻塞),而apache采用select模型。
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
selectepoll模型的区别
select:当用户发起一次请求,select模型就会进行一次遍历扫描,从而导致性能低下
epoll:当用户发起请求,epoll模型会直接进行处理,效率高效,并无连接限制。

selectepoll对比

select
随着连接数增加,急剧下降。处理成千上万并发连接数时,性能很差。
连接数有限制,处理的最大连接数不超过1024。如果要处理超过1024个连接数,则需要修改FD_SETSIZE宏,并重新编译 。
线性轮询
开发复杂性低
epoll
随着连接数增加,性能基本上没有下降。处理成千上万并发连接时,性能很好。
连接数无限制。
回调callback
开发复杂性中

nginx应用场景:

静态服务:
浏览器缓存,防资源盗用,资源分类,资源压缩,资源缓存,跨域访问
代理服务:
协议类型,正向代理,反向代理,负载均衡,代理缓存,动静分离
安全服务:
访问控制,访问限制,流量限制,拦截共计,拦截异常请求,拦截sql注入
流行框架
nginx+php,nginx+java ,nginx+python

二.nginx安装

http://nginx.org/en/download.html #nginx官网地址

nginx一般有两种安装方式:

源码安装和rpm安装:

rpm安装:

epel源:版本低,功能少
官方源:官方编译好的,封装成rpm包,提供yum源 版本新

yum安装

官方源:

1
sudo yum install yum-utils

To set up the yum repository, create the file named /etc/yum.repos.d/nginx.repo with the following contents:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
[nginx-stable]
name=nginx stable repo
baseurl=http://nginx.org/packages/centos/$releasever/$basearch/
gpgcheck=1
enabled=1
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

[nginx-mainline]
name=nginx mainline repo
baseurl=http://nginx.org/packages/mainline/centos/$releasever/$basearch/
gpgcheck=1
enabled=0
gpgkey=https://nginx.org/keys/nginx_signing.key
module_hotfixes=true

By default, the repository for stable nginx packages is used. If you would like to use mainline nginx packages, run the following command:

1
sudo yum-config-manager --enable nginx-mainline

To install nginx, run the following command:

1
sudo yum install nginx

When prompted to accept the GPG key, verify that the fingerprint matches 573B FD6B 3D8F BC64 1079 A6AB ABF5 BD82 7BD9 BF62, and if so, accept it.

上面的为最新包的安装,下面的为稳定版的安装,文档内容截自官方文档,如为其他系统则参考官方文档 :http://nginx.org/en/linux_packages.html#RHEL-CentOS

epel源:

1
2
3
4
5
yum -y install epel-release.noarch  ```#首先安装epel源,如已有则跳过,如还没有yum源则先把yum源配置好
yum makecache #加载epel源
yum -y install nginx #安装nginx
安装完成以后
nginx -V 查看nginx安装配置以及版本

源码安装:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
wget http://nginx.org/download/nginx-1.19.6.tar.gz #下载nginx

useradd -s /sbin/nologin -M nginx #添加nginx用户

tar -xvf nginx-1.19.6.tar.gz && cd nginx-1.19.6/

yum install -y gcc gcc-c++ make libtool zlib zlib-devel openssl openssl-devel pcre pcre-devel #解决依赖

./configure --prefix=/usr/local/nginx --user=nginx --group=nginx --with-file-aio --with-ipv6 --with-http_ssl_module --with-http_v2_module --with-http_realip_module --with-http_addition_module --with-http_xslt_module=dynamic --with-http_image_filter_module=dynamic --with-http_sub_module --with-http_dav_module --with-http_flv_module --with-http_mp4_module --with-http_gunzip_module --with-http_gzip_static_module --with-http_random_index_module --with-http_secure_link_module --with-http_degradation_module --with-http_slice_module --with-http_stub_status_module --with-http_perl_module=dynamic --with-http_auth_request_module --with-mail=dynamic --with-mail_ssl_module --with-pcre --with-pcre-jit --with-stream=dynamic --with-stream_ssl_module --with-debug


make && make install #编译

ll /usr/local/nginx/ #查看nginx

源码安装的好处在于其所有nginx相关文件都可以放在一起,方便数据迁移。相比于yum麻烦的是:

源码安装完成以后linux环境变量没有nginx路径,需要配置(才能直接在命令行找到命令)

systemd不会自动生成nginx启动文件(无法通过systemctl直接启动关闭nginx)

所以这两个都需要手动进行生成

systemd:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
cat > /etc/systemd/system/nginx.service << EOF
[Unit]
Description=The nginx HTTP and reverse proxy server
After=network.target remote-fs.target nss-lookup.target[Service]
Type=forking
PIDFile=/usr/local/nginx/logs/nginx.pid
# Nginx will fail to start if /run/nginx.pid already exists but has the wrong
# SELinux context. This might happen when running `nginx -t` from the cmdline.
# https://bugzilla.redhat.com/show_bug.cgi?id=1268621
ExecStartPre=/usr/bin/rm -f $PIDFile
ExecStartPre=/usr/local/nginx/sbin/nginx -t
ExecStart=/usr/local/nginx/sbin/nginx
ExecReload=/bin/kill -s HUP PIDFileExecStartPre=/usr/local/nginx/sbin/nginx−tExecStart=/usr/local/nginx/sbin/nginxExecReload=/bin/kill−sHUP$MAINPID
KillSignal=SIGQUIT
TimeoutStopSec=5
KillMode=mixed
PrivateTmp=true[Install]
WantedBy=multi-user.target
EOF

将systemd文件写入以后可以使用systemctl start nginx测试一下

加入环境变量

1
2
3
4
5
cat > /etc/profile.d/nginx.sh << EOF
export PATH=/usr/local/nginx/sbin:$PATH
EOF
source /etc/profile.d/nginx.sh #生效到当前环境变量
nginx -V #使用命令测试一下

三. nginx配置文件

nginx配置文件:
主配置文件:
/etc/nginx
/etc/nginx/nginx.conf
/etc/nginx/conf.d/*
cgi,fastcgi,uwcgi配置文件
/etc/nginx/fastcgi_params
/etc/nginx/scgi_params
/etc/nginx/uwsgi_params
编码转换映射文件
/etc/nginx/win-utf
/etc/nginx/koi-utf
/etc/nginx/koi-win
http协议的conten-type与扩展名
/etc/nginx/mime.types
systemd:
/usr/lib/systemd/system/nginx.service
nginx日志轮询,日志切割
/etc/logrotate.d/nginx
模块目录
/etc/nginx/modules
/usr/lib64/nginx
/usr/lib64/nginx/modules
默认站点目录
/usr/share/nginx
/usr/share/nginx/html/*.html
logs:
/var/log/nginx
缓存:
/var/cache/nginx

默认使用rpm包的nginx相关配置文件如上,如果是源码安装的如果没特别指定路径一般在编译安装prefix指定的nginx根目录下,也有些文件夹不会自动生成可以手动生成。比较重要的配置文件有

conf/nginx.conf:这个是nginx的根配置文件

html站点目录:这个是网站文件夹的路径(也可以不用默认的路径)

nginx.logs:nginx日志生成目录

nginx.conf

nginx配置文件格式一般为:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
...   # 全局配置段,例如nginx日志文件路径,pid文件路径,nginx用户,进程信息在这里配置
events{

... #事件驱动配置端,可定义nginx的事件驱动模型,最大连接数等信息
}

http {

... #http定义一个http服务的相关配置,一般下面会包含多个server,一个server又会包含多个location
server{

... #server定义的是一个虚拟主机的信息,下面可能会有多个location
location {

.. #location定义的是虚拟主机,location 指令的功能是用来匹配不同的 URI 请求,进而对请求做不同的处理和响应。例如一个网站的/根目录会匹配到服务器主机的哪个文件目录,就是在这里定义的
}

}

} #一个配置段由{ 开始 } 结尾, ...表示省略的具体配置信息

完整配置文件以及常用到的一些配置:

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
#定义Nginx运行的用户和用户组
user www www;
#启动进程,通常设置成和cpu的数量相等
worker_processes 8;
worker_cpu_affinity 00000001 00000010 00000100 00001000 00010000 00100000 01000000 10000000;
#为每个进程分配cpu,上例中将8个进程分配到8个cpu,当然可以写多个,或者将一个进程分配到多个cpu。
worker_rlimit_nofile 102400;
#这个指令是指当一个nginx进程打开的最多文件描述符数目,理论值应该是最多打
#开文件数(ulimit -n)与nginx进程数相除,但是nginx分配请求并不是那么均匀
#,所以最好与ulimit -n的值保持一致。
#全局错误日志及PID文件
error_log /usr/local/nginx/logs/error.log;
#错误日志定义等级,[ debug | info | notice | warn | error | crit ]
pid /usr/local/nginx/nginx.pid;
#一个nginx进程打开的最多文件描述符数目,理论值应该是最多打开文件数(系统的值ulimit -n)与nginx进程数相除,但是nginx分配请求并不均匀.
#所以建议与ulimit -n的值保持一致。
worker_rlimit_nofile 65535;
#工作模式及连接数上限
events {
use epoll; #epoll是多路复用IO(I/O Multiplexing)中的一种方式,但是仅用于linux2.6以上内核,可以大大提高nginx的性能
worker_connections 102400; #单个后台worker process进程的最大并发链接数 (最大连接数=连接数*进程数)
multi_accept on; #尽可能多的接受请求
}
#设定http服务器,利用它的反向代理功能提供负载均衡支持
http {
#设定mime类型,类型由mime.type文件定义
include mime.types;
default_type application/octet-stream;
#设定日志格式
access_log /usr/local/nginx/log/nginx/access.log;
sendfile on;
#sendfile 指令指定 nginx 是否调用 sendfile 函数(zero copy 方式)来输出文件,对于普通应用必须设为 on
#如果用来进行下载等应用磁盘IO重负载应用,可设置为 off,以平衡磁盘与网络I/O处理速度,降低系统的uptime.
#autoindex on; #开启目录列表访问,合适下载服务器,默认关闭。
tcp_nopush on; #防止网络阻塞
keepalive_timeout 60;
#keepalive超时时间,客户端到服务器端的连接持续有效时间,当出现对服务器的后,继请求时,keepalive-timeout功能可避免建立或重新建立连接。
tcp_nodelay on; #提高数据的实时响应性
#开启gzip压缩
gzip on;
gzip_min_length 1k;
gzip_buffers 4 16k;
gzip_http_version 1.1;
gzip_comp_level 4; #压缩级别大小,最大为9,值越小,压缩后比例越小,CPU处理更快。
#值越大,消耗CPU比较高。
gzip_types text/plain application/x-javascript text/css application/xml;
gzip_vary on;
client_max_body_size 10m; #允许客户端请求的最大单文件字节数
client_body_buffer_size 128k; #缓冲区代理缓冲用户端请求的最大字节数,
proxy_connect_timeout 120; #nginx跟后端服务器连接超时时间(代理连接超时)
proxy_send_timeout 120; #后端服务器数据回传时间(代理发送超时)
proxy_read_timeout 120; #连接成功后,后端服务器响应时间(代理接收超时)
proxy_buffer_size 4k; #设置代理服务器(nginx)保存用户头信息的缓冲区大小
proxy_buffers 4 32k; #proxy_buffers缓冲区,网页平均在32k以下的话,这样设置
proxy_busy_buffers_size 64k; #高负荷下缓冲大小(proxy_buffers*2)

#设定请求缓冲
large_client_header_buffers 4 4k;
client_header_buffer_size 4k;
#客户端请求头部的缓冲区大小,这个可以根据你的系统分页大小来设置,一般一个请求的头部大小不会超过1k
#不过由于一般系统分页都要大于1k,所以这里设置为分页大小。分页大小可以用命令getconf PAGESIZE取得。
open_file_cache max=102400 inactive=20s;
#这个将为打开文件指定缓存,默认是没有启用的,max指定缓存数量,建议和打开文件数一致,inactive是指经过多长时间文件没被请求后删除缓存。
open_file_cache_valid 30s;
#这个是指多长时间检查一次缓存的有效信息。
open_file_cache_min_uses 1;
#open_file_cache指令中的inactive参数时间内文件的最少使用次数,如果超过这个数字,文件描述符一直是在缓存中打开的,如上例,如果有一个文件在inactive
#包含其它配置文件,如自定义的虚拟主机
#include vhosts.conf;
#这里为后端服务器wugk应用集群配置,根据后端实际情况修改即可,tdt_wugk为负载均衡名称,可以任意指定
#但必须跟vhosts.conf虚拟主机的pass段一致,否则不能转发后端的请求。weight配置权重,在fail_timeout内检查max_fails次数,失败则剔除均衡。
upstream tdt_wugk {
server 127.0.0.1:8080 weight=1 max_fails=2 fail_timeout=30s;
server 127.0.0.1:8081 weight=1 max_fails=2 fail_timeout=30s;
}
#虚拟主机配置
server {
#侦听80端口
listen 80;
#定义使用www.wuguangke.cn访问
server_name www.wuguangke.cn;
#设定本虚拟主机的访问日志
access_log logs/access.log main;
root /data/webapps/wugk; #定义服务器的默认网站根目录位置
index index.php index.html index.htm; #定义首页索引文件的名称
#默认请求
location ~ /{
root /data/www/wugk; #定义服务器的默认网站根目录位置
index index.php index.html index.htm; #定义首页索引文件的名称
#以下是一些反向代理的配置.
proxy_next_upstream http_502 http_504 error timeout invalid_header;
#如果后端的服务器返回502、504、执行超时等错误,自动将请求转发到upstream负载均衡池中的另一台服务器,实现故障转移。
proxy_redirect off;
#后端的Web服务器可以通过X-Forwarded-For获取用户真实IP
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_pass http://tdt_wugk; #请求转向后端定义的均衡模块
}
#配置Nginx动静分离,定义的静态页面直接从Nginx发布目录读取。
location ~ .*\.(html|htm|gif|jpg|jpeg|bmp|png|ico|txt|js|css)$
{
root /data/www/wugk;
#expires定义用户浏览器缓存的时间为3天,如果静态页面不常更新,可以设置更长,这样可以节省带宽和缓解服务器的压力。
expires 30d;
}
#PHP脚本请求全部转发到 FastCGI处理. 使用FastCGI默认配置.
location ~ \.php$ {
root /root;
fastcgi_pass 127.0.0.1:9000;
fastcgi_index index.php;
fastcgi_param SCRIPT_FILENAME /data/www/wugk$fastcgi_script_name;
include fastcgi_params;
}
#设定查看Nginx状态的地址
location /NginxStatus {
stub_status on;
}
}
}

四.nginx常用命令

nginx -v #查看版本号

nginx -V #查看版本号以及安装时安装的模块

nginx -s reload | stop 重新载入配置文件|停止nginx

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

nginx 直接输入命令表示启动nginx进程

五.nginx常用模块功能

1.nginx目录索引

目录索引模块:ngx_http_autoindex_module

默认:编译进内核

编译参数:--without-http_autoindex_module

1
2
3
4
5
6
7
8
9
10
autoindex on;
加在对应location里面即可实现目录索引浏览(autoindex也可加在http,server里面,但一般不这么用)Syntax:autoindex on|off;
default: autoindex off;
context: http server location常用参数
autoindex_exact_size off;
默认为on,显示出文件的确切大小,单位为bytes
off,显示文件的大概大小,单位为kb or MB or GBautoindex_localtime on;
默认为off,显示的文件时间为GMT时间
默认为on,显示的文件时间为文件的服务器时间charset utf-8,gbk;
默认中文目录乱码,添加防止乱码。

示例:

image.png

nginx -s reload #重载配置文件

访问:

image.png

2.nginx状态监控

状态监控模块:ngx_http_stub_status_module

默认:不编译进内核

编译参数:--with-http_stub_status_module

配置实例

1
2
3
4
5
location = /status {
stub_status;
access_log off;
}
#启动状态时可关闭日志。

访问:

image.png

因安全缘由,建议status状态页面仅内网开放访问或限制访问ip访问认证限制。

3.nginx访问控制

基于IP的访问控制模块: http_access_module 默认:编译进内核 编译参数:--without-http_access_module
基于用户登录认证模块: http_auth_basic_module 默认:编译进内核 编译参数:--without-http_auth_basic_module

IP:

1
2
3
4
5
6
7
8
允许:
syntax: allow address |CIDR |unix: |all;
Default:-
context: httpx server,location,limit_except
拒绝:
syntax: deny address |CIDR |unix: |all;
context: http, server, location, limit_except
default: -

示例

image.png

本机访问(本机ip为10.10.10.214)

image.png

已被拒绝,其他同网端服务器访问没问题。

image.png

登录认证访问:

1
2
3
4
5
6
7
8
9
10
//配置语法
syntax: auth_basic string|off;
default: auth_basic off;
Context:
http, server, location,limit_except
//用户密码记录配置文件
syntax: auth_basic_user_file file;
Default: -
Context:
http, server, location,limit_except

yum -y install httpd-tools (安装http工具包)
htpasswd -b -c /x/x/x admin 123456

前面是用户后面是密码,生产用户密码文件

示例:

image.png

image.png

image.png

4.访问限制

经常会遇到这种情况,服务器流量异常,负载过大等等。对于大流量恶意的攻击访问,会带来带宽的浪费,服务器压力,影响业务,往往考虑对同一个IP的连接数,并发数进行限制。

限制连接数:ngx_http_limit_req_module

限制请求频率:ngx_http_limit_conn_module

默认:编译进内核

编译参数:--without-http_limit_conn_module

1
--without-http_limit_req_module

limit_req_zone 用来限制单位时间内的请求数,即速率限制,采用的漏桶算法 “leaky bucket”

limit_conn_zone 用来限制同一时间连接数,即并发限制

limit_conn_zone:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
句法:	limit_conn_zone key zone=name:size;
默认: —
内容: http
Syntax: limit_conn zone number
Default: —
Context: http,server, location
可能有几个`limit_conn`指令。例如,以下配置将限制每个客户端IP与服务器的连接数,并同时限制与虚拟服务器的连接总数:
limit_conn_zone $binary_remote_addr zone=addr:10m;

server {
location /download/ {
limit_conn addr 1;#一次每个IP地址只允许一个连接。
}
limit_conn_zone $binary_remote_addr zone=perip:10m;
limit_conn_zone $server_name zone=perserver:10m;

server {
...
limit_conn perip 10;
limit_conn perserver 100;
}

当且仅当limit_conn当前级别上未定义任何指令时,这些指令才从先前的配置级别继承。

1
2
3
4
句法:	limit_conn_dry_run on | off;
默认:
limit_conn_dry_run off;
内容: http,serverlocation

启用空运行模式。在这种模式下,连接数不受限制,但是,在共享内存区域中,过多连接的数将照常计算。

1
2
3
4
句法:	limit_conn_log_level info | notice | warn | error;
默认:
limit_conn_log_level error;
内容: http,serverlocation

为服务器限制连接数的情况设置所需的日志记录级别。

1
2
3
4
句法:	limit_conn_status code;
默认:
limit_conn_status 503;
内容: http,server,location

设置状态代码以响应被拒绝的请求而返回。

limit_req_zone:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
句法:	limit_req_zone key zone=name:size rate=rate [sync];
默认: —
内容: http

Sntax: limit_req zone=name [burst=number] [nodelay | delay=number];
Default: —
Context: http, server, location
http {
limit_req_zone $binary_remote_addr zone=one:10m rate=1r/s;

...

server {

...

location /search/ {
limit_req zone=one burst=5;
}

http{
//http段配置请求限制,rate限制速率,限制一秒钟最多一个IP请求
limit_req_zone $binary_remote_addr zone=req_zone:10m rate=1r/s;

server {

location / {
//1r/s只接收一个请求,其余请求拒绝处理并返回错误码给客户端..
limit_req zone=req_zone;
//请求超过1r/s,剩下的将被延迟处理,请求数超过burst定义的数量,多余的请求返回503
#limit_req zone=req_zone burst=3 nodelay;
}
}}
rate=1r/s表示每秒最大一个请求,burst=3表示请求队列最大为3

1
2
3
4
句法:	limit_req_dry_run on | off;
默认:
limit_req_dry_run off;
内容: http,serverlocation

启用空运行模式。在这种模式下,请求处理速率不受限制,但是,在共享内存区域中,过多请求的数量将照常计算。

1
2
3
4
句法:	limit_req_log_level info | notice | warn | error;
默认:
limit_req_log_level error;
内容: http,serverlocation

在服务器由于速率超出而拒绝处理请求或延迟请求处理的情况下,设置所需的日志记录级别。延迟的记录级别比拒绝的记录级别少1分;例如,如果limit_req_log_level notice指定“ ” ,则将延迟记录为该info级别。

1
2
3
4
句法:	limit_req_status code;
默认:
limit_req_status 503;
内容: http,server,location

设置状态代码以响应被拒绝的请求而返回。

1
2
3
4
5
$server_name 表示服务器的变量
$binary_remote_addr 变量长度是固定的4字节
$remote_addr 变量长度是7-15字节
一个IP地址=32bit=4字节,所以一般用第一个变量即可
两个都是代表IP地址的变量,区别在于变量存储长度(也可直接换成某个IP地址,但是限制一般针对所有IP地址,而非一个ip地址,所以使用变量)

5.日志模块

日志模块:

默认:编译进内核(在官方文档的编译模块中,没有日志模块的编译或不编译进内核的选项)

1
2
3
4
5
6
7
8
9
10
Syntax:	log_format name [escape=default|json|none] string ...;
Default:
log_format combined "...";
Context: http

Syntax: access_log path [format [buffer=size] [gzip[=level]] [flush=time] [if=condition]];
access_log off;
Default:
access_log logs/access.log combined;
Context: http, server, location, if in location, limit_except

配置示例:

1
2
3
4
5
   log_format  main  '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';

access_log logs/access.log main;

log_format是定义的日志格式,access_log是存放的位置。main为日志的名称,下面通过这个main来进行调用

log_format 后面首先定义日志名称,然后’’中间代表日志显示格式,调用的是nginx变量,例如$remote_addr是客户端ip地址 , remote_user是客户端用户,下面是日志实际显示示例:

image.png

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
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
嵌入式变量
该ngx_http_core_module模块支持名称与Apache Server变量匹配的嵌入式变量。首先,这些是代表客户端请求标头字段的变量,例如$http_user_agent,$http_cookie等。另外还有其他变量:

$arg_name
name请求行中的 参数

$args
请求行中的参数

$binary_remote_addr
客户端地址(二进制形式),对于IPv4地址,值的长度始终为4个字节,对于IPv6地址,值的长度始终为16个字节

$body_bytes_sent
发送给客户端的字节数,不计算响应头;此变量与 Apache模块 的“ %B”参数 兼容mod_log_config

$bytes_sent
发送给客户端的字节数(1.3.81.2.5

$connection
连接序列号(1.3.81.2.5

$connection_requests
通过连接发出的当前请求数(1.3.81.2.5

$content_length
“内容长度”请求标头字段

$content_type
“内容类型”请求标头字段

$cookie_name
该name饼干

$document_root
当前请求的根或别名指令的值

$document_uri
和...一样 $uri
$host
优先顺序如下:请求行中的主机名,或“主机”请求标头字段中的主机名,或与请求匹配的服务器名

$hostname
主机名

$http_name
任意请求头字段;变量名称的最后一部分是字段名称,该字段名称已转换为小写,并用短划线代替了下划线

$https
on如果连接以SSL模式运行,则为 “ ”,否则为空字符串

$is_args
“ ?”(如果请求行包含参数),否则为空字符串

$limit_rate
设置此变量将启用响应率限制;参见limit_rate

$msec
以毫秒为单位的当前时间(以秒为单位)(1.3.91.2.6

$nginx_version
Nginx版本

$pid
工作进程的PID

$pipe
“ p”如果请求被流水线.“ ”否则(1.3.121.2.7

$proxy_protocol_addr
来自PROXY协议标头(1.5.12)的客户端地址
必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。

$proxy_protocol_port
PROXY协议标头(1.11.0)中的客户端端口
必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。

$proxy_protocol_server_addr
PROXY协议标头中的服务器地址(1.17.6
必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。

$proxy_protocol_server_port
PROXY协议标头中的服务器端口(1.17.6
必须通过proxy_protocol在listen指令中设置参数来预先启用PROXY协议 。

$query_string
和...一样 $args
$realpath_root
绝对路径名,对应于当前请求的 根或别名指令的值,所有符号链接都解析为真实路径
$remote_addr
客户地址

$remote_port
客户端口

$remote_user
基本身份验证随附的用户名

$request
完整的原始请求行

$request_body
请求主体
当将请求正文读取到内存缓冲区时, 该变量的值可在proxy_pass, fastcgi_pass, uwsgi_pass和 scgi_pass指令处理的位置 使用。

$request_body_file
带有请求正文的临时文件的名称
在处理结束时,需要删除文件。要始终将请求正文写入文件, 需要启用client_body_in_file_only。当在代理请求中或在对FastCGI / uwsgi / SCGI服务器的请求中传递临时文件的名称时,应分别通过 proxy_pass_request_body off, fastcgi_pass_request_body off, uwsgi_pass_request_body off或 scgi_pass_request_body off 指令来禁用传递请求正文。 。

$request_completion
“ OK”(如果请求已完成),否则为空字符串

$request_filename
基于root或alias 指令以及请求URI 的当前请求的文件路径

$request_id
16个随机字节生成的唯一请求标识符,以十六进制(1.11.0

$request_length
请求长度(包括请求行,标头和请求正文)(1.3.121.2.7

$request_method
请求方法,通常是“ GET”或“ POST”

$request_time
请求以毫秒为单位的处理时间(以秒为单位)(1.3.91.2.6);从客户端读取第一个字节以来经过的时间

$request_uri
完整的原始请求URI(带有参数)

$scheme
请求方案,“ http”或“ https”

$sent_http_name
任意响应头字段;变量名称的最后一部分是字段名称,该字段名称已转换为小写,并用短划线代替了下划线

$sent_trailer_name
在响应末尾发送的任意字段(1.13.2);变量名称的最后一部分是字段名称,该字段名称已转换为小写,并用短划线代替了下划线

$server_addr
接受请求的服务器的地址
计算此变量的值通常需要一个系统调用。为避免系统调用,listen伪指令必须指定地址并使用bind参数。

$server_name
接受请求的服务器的名称

$server_port
接受请求的服务器的端口

$server_protocol
请求协议,通常是“ HTTP/1.0”,“ HTTP/1.1”或“ HTTP / 2.0

$status
响应状态(1.3.21.2.2

$tcpinfo_rtt, $tcpinfo_rttvar, $tcpinfo_snd_cwnd, $tcpinfo_rcv_space
有关客户端TCP连接的信息;在支持TCP_INFO套接字选项的 系统上可用

$time_iso8601
ISO 8601标准格式(1.3.121.2.7)的本地时间

$time_local
通用日志格式的本地时间(1.3.121.2.7

$uri
请求中的当前URI,已规范化

$uri在请求处理期间,例如在进行内部重定向或使用索引文件时, 的值可能会更改。

更多变量:https://nginx.org/en/docs/http/ngx_http_core_module.html#var_status

error_log(核心模块):

1
2
3
4
Syntax:	error_log file [level];
Default:
error_log logs/error.log error;
Context: main, http, mail, stream, server, location

6.虚拟站点

所属模块:ngx_http_core_module(server和location都属于该模块)

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Syntax:	server { ... }
Default: —
Context: http

Syntax: server_name name ...;
Default:
server_name "";
Context: server

Syntax: listen address[:port] [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
listen port [default_server] [ssl] [http2 | spdy] [proxy_protocol] [setfib=number] [fastopen=number] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [ipv6only=on|off] [reuseport] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
listen unix:path [default_server] [ssl] [http2 | spdy] [proxy_protocol] [backlog=number] [rcvbuf=size] [sndbuf=size] [accept_filter=filter] [deferred] [bind] [so_keepalive=on|off|[keepidle]:[keepintvl]:[keepcnt]];
Default:
listen *:80 | *:8000;
Context: server

一个server表示一个虚拟主机,一个服务器可能有多个虚拟主机(多个网站),实现虚拟主机的方式有三种:

基于IP:

每个server监听不同的IP地址,用server_name来指定(域名和IP都是通过server_name指定)

image.png

基于域名:

image.png

需要注意的是基于域名的虚拟主机首先需要通过DNS能解析到,所以要么是已经购买的域名并且配置解析到该服务器的IP上,要么是本地内部DNS配置以后整个内网可以访问到。需要基于DNS解析。但这里是测试,所以把解析放在 /etc/hosts文件即可(linux在解析主机名时会优先去查看hosts文件是否有解析条目)。域名相较于IP和端口的优点是只需要一个端口和一个ip地址即可用于多个虚拟主机,但需要多个域名以区分访问地址。

基于端口:

image.png

修改listen后的数字即可,默认是80,如果是https的话需要监听443且拥有证书。改为非80(443)端口后再浏览器访问时需主动输入端口号,不然浏览器默认会访问80端口。

7. location

1
2
3
4
Syntax:	location [ = | ~ | ~* | ^~ ] uri { ... }
location @name { ... }
Default: —
Context: server, location

location一般放置与server里面,一个server可以有多个location,location是用于匹配访问地址的uri

1
2
3
4
=  精确匹配。如果这个查询匹配,那么将停止搜索并立即处理此请求。
~ 为区分大小写匹配(可用正则表达式)
~* 为不区分大小写匹配(可用正则表达式)
^~ 如果把这个前缀用于一个常规字符串,那么告诉nginx 如果路径匹配那么不测试正则表达式。

location匹配优先级:

1
```(location `=` ) > (location `完整路径` ) > (location `^~` 路径) > (location `~`,`~*` 从上向下正则顺序,匹配在最后一条终止) > (location 部分起始路径) > (`/`)

例子:

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
location = / {
[ configuration A ]
}

location / {
[ configuration B ]
}

location /documents/ {
[ configuration C ]
}

location ^~ /images/ {
[ configuration D ]
}

location ~* \.(gif|jpg|jpeg)$ {
[ configuration E ]
}

The “/” 匹配 configuration A,
the “/index.html” 匹配 configuration B,
the “/documents/document.html” 匹配 configuration C,
the “/images/1.gif” 匹配 configuration D,
and the “/documents/1.jpg” 匹配 configuration E.

locaiton定义以后还需要将其匹配到linux服务器上对应的文件,就需要用到两个配置参数,root和index

1
2
3
4
5
6
7
8
9
Syntax:	root path;
Default:
root html;
Context: http, server, location, if in location
Module ngx_http_index_module:(INDEX非core模块,而是单独模块)
Syntax: index file ...;
Default:
index index.html;
Context: http, server, location

root是定义其的路径,如root /tmp 放在/的location里面则,当访问路径为根时,会访问到/tmp目录,但是到具体的访问文件时,是由index定义的,一般index定义为index.html或index.htm,如为.php会涉及到fastcgi协议,因为nginx本身只能处理静态html文件。

8.rewrite

所属模块:Module ngx_http_rewrite_module

默认:编译进模块 编译参数:--without-http_rewrite_module

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
Syntax:	rewrite regex replacement [flag];
Default: —
Context: server, location, if

rewrite的含义:该指令是实现URL重写的指令。
regex的含义:用于匹配URI的正则表达式。
replacement:将regex正则匹配到的内容替换成 replacement。
flag: flag标记。

flag有如下值:

last: 本条规则匹配完成后,继续向下匹配新的location URI 规则。(不常用)
break: 本条规则匹配完成即终止,不再匹配后面的任何规则(不常用)。
redirect: 返回302临时重定向,浏览器地址会显示跳转新的URL地址。
permanent: 返回301永久重定向。浏览器地址会显示跳转新的URL地址。

例:

1
2
3
rewrite ^(/download/.*)/media/(.*)\..*$ $1/mp3/$2.mp3 break;
rewrite ^(/download/.*)/audio/(.*)\..*$ $1/mp3/$2.ra break;
rewrite ^/(.*) http://www.test.com/$1 permanent;

服务器如需看rewrite日志需要做以下配置:

1.设置nginx的错误日志级别为notice
error_log /var/log/nginx/error.log notice;
2.在http模块层,增加一行rewrite_log日志
http{

rewrite_log on;

}

if:

1
2
3
Syntax:	if (condition) { ... }
Default: —
Context: server, location

指定的condition被评估。如果为true,则执行括号内指定的此模块伪指令,并在伪指令内为请求分配配置 ifif指令中的配置是从先前的配置级别继承的。

条件可以是以下任意一种:

  • 变量名;如果变量的值为空字符串或“

    1
    0

    ”,则为false;否则为false 。

    在1.0.1版之前,任何以“ 0”开头的字符串都被视为错误值。

  • 使用“ =”和“ !=”运算符将变量与字符串进行比较;

  • 使用“ ~”(区分大小写的匹配)和“ ~*”(区分大小写的匹配)运算符将变量与正则表达式进行匹配。正则表达式可以包含捕获,这些捕获可用于以后在$1..$9变量中重用。负运算符“ !~”和“ !~*”也可用。如果正则表达式包含“ }”或“ ;”字符,则整个表达式应用单引号或双引号引起来。

  • 使用“ -f”和“ !-f”运算符检查文件是否存在;

  • 使用“ -d”和“ !-d”运算符检查目录是否存在;

  • 使用“ -e”和“ !-e”运算符检查文件,目录或符号链接是否存在;

  • 使用“ -x”和“ !-x”运算符检查可执行文件。

例子:

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
#如果UA包含"MSIE",rewrite请求到/msid/目录下

if ($http_user_agent ~ MSIE) {

rewrite ^(.*)$ /msie/$1 break;

}



#如果cookie匹配正则,设置变量$id等于正则引用部分

if ($http_cookie ~* "id=([^;]+)(?:;|$)") {

set $id $1;

}



#如果提交方法为POST,则返回状态405(Method not allowed)。return不能返回301,302

if ($request_method = POST) {

return 405;

}



#限速,$slow可以通过 set 指令设置

if ($slow) {

limit_rate 10k;

}



#如果请求的文件名不存在,则反向代理到localhost 。这里的break也是停止rewrite检查

if (!-f $request_filename){

break;

proxy_pass http://127.0.0.1;

}



#如果query string中包含"post=140",永久重定向到example.com

if ($args ~ post=140){

rewrite ^ http://example.com/ permanent;

}



#防盗链

location ~* \.(gif|jpg|png|swf|flv)$ {

valid_referers none blocked www.jefflei.com www.leizhenfang.com;

if ($invalid_referer) {

return 404;

}

}

if可使用的全局变量:

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
变量名称

变量说明

$args

这个变量等于请求行中的参数,同$query_string

$content_length

请求头中的Content-length字段

$content_type

请求头中的Content-Type字段

$document_root

当前请求在root指令中指定的值

$host

请求主机头字段,否则为服务器名称

$http_user_agent

客户端agent信息

$http_cookie

客户端cookie信息

$limit_rate

这个变量可以限制连接速率

$request_method

客户端请求的动作,通常为GET或POST

$remote_addr

客户端的IP地址

$remote_port

客户端的端口

$remote_user

已经经过Auth Basic Module验证的用户名

$request_filename

当前请求的文件路径,由root或alias指令与URI请求生成

$scheme

HTTP方法(如http,https)

$server_protocol

请求使用的协议,通常是HTTP/1.0或HTTP/1.1

$server_addr

服务器地址,在完成一次系统调用后可以确定这个值

$server_name

服务器名称

$server_port

请求到达服务器的端口号

$request_uri

包含请求参数的原始URI,不包含主机名,如:”/foo/bar.php?arg=baz”

$uri

不带请求参数的当前URI,$uri不包含主机名,如”/foo/bar.html”

$document_uri

$uri相同

9.proxy模块

所属模块:ngx_http_proxy_module

默认:编译进模块 编译参数:--without-http_proxy_module

1
2
3
4
5
6
7
8
9
句法:	proxy_pass URL;
默认: —
内容: location,if in location,limit_except

Syntax: proxy_set_header field value;
Default:
proxy_set_header Host $proxy_host;
proxy_set_header Connection close;
Context: http, server, location

proxy:

proxy_pass和proxy_set_header是proxy模块中最常用到的两个功能

proxy_pass例子:

proxy_pass http:// localhost:8000 / uri /;

proxy_pass http://unix/tmp/backend.socket/uri/;

一般放在location下面,当location匹配到对应的uri之后,如果下面是proxy_pass而不是root,就会通过nginx去反向代理到proxy_pass指定的地址上面去请求访问。

反代的地址可以是ip地址,域名,sock文件地址,也可以是upstream指定的名称。

这个upstream是nginx的另一个模块叫做:ngx_http_upstream_module

ngx_http_upstream_module

upstream最重要的功能是定义一组后端服务器,然后proxy_pass可以根据upstream定义好的直接调用,完成以后proxy_pass收到请求会将反向代理到upstream所定义的一组服务器上。

1
2
3
Syntax:	upstream name { ... }
Default: —
Context: http

例子:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream backend {
server backend1.example.com weight=5;
server backend2.example.com:8080;
server unix:/tmp/backend3;

server backup1.example.com:8080 backup;
server backup2.example.com:8080 backup;
}

server {
location / {
proxy_pass http://backend;
}
}

upstream定义了一组后端服务器后,当然也会有调度方式:

1.如不进行任何配置,默认的调度方式为轮训调度。

2.weight:设置后端服务器的权重,权重大的优先访问

server 192.168.0.15 weight=10;

3.ip_hash:每个请求按访问ip的hash结果分配,这样每个访客固定访问一个后端服务器,可以解决session的问题

upstream backend {
ip_hash;
server 192.168.0.14:88;}

4.fair(第三方)
按后端服务器的响应时间来分配请求,响应时间短的优先分配。

upstream backend {

fair;

server 192.168.0.14:88;}

5.url_hash(第三方)
按访问url的hash结果来分配请求,使每个url定向到同一个后端服务器,后端服务器为缓存时比较有效。

6.least_conn:

最少连接数,那个机器连接数少就分发(lc)
7.wlc:
加权最少连接

1
2
3
4
5
6
7
8
9
10
11
12
13
14
upstream backend {
server squid1:3128;
server squid2:3128;
hash $request_uri;
hash_method crc32;
}
#定义负载均衡设备的Ip及设备状态
upstream backend{
ip_hash;
server 127.0.0.1:9090 down;
server 127.0.0.1:8080 weight=2;
server 127.0.0.1:6060;
server 127.0.0.1:7070 backup;
}

常用参数:down ,backup,fail_timeout=time,max_fails=number,wight,max_conns=number
down:
当前的server暂时不参与负载均衡
backup:
预留的备份服务器
max_fails:
允许请求失败的次数
fail_timeout:
经过max_fails夫败后,服务暂停时间
max_conns:
限制最大的接收连接数

proxy_set_header:

这几个的参数的作用是向后端转发的时候添加头信息;

1
2
3
proxy_set_header   Host    $host:$server_port;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

本文要说明nginx中的Host、X-Real-IP、X-Forwarded-For。

先看一个配置示例:

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
server {
listen 80;
server_name 192.168.1.2;
error_log /usr/local/etc/nginx/logs/test.error.log;
access_log /usr/local/etc/nginx/logs/test.access.log;
location / {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $http_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
proxy_http_version 1.1;
add_header Access-Control-Allow-Origin *;
proxy_pass http://127.0.0.1:8889;
}
location /app {
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_set_header Host $proxy_host;
proxy_set_header X-NginX-Proxy true;
proxy_set_header Connection "";
proxy_http_version 1.1;
proxy_pass http://192.168.1.3;
}
}

客户端地址(请求服务的地址):192.168.1.1

nignx服务器地址:192.168.1.2

后端服务器地址:192.168.1.3

首先说明proxy_set_header是用来设置请求头的,设置了请求头后,后端服务器就可以获取到这些变量值。

一、X-Real-IP

是指客户端的真实IP,如果设置了$remote_addr这个值,后端服务器就能获取到客户端的真实IP,也就是此例中的192.168.1.1

二、Host

host的值设置为$proxyhost,是指proxy_pass中设置的host值,也就是192.168.1.3,也就是服务器的IP地址。

若客户端发过来的请求header中有HOST这个字段,$http_host和$host表示的就是原始请求host,比如请求的时候HOST的值是http://test.com,那么反代后还是http://test.com

若客户端发过来的请求header中没有HOST这个字段,$host表示nginx代理服务器的地址,也就是此例中的192.168.1.2。

$httphost不是一个固定的变量,他其实是$http_HEADER通配后的结果,这里的HEADER是一个通配符,通配的是请求头里的header属性,例如$http_content_type表示请求头里content-type属性的值,同理,$http_host指的就是请求头里的host属性。

三、X-Forwarded-For

这个变量的值有$proxy_add_x_forwarded_for和$remote_addr,在只有一个代理服务器的转发的情况下,两者的效果貌似差不多,都可以真实的显示出客户端原始ip。

举例说明,用户A的IP是192.168.1.1,请求一个经过两次nginx转发的应用,在第一台nginx中(192.168.1.2),配置如下:

1
proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

现在$proxy_add_x_forwarded_for变量的”X-Forwarded-For”部分是空的,所以只有$remote_addr,而$remote_addr的值是用户的ip,那么X-Forwarded-For变量的值就是用户的ip:192.168.1.1。

到第二台nginx,配置如下:

1
proxy_set_header  X-Forwarded-For $proxy_add_x_forwarded_for;

现在的$proxy_add_x_forwarded_for变量,X-Forwarded-For部分包含的是用户的真实ip,$remote_addr部分的值是上一台nginx的ip地址,那么X-Forwarded-For的值就变成了”用户的真实ip,第一台nginx的ip”,也就是“192.168.1.1, 192.168.1.2”

所以还是建议X-Forwarded-For的值设置成$proxy_add_x_forwarded_for。

nginx正向代理:

示例配置:

1
2
3
4
5
6
    listen       80;
server_name localhost;
resolver 223.5.5.5;
location / {
proxy_pass http://$http_host$request_uri;
}

其中重要的配置主要是:proxy_pass和 resolver

proxy指定其正向代理所转发的地址 $http_host为其url

$request_uri为其请求的uri

resolver后面跟的是其转发时使用的dns地址,如没指定,nginx无法正常解析dns,则无法访问域名网站。

10.四层负载均衡

proxy模块默认只支持七层代理,也就是基于http协议代理,如果想要进行四层转发的话(也就是对其他协议进行转发),可以用到stream模块:

所属模块:ngx_stream_core_module

默认:该ngx_stream_core_module模块自1.9.0版开始可用。默认情况下未构建此模块,应使用--with-stream 配置参数启用它 。使用官方源默认会编译该模块

1
2
3
Syntax:	stream { ... }
Default:
Context: main

在配置文件里面,其模块位置于http同级,下面是示例

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
worker_processes auto;

error_log /var/log/nginx/error.log info;

events {
worker_connections 1024;
}

stream {
upstream backend {
hash $remote_addr consistent;

server backend1.example.com:12345 weight=5;
server 127.0.0.1:12345 max_fails=3 fail_timeout=30s;
server unix:/tmp/backend3;
}

upstream dns {
server 192.168.0.1:53535;
server dns.example.com:53;
}

server {
listen 12345;
proxy_connect_timeout 1s;
proxy_timeout 3s;
proxy_pass backend;
}

server {
listen 127.0.0.1:53 udp reuseport;
proxy_timeout 20s;
proxy_pass dns;
}

server {
listen [::1]:12345;
proxy_pass unix:/tmp/stream.socket;
}
}

这里于七层代理在配置文件上最大的区别就是http换成了stream

下面是我在本地做的一个实例:

效果为将一台服务器的ssh协议转发到后端两台服务器

调度器:10.10.10.105

后端服务器:10.10.10.187 ,10.10.10.243

调度服务器nginx 配置添加如下

stream {
upstream backend {
server 10.10.10.187:22;
server 10.10.10.243:22;
}
server {
listen 88 ;
proxy_pass backend;
}
}

三台服务器都是虚拟机,添加好配置以后使用xshell进行测试

image.png

在弹出的对话框输入账号密码,然后测试成功!

需要注意的是经过测试,stream模块是转发请求而非代理,严格意义上来说是四层转发,其功能于lvs无异。

11.HTTPS

https在http中加入TLS/SSL层,http为明文传输,而https为密文传输,也更为安全。https默认监听端口443,需要证书进行认证,一般证书都有第三方机构或CA颁发。

所属模块:http_ssl_module

默认:不编译进内核 编译参数:–with-http_ssl_module

1
2
3
4
5
6
7
8
9
10
11
syntax: ssl on | off;
Default: ssl off;
context: http, server

syntax : ssl_certificate file;
Default: -
context: http, server

syntax: ssl_certificate_key file;
Default: -
context: http, server

nginx.conf配置:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
server {
listen 443 ssl;
server_name www.oldboy.com;

ssl_certificate ssl_key/server.crt;
ssl_certificate_key ssl_key/server.key;

ssl_session_cache shared:SSL:1m;
ssl_session_timeout 5m;
# ssl_ciphers HIGH:!aNULL:!MD5;
# ssl_prefer_server_ciphers on;

location / {
root /code/https;
index index.html index.htm;
}
}

其中ssl_certificate为证书文件,ssl_certificate_key为秘钥文件。

在公司内部使用时,也可使用私有证书(公网中无法验证证书)。

私有证书颁发步骤:

1.生成key秘钥
2.生成证书签名请求文件 csr
3.生成证书签名文件 ca

要求:
1.openssl大于1.0.2
[root@localhost ~]# openssl version
OpenSSL 1.1.1g FIPS 21 Apr 2020

2.nginx必须有ssl模块
nginx -V

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
生成RSA密钥(过程需要设置一个密码,记住这个密码)
openssl genrsa -des3 -out domain.key 1024

拷贝一个不需要输入密码的密钥文件
openssl rsa -in domain.key -out domain_nopass.key
生成一个证书请求
openssl req -new -key domain.key -out domain.csr
这里会提示输入国家,地区组织,email等信息.最重要的一个是"common name",需要与网站域名相同.

Enter pass phrase for domain.key: # 之前设置的密码
-----
Country Name (2 letter code) [XX]:CN # 国家
State or Province Name (full name) []:Jilin # 地区或省份
Locality Name (eg, city) [Default City]:Changchun # 地区局部名
Organization Name (eg, company) [Default Company Ltd]:Python # 机构名称
Organizational Unit Name (eg, section) []:Python # 组织单位名称
Common Name (eg, your name or your server's hostname) []:domain.com # 网站域名
Email Address []:123@domain.com # 邮箱
A challenge password []: # 私钥保护密码,可直接回车
An optional company name []: # 一个可选公司名称,可直接回车

输入完这些就会生成一个domain.csr文件,提交给ssl提供商的时候就是这个csr文件.当然这里并没有向任何证书提供商申请,而是自己签发证书.

使用上面的密钥和CSR对证书签名
openssl x509 -req -days 365 -in domain.csr -signkey domain.key -out domain.crt
最后将crt文件与key文件放入nginx配置文件中去

本博客所有文章除特别声明外,均采用 CC BY-SA 4.0 协议 ,转载请注明出处!