nginx|nginx 防盗链 地址重写 rewrite

nginx 防盗链问题
两个网站 A 和 B, B网站引用了A网站上的图片,这种行为就叫做盗链。 防盗链,就是要防止B引用A的图片。
1、nginx 防止网站资源被盗用模块
ngx_http_referer_module
如何区分哪些是不正常的用户?
HTTP Referer是Header的一部分,当浏览器向Web服务器发送请求的时候,一般会带上Referer,
告诉服务器我是从哪个页面链接过来的,服务器借此可以获得一些信息用于处理,例如防止未经允许
的网站盗链图片、文件等。因此HTTP Referer头信息是可以通过程序来伪装生成的,所以通过Referer
信息防盗链并非100%可靠,但是,它能够限制大部分的盗链情况。
2. 防盗链配置
配置要点:
[root@nginx-server ~]# vim /etc/nginx/nginx.conf
# 日志格式添加"$http_referer"
log_formatmain'$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
# valid_referers 使用方式
Syntax:valid_referers none | blocked | server_names | string ...;
Default:—
Context: server, location
none : 允许没有http_refer的请求访问资源;
blocked : 允许不是http://开头的,不带协议的请求访问资源---被防火墙过滤掉的;
server_names : 只允许指定ip/域名来的请求访问资源(白名单);
准备两台机器,一张图片网站服务器
图片网站服务器:上传图片192.168.1.9
[root@nginx-server ~]# cp test.jpg /usr/share/nginx/html/
[root@nginx-server ~]# cd /etc/nginx/conf.d/
[root@nginx-server conf.d]# cp default.conf default.conf.bak
[root@nginx-server conf.d]# mv default.conf nginx.conf
[root@nginx-server conf.d]# vim nginx.conf
server {
listen80;
server_namelocalhost;
location / {
root/usr/share/nginx/html;
indexindex.html index.htm;
}
}
[root@nginx-server conf.d]# nginx -t
[root@nginx-server conf.d]# systemctl restart nginx
访问:
Referer:这个匹配的连接为空 “-”
盗链机器配置:192.168.1.10
[root@nginx-client ~]# cd /usr/share/nginx/html/
[root@nginx-client html]# cp index.html index.html.bak
[root@nginx-client html]# vim index.html



qf.com - 锐客网





[root@nginx-client html]# systemctl restart nginx
查看服务器日志:
Referer记录了:连接是1.10这台机器。
在图片服务器操作
[root@nginx-server conf.d]# vim nginx.conf
server {
listen80;
server_namelocalhost;
location / {
root/usr/share/nginx/html;
indexindex.html index.htm;
?
valid_referers none blocked www.jd.com; #允许这些访问
if($invalid_referer) {
return403;
}
}
}
[root@nginx-server conf.d]# systemctl restart nginx
测试访问:
图片服务器查看日志:
上面配置并没有允许192.168.1.10这台机器访问。
实例二,继续在图片服务器上面操作
[root@nginx-server html]# vim /etc/nginx/conf.d/nginx.conf #将原来的删除掉
server {
listen80;
server_namelocalhost;
location ~.*\.(gif|jpg|png|jpeg)$ {
root/usr/share/nginx/html;
?
valid_referers none blocked *.qf.com192.168.1.10;
if($invalid_referer) {
return403;
}
}
}
因为none允许为空值访问,所以加不加ip都可以访问,如果把none擦除,就不可以了
重载nginx服务
[root@nginx-server ~]# nginx -s reload
在其中一台机器测试:
测试不带http_refer:
[root@nginx-server conf.d]# curl -I "http://192.168.1.9/test.jpg"
HTTP/1.1200OK
Server: nginx/1.16.1
Date: Mon,02Sep201914:02:56 GMT
Content-Type: image/jpeg
Content-Length:27961
Last-Modified: Mon,02Sep201913:23:12 GMT
Connection: keep-alive
ETag:"5d6d17c0-6d39"
Accept-Ranges: bytes
?
测试带非法http_refer:
[root@nginx-server conf.d]# curl -e http://www.baidu.com -I "http://192.168.1.9/test.jpg"
HTTP/1.1403Forbidden
Server: nginx/1.16.1
Date: Mon,02Sep201914:03:48 GMT
Content-Type: text/html
Content-Length:153
Connection: keep-alive
?
测试带合法的http_refer:
[root@nginx-server conf.d]# curl -e http://www.qf.com -I "http://192.168.1.9/test.jpg"
HTTP/1.1200OK
Server: nginx/1.16.1
Date: Mon,02Sep201914:04:52 GMT
Content-Type: image/jpeg
Content-Length:27961
Last-Modified: Mon,02Sep201913:23:12 GMT
Connection: keep-alive
ETag:"5d6d17c0-6d39"
Accept-Ranges: bytes
?
[root@ansible-server conf.d]# curl -e http://192.168.1.10 -I "http://192.168.1.9/test.jpg"
HTTP/1.1200OK
Server: nginx/1.16.1
Date: Mon,02Sep201914:05:36 GMT
Content-Type: image/jpeg
Content-Length:27961
Last-Modified: Mon,02Sep201913:23:12 GMT
Connection: keep-alive
ETag:"5d6d17c0-6d39"
Accept-Ranges: bytes
如果用户直接在浏览器输入你的图片地址,那么图片显示正常,因为它符合规则。
在图片服务器查看日志:
nginx 地址重写 rewrite
1、什么是Rewrite
Rewrite对称URL Rewrite,即URL重写,就是把传入Web的请求重定向到其他URL的过程。
URL Rewrite最常见的应用是URL伪静态化,是将动态页面显示为静态页面方式的一种技术。比如http://www.123.com/news/index.php?id=123 使用URLRewrite 转换后可以显示为 http://www.123.com/news/123.html对于追求完美主义的网站设计师,就算是网页的地址也希望看起来尽量简洁明快。理论上,搜索引擎更喜欢静态页面形式的网页,搜索引擎对静态页面的评分一般要高于动态页面。所以,UrlRewrite可以让我们网站的网页更容易被搜索引擎所收录。
从安全角度上讲,如果在URL中暴露太多的参数,无疑会造成一定量的信息泄漏,可能会被一些黑客利用,对你的系统造成一定的破坏,所以静态化的URL地址可以给我们带来更高的安全性。
实现网站地址跳转,例如用户访问360buy.com,将其跳转到jd.com。例如当用户访问tianyun.com的80端口时,将其跳转到443端口。
2、Rewrite 相关指令
Nginx Rewrite 相关指令有 if、rewrite、set、return
2.1、if 语句
应用环境
server,location
语法:
if(condition) { … }
if可以支持如下条件判断匹配符号
~正则匹配 (区分大小写)
~*正则匹配 (不区分大小写)
!~正则不匹配 (区分大小写)
!~*正则不匹配(不区分大小写)
-f和!-f用来判断是否存在文件
-d和!-d用来判断是否存在目录
-e和!-e用来判断是否存在文件或目录
-x和!-x用来判断文件是否可执行
?
在匹配过程中可以引用一些Nginx的全局变量
$args请求中的参数;
$document_root针对当前请求的根路径设置值;
$host请求信息中的"Host",如果请求中没有Host行,则等于设置的服务器名;
$limit_rate对连接速率的限制;
$request_method请求的方法,比如"GET"、"POST"等;
$remote_addr客户端地址;
$remote_port客户端端口号;
$remote_user客户端用户名,认证用;
$request_filename当前请求的文件路径名(带网站的主目录/usr/local/nginx/html/images /a.jpg)
$request_uri当前请求的文件路径名(不带网站的主目录/images/a.jpg)
$query_string与$args相同;
$scheme用的协议,比如http或者是https
$server_protocol请求的协议版本,"HTTP/1.0"或"HTTP/1.1";
$server_addr服务器地址,如果没有用listen指明服务器地址,使用这个变量将发起一次系统调用以取得地址(造成资源浪费);
$server_name请求到达的服务器名;
$document_uri与$uri一样,URI地址;
$server_port请求到达的服务器端口号;
2.2、Rewrite flag
rewrite指令根据表达式来重定向URI,或者修改字符串。可以应用于server,location, if环境下每行rewrite指令最后跟一个flag标记,支持的flag标记有:
last相当于Apache里的[L]标记,表示完成rewrite。默认为last。
break本条规则匹配完成后,终止匹配,不再匹配后面的规则
redirect返回302临时重定向,浏览器地址会显示跳转后的URL地址
permanent返回301永久重定向,浏览器地址会显示跳转后URL地址
redirect 和 permanent区别则是返回的不同方式的重定向,对于客户端来说一般状态下是没有区别的。而对于搜索引擎,相对来说301的重定向更加友好,如果我们把一个地址采用301跳转方式跳转的话,搜索引擎会把老地址的相关信息带到新地址,同时在搜索引擎索引库中彻底废弃掉原先的老地址。使用302重定向时,搜索引擎(特别是google)有时会查看跳转前后哪个网址更直观,然后决定显示哪个,如果它觉的跳转前的URL更好的话,也许地址栏不会更改。
2.3、Rewrite匹配参考示例
本地解析host文件(windows)
192.168.62.153 www.testpm.com
?
例1:
[root@nginx html]# pwd
/html
[root@nginx html]# ls
ab
[root@nginx html]# cat a/1.html
1.html
[root@nginx html]# cat b/2.html
22
?
# http://www.testpm.com/a/1.html ==> http://www.testpm.com/b/2.html
server {
listen80;
server_namewww.testpm.com;
?
location /a {
root /html;
index1.html index.htm;
rewrite .* /b/2.html permanent;
}
?
location /b {
root/html;
index2.html index.htm;
}
?
}
?
?
例2:
[root@mycat html]# pwd
/var/www/html
[root@mycat html]# ls
20182019
[root@mycat html]# cat 2018/a/1.html
2018
[root@mycat html]# cat 2019/a/1.html
2019
?
# http://www.testpm.com/2019/a/1.html ==> http://www.testpm.com/2018/a/1.html
server {
listen80;
server_namewww.testpm.com;
?
location /2019/a {
root/var/www/html;
index1.html index.hml;
rewrite ^/2019/(.*)$ /2018/$1permanent;
}
?
location /2018/a {
root/var/www/html;
index1.html index.htl;
}
?
}
?
?
例3:
# http://www.qf.com/a/1.html ==> http://jd.com
location /a {
root/html;
if($host~* qf.com ) {
rewrite .* http://jd.com permanent;
}
}
?
?
例4:
# http://www.youngfit.com/a/1.html ==> http://jd.com/a/1.html
location /a {
root /html;
if($host~* youngfit.com ){
rewrite .* http://jd.com$request_uripermanent;
}
}
?
?
例5: 在访问目录后添加/(如果目录后已有/,则不加/)
[root@nginx-server c]# pwd
/usr/share/nginx/html/a/b/c
?
【nginx|nginx 防盗链 地址重写 rewrite】# http://www.qf.com/a/b/c
# $1: /a/b/
# $2: c
# http://$host$1$2/
location /a/b/c {
root/usr/share/nginx/html;
indexindex.html index.hml;
if(-d$request_filename) {
rewrite ^(.*)([^/])$ http://$host$1$2/ permanent;
}
}
?
例6:
[root@nginx html]# pwd
/usr/share/nginx/html
[root@nginx html]# ls
50x.htmlindex.htmlindex.html.bak1reg
[root@nginx html]# cat reg/login.html
login
# http://www.qf.com/login/qf.html ==>http://www.qf.com/reg/login.html?user=qf
location /login {
root/usr/share/nginx/html;
rewrite ^/login/(.*)\.html$ http://$host/reg/login.html?user=$1;
}
location /reg {
root /usr/share/nginx/html;
index login.html;
}
?
例7:
[root@nginx-server33]# pwd
/html/qf/11/22/33
[root@nginx-server33]# cat 1.html
hello nginx
?
#http://www.qf.com/qf/11-22-33/1.html==>http://www.qf.com/qf/11/22/33/1.html
location /qf {
rewrite ^/qf/([0-9]+)-([0-9]+)-([0-9]+)(.*)$ /qf/$1/$2/$3$4permanent;
}
?
location /qf/11/22/33 {
root /html;
index1.html;
}

2.4、set 指令
set 指令是用于定义一个变量,并且赋值
应用环境:
server,location,if
应用示例
例8:
#http://alice.testpm.com ==> http://www.testpm.com/alice
#http://jack.testpm.com ==> http://www.testpm.com/jack
?
[root@nginx-server conf.d]# cd /usr/share/nginx/html/
[root@nginx-server html]# mkdir jack alice
[root@nginx-server html]# echo "jack.." >> jack/index.html
[root@nginx-server html]# echo "alice.." >> alice/index.html
?
本地解析域名host文件
192.168.62.153 www.testpm.com
192.168.62.153 alice.testpm.com
192.168.62.153 jack.testpm.com
编辑配置文件:
server {
listen80;
server_namewww.testpm.com;
?
location / {
root/usr/share/nginx/html;
indexindex.html index.htm;
if($host~* ^www.testpm.com$){
break;
}
if($host~*"^(.*)\.testpm\.com$" ) {
set $user $1;
rewrite .* http://www.testpm.com/$userpermanent;
}
}
location /jack {
root /usr/share/nginx/html;
indexindex.html index.hml;
}
location /alice {
root /usr/share/nginx/html;
index index.html index.hml;
}
}
2.5、return 指令
return 指令用于返回状态码给客户端
server,location,if
应用示例:
例9:如果访问的.sh结尾的文件则返回403操作拒绝错误
http://www.testpm.com/1.sh返回403
server {
listen80;
server_namewww.testpm.cn;
#access_log/var/log/nginx/http_access.logmain;
?
location / {
root/usr/share/nginx/html;
indexindex.html index.htm;
}
?
location ~* \.sh$ {
return403;
}
}
?
例10:80======>443:80转443端口
server {
listen80;
server_namewww.testpm.cn;
access_log/var/log/nginx/http_access.logmain;
return301https://www.testpm.cn$request_uri;
}
?
server {
listen443ssl;
server_name www.testpm.cn;
access_log/var/log/nginx/https_access.logmain;
?
#ssl on;
ssl_certificate/etc/nginx/cert/2447549_www.testpm.cn.pem;
ssl_certificate_key/etc/nginx/cert/2447549_www.testpm.cn.key;
ssl_session_timeout 5m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphersALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;
ssl_prefer_server_ciphers on;
?
location / {
root/usr/share/nginx/html;
index index.html index.htm;
}
}
?
[root@nginx-server ~]# curl -I http://www.testpm.cn
HTTP/1.1301Moved Permanently
Server: nginx/1.16.0
Date: Wed,03Jul201913:52:30 GMT
Content-Type: text/html
Content-Length:169
Connection: keep-alive
Location: https://www.testpm.cn/
3、last,break详解
[root@localhost test]# cat /etc/nginx/conf.d/last_break.conf
server {
listen80;
server_namelocalhost;
access_log/var/log/nginx/last.access.logmain;
?
location / {
root/usr/share/nginx/html;
indexindex.html index.htm;
}


location /break/ {
root /usr/share/nginx/html;
rewrite .* /test/break.html break;
}


location /last/ {
root /usr/share/nginx/html;
rewrite .* /test/last.html last;
}
?
location /test/ {
root /usr/share/nginx/html;
rewrite .* /test/test.html break;
}
?
}
[root@localhost conf.d]# cd /usr/share/nginx/html/
[root@localhost html]# mkdir test
[root@localhost html]# echo "last" > test/last.html
[root@localhost html]# echo "break" > test/break.html
[root@localhost html]# echo "test" > test/test.html
?
http://192.168.62.159/break/break.html
http://192.168.62.159/last/last.html
注意:
last 标记在本条 rewrite 规则执行完后,会对其所在的 server { … } 标签重新发起请求;
break 标记则在本条规则匹配完成后,停止匹配,不再做后续的匹配;
4.Nginx 的 https( rewrite )
server {
listen80;
server_name*.vip9999.top vip9999.top;
?
if($host~*"^www.vip9999.top$|^vip9999.top$" ) {
return 301 https://www.vip9999.top$request_uri;
}
?
if($host~*"^(.*).vip9999.top$" ) {
set $user $1;
return301https://www.vip9999.top/$user;
}
?
}
?
# Settings for a TLS enabled server.
server {
listen443ssl;
server_namewww.vip9999.top;
?
location / {
root/usr/share/nginx/html;
indexindex.php index.html;
}
?
#pass the PHP scripts to FastCGI server listening on 127.0.0.1:9000
location ~ \.php$ {
root/usr/share/nginx/html;
fastcgi_pass127.0.0.1:9000;
fastcgi_indexindex.php;
fastcgi_paramSCRIPT_FILENAME$document_root$fastcgi_script_name;
includefastcgi_params;
}
ssl on;
ssl_certificate cert/214025315060640.pem;
ssl_certificate_key cert/214025315060640.key;
ssl_session_cache shared:SSL:1m;
ssl_session_timeout10m;
ssl_ciphers HIGH:!aNULL:!MD5;
ssl_prefer_server_ciphers on;
}
5、Apache 的 https ( rewrite )拓展
[root@localhost ~]# yum -y install httpd mod_ssl
[root@localhost ~]# vim /etc/httpd/conf.d/vip9999.conf
nginx的location指令详解
Nginx 的 HTTP 配置主要包括三个区块,结构如下:
http {# 这个是协议级别
include mime.types;
default_type application/octet-stream;
keepalive_timeout65;
gzip on;
server {# 这个是服务器级别
listen80;
server_name localhost;
location / {# 这个是请求级别
root html;
index index.html index.htm;
}
}
}
1、location 区段
location 是在 server 块中配置,根据不同的 URl使用不同的配置,来处理不同的请求。
location 是有顺序的,会被第一个匹配的location 处理。
基本语法如下:
location [=|~|~*|^~|@] pattern{……}
2、location 前缀含义
=表示精确匹配,优先级也是最高的
^~表示url以某个常规字符串开头,理解为匹配url路径即可
~表示区分大小写的正则匹配
~*表示不区分大小写的正则匹配
!~表示区分大小写不匹配的正则
!~*表示不区分大小写不匹配的正则
/通用匹配,任何请求都会匹配到
3、location 配置示例
本地解析域名host
1、没有修饰符 表示:必须以指定模式开始
[root@nginx-server nginx]# pwd
/home/www/nginx
[root@nginx-server nginx]# cat abc/2.html
2.html
?
server {
listen80;
server_namewww.qf.com;
?
location/abc {
root/home/www/nginx;
index2.html;
}
}
那么,如下是对的:
http://www.qf.com/abc
2、=表示:必须与指定的模式精确匹配
server {
listen80;
server_namewww.testpm.cn;
access_log/var/log/nginx/http_access.logmain;
?
location / {
root /usr/share/nginx/html;
index a.html index.htm;
}
location=/ {
root /usr/share/nginx/html;
index b.html index.htm;
}
}
?
进行测试:
http://www.testpm.cn
http://www.testpm.cn/a.html
3、~ 表示:指定的正则表达式要区分大小写
[root@nginx-server nginx]# pwd
/home/www/nginx
[root@nginx-server nginx]# ls
2.htmlabcABC
[root@nginx-server nginx]# cat abc/2.html
abc
[root@nginx-server nginx]# cat ABC/2.html
ABC
?
server {
server_name localhost;
location ~ /abc {
root /home/www/nginx;
index2.html index.html;
}
}
?
那么:
http://192.168.62.153/abc/
4、~* 表示:指定的正则表达式不区分大小写
[root@nginx-server nginx]# pwd
/home/www/nginx
[root@nginx-server nginx]# ls
2.htmlabcABC
[root@nginx-server nginx]# cat abc/2.html
abc
[root@nginx-server nginx]# cat ABC/2.html
ABC
?
server {
server_name localhost;
location ~* /abc {
root /home/www/nginx;
index2.html index.html;
}
}
那么:
http://192.168.62.153/ABC/
5、^~ :类似于无修饰符的行为,也是以指定模式开始,不同的是,如果模式匹配,那么就停止搜索其他模式了。
查找顺序和优先级
=大于 ^~大于 ~|~*|!~|!~* 大于 /
多个location配置的情况下匹配顺序为:首先匹配=,其次匹配^~, 其次是按正则匹配,最后是交给 / 通用匹配。当有匹配成功时候,停止匹配,按当前匹配规则处理请求。
================================================
(1)=:表示完全匹配;
(2) ^~:匹配URI的前缀,如果一个URI同时满足两个规则的话,匹配最长的规则;
(3) ~:匹配正则表达式,大小写敏感;
(4) ~*:匹配正则表达式,大小写不敏感;
优先级:(1)> (2) > (3)=(4)
location 区段匹配示例
?
location=/ {
# 只匹配 / 的查询.
[ configuration A ]
}
location / {
# 匹配任何以 / 开始的查询,但是正则表达式与一些较长的字符串将被首先匹配。
[ configuration B ]
}
location ^~ /images/ {
# 匹配任何以 /images/ 开始的查询并且停止搜索,不检查正则表达式。
[ configuration C ]
}
location ~* \.(gif|jpg|jpeg)$ {
# 匹配任何以gif, jpg, or jpeg结尾的文件,但是所有 /images/ 目录的请求将在Configuration C中处理。
[ configuration D ]
}
各请求的处理如下例:
/ → configuration A
/documents/document.html → configuration B
/images/1.gif → configuration C
/documents/1.jpg → configuration D
4、root 、alias 指令区别
location /img/ {
alias /var/www/image/;
}
#若按照上述配置的话,则访问/img/目录里面的文件时,ningx会自动去/var/www/image/目录找文件
location /img/ {
root /var/www/image;
}
#若按照这种配置的话,则访问/img/目录下的文件时,nginx会去/var/www/image/img/目录下找文件。
alias 是一个目录别名的定义,
root 则是最上层目录的定义。
还有一个重要的区别是alias后面必须要用“/”结束,否则会找不到文件的,而root则可有可无

    推荐阅读