Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法


Posted in Python onAugust 16, 2015

HTTPS简介
HTTPS(Hyper Text Transfer Protocol Secure),是一种基于SSL/TLS的HTTP,所有的HTTP数据都是在SSL/TLS协议封装之上进行传输的。HTTPS协议是在HTTP协议的基础上,添加了SSL/TLS握手以及数据加密传输,也属于应用层协议。Https使用的默认端口是443。更多HTTPS原理可以参考阮一峰老师的文章:http://www.ruanyifeng.com/blog/2014/02/ssl_tls.html

SSL证书
证书类型简介
要设置安全服务器,使用公共钥创建一对公私钥对。大多数情况下,发送证书请求(包括自己的公钥),你的公司证明材料以及费用到一个证书颁发机构(CA)。CA验证证书请求及您的身份,然后将证书返回给您的安全服务器。
但是内网实现一个服务器端和客户端传输内容的加密,可以自己给自己颁发证书,只需要忽略掉浏览器不信任的警报即可!
由CA签署的证书为您的服务器提供两个重要的功能:

  1.     浏览器会自动识别证书并且在不提示用户的情况下允许创建一个安全连接。
  2.     当一个CA生成一个签署过的证书,它为提供网页给浏览器的组织提供身份担保。

    多数支持ssl的web服务器都有一个CA列表,它们的证书会被自动接受。当一个浏览器遇到一个其授权CA并不在列表中的证书,浏览器将询问用户是否接受或拒绝连接。

制作CA证书
ca.key CA私钥:

    openssl genrsa -des3 -out ca.key 2048  

Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

    ca.crt CA根证书(公钥):

openssl req -new -x509 -days 365 -key ca.key -out ca.crt

Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

制作网站的证书并用CA签名认证
这里,假设网站域名为www.example.com,生成com.example.com证书私钥:

 

openssl genrsa -des3 -out www.example.com.pem 1024

Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

    制作解密后的www.example.com证书私钥:

openssl rsa -in www.example.com.pem -out www.example.com.key

Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

    生成签名请求:

openssl req -new -key www.example.com.pem -out www.example.com.csr

   

Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

    可以在Common Name中填入网站域名,即可生产该网站的证书。
用CA进行签名:

   
openssl ca -policy policy_anything -days 365 -cert ca.crt -keyfile ca.key -in www.example.com.csr -out www.example.com.crt 
可能执行签名时,会出现“I am unable to access the ./demoCA/newcerts directory”问题:

Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

解决方法:

mkdir -p demoCA/newcerts 
  touch demoCA/index.txt 
  touch demoCA/serial 
  echo "01" > demoCA/serial

然后,再执行签名命令即可。

基于Nginx搭建HTTPS虚拟主机
虚拟主机配置文件

upstream sslfpm { 
    server 127.0.0.1:9000  weight=10  max_fails=3 fail_timeout=20s; 
  } 
   
  server {  
    listen    192.168.1.*:443;  
    server_name 192.168.1.*;  
     
    #为一个server开启ssl支持 
    ssl         on; 
    #为虚拟主机指定pem格式的证书文件 
    ssl_certificate   /home/wangzhengyi/ssl/wangzhengyi.crt;  
    #为虚拟主机指定私钥文件 
    ssl_certificate_key /home/wangzhengyi/ssl/wangzhengyi_nopass.key;  
    #客户端能够重复使用存储在缓存中的会话参数时间 
    ssl_session_timeout 5m; 
    #指定使用的ssl协议  
    ssl_protocols SSLv3 TLSv1;  
    #指定许可的密码描述 
    ssl_ciphers ALL:!ADH:!EXPORT56:RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv2:+EXP;  
    #SSLv3和TLSv1协议的服务器密码需求优先级高于客户端密码 
    ssl_prefer_server_ciphers  on;  
   
    location / {  
      root  /home/wangzhengyi/ssl/; 
      autoindex on; 
        autoindex_exact_size  off; 
        autoindex_localtime on; 
    }  
      # redirect server error pages to the static page /50x.html 
      # 
      error_page  500 502 503 504 /50x.html; 
      error_page  404 /404.html; 
   
    location = /50x.html { 
        root  /usr/share/nginx/www; 
      } 
    location = /404.html { 
        root  /usr/share/nginx/www; 
      } 
     
      # proxy the PHP scripts to fpm 
      location ~ \.php$ { 
      access_log /var/log/nginx/ssl/ssl.access.log main; 
      error_log /var/log/nginx/ssl/ssl.error.log; 
      root /home/wangzhengyi/ssl/;  
      fastcgi_param  HTTPS  on; 
        include /etc/nginx/fastcgi_params;  
        fastcgi_pass  sslfpm; 
      } 
  }

HTTPS服务器优化
方法
SSL操作需要消耗CPU资源,所以在多处理器的系统,需要启动多个工作进程,而且数量需要不少于可用CPU的个数。最消耗CPU资源的SSL操作是SSL握手,有两种方法可以将每个客户端的握手操作数量降到最低:

    保持客户端长连接,在一个SSL连接发送多个请求
    在并发的连接或者后续的连接中重用SSL会话参数,这样可以避免SSL握手操作。

会话缓存用于保存SSL会话,这些缓存在工作进程间共享,可以使用ssl_session_cache指令进行配置。1M缓存可以存放约4000个会话。默认的缓存超时时间是5m,可以使用ssl_session_timeout加大它。
ssl_session_cache指令

    语法:ssl_session_cache off|none|builtin:size|shared:name:size 
    使用环境:main,server 
    缓存类型: 
    off -- 硬关闭,nginx明确告诉客户端这个会话不可重用 
    none -- 软关闭,nginx告诉客户端会话能够被重用,但是nginx实际上不会重用它们 
    bultin -- openssl内置缓存,仅可用于一个工作进程.可能导致内存碎片 
    shared -- 所有工作进程的共享缓存。(1)缓存大小用字节数指定(2)每个缓存必须拥有自己的名称(3)同名的缓存可用于多个虚拟主机 

优化示例

#优化ssl服务 
  ssl_session_cache  shared:wzy:10m;  
  #客户端能够重复使用存储在缓存中的会话参数时间 
  ssl_session_timeout 10m;

nginx强制使用https访问(http跳转到https)

基于nginx搭建了一个https访问的虚拟主机,监听的域名是test.com,但是很多用户不清楚https和http的区别,会很容易敲成http://test.com,这时会报出404错误,所以我需要做基于test.com域名的http向https的强制跳转

nginx的rewrite方法

思路
这应该是大家最容易想到的方法,将所有的http请求通过rewrite重写到https上即可

配置

server { 
    listen 192.168.1.111:80; 
    server_name test.com; 
     
    rewrite ^(.*)$ https://$host$1 permanent; 
  }

搭建此虚拟主机完成后,就可以将http://test.com的请求全部重写到https://test.com上了

nginx的497状态码

error code 497

  497 - normal request was sent to HTTPS

解释:当此虚拟站点只允许https访问时,当用http访问时nginx会报出497错误码

思路
利用error_page命令将497状态码的链接重定向到https://test.com这个域名上

配置

server { 
    listen    192.168.1.11:443; #ssl端口 
    listen    192.168.1.11:80;  #用户习惯用http访问,加上80,后面通过497状态码让它自动跳到443端口 
    server_name test.com; 
    #为一个server{......}开启ssl支持 
    ssl         on; 
    #指定PEM格式的证书文件  
    ssl_certificate   /etc/nginx/test.pem;  
    #指定PEM格式的私钥文件 
    ssl_certificate_key /etc/nginx/test.key; 
     
    #让http请求重定向到https请求  
    error_page 497 https://$host$uri?$args; 
  }

index.html刷新网页

思路
上述两种方法均会耗费服务器的资源,我们用curl访问baidu.com试一下,看百度的公司是如何实现baidu.com向www.baidu.com的跳转

Nginx搭建HTTPS服务器和强制使用HTTPS访问的方法

可以看到百度很巧妙的利用meta的刷新作用,将baidu.com跳转到www.baidu.com.因此我们可以基于http://test.com的虚拟主机路径下也写一个index.html,内容就是http向https的跳转

index.html

  <html> 
  <meta http-equiv="refresh" content="0;url=https://test.com/"> 
  </html>
Python 相关文章推荐
Python实现周期性抓取网页内容的方法
Nov 04 Python
Python使用smtp和pop简单收发邮件完整实例
Jan 09 Python
Python中关键字global和nonlocal的区别详解
Sep 03 Python
Python元组知识点总结
Feb 18 Python
Django之无名分组和有名分组的实现
Apr 16 Python
python使用opencv在Windows下调用摄像头实现解析
Nov 26 Python
python内置模块collections知识点总结
Dec 19 Python
python可视化text()函数使用详解
Feb 11 Python
Python读取分割压缩TXT文本文件实例
Feb 14 Python
pytorch查看通道数 维数 尺寸大小方式
May 26 Python
python怎么判断素数
Jul 01 Python
Python Process创建进程的2种方法详解
Jan 25 Python
使用Python操作MySQL的一些基本方法
Aug 16 #Python
Python中list列表的一些进阶使用方法介绍
Aug 15 #Python
Python中的super()方法使用简介
Aug 14 #Python
在Python中使用正则表达式的方法
Aug 13 #Python
简单讲解Python中的闭包
Aug 11 #Python
Python实现短网址ShortUrl的Hash运算实例讲解
Aug 10 #Python
python实现web方式logview的方法
Aug 10 #Python
You might like
PHP新手上路(十四)
2006/10/09 PHP
php preg_match_all结合str_replace替换内容中所有img
2008/10/11 PHP
php中取得URL的根域名的代码
2011/03/23 PHP
php skymvc 一款轻量、简单的php
2011/06/28 PHP
php标签云的实现代码
2012/10/10 PHP
利用浏览器的Javascript控制台调试PHP程序
2014/01/08 PHP
PHP SOCKET编程详解
2015/05/22 PHP
详细解读php的命名空间(二)
2018/02/21 PHP
指定js可访问其它域名的cookie的方法
2007/09/18 Javascript
JavaScript 关键字屏蔽实现函数
2009/08/02 Javascript
nodejs npm install全局安装和本地安装的区别
2014/06/05 NodeJs
Jquery自定义button按钮的几种方法
2014/06/11 Javascript
JavaScript 学习笔记之变量及其作用域
2015/01/14 Javascript
js+CSS实现弹出居中背景半透明div层的方法
2015/02/26 Javascript
js实现完全自定义可带多级目录的网页鼠标右键菜单方法
2015/02/28 Javascript
JavaScript实现跑马灯抽奖活动实例代码解析与优化(一)
2016/02/16 Javascript
php基于redis处理session的方法
2016/03/14 Javascript
Bootstrap表单使用方法详解
2017/02/17 Javascript
实例解析ES6 Proxy使用场景介绍
2018/01/08 Javascript
vue-infinite-loading2.0 中文文档详解
2018/04/08 Javascript
通过vue-cli3构建一个SSR应用程序的方法
2018/09/13 Javascript
JavaScript:ES2019 的新特性(译)
2019/08/08 Javascript
微信浏览器左上角返回按钮监听的实现
2020/03/04 Javascript
vue2.0 watch里面的 deep和immediate用法说明
2020/10/30 Javascript
python超简单解决约瑟夫环问题
2015/05/12 Python
老生常谈Python之装饰器、迭代器和生成器
2017/07/26 Python
Python探索之Metaclass初步了解
2017/10/28 Python
Python实现简易版的Web服务器(推荐)
2018/01/29 Python
Python基于dom操作xml数据的方法示例
2018/05/12 Python
Keras 切换后端方式(Theano和TensorFlow)
2020/06/19 Python
编程实现去掉XML的重复结点
2014/05/28 面试题
土木工程实习生自我鉴定
2013/09/19 职场文书
青年标兵事迹材料
2014/08/16 职场文书
党的群众路线教育实践活动个人对照检查材料范文
2014/09/25 职场文书
公务员群众路线心得体会
2014/11/03 职场文书
结婚保证书(三从四德)
2015/02/26 职场文书