Linux学习108 nginx实现模块化应用实战

一、相应模块

  1、ngx_http_ssl_module模块

    a、ssl on | off

      Enables the HTTPS protocol for the given virtual server

    b、ssl_certificate file

      当前虚拟主机上与其证书匹配的私钥文件

    c、ssl_protocols [SSLv2] [SSLv3] [TLSv1] [TLSv1.1] [TLSv1.2];

      支持ssl协议版本,默认为后三个

    d、ssl_session_cache off | none | [builtln[:size]] [shared:name:size];

      builtin[size]:使用OpenSSL内建的缓存,此缓存为每worker进程私有

      [shared:name:size]:在各worker之间使用一个共享的缓存

    e、ssl_session_timeout time

      客户端一侧的连接可以复用ssl session cache中缓存的ssl参数的有效时长。

    f、配置示例

      (1)、我们在192.168.10.13上配置一个https的虚拟主机。我们把192.168.10.14节点作为CA服务器。

      (2)、我们先在192.168.10.14上创建一个CA

        1)、首先我们创建私钥

[root@node2 ~]# (umask 077;openssl genrsa -out /etc/pki/CA/private/cakey.pem 2048)
Generating RSA private key, 2048 bit long modulus
............................................................+++
.....................................+++
e is 65537 (0x10001)
[root@node2 ~]# ll /etc/pki/CA/private/cakey.pem 
-rw------- 1 root root 1675 Jun 17 20:09 /etc/pki/CA/private/cakey.pem

        2)、然后我们创建一个自签证书

[root@node2 ~]# openssl req -new -x509 -key /etc/pki/CA/private/cakey.pem -out /etc/pki/CA/private/cacert.pem -days 365 
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Chengdu
Locality Name (eg, city) [Default City]:Chengdu
Organization Name (eg, company) [Default Company Ltd]:wohaoshuai
Organizational Unit Name (eg, section) []:devops
Common Name (eg, your name or your server's hostname) []:cahost.wohaoshuai.com
Email Address []:

        3)、创建相应的文件和路径

[root@node2 ~]# echo 01 > /etc/pki/CA/serial

      (3)、我们在192.168.10.13上创建相应的私钥和证书申请文件

        1)、创建存放路径

[root@www /]# mkdir -p /etc/nginx/ssl
[root@www /]# cd /etc/nginx/ssl

        2)、创建nginx的私钥

[root@www ssl]# (umask 077; openssl genrsa -out /etc/nginx/ssl/nginx.key 2048)
Generating RSA private key, 2048 bit long modulus
..........................+++
...+++
e is 65537 (0x10001)

        3)、创建证书签署请求

[root@www ssl]# openssl req -new -key /etc/nginx/ssl/nginx.key -out /etc/nginx/ssl/nginx.csr -days 365
You are about to be asked to enter information that will be incorporated
into your certificate request.
What you are about to enter is what is called a Distinguished Name or a DN.
There are quite a few fields but you can leave some blank
For some fields there will be a default value,
If you enter '.', the field will be left blank.
-----
Country Name (2 letter code) [XX]:CN
State or Province Name (full name) []:Chengdu 
Locality Name (eg, city) [Default City]:Chengdu
Organization Name (eg, company) [Default Company Ltd]:wohaoshuai
Organizational Unit Name (eg, section) []:devops
Common Name (eg, your name or your server's hostname) []:www.wohaoshuai1.com
Email Address []:1209989516@qq.com

Please enter the following 'extra' attributes
to be sent with your certificate request
A challenge password []:    
An optional company name []:

        4)、然后将这个证书签署请求从192.168.10.13复制到192.168.10.14进行签署

[root@www ssl]# scp /etc/nginx/ssl/nginx.csr root@192.168.10.14:/tmp/
root@192.168.10.14's password: 
nginx.csr

          然后在192.168.10.14进行签署

[root@node2 CA]# openssl ca -in /tmp/nginx.csr -out /etc/pki/CA/certs/nginx.crt -days 365
Using configuration from /etc/pki/tls/openssl.cnf
Check that the request matches the signature
Signature ok
Certificate Details:
        Serial Number: 1 (0x1)
        Validity
            Not Before: Jun 18 01:58:12 2020 GMT
            Not After : Jun 18 01:58:12 2021 GMT
        Subject:
            countryName               = CN
            stateOrProvinceName       = Chengdu
            organizationName          = wohaoshuai
            organizationalUnitName    = devops
            commonName                = www.wohaoshuai1.com
            emailAddress              = 1209989516@qq.com
        X509v3 extensions:
            X509v3 Basic Constraints: 
                CA:FALSE
            Netscape Comment: 
                OpenSSL Generated Certificate
            X509v3 Subject Key Identifier: 
                B1:1A:16:00:86:31:44:A5:C6:EA:E1:2C:CC:4F:49:EA:EE:0D:41:7C
            X509v3 Authority Key Identifier: 
                keyid:CF:B4:6A:51:6B:CE:9E:E8:25:6B:91:65:09:CC:4B:AE:53:66:85:28

Certificate is to be certified until Jun 18 01:58:12 2021 GMT (365 days)
Sign the certificate? [y/n]:y


1 out of 1 certificate requests certified, commit? [y/n]y
Write out database with 1 new entries
Data Base Updated

          然后将签署的证书复制到192.168.10.13上

        5)、然后我们在192.168.10.13主机上就可以看到相应的证书了

[root@www nginx]# ll /etc/nginx/ssl/
总用量 16
-rw-r--r-- 1 root root 4603 6月  18 10:00 nginx.crt
-rw-r--r-- 1 root root 1070 6月  18 09:56 nginx.csr
-rw------- 1 root root 1675 6月  18 09:55 nginx.key

      (4)、然后我们在192.168.10.13上开始做证书配置

[root@www /]# cat  /etc/nginx/conf.d/vhost1_ssl.conf 
server {
    listen 443 ssl; 
    server_name www.wohaoshuai1.com;
    root /data/nginx/vhost1;
    access_log /var/log/nginx/vhost1_ssl_access.log main; #这个main是主配置文件/etc/nginx/nginx.conf中定义的main类日志格式

    #ssl on;
    ssl_certificate /etc/nginx/ssl/nginx.crt;
    ssl_certificate_key  /etc/nginx/ssl/nginx.key;
    ssl_protocols sslv3 tlsv1 tlsv1.1 tlsv1.2;    
    ssl_session_cache shared:SSL:10m;

    location / {
        #root /data/nginx/vhost2; 
        allow all;
}
    location ~* ^/(admin|login) {
        auth_basic "admin area or login url";
        auth_basic_user_file /etc/nginx/.ngxpasswd;
        access_log /var/log/nginx/vhost1_admin_access.log main;
} 

    location ~*\.(jpg|png)$ {
        deny 192.168.10.14;
        allow all;
}
    location ^~ /images/ {
        alias /data/pictures/;
}
    error_page 404 =200 /notfound.html;
    location = /notfound.html {
        root /data/nginx/error_pages;
}
    location /ngxstatus { #最好把auth_basic也写上,因为不能随意让其他人访问
        stub_status;
        access_log off;
}
}
[root@www /]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@www /]# nginx -s reload
[root@www /]# netstat -anpt|grep 443
tcp        0      0 0.0.0.0:443             0.0.0.0:*               LISTEN      2924/nginx: master 

      (5)、然后我们在浏览器中导入192.168.10.14的自签证书就可以正常进行https访问了。

  2、ngx_http_rewrite_module模块

    a、The ngx_http_rewrite_module module is used to change request URI using PCRE regular expressions,return redirects,and conditionally select configurations

    b、bbs.wohaoshuai.com/  --> www.wohaoshuai.com/bbs/,http://www.wohaoshuai.com/ --> https://www.wohaoshuai.com/  :重写的意思是,可以看到我们用户去访问bbs.wohaoshuai.com下面的/的时候我们要将其路径转换为www.wohaoshuai.com/bbs/这个路径

      http://www.wohaoshuai.com/login.php:username=tom --> http://www.wohaoshuai.com/tom/

      所以这个请求就变成这样:我们客户端发请求请求的URL是www.wohaoshuai.com/bbs,我们主机在自己内部读取配置文件时发现这个URL其实已经本地不存在了改成别的了,于是返回一个信息给客户端告诉你新位置在响应报文中使用location这个响应报文守护,指定新位置为http://bbs.wohaoshuai.com/,于是你的客户端浏览器会再一次自动的去找bbs.wohaoshuai.com这个域名,这个域名可能是另外一台服务器,那么bbs.wohaoshuai.com这台服务器就返回结果给我们的主机。

      还有一种情形,假如我们网站做的全栈https,比如你访问www.wohaoshuai.com就是明文的,现在假如我们不期望是明文的要怎么办呢?这时候我们就可以重定向,即将www.wohaoshuai.com的访问重定向到https://www.wohaoshuai.com上

      假如现在我们有http://www.wohaoshuai.com/media/audio/.wmv这个站点文件,这是一个音频文件,这个文件压缩以后失真比较大,我们后来对各种音频文件重新提供了mp3格式的,但是很多人通常还是习惯访问这种格式要怎么办呢?而且我们把路径也改了,改成了http://www.wohaoshuai.com/media/mp3/a.mp3了,于是再有人访问我们原链接时我们就将其重写为http://www.wohaoshuai.com/media/mp3/a.mp3。

    c、将用户请求的URL基于regex所描述的模式进行检查,而后完成替换

    d、rewrite regex replacement [flag]

      (1)、将用户请求的URL基于regex所描述的模式进行检查,匹配到时将其替换为replacement指定的新的URL;

      (2)、注意:如果在同一级配置块中存在多个rewrite规则,那么会自上而下逐个检查,被某条件规则替换完成后,会重新一轮的替换检查,因此,隐含有循环机制;[flag]所表示的标志位用于控制此循环机制

      (3)、如果replacement是以http://或https://开头,则替换结果会直接以重向返回给客户端

        301:永久重定向

    e、[flag]:

      (1)、last:重写完成后停止对当前URL在当前location中后续的其它重写操作,而后对新的URL启动新一轮重写检查,提前重启新一轮循环。即在一个配置段中你很有可能有多条rewrite规则,比如某个location其内部的rewrite规则有三条,他是怎么去实现这些规则检查的呢?其实他的工作逻辑是这样的,即用户请求这个url时他只要匹配到这个URL他才会到里面的rewrite上来,第一个rewrite检查完以后就重写完成了,完成后意味着已经是一个新URL了,新的URL还能匹配这个location么?是不一定的,因此一旦规则重写完以后他会拿着新的URL去重新检查整个配置文件的,或者你可以理解为他会再去检查整个配置文件中location的规则。直到循环到再也匹配不到谁了于是这个location就处理完往后走了。我们发现我们的循环有点像continue,即一旦被某个规则匹配了那就提前结束本轮循环而进入下一轮,而下一轮如果被某个rewrite匹配了就又提前结束本轮循环再到下一轮。我们的默认的行为就是这样的。因此我们每一个循环后面我们可以写一个last标志,他的意思是如果本次匹配到了就将重写后的URL拿过来再重新循环进行匹配检查。但是我们这种行为有可能导致死循环,因为有可能存在说第一条改回去被第二条匹配,第二条改回去又被第一条匹配。

        

      (2)、break,那么我们如果明知道第一条改写完后第二条能匹配,第二条改写完后第一条能匹配,现在我们期望的是由第一条改完以后第二条就不要检查了,或者由第二条改完以后第一条就不要再检查了,我们就可以使用break,即跳出循环。

        

 

         图中表示如果第一个rewrite检查匹配了就直接跳到后面的配置中去了,就不需要再循环检查了。

      (3)、redirect,表示重定向。即使用302的重定向响应码来响应,即告诉客户端这是重定向的。我们一般默认的响应码都是200,即浏览器自己就给你重定向新位置去了。如果我们改成了redirect,那么他会告诉客户端新的位置在哪儿,然后客户端就自己请求新位置。即使用redirect就是客户端你自己动,不使用redirect的话就是服务器主动。

      (4)、permanent,表示永久重定向,即客户端请求的时候重定向响应码为301,但是访问到的资源的响应码为200。此配置也是需要浏览器重新发请求的。

    f、return

      return code [text];

      return code URL;

      return URL;

      Stops processing and returns the specified code to a client

    g、rewrite_log on | off

      是否开启重写日志

    h、if (condition){...}

      (1)、引入一个新的配置上下文,条件满足时,执行配置块中的配置命令;server,location

      (2)、condition:

        1)、比较操作符:

          ==

          !=

          ~:模式匹配,区分字符大小写

          ~*:模式匹配,不区分字符大小写

          !~:模式不匹配,区分字符大小写

          !~*:模式不匹配,不区分字符大小写

        2)、文件即目录存在性判断:

          -e,!-e

          -f,!-f

          -d,!-d

          -x,!-x

    i、set $variable value

      用户自定义变量;

    g、示例

      (1)示例1:假如此前我们访问我们服务器上的图片都是png格式的,后来我们提供了jpg格式的,即只要访问png格式的我们统统给你重写成jpg结尾的。

      :  1)、在配置文件中进行配置

server {
    listen 80;
    server_name www.wohaoshuai1.com;
    root /data/nginx/vhost1;
    access_log /var/log/nginx/vhost1_access.log main; #这个main是主配置文件/etc/nginx/nginx.conf中定义的main类日志格式
    rewrite /(.*)\.png$ /$1.jpg;
    location / {
        #root /data/nginx/vhost2; 
        allow all;
}
    location ~* ^/(admin|login) {
        auth_basic "admin area or login url";
        auth_basic_user_file /etc/nginx/.ngxpasswd;
        access_log /var/log/nginx/vhost1_admin_access.log main;
} 

    location ~*\.(jpg|png)$ {
        deny 192.168.10.14;
        allow all;
}
    location ^~ /images/ {
        alias /data/pictures/;
}
    error_page 404 =200 /notfound.html;
    location = /notfound.html {
        root /data/nginx/error_pages;
}
    location /ngxstatus { #最好把auth_basic也写上,因为不能随意让其他人访问
        stub_status;
        access_log off;
}
}

          配置文件中的/(.*)\.png$  /$1.jpg 的意思是/下匹配任意多个内容然后以.png结尾的文件都重写成/下任意内容.jpg,其中的这个$1是引用的前面的这个(.*)。后面重写的/$1.jpg这一项是不支持正则表达式的,因此我们的点号不用添加转义。

          2)、我们查看我们相应目录中的图片

[root@www images]# ll /data/pictures/
总用量 960
drwxr-xr-x 2 root root     25 6月  18 13:23 images
-rw-r--r-- 1 root root 980265 6月  18 13:25 morning.jpg

          3)、然后我们访问http://www.wohaoshuai1.com/images/morning.png,可以看到我们服务器上并没有morning.png这个图片,但是我们可以访问到morning.jpg,这是因为我们对访问的url进行了重写。

      (2)、示例2:用户无论请求任何内容,都统统改写为https://www.wohaoshuai1.com/加相应的路径内容

        1)、配置文件配置

[root@www images]# cat /etc/nginx/conf.d/vhost1.conf
server {
    listen 80;
    server_name www.wohaoshuai1.com;
    root /data/nginx/vhost1;
    access_log /var/log/nginx/vhost1_access.log main; #这个main是主配置文件/etc/nginx/nginx.conf中定义的main类日志格式
    #rewrite /(.*)\.png$ /$1.jpg;
    rewrite /(.*)$ https://www.wohaoshuai1.com/$1;
    location / {
        #root /data/nginx/vhost2; 
        allow all;
}
    location ~* ^/(admin|login) {
        auth_basic "admin area or login url";
        auth_basic_user_file /etc/nginx/.ngxpasswd;
        access_log /var/log/nginx/vhost1_admin_access.log main;
} 

    location ~*\.(jpg|png)$ {
        deny 192.168.10.14;
        allow all;
}
    location ^~ /images/ {
        alias /data/pictures/;
}
    error_page 404 =200 /notfound.html;
    location = /notfound.html {
        root /data/nginx/error_pages;
}
    location /ngxstatus { #最好把auth_basic也写上,因为不能随意让其他人访问
        stub_status;
        access_log off;
}
}
[root@www images]# nginx -t
nginx: the configuration file /etc/nginx/nginx.conf syntax is ok
nginx: configuration file /etc/nginx/nginx.conf test is successful
[root@www images]# nginx -s reload

        2)、然后我们访问http://www.wohaoshuai1.com/的时候就发现会被重定向到https://www.wohaoshuai1.com/

      (3)、示例3

        1)、如果我们上面的两个rewrite都写上,那么两个规则都会生效的,比如我们请求http://www.wohaoshuai1.com/images/morning.png他就会将我们的连接重写为http://www.wohaoshuai1.com/images/morning.jpg,然后他又会将我们的http://www.wohaoshuai1.com/images/morning.jpg链接重写为https://www.wohaoshuai1.com/images/morning.jpg。我们在示例1中请求的内容在浏览器中看到的是http://www.wohaoshuai1.com/images/morning.png,而此时我们在浏览器中看到的就是https://www.wohaoshuai1.com/images/morning.jpg了。因此两个规则都生效的。即我们的规则是会自上而下依次检查匹配的。那么这儿检查是怎么实现的呢?为什么检查完第一个还要检查第二个呢?我能不能改成别的呢?并且万一我们写了两条规则造成死循环,第一条匹配完就匹配第二条第二条匹配完后又匹配第一条。

      (4)、rewrite flag配置

[root@www images]# cat /etc/nginx/conf.d/vhost1.conf
server {
    listen 80;
    server_name www.wohaoshuai1.com;
    root /data/nginx/vhost1;
    access_log /var/log/nginx/vhost1_access.log main; #这个main是主配置文件/etc/nginx/nginx.conf中定义的main类日志格式
    #rewrite /(.*)\.png$ /$1.jpg;
    rewrite /(.*)$ https://www.wohaoshuai1.com/$1 break;
    location / {
        #root /data/nginx/vhost2; 
        allow all;
}
    location ~* ^/(admin|login) {
        auth_basic "admin area or login url";
        auth_basic_user_file /etc/nginx/.ngxpasswd;
        access_log /var/log/nginx/vhost1_admin_access.log main;
} 

    location ~*\.(jpg|png)$ {
        deny 192.168.10.14;
        allow all;
}
    location ^~ /images/ {
        alias /data/pictures/;
}
    error_page 404 =200 /notfound.html;
    location = /notfound.html {
        root /data/nginx/error_pages;
}
    location /ngxstatus { #最好把auth_basic也写上,因为不能随意让其他人访问
        stub_status;
        access_log off;
}
}

   3、ngx_http_referer_module模块

    a、The ngx_http_referer_module module is used to block access to a site for requests with invalid values in the "Referer" header field。即我们的网站允许谁来引用

    b、valid_referers none | blocked | server_names | string ...; #即合法引用,即我们网站的图片只允许我们自己的站点来引用,别的网站引用我都可以拒绝你。我们这儿是定义谁是合法的,不符合我们定义的都是非法的

      (1)、定义referer首部的合法可用值

        none:请求报文首部没有referer首部。即request报文中没有referer引用标签的话就合法,即可以引用我们的资源。我们如果一开始直接输入我们的连接的话就没有引用,即request中没有referer字段,如果我们是从某个链接跳转过去的那么就有referer字段了,我们也就没法引用了。

        blocked:请求报文的referer首部没有值。即我们request中有referer字段但是没有值,他没有值的话就无法判定他来自于哪儿,有可能这个值被他的代理服务器给删掉了,所以就只能委屈的放行让其访问了。

        server_names:参数,其可以有值作为主机名或主机名模式

        regular expression:被指定的正则表达式模式匹配到的字符串;要使用~打头,例如~.*\.wohaoshuai\.com;

    c、配置示例:

      valid_referers none block server_names *.wohaoshuai.com *.wohaooshuai.com  wohaoshuai.*  wohaooshuai.*  ~\.wohaoshuai\.;

      if($invalid_referer){

          return 403;

        }

       上面的意思是我们网站允许哪些站点引用,如果不是被允许的就返回403,即非法引用就返回403;

      我们还可以将其return到某个链接上去,比如

      if($invalid_referer){

          return http://www,wohaoshuai.com/invalid.jpg;

        }

 

posted @ 2020-06-17 20:26  Presley  阅读(259)  评论(0编辑  收藏  举报