http 切换至 https 相关配置

本贴最后更新于 2903 天前,其中的信息可能已经沧海桑田

1. 背景

为了更好的用户体验以及满足 apple 相关政策,启用了 https,需要去各大主机商那里购买 SSL 证书,https 的好处大概以下几点:

  • 数据传输加密,防止信息被窃取;
  • 防止被欺诈,增加网站信任,防钓鱼;
  • 防止被劫持;

部署了 https 的整体结构如图:

tool-manage

2. 应用中配置 https

https 配置,以 nginx 为例,参考:http://www.cnblogs.com/wang_yb/p/4330689.htmlhttps://iyaozhen.com/nginx-https-conf.html

2.1 生成证书,使用 openssl 工具来生成对应的证书:


cd /etc/nginx

openssl genrsa -des3 -out server.key 1024         # 设置证书密码

openssl req -new -key server.key -out server.csr  # 根据提示输入各种信息

cp server.key server.key.org

openssl rsa -in server.key.org -out server.key

openssl x509 -req -days 365 -in server.csr -signkey server.key -out server.crt

生成的 csr 文件包含了主要的证书信息,key 文件主要包含了密钥交换和加密等信息,属于私钥,要保存好。将 csr 文件提交给 CA 厂商,会在几天后发给一份签好的证书文件 crt 文件,同时会给你 CA 的证书链。

2.2 nginx 设置 https 证书


server

{

        listen 80;

        listen 443 ssl;

        server_name staging_activity.zhen.com;

        ssl_certificate      /usr/local/nginx/ca/server.cer;

        ssl_certificate_key  /usr/local/nginx/ca/server.key;

        ssl_session_cache    shared:SSL:1m;

        ssl_session_timeout  5m;

        ssl_ciphers  HIGH:!aNULL:!MD5;

        ssl_prefer_server_ciphers  on;

...

ssl_protocols,表示 SSL 的协议;ssl_ciphers 参数指的是加密算法,根据自身机器 openssl 版本不同,支持算法也不同;ssl_prefer_server_ciphers 表示服务端加密算法优先于客户端加密算法,防止降级攻击。

如果使用了第三方代理(云安全,CDN 等)的服务,还需要根据秘钥文件和证书文件,一般都有对应的说明,可以根据提交相关证书完成相关设置即可。

2.3 Tomcat 转发

浏览器和 nginx 之间走的 https,而 nginx 和 tomcat 之间是通过 proxy_pass,走的是普通 http 连接。所以在 tomcat 端的 Host 中需要增加以下配置,用于设置转发:


                  remoteIpHeader="x-forwarded-for"

                  remoteIpProxiesHeader="x-forwarded-by"

                  protocolHeader="x-forwarded-proto"

            />

配置方案是浏览器和 Nginx 之间走的 HTTPS 通讯,而 Nginx 到 Tomcat 通过 proxy_pass 走的是普通 HTTP 连接。 环境基础假定 nginx、tomcat web 服务已经安装并部署,crt(证书)和 key(私钥)文件已经生成(本示例是用 openssl 生成的,生产环境可到第三方购买)。

nginx 允许一个 server 同时支持 http 和 https 两种协议,可分别定义 80 和 443 两个协议和端口号,也可能单独配置使其仅支持 https 协议。

nginx 收到请求后,将通过 http 协议转发给 tomcat,由于 nginx 和 tomcat 在同一台服务器中,因此 nginx 核 tomcat 之间无需使用 https 协议。而正由于对于 tomcat 来说,收到的是普通的 http 请求,当 tomcat 中的应用发生转向请求时正常,我们需要告诉 tomcat 已被 https 代理,增加 X-Forwarded-Proto 和 X-Forwarded-Port 两个 HTTP 头信息。

下面是详细的配置(Nginx 端口 80/443,Tomcat 的端口 8080):

Nginx 这一侧的配置没什么特别的:


http {

    include       mime.types;

    default_type  application/octet-stream;

    sendfile        on;

   keepalive_timeout  65;

 

    upstream tomcat {

      server 192.168.1.124:8080;

    }

        

       # HTTPS server

       server {

           listen       443 ssl;

           server_name  192.168.1.124;

        

           ssl_certificate      ca/server.crt;

          ssl_certificate_key  ca/server.key;

 

           #ssl_client_certificate  /opt/nginx/ca/private/ca.crt;

        

           #ssl_verify_client       on;服务器验证客户端,暂时不开启

           ssl_session_cache    shared:SSL:1m;

           ssl_session_timeout  5m;

        

           ssl_ciphers  HIGH:!aNULL:!MD5;

           ssl_prefer_server_ciphers  on;

        

           location / {

               proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

               proxy_set_header Host $http_host;

               proxy_set_header X-Forwarded-Proto https;

               proxy_redirect off;

               proxy_connect_timeout      240;

               proxy_send_timeout         240;

               proxy_read_timeout         240;

               # note, there is not SSL here! plain HTTP is used

               proxy_pass http://192.168.1.124:8080;

           }

       }

}

其中最为关键的就是 ssl_certificate 和 ssl_certificate_key 这两项配置文件位置及相关访问权限请自行注意并更改,其他的按正常配置。不过多了一个 proxy_set_header X-Forwarded-Proto https; 配置。

最主要的配置来自 Tomcat,下面是我测试环境中的完整 server.xml:


               connectionTimeout="20000"

               redirectPort="443" proxyPort="443"

               URIEncoding="UTF-8"/>

以及后面的 hostname:


            unpackWARs="true" autoDeploy="true">

        

                  remoteIpHeader="x-forwarded-for"

                  remoteIpProxiesHeader="x-forwarded-by"

                  protocolHeader="x-forwarded-proto" />

上述的配置中没有什么特别的,但是特别特别注意的是必须有 proxyPort="443",当然 redirectPort 也必须是 443。同时 节点的配置也非常重要,否则你在 Tomcat 中的应用在读取 getScheme() 方法以及在 web.xml 中配置的一些安全策略会不起作用。

需要值得注意的是,配置后 tomcat 的 8080 端口在外部依然可以直接访问,如果是集群环境,将会带来极大的安全隐患且此次配置也毫无意义了。所以应该在整个服务器局域网外围切断 8080 端口的访问(之前与第三方有交互并已经预定 8080 端口访问的服务可以酌情开放)并且在局域网内部开放 8080 端口的访问。

3. http 与 https 的自动跳转

在我们使用 baidu 时,如果没有使用 http 的话,也会直接转换成 https,不需要用户手动操作,当前在我们的服务器中,既能支持 http,也支持 https,如果是恶意用户,可以不使用 http 进行操作,所以我们也需要增加这一功能。

需要将 80 和 443 拆开,443https 端口仍然保持原样,80 端口,使用 301 http code 转移至 https:


server {

        listen  80;

        server_name home.xxx.com;

        access_log /usr/local/nginx/main.xxx.com.log  open1;

        return 301 https://home.xxx.com$request_uri;

}

301 和 302 之间的区别可以参考:http://blog.csdn.net/qmhball/article/details/7838989,一个表示永久转移,一个表示暂时转移,对于用户来说,仅仅是一个跳转,浏览器中旧的 url 变成了新的 url,但 302 可能会有 URL 规范化和网站劫持的问题,被搜索引擎判断为可疑转向,甚至认为是作弊,因此我们这里采用 301。

https 仍然按照之前的配置即可:


server {

        listen 443 ssl;

        ssl_certificate      /usr/local/nginx/ca/server.cer;

        ssl_certificate_key  /usr/local/nginx/ca/server.key;

        ssl_session_cache    shared:SSL:1m;

        ssl_session_timeout  5m;

...

但内网我们使用的 named 服务,可以根据内网域名来进行请求分发,仅使用 http,因此还需要为.net 域名额外指定一个虚拟主机,因为是内网访问,所以仅支持 http。

  • HTTPS
    99 引用 • 274 回帖 • 3 关注

相关帖子

欢迎来到这里!

我们正在构建一个小众社区,大家在这里相互信任,以平等 • 自由 • 奔放的价值观进行分享交流。最终,希望大家能够找到与自己志同道合的伙伴,共同成长。

注册 关于
请输入回帖内容 ...