nginx反向代理-SSL连接

使用nginx的stream模块对内部socket服务进行反向代理,nginx作为接入服务器对外提供SSL安全连接(单向认证),网络拓扑如图1-1所示。其中服务器A与服务器B提供相同服务,可配置成主备或负载均衡模式。

网络拓扑结构图1-1 网络拓扑结构

总体配置过程分为:nginx安装、ssl证书生成、nginx配置及最后的服务测试。其中nginx安装过程可参照网络上的介绍,为实现socket反向代理并启用SSL的功能,在安装nginx时需要添加 –with-stream  –with-stream_ssl_module 参数。

本实验基于CentOS 6,需要安装OpenSSL、pcre。

1. 证书生成

证书生成过程中会需要输入证书相关信息。

openssl genrsa -des3 -out ssl.key 1024
mv ssl.key server.key
openssl rsa -in server.key -out ssl.key 
rm server.key 
openssl req -new -key ssl.key -out ssl.csr 
openssl x509 -req -days 3650 -in ssl.csr -signkey ssl.key -out ssl.crt 

2. nginx配置

修改nginx配置文件,添加stream模块配置,并且配置后端服务器信息(对应样例中的backend),配置相应的server,server中指定nginx对外监听的端口、实际代理的服务器、SSL证书及代理相关的配置,具体可参照nginx官方文档ngx_stream_*部分(在最底部)。配置完成后使用 nginx -s reload命令重新加载配置文件。以下配置供参考。

stream {
    upstream backend {
        hash $remote_addr consistent;

        server 127.0.0.1:12345  max_fails=3 fail_timeout=30s;
        server 127.0.0.1:12346  max_fails=3 fail_timeout=30s;
    }

    # 非SSL连接
    server {
        listen 3333;
        proxy_connect_timeout 5s;
        proxy_timeout 120s;
        proxy_pass backend;
    }

    # SSL 连接
    server {
        listen              18443 ssl;

        ssl_protocols  TLSv1 TLSv1.1 TLSv1.2;
        ssl_ciphers    AES128-SHA:AES256-SHA:RC4-SHA:DES-CBC3-SHA:RC4-MD5;
        ssl_certificate     /data/server/nginx/cert/ssl.crt;
        ssl_certificate_key /data/server/nginx/cert/ssl.key;

        ssl_session_cache   shared:SSL:10m;
        ssl_session_timeout 10m;

        proxy_connect_timeout 5s;
        proxy_timeout 120s;
        proxy_pass backend;
    }
}

3. 连接测试

测试中,后端服务器使用python做了一个简单的回显服务器,分别监听12345、12346端口,python代码如下:

#!/usr/bin/python
#coding=utf-8

import socket
import commands

HOST = '127.0.0.1'
PORT = 12345
s    = socket.socket(socket.AF_INET,socket.SOCK_STREAM)   #定义socket类型,网络通信,TCP

s.bind((HOST,PORT))   #套接字绑定的IP与端口
s.listen(1)           #开始TCP监听
while 1:
        conn, addr = s.accept()
        print ('Connected by', addr)

        while 1:
                data = conn.recv(1024)

                if len(data) == 0 :
                        print ("Connection closed : ", addr)
                        break
                else:
                        conn.sendall(data)
                        print ("recv: ", data)
        conn.close()

 

使用OpenSSL作为SSL客户端连接服务进行测试的命令为格式如下:

openssl s_client -connect localhost:18443