如何使用TCP负载平衡配置Nginx SSL/TLS直通
如何在Linux或类似Unix的系统上运行的Nginx负载均衡器上配置SSL/TLS传递?如何对TCP流量进行负载平衡并设置SSL直通,以将在负载平衡器处接收到的SSL流量传递到后端Web服务器上?
通常,SSL终止发生在负载平衡器,未加密的流量发送到后端Web服务器。所有HTTPS/SSL/TLS和HTTP请求都在Nginx服务器本身上终止。 Nginx服务器使用HTTP协议与后端服务器对话。您必须格外小心,以确保没有人在您的专用网络之间监听流量。在共享环境中,专用网络可能不安全,或者您可能无法获得专用网络的VLAN和VPN。在这种情况下,您可以配置Nginx将所有加密的流量直接传递到后端Web服务器。所有后端Web服务器之间的通信均保持加密:请注意,必须在所有后端服务器(例如192.168.1.100和192.168.1.101)上安装SSL/TLS。
如何在Nginx负载均衡后端服务器中安装配置SSL/TLS。
如何在Linux/Nignx上运行的Nginx负载均衡器上配置SSL/TLS传递?
如何对TCP流量进行负载平衡并设置SSL直通,以将在负载平衡器处接收到的SSL流量传递到后端Web服务器上?
通常,所有HTTPS/SSL/TLS和HTTP请求在Nginx服务器上终止。抵达不了后端服务器。Nginx服务器和后端服务器是通过HTTP协议通讯的。
那么,我们该如何配置Nginx,使其将所有加密的流量直接传递到后端Web服务器?
使用nginx stream模块
我们需要使用ngx_stream_core_module模块进行TCP负载平衡,该模块自1.9.0版开始可用。
默认情况下,Debian/Ubuntu Linux上自带的nginx没有,所以需要使用--with-stream配置参数来自己编译。
安装Nginx LB(将Nginx作为负载均衡器)
在Ubuntu Linux 16.04 LTS服务器上安装Nginx LB
首先使用wget命令获取PGP密钥:
$ cd /tmp/ $ wget https://nginx.org/keys/nginx_signing.key
使用apt-get命令安装密钥:
$ sudo apt-key add nginx_signing.key
创建一个配置文件:
$ sudo vi /etc/apt/sources.list.d/nginx.list
内容如下:
deb http://nginx.org/packages/ubuntu/ xenial nginx deb-src http://nginx.org/packages/ubuntu/ xenial nginx
更新仓库并安装nginx:
$ sudo apt-get update $ sudo apt-get install nginx
在Debian Linux 9.x服务器上安装Nginx LB
首先使用wget命令获取PGP密钥:
$ cd /tmp/ $ wget http://nginx.org/keys/nginx_signing.key
使用apt-get命令安装密钥:
$ sudo apt-key add nginx_signing.key
创建一个配置文件:
$ sudo vi /etc/apt/sources.list.d/nginx.list
内容如下:
## [ NOTE: Debian 8.x user replace stretch with jessie ] ## deb http://nginx.org/packages/debian/ stretch nginx deb-src http://nginx.org/packages/debian/ stretch nginx
保存并关闭文件。更新仓库并安装nginx:
$ sudo apt-get update $ sudo apt-get install nginx
在RHEL/CentOS Linux 6.x/7.x服务器上安装Nginx LB
为RHEL/CentOS设置yum存储库,创建一个文件/etc/yum.repos.d/nginx.repo:
$ sudo vi /etc/yum.repos.d/nginx.repo
添加以下配置:
## Replace "OS" with rhel or centos depending on the distribution used ## Replace "OSRELEASE" with 6 or 7, for 6.x or 7.x versions, respectively ## An example for CentOS 7.x is as follows: [nginx] name=nginx repo baseurl=http://nginx.org/packages/centos/7/$basearch/ gpgcheck=0 enabled=1
运行以下yum命令:
$ sudo yum update $ sudo yum install nginx
配置Nginx LB
编辑/etc/nginx/nginx.conf文件
$ sudo vi /etc/nginx/nginx.conf
添加一行:
include /etc/nginx/passthrough.conf;
nginx.conf示例:
user nginx;
worker_processes 1;
error_log /var/log/nginx/error.log warn;
pid /var/run/nginx.pid;
events {
worker_connections 1024;
}
http {
include /etc/nginx/mime.types;
default_type application/octet-stream;
log_format main '$remote_addr - $remote_user [$time_local] "$request" '
'$status $body_bytes_sent "$http_referer" '
'"$http_user_agent" "$http_x_forwarded_for"';
access_log /var/log/nginx/access.log main;
sendfile on;
#tcp_nopush on;
keepalive_timeout 65;
#gzip on;
include /etc/nginx/conf.d/*.conf;
}
include /etc/nginx/passthrough.conf;
创建一个文件:
$ sudo vi /etc/nginx/passthrough.conf
内容如下:
## tcp LB and SSL passthrough for backend ##
stream {
upstream theitroadbackgroup {
server 192.168.1.100:443 max_fails=3 fail_timeout=10s;
server 192.168.1.101:443 max_fails=3 fail_timeout=10s;
}
log_format basic '$remote_addr [$time_local] '
'$protocol $status $bytes_sent $bytes_received '
'$session_time "$upstream_addr" '
'"$upstream_bytes_sent" "$upstream_bytes_received" "$upstream_connect_time"';
access_log /var/log/nginx/www.theitroad.local_access.log basic;
error_log /var/log/nginx/wwww.theitroad.local_error.log;
server {
listen 443;
proxy_pass theitroadbackgroup;
proxy_next_upstream on;
}
}
检查配置文件语法:
$ nginx -t
重新加载Nginx服务器使配置生效:
$ sudo systemctl reload nginx
或者
$ sudo /etc/init.d/nginx reload
在Nginx(负载均衡器,运行在公网IP)上打开端口443和80
在Debian/Ubuntu Linux上使用ufw命令打开端口443:
$ sudo ufw allow proto tcp from any to 202.54.1.5 port 443 $ sudo ufw allow proto tcp from any to 202.54.1.5 port 80
在CentOS7/RHEL7上使用以下命令打开端口80/443:
# firewall-cmd --get-default-zone # firewall-cmd --get-active-zones # firewall-cmd --permanent --add-service=http # firewall-cmd --permanent --add-service=https # firewall-cmd --reload
后端服务器设置
后端服务器(192.168.1.100和192.168.1.101)必须设置SSL/TLS。
这里我们使用Lets Encrypt SSL免费证书。
$ sudo apt-get install git bc wget curl
$ cd /tmp/
$ git clone https://github.com/Neilpang/acme.sh.git
$ cd acme.sh/
$ sudo -i
# ./acme.sh --install
$ sudo source ~/.bashrc
# D=/var/www/html
# DOM='www.theitroad.local'
# mkdir -vp ${D}/.well-known/acme-challenge/
###---[ NOTE: Adjust permission as per your setup ]---###
# chown -R www-data:www-data ${D}/.well-known/acme-challenge/
# chmod -R 0555 ${D}/.well-known/acme-challenge/
# mkdir -p /etc/nginx/ssl/${DOM}/
# cd /etc/nginx/ssl/${DOM}/
# openssl dhparam -out dhparams.pem -dsaparam 4096
# acme.sh --issue -w $D -d $DOM -k 4096
# vi /etc/nginx/sites-available/default
编辑ssl的配置:
## START: SSL/HTTPS www.theitroad.local ###
server {
#------- Start SSL config with http2 support ----#
listen 443 http2;
server_name www.theitroad.local;
ssl on;
ssl_certificate /etc/nginx/ssl/www.theitroad.local/www.theitroad.local.cer;
ssl_certificate_key /etc/nginx/ssl/www.theitroad.local/www.theitroad.local.key;
ssl_session_timeout 30m;
ssl_protocols TLSv1 TLSv1.1 TLSv1.2;
ssl_ciphers ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+3DES:!aNULL:!MD5:!DSS;
ssl_session_cache shared:SSL:10m;
ssl_dhparam /etc/nginx/ssl/www.theitroad.local/dhparams.pem;
ssl_prefer_server_ciphers on;
## Improves TTFB by using a smaller SSL buffer than the nginx default
ssl_buffer_size 8k;
## Enables OCSP stapling
ssl_stapling on;
resolver 8.8.8.8;
ssl_stapling_verify on;
## Send header to tell the browser to prefer https to http traffic
add_header Strict-Transport-Security max-age=31536000;
## SSL logs ##
access_log /var/log/nginx/ssl_access.log;
error_log /var/log/nginx/ssl_error.log;
#-------- END SSL config -------##
# Add rest of your config below like document path and more ##
}
## END SSL www.theitroad.local ######
然后创建一个shell脚本/root/hook.sh,
用于将/etc/nginx/配置从192.168.1.100复制到第二台服务器(192.168.1.101)中并。
脚本参考:
#!/bin/bash
# ---------------------------------------------------------------------
_rsync="/usr/bin/rsync"
_ssh="/usr/bin/ssh"
_lxc="/usr/bin/lxc"
_rsync_opt='-az -H --delete --numeric-ids '
u="root"
## 后端服务器ip ##
servers="192.168.1.101"
S='/etc/nginx/'
D=/etc/nginx
for b in ${servers}
do
${_rsync} ${_rsync_opt} "$@" ${S} ${u}@${b}:${D}
${_ssh} ${u}@${b} /etc/init.d/nginx reload
done
## Reload 192.168.1.100 too ##
/etc/init.d/nginx reload
执行以下命令:
# acme.sh --installcert -d $DOM --keypath /etc/nginx/ssl/$DOM/$DOM.key --fullchainpath /etc/nginx/ssl/$DOM/$DOM.in.cer --reloadcmd '/root/hook.sh'
现在,添加cron任务,自动创建证书并运行/root/hook.sh:
## default cron installed by acme.sh ## no need to create it ## 33 0 * * * "/root/.acme.sh"/acme.sh --cron --home "/root/.acme.sh" > /dev/null ## 每90天更新一次证书 ##

