文件结构
全局块: 配置影响全局, 包括运行nginx 的用户组,进程存放, 日志, 配置文件等
events: 配置影响nginx 服务器与客户端的网络连接, 包括进程最大连接数, 数据驱动模型, 序列化等
http: 配置代理, 缓存, 日志, 第三方模块等, 可嵌套多个 server
server: 配置虚拟主机的参数
location: 配置请求路由, 页面处理
# 全局配置
...
# events 配置
events {
...
}
# http 配置
http{
# http 全局配置
...
# server 配置
server {
# server 全局配置
...
# location 配置
location [pattren(规则)] {
...
}
}
}
全局配置
# 指定nginx 运行的用户以及用户组, 默认为nobody
#user nobody nobody;
# 开启线程数, 最大值可设置逻辑cpu 核数
#worker_processes 1;
# 定位全局错误日志文件, 级别以 notice 显示, 还有 debug, info, warn, error, crit
# debug 输出最多, crit输出最少
#error_log logs/error.log;
#error_log logs/error.log notice;
#error_log logs/error.log info;
# 指定进程id的存储文件位置
#pid logs/nginx.pid
# 指定一个 nginx 进程打开的最多文件描述符数目, 受系统进程的最大打开文件数量限制
# worker_rlimit_nofile 65535;
# events 配置
...
#http 配置
...
events 配置
events{
# 设置工作模式为 epoll, 还有 select, poll, kqueue, rtsig, dev/poll 模式
use epoll;
# 定义每个进程的最大连接数, 受系统进程的最大打开文件数量限制
worker_connections 1024;
}
http 配置
http{
# 主模式指令, 实现对配置文件所保护的文件的设定, 可以减少主配置文件的复杂度
include mime.types;
# 核心模块指令, 默认设置为二进制流, 也就是当文件类似未定义时使用这种方式
default_type application/octet-stream
# 日志格式的设定, main 为日志格式名称,
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# 引用日志main 格式
acces_log logs/acces.log main;
# 设置允许客户端请求的最大单个文件字节数
client_max_body_size 20M;
# 指定来自客户端请求头的headebuffer 大小
client_header_buffer_size 32k;
# 指定连接请求试图写入缓存文件的目录路径
client_body_temp_path ./tmp/client_body/temp;
# 指定客户端请求中较大的消息头的缓存最大数量和大小, 目前设置为 4个 32k
large client_header_buffers 4 32k;
# 开启高效文件传输模式
sendfile on;
# 开启防止网络阻塞
tcp_nopush on;
# 开启防止网络阻塞
tcp_nodelay on;
# 设置客户端连接保存活动的超时时间
# keepalive_timeout 0; # 无限时间
keepalive_timeout 65;
# 设置客户端请求读取header 超时时间
client_header_timeout 10;
# 设置客户端请求body读取超时时间
client_body_timeout 10;
# httpGzip模块配置
# 开启 gzip 压缩
gzip on;
# 设置允许压缩的页面最下字节数
gzip_min_length 1k;
# 申请4个单位为16k的内存作为压缩结果流缓存
gzip_buffers 4 16k;
# 设置识别http协议的版本, 默认1.1
gzip_http_version 1.1;
# 指定gzip压缩比, 1-9 数字越小, 压缩比越小, 速度越快
gzip_com_level 2;
# 指定压缩的类型
gzip_types text/plain application/x-javascript text/css application/xml;
# 让前端的缓存服务器进gzip 压缩的页面
gzip_vary on;
}
server 配置
server {
# 单连接请求上限次数
keepalive_requests 120;
# 监听端口
listen 88;
# 监听地址, ip,域名
server_name 11.1.1.1
# server_name www.123.com
# 设置访问的语言编码
charset utf-8;
# 设置虚拟主机访问日志的存放路径以及日志的格式为main
acces_log ./logs/acces.log main; # 响应日志
error_log ./logs/error.log main; # 错误日志
# PHP-INFO-START php 引用配置,可注释或者修改
include enable-php-74.conf
# PHP-INFO-END
# REWRITE-START url 重写规则引用
include ./conf/rewrite.conf
# REWRITE-END
# 设置主机基本信息
# 请求的url 过滤, 正则匹配, ~: 区分大小写, ~*: 不区分大小写
location ~*^.+$ {
# 根目录
root html;
# 设置默认页
index index.html index.htm;
# 拒绝的ip, 黑名单
deny 127.0.0.1;
# 允许的ip ,白名单
allow 172.182.4.4;
}
# 禁止访问的文件或目录
location ~ ^/(\.user.ini|\.htaccess|\.git|\.svn|\.project|LICENSE|README.md) {
return 404;
}
# ssl 证书验证目录相关设置
location ~ \.well-know {
allow all;
}
# 图片资源设置
location ~ .*\.(gif|jpg|png|bmp|swf)${
expires 30d;
error_log /dev/null;
acces_log off;
}
# 网站js 与css 资源配置
location ~ .*\.(js|css)?${
expires 12h;
error_log /dev/null;
access_log off;
}
# 访问异常页面配置
error_page 404 ./html/error/404.html
error_page 500 502 503 504 ./html/error/50x.html
location = /50x.html {
root html;
}
}
Rewrite
地址重写, 地址转发, 重定向
地址重写: 为了标准化, 如: baidu.com和www.baidu.com 都会被重写到 www.baidu.com,在浏览器看到的也是这个
地址转发: 指在网络数据传输过程中数据分组到达路由器或桥接器后, 该设备通过检查分组地址并将数据转发到最近的局域网的过程
异同:
地址重写会改变浏览器中的地址, 使其变成重写成浏览器最新的地址,而地址转发不会改变
地址重写会产生两次请求, 而地址转发只会请求一次
地址转发一般发生在同一个站点项目内部, 而地址重写不受限制
地址转发的速度比地址重定向快
$args: 变量中存放了请求url 中的请求指令, 如: http://127.0.0.1:8888?arg1=value&agr2=value2
$content_length: 变量中存放了请求头中content-length字段
$content_type: 变量中存放了请求头中的content-type 字段
$document_root: 变量中存放了针对当前请求的根路径
$document_uri: 变量中存放了请求的当前uri, 但是不包括请求指令,
如: http://xxx.abc.com/home/1?arg1=value1&arg2=value2 中的/home/1
$host: 变量中存放了请求的url中的主机部分字段, 如: http://xxx.abc.com:9999/home 中的xxx.abc.com
**http host **: 变量与host 唯一区别带有端口号, 如: xxx.abc.com:8888
$http_user_agent: 变量中存放客户端的代理信息
$http_cookie: 变量中存放客户端cookie 信息
$remote_addr: 变量中存放客户端的地址
$remote_port: 变量中存放客户端与服务器建立连接的端口号
$remote_user: 变量中存放客户端的用户名
$request_body_file: 变量中存放了发给后端服务器的本地文件资源的名称
$request_method: 变量中存放了客户端的请求方式, 如: GET, POST
$request_filename: 变量中存放了当前请求的资源文件的路径名
$request_uri: 变量中存放了当前请求的uri, 并且带请求指令
**query string** : 和变量 args含义一样
$scheme: 变量中存放了客户端请求使用的协议, 如: http,https 等
$server_protocol: 变量中存放了客户端请求协议的版本, 如: HTTP/1.0, HTTPS/1.1 等
URL 重写
在 nginx 中通过在 server 或location 中配置rewrite 指令实现
rewrite regex replacement [flag]
rewirte: 实现url 重写的指令
regex: 匹配url 正则表达式
replacement: 将regex正则匹配到的内容替换成 replacement
flag: 标记
last: 本条规则匹配完成后, 继续向下匹配新的location url规则(不常用)
break: 本条规则匹配完成即终止, 不再匹配后面的规则(不常用)
redirect: 返回302 临时重定向, 浏览器地址会显示跳转新的url 地址
permanent: 返回 301 永久重定向, 浏览器地址会显示跳转新的url 地址
例:
rewrite ^/(.*) http://www.baidu.com/$1 permanent;
正则表达式
\: 转义字符标记, 如\n匹配一个换行符, 而\$则匹配$
^: 匹配输入字符串的起始位置
$: 匹配输入字符串的结束位置
*: 匹配阡陌的字符串零次或多次, 如 lo* 可以匹配o,lo, loo
+: 匹配前面的字符一次或多次, 如lo+ 可以匹配lo,loo, 但不能匹配l
?: 匹配前面的字符零次或一次, 如 do(es)? 可以匹配do, does, ? 等效:{0,1}
.: 匹配除 \n 之外的任何单个字符, 若要匹配包括\n在内的任意字符,需要使用[.\n]之类的模式
(pattern): 匹配括号内pattern并可以在后面获取对应的匹配, 常用 $0...$9 属性获取小括号中的匹配内容,
要匹配圆括号字符需要\(content\)
~: 匹配过程对大小写敏感
~*: 匹配过程中对大小写不敏感
!~: 如果~匹配失败时, 则条件为true
!~*: 如果 ~*匹配失败时, 则条件为 true
指令判断
# 判断请求的文件是否存在
if( -f $request_filename){
}
# 判断请求的文件是否不存在
if( !-f $request_filename){
}
# 指令
-f, !-f: 判断请求文件是否存在
-d, !-d: 判断请求目录是否存在
-e, !-e: 判断请求的文件或目录是否存在
-x, !-x: 判断请求的文件是否可执行
# 判断手机访问
if( $request_user_agent ~* "(Android)|(iPhone)|(Mobile)|(WAP)|(UCWEB)" ){
rewrite ^/& http://www.cnblogs.com permanent;
}
# 判断指定host 时, 重定向跳转
server{
location /{
proxy_pass http://127.0.0.1:8888;
if ($host='xx.abc.com'){
rewrite ^/(.*) http://www.cnblogs.com redirect;
}
}
}
防盗链
可以理解为盗图链接, 就是把别人的图片偷过来用在自己的服务器上, 那么防盗链可以理解为防止其他人把我的图片盗取过去
实现原理
客户端向服务端请求资源时, 为了减少网络宽带,提供响应时间, 服务器一般不会一次将所有资源完整的传回客户端
如: 在请求一个网页时, 首先会传回该网页的文本内容, 到客户端浏览器在解析文本的过程中发现有图片存在时,
会再次发起对该图片资源的请求, 服务器将存储的图片资源再发送给客户端,
但是如果该图片是链接到其他站点的服务器上了, 如在项目中引用了淘宝的一张图片, 那么重新加载的时候,
就会请求淘宝服务器, 可能会造成淘宝服务器负担, 这个就是盗链行为
使用http协议中请求头部的Referer 头域来判断当前访问的网页或文件的源地址,
通过该头域的值, 可以检测访问目标资源的源地址, 如果源地址不是我们自己站内的url的话,
需要采取措施, 实现防盗链, 但 referer 头域中的值是可以被更改的, 所以该方法不能完全实现
nginx 中有一个指令 valid_referer 该指令可以用来获取 referer 头域中的值,
并且根据该值的情况给nginx 全局变量 invalidreferer 赋值
语法:
valid_referers none | blocked |server_names |string
none: 检测referer 头域不存在的情况
blocked: 检测referer 头域的值被防火墙或者代理服务器删除或者伪装的情况, 这种情况, 头域的值不以: http://, https:// 开头
server_names: 设置一个或多个url, 检测referer头域的值是否是rul 中的某个
所以可以使用 valid_referers 指令和 $invalid_referer 变量的值, 通过rewrite 功能来实现
server{
listen 8080;
server_name xxx.abc.com;
location ~* ^.+\.(gif|jpg|png|swf|flv|rar|zip){
valid_referers none blocked www.xxx.com www.yyy.com *.baidu.com *.tabobao.com;
if($invalid_referer){
rewirte ^/ http://www.xxx.com/images/xx.png;
}
}
}
当有网络请求图片资源时, 如果检测到referer 头域中没有符合valid_referers 指令的话,
则不符合本站的资源请求, 会重定向到一张网络图片中
server{
listen 8080;
server_name xxx.abc.com;
location /file/{
root /server/file/;
valid_referers none blocked www.xxx.com www.yyy.com *.baidu.com *.tabobao.com;
if($invalid_referer){
rewrite ^/ http://www.xxx.com/images/xxx.png;
}
}
}
其他例子
1. 域名跳转
server{
listen 80;
server_name abc.com;
# 跳转到 www.ab.com 网站
rewrite ^/(.*) http://www.ab.com/$1 permanent;
}
server{
listen 80;
server_name www.myweb.com www.web.info;
if($host ~ myweb\.info){ # . 需要使用 \转义
rewrite ^\(.*) http://www.myweb.com/&1 permanent;
}
}
2. 防盗链
location ~* \.(gif|jpg|png|swf|flv)${
valid_referers none blocked www.vison.com www.wsvison.com;
# 如果上面没有匹配成功, $invalid_referer 为1 否则0
if($invalid_referer){
return 404;
}
}
3. 其他
if($http_user_agent ~ MSIE){
# 如果 UA 包含MSIE , 请求到 msid 目录
rewrite ^\(.*)$ /msie/$1 break;
}
if($http_cookie ~* "id=[^;]+)(?:;|$)"){
# 如果cookie 匹配到正则, 设置变量$id 为正则引用部分
set $id $1;
}
if($request_method=POST){
# 如果提交方法为post, 则返回状态405
return 405;
}
if($slow){
# 限速, $slow 可以通过set 指令设置
limit_rate 10k;
}
if(!-f $request_filename){
#如果请求的文件名不存在, 则反向代理到localhost
break; # 停止 rewrite 检查
proxy_pass http://127.0.0.1;
}
if($args ~ post=140){
# 如果query string 中包含post=140 , 则重定向到 example.com
rewrite ^ http://example.com/ permanent;
}