Nginx 诡异 SSL_PROTOCOL_ERROR 问题排查

这两天在检查一台 Nginx 配置的时候,遇到了一个极端诡异的问题。一段很通用的配置,配在这个服务器上,就会 100% 导致 Chrome 报 ERR_SSL_PROTOCOL_ERROR 。但是这段配置非常的通用,是用 Mozilla 提供的工具生成的。

而且在 iPhone 的 Safari 上访问又是完全正常的,服务器日志也看不到任何错误。看到的请求相应码也是完全正确的 200 。

先贴出配置:

# https://mozilla.github.io/server-side-tls/ssl-config-generator/
    listen 443 ssl http2;

    # certs sent to the client in SERVER HELLO are concatenated in ssl_certificate
    ssl_certificate (更多…)

nginx rewrite 的一个小坑

今天在配置 Nginx 的时候写了这么一个 location

location /a {
    rewrite /a/(.*) /$1 break;
    ...
}

然后发现当我直接访问 /a 的时候,rewrite 并没有生效,后端收到的还是 /a 而不是我想象中的 / 。想了想可能是结尾 / 的问题,于是这样改:

location /a {
    rewrite /a(.*) $1 break;
    ...
}

结果新的问题来了,由于这样匹配到的 $1 是空的,所以 Nginx 报错了,the rewritten URI has a zero length

所以这种情况下只好这么写:

location /a/ {
    rewrite /a(.*) $1 break;
    ...
}

注意第一行的末尾 / 。这种情况下,访问 /a 会被 (更多…)

Nginx 配置 ECC RSA 双证书

Config Nginx for parallel ECC and RSA Certificate

先决条件

Nginx 1.11.0 以上

OpenSSL 1.0.2 以上

申请证书

首先申请 ECC 证书,这个不多说,很多方法都可以,大部分 CA 现在也都可以签署。生成 CSR 的命令是:

openssl ecparam -out 证书名.key -name prime256v1 -genkey && openssl req -new -key 证书名.key -nodes -out 证书名.csr

拿到证书之后,还是像之前一样将中级 CA 拼接在证书后面,得到给 Nginx 使用的 domain-cert.crt

配置 Nginx

首先是将两个证书链都加入 Nginx 的配置文件:

ssl_certificate     example.com.rsa.crt;
ssl_certificate_key (更多…)

Nginx 配置 403 Error Page

今天遇到一个很有意思的问题,就是给 Nginx 配置 403 时候的错误页面。因为这台 Nginx 针对访问 IP 做了一些限制,所以需要给无权限访问的用户展示一个友好的界面。

一开始我的设置是这么写的:

...
allow 10.0.0.0/24;
allow 192.168.0.0/24;
deny 1.2.3.4;
deny 2.3.4.5;

error_page 403 /403.html;
...

可是实际使用发现,无论如何 Nginx 展示的都是内置 Hard Code 进去的那个 404 页面,并不是我想让他展示的友好的界面。

在排除了各种文件权限之类的错误之后,我 Google 了一下发现,这个真正的原因在于前面配置的 deny 不仅 deny 掉了正常页面的访问,同时也将对 /404.html 页面的访问也 deny 掉了。

所以正确的配置是加上下面几句:

location (更多…)

使用 Nginx 反代 Apache 安装 WordPress

最近由于原先博客主机极度不稳定,所以准备了很久,准备进行主机迁移。由于迁移前的环境和迁移后还是有较大的区别,整体架构也不太一样,所以在这里说说迁移过程中遇到的问题。

环境对比

原主机 新主机
操作系统 CentOS 6 CentOS 7
Web 服务器 Apache 2.2 Openresty 1.9.7 + Apache 2.4
PHP 版本 5.5 5.6
其他 SELinux

SELinux

很多人为了省事,在拿到主机的第一时间就直接禁用了 SELinux。不过在学习了一段时间之后,我发现其实 SELinux 是一个很好的保护机器的手段。

这里简单列举几个需要注意的 SELinux 的配置:

 

httpd_can_network_connect_db boolean (更多…)

什么是 ALPN(应用层协议协商) What is ALPN (Application-Layer Protocol Negotiation)

在没有启用 ALPN 的时候,加载一个 HTTP/2 页面的步骤是:

Without ALPN, the steps to load a HTTP/2 page would be like:

  1. TLS 握手 (TLS handshake)
  2. 浏览器/客户端 发送带有 “Upgrade: h2c” 头的 HTTP/1.1 请求 (Browser/Client speaks HTTP/1.1 to server with “Upgrade: h2c” Header)
  3. 服务器回复 101 Switching 并将链接升级至 HTTP2 (Server responds with 101 Switching to upgrade to HTTP2)
  4. 现在服务器和客户端采用 HTTP2 协议交流 (Now they talks via HTTP2)

在启用了 (更多…)

SSL 双向认证的一个小问题

最近一直在研究 SSL 双向认证,工作中也经常用到。然后今天遇到了一个非常奇怪的问题,那就是就算配置了

ssl_verify_client optional_no_ca

客户端的访问仍然会失败,证书认证仍然不过。调试了半天,发现了两个问题,那就是:
1. optional_no_ca 并不会像 off 一样放过所有请求,而是对于提交了证书的请求,如果证书验证不过就会握手出错
2. 对于下面这个配置项的设置存在错误:

ssl_verify_depth 1

经过查找资料,找到了这个选项相关的一些说明。(注:以下实验均在 Nginx 和 Apache2.2 上同时进行过)

The depth actually is the maximum number of intermediate certificate issuers, i.e. the number of CA certificates (更多…)

生成Certificate Signing Request(CSR)

众所周知,申请SSL证书前需要先生成证书注册请求,这里一般使用

openssl req -nodes -newkey rsa:2048 -keyout myserver.key -out server.csr

这条命令来生成。生成过程中会填写一些信息,随便写就好。当然最好按实际的填。

Country Name (2 letter code) [AU]: GB
State or Province Name (full name) [Some-State]: Yorks
Locality Name (eg, city) []: York
Organization Name (eg, company) [Internet Widgits Pty Ltd]: MyCompany Ltd
Organizational Unit Name (eg, section) []: IT
Common (更多…)

Nginx限制每个IP或虚拟机的并发连接数

摘自http://nginx.org/cn/docs/http/ngx_http_limit_conn_module.html

ngx_http_limit_conn_module 模块可以按照定义的键限定每个键值的连接数。特别的,可以设定单一 IP 来源的连接数。

并不是所有的连接都会被模块计数;只有那些正在被处理的请求(这些请求的头信息已被完全读入)所在的连接才会被计数。

配置范例

http {
limit_conn_zone $binary_remote_addr zone=addr:10m;

...

server {

...

location /download/ {
limit_conn addr 1;
}

指令

语法: limit_conn zone number;
默认值: —
上下文: http, server, (更多…)