如何使用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天更新一次证书 ##