Nginx配置HTTPS与http运维实践(2018-8-28更新)

0x00前言

最近采用Linux+Nginx+PHP+Mysql的方式搭建一个CodeIgniter框架的系统,需求为除了某个特定URL采用HTTP访问以外,其余均强制采用HTTPS访问。
2018-8-28更新配置实现,特定路径(如:/api/*)采用HTTP访问以外,其余均强制采用HTTPS访问。

0x01系统搭建

0x02特定URL采用HTTP访问以外,其余均强制采用HTTPS访问的Nginx配置

  1. 按照前面系统搭建过程安装并配置、选择采用全部重定向HTTPS的默认配置文件如下:

    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
    server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    server_name 域名或IP地址;

    location / {
    try_files $uri $uri/ =404;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root /usr/share/nginx/html;
    }

    location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    }
    listen 443 ssl; # managed by Certbot
    ssl_certificate fullchain.pem文件路径; # managed by Certbot
    ssl_certificate_key privkey.pem文件路径; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot


    if ($scheme != "https") {
    return 301 https://$host$request_uri;
    } # managed by Certbot
    }
  2. 根据需求添加对CodeIgniter框架的支持和某个特定URL采用HTTP访问,其余均强制采用HTTPS访问。

    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
    server {
    listen 80 default_server;
    listen [::]:80 default_server ipv6only=on;

    root /usr/share/nginx/html;
    index index.php index.html index.htm;

    server_name 域名;

    location / {
    try_files $uri $uri/ =404;
    }

    location /二级目录/ {
    try_files $uri /二级目录/index.php;
    }

    error_page 404 /404.html;
    error_page 500 502 503 504 /50x.html;
    location = /50x.html {
    root /usr/share/nginx/html;
    }

    location ~ \.php$ {
    try_files $uri =404;
    fastcgi_split_path_info ^(.+\.php)(/.+)$;
    fastcgi_pass unix:/var/run/php5-fpm.sock;
    fastcgi_index index.php;
    fastcgi_param PATH_INFO $fastcgi_path_info;
    fastcgi_param SCRIPT_FILENAME $document_root$fastcgi_script_name;
    include fastcgi_params;
    }

    listen 443 ssl; # managed by Certbot
    ssl_certificate /etc/letsencrypt/live/域名/fullchain.pem; # managed by Certbot
    ssl_certificate_key /etc/letsencrypt/live/域名/privkey.pem; # managed by Certbot
    include /etc/letsencrypt/options-ssl-nginx.conf; # managed by Certbot
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem; # managed by Certbot

    set $flag 0;
    if ($scheme != "https") {
    set $flag "${flag}1";
    }
    if ($request_uri != "特定的URL") {
    set $flag "${flag}2";
    }

    if ($flag = "012") {
    return 301 https://$host$request_uri;
    } # managed by Certbot

    }

其中主要添加如下两处配置配置:

  • 对CodeIgniter框架的支持

    1
    fastcgi_param   PATH_INFO $fastcgi_path_info;
  • 某个特定URL采用HTTP访问以外,其余均强制采用HTTPS访问添加的配置,由于Nginx的判断if条件不支持逻辑&&,需求的等价逻辑如下:

    1
    2
    3
    if ($scheme != "https" && $request_uri != "特定的URL" ){
    return 301 https://$host$request_uri;
    }

曲折的具体实现为:

1
2
3
4
5
6
7
8
9
10
11
set $flag 0;
if ($scheme != "https") {
set $flag "${flag}1";
}
if ($request_uri != "特定的URL") {
set $flag "${flag}2";
}

if ($flag = "012") {
return 301 https://$host$request_uri;
} # managed by Certbot

0x03特定路径(如:/api/*)采用HTTP访问以外,其余均强制采用HTTPS访问的Nginx配置

曲折的具体实现为:

1
2
3
4
5
6
7
8
9
10
11
set $flag 0;
if ($scheme != "https") {
set $flag "${flag}1";
}
if ($request_uri !~= /特定路径/*) {
set $flag "${flag}2";
}

if ($flag = "012") {
return 301 https://$host$request_uri;
} # managed by Certbot

0x04小结

通常网络上关于NginxHTTPS配置主要有两种:HTTP和HTTPS同时存在或者所有HTTP强制转发HTTPS。然而项目需要特定URL支持HTTP访问,其余URL强制采用HTTPS,所有产生了本文。此外添加$scheme != “https”的判断是为了防止请求被循环重定向导致网页无法正常访问的问题,由于Nginx配置文件不支持逻辑与(and),采用等价的配置完成需要的功能。