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_format  main'$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_name  localhost;

   location / {

       root   /usr/share/nginx/html;

       index  index.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_name  localhost;

   location / {

       root   /usr/share/nginx/html;

       index  index.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_name  localhost;

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

a  b

[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_name  www.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_name  www.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

# 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;

       index   index.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.html  index.html  index.html.bak1  reg

[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_name  www.testpm.com;

   location / {

        root   /usr/share/nginx/html;

        index  index.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;

        index  index.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_name  www.testpm.cn;

#access_log  /var/log/nginx/http_access.log  main;

   location / {

       root   /usr/share/nginx/html;

       index  index.html index.htm;

       }

location ~* \.sh$ {

return403;

       }

}

例10:80======>443:80转443端口

server {

listen80;

   server_name  www.testpm.cn;

   access_log  /var/log/nginx/http_access.log  main;

return301https://www.testpm.cn$request_uri;

}

server {

listen443ssl;

   server_name www.testpm.cn;

   access_log  /var/log/nginx/https_access.log  main;

#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_ciphers  ALL:!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_name  localhost;

   access_log  /var/log/nginx/last.access.log  main;

   location / {

       root   /usr/share/nginx/html;

       index  index.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_name  www.vip9999.top;

       location / {

               root      /usr/share/nginx/html;

               index     index.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_index  index.php;

fastcgi_param  SCRIPT_FILENAME$document_root$fastcgi_script_name;

           include        fastcgi_params;

       }

       ssl on;

       ssl_certificate cert/214025315060640.pem;

       ssl_certificate_key cert/214025315060640.key;

       ssl_session_cache shared:SSL:1m;

       ssl_session_timeout  10m;

       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_name  www.qf.com;

   location  /abc {

       root    /home/www/nginx;

index2.html;

       }

}

那么,如下是对的:

http://www.qf.com/abc

2、=表示:必须与指定的模式精确匹配

server {

listen80;

   server_name  www.testpm.cn;

   access_log  /var/log/nginx/http_access.log  main;

   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.html  abc  ABC

[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.html  abc  ABC

[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则可有可无

你可能感兴趣的:(nginx 防盗链 地址重写 rewrite)