GX博客

分享个人 Full-Stack JavaScript 项目开发经验

用Nginx作为SSL连接器并扩展上游服务器

Nginx 能够作为一个 SSL 连接器来分开客户端与应用程序服务器的连接,并提供额外的约束访问等安全措施。反向代理服务器本身应该足够安全,以至攻击者找不到任何入口。基本的安全措施包括设置服务器入站规则的端口限制、使用低权限用户运行 Nginx 和使用加密连接等。同时,为了让应用程序有更强的处理能力,会使用到 Nginx 的上游服务器池。


使用 upstream 模块定义一组上游服务器

在 http 块内配置一个 upstream,名称自定义,如 blog_website:

http {
    upstream blog_website {
        #ip_hash;
        least_conn;
        server 127.0.0.1:3010;
        server 127.0.0.1:3011;
        server 127.0.0.1:3012;
        keepalive 32;
    }
}

有关 upstream 模块的指令说明如下:

指令说明
ip_hash使用基于客户端 IP 地址的哈希值与服务器之间的负载均衡方法。该方法确保同一客户端请求将始终传递到同一上游服务器。
keepalive指定每个 worker 进程的缓存中保留的上游服务器的最大空闲 keepalive 连接数(重用现有的 TCP 握手连接)。高峰时,Nginx 会打开更多的连接以满足需要。高峰后,Nginx 会关闭最近最少使用的连接,使连接数回落到该设定值。它应该足够少,以允许上游服务器处理新的传入连接。
least_conn激活使用最少活动连接数的上游服务器提供下一个新连接的负载均衡算法。
server定义一个服务器地址。它的可选参数如下:
  • weight

    设置负载权重,默认值为:1。例子:server 127.0.0.1:3010 weight=2;

  • fail_timeout

    在这个指定时间内没有收到响应,则把该服务器视为不可用。默认值为:10s。

  • max_fails

    设置 fail_timeout 时间内,尝试对服务器连接的最大次数。默认值为:1。例子:server 127.0.0.1:3010 max_fails=3 fail_timeout=30s;

  • backup

    标记备用服务器,当其它服务器不可用时使用,例子:server 127.0.0.1:3011 backup;

  • down

    标记一个服务器不再接受请求,例子:server 127.0.0.1:3012 down;


配置 Nginx 从本地磁盘中提供静态内容,并为用户启动本地缓存

使 Nginx 统一为上游服务器提供静态内容,并自动设置相关缓存响应头,告诉客户端对某些静态资源缓存 24h:

# 拒绝通过 ip 的访问
# 状态码 444 表示 Nginx 不向客户端发送任何数据,并关闭连接
server {
    listen 80;
    server_name xx.xx.xx.xx;
    return 444;
}

# 拒绝通过 ip 的访问
server {
    listen 443;
    server_name xx.xx.xx.xx;
    return 444;
}

# 监听 80 端口,并永久重定向到 https 地址
# 注意,建议同时设置 Strict-Transport-Security 响应标头
server {
    listen 80;
    server_name leeguangxing.cn www.leeguangxing.cn;
    return 301 https://www.leeguangxing.cn$request_uri;
}

server {

    # 使用 listen 指令的 ssl 参数激活 SSL 模块
    listen 443 ssl;
    server_name leeguangxing.cn www.leeguangxing.cn;

    # 省略....

    include my_ssl.conf;

    # 设置文档的根目录
    root public;

    location / {
        try_files $uri @blog_proxy;
    }

    # 命名 location
    location @blog_proxy {
        include my_proxy.conf;
        # 其它反响代理配置......
        proxy_pass http://blog_website;
    }

    # 其中的 ~* 代表使用不区分大小写的正则表达式匹配 location
    location ~* \.(?:js|css|jpg|png|gif)$ {
        expires 24h;
    }

    # 定义指定错误显示的 URI(可以包含变量)
    # error_page 还可以修改状态码,如 500=200 /50x.html
    #error_page 500 502 503 504 /50x.html;
    #location = /50x.html {
    #    root html;
    #}

    # 省略....
}

反向代理的基本配置

my_proxy.conf

proxy_redirect off;

proxy_set_header Host $host;

proxy_set_header X-Real-IP $remote_addr;

proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

proxy_set_header X-Forwarded-Proto https;

proxy_set_header Connection "";

proxy_http_version 1.1;

proxy_connect_timeout 10s;

proxy_send_timeout 15s;

proxy_read_timeout 15s;

client_max_body_size 2m;

client_body_buffer_size 24k;

proxy_intercept_errors on;

上述配置的说明如下:

  • proxy_redirect off;

    不重写来自上游服务器的 Location 和 Refresh 的响应头。

  • proxy_set_header Host $host;

    设置请求头 Host 为用户输入的 URL 的主机部分传递给上游服务器。

  • proxy_set_header X-Real-IP $remote_addr;

    转发直接连接的客户端 IP 地址给上游服务器。

  • proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;

    转发客户端使用的代理 IP 列表给上游服务器。

  • proxy_set_header X-Forwarded-Proto https;

    告诉上游服务器,反向代理与客户端之间使用的协议为 https。

  • proxy_set_header Connection "";

    通过设置请求头 Connection 为空从而不向上游服务器发送这个请求头,因为它的值可能被设置为 close。

  • proxy_http_version 1.1;

    keepalive 连接只有在 HTTP 1.1 开始支持,proxy_http_version 默认值为:1.0。

  • proxy_connect_timeout

    在生成一个到上游服务器的请求时,等待它的连接被接受的超时时间。默认值为:60s。当上游服务器在给定时间内没有响应时,Nginx 可能会投递 504 Gateway Timeout Error。

  • proxy_send_timeout

    连接关闭前,对上游服务器两次连续写入操作之间的超时时间。默认值为:60s。

  • proxy_read_timeout

    连接关闭前,从上游服务器两次连续读取响应操作之间的超时时间。默认值为:60s。如果上有服务器在这时间内未传输任何内容,则关闭该连接。

  • client_max_body_size

    这不是严格的代理模块指令。它用于设置允许的客户端请求体的最大大小,超过则给客户端返回 413 Request Entity Too Large 错误。当需要上传文件到上游服务器时,该值要作相应调整。

  • client_body_buffer_size

    当客户端请求体大小超过该缓存大小,则将其写入临时文件,默认值为:8k|16k(平台依赖)。

  • proxy_intercept_errors

    设置当上游服务器状态码大于等于 300 时,是直接传递给客户端,还是重定向到 Nginx 以便使用 error_page 指令进行处理。默认值为:off。


了解更多官方 http 代理模块的最新说明,请点击这里

用Nginx作为SSL连接器加密流量

my_ssl.conf

ssl_certificate your_certificate.pem;

ssl_certificate_key your_certificate_key.key;

ssl_password_file your_certificate_key_pass.pass;

#ssl_session_timeout 5m;

ssl_session_cache shared:WEB:10m;

#ssl_protocols TLSv1 TLSv1.1 TLSv1.2;

ssl_ciphers RC4:HIGH:!aNULL:!MD5:@STRENGTH;

#ssl_prefer_server_ciphers off;

上面配置的说明如下:

  • ssl_certificate

    给虚拟服务器指定 PEM 格式的证书。(浏览器在发送 HTTP 请求之前建立 SSL 连接,nginx 不知道所请求服务器的名称,浏览器将接收默认服务器的证书。这时可使用SNI以允许服务器在相同的 IP 地址和 TCP 端口号上显示多个证书。)

  • ssl_certificate_key

    给虚拟服务器指定 PEM 格式的证书密钥。(这个 key 文件的权限应该设置为仅能够被 master 进程读取。)

  • ssl_password_file

    指定私钥密码的文件。其中每个密码都在单独的行中指定,在加载密钥时依次尝试每个密码。

  • ssl_session_timeout

    指定客户端可以重用会话参数的时间。默认值为:5m。

  • ssl_session_cache

    设置 SSL 缓存的类型和大小,用于存储会话参数。默认值为:none。可选值说明如下:

    • off

      严格禁止使用会话缓存,Nginx 明确告诉客户端会话可能不会被重用。

    • none

      禁止使用会话缓存,Nginx 告诉客户端会话可以重用,但实际上并不会将会话参数存储在缓存中。

    • builtin

      使用 OpenSSL 构建的缓存,仅由一个 worker 进程使用。缓存大小在会话中指定。如果未给出大小,则大小等于 20480 个会话。使用内置缓存可能会导致内存碎片。

    • shared

      所有 worker 进程之间共享缓存。1Mb 可以存储大约 4000 个会话。可以在多个虚拟服务器中使用具有相同名称的缓存。这样可以使所有 worker 进程能够从每个客户端昂贵的 SSL 自动协商中获益。

  • ssl_protocols

    启用指定的 SSL 协议。默认值为:TLSv1 TLSv1.1 TLSv1.2。

  • ssl_ciphers

    指定启用的加密算法。需要使用 OpenSSL 库支持的格式。默认值为:HIGH:!aNULL:!MD5(不包括提供空认证及 MD5 算法)。配置中开始使用 RC4,目的是为了不易受到BEAST攻击。并在密码的排列中,按照密钥算法在密码的最末尾给出加密的长度。

  • ssl_prefer_server_ciphers

    设置为 on,则在使用 SSLv3 和 TLS 协议时,服务器密码应优先于客户端密码。默认值为:off。


了解更多官方 http SSL模块的最新说明,请点击这里

版权声明:

本文为博主原创文章,若需转载,须注明出处,添加原文链接。

https://leeguangxing.cn/blog_post_33.html