如何使用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。
stream 模块
您需要使用ngx_stream_core_module模块进行TCP负载平衡,该模块自1.9.0版开始可用。
默认情况下,该模块不是在Debian/Ubuntu或任何其他发行版上构建的,应该使用--with-stream
配置参数来启用。
但是,您可以安装官方的Nginx软件包并使用此模块。
步骤1:安装Nginx LB
根据您的Linux发行版运行命令:
Ubuntu Linux 16.04 LTS服务器
首先使用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服务器
首先使用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服务器
您必须为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
步骤2:配置Nginx LB
编辑/etc/nginx/nginx.conf文件,运行:
$ sudo vi /etc/nginx/nginx.conf
追加以下行:
include /etc/nginx/passthrough.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 theitroadcomapache { 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 theitroadcomapache; proxy_next_upstream on; } }
保存并关闭文件。
测试一下:
$ nginx -t
重新启动或重新加载Nginx服务器,运行:
$ sudo systemctl reload nginx
或者
$ sudo /etc/init.d/nginx reload
打开端口443和80(必须在公共IP上运行的Nginx服务器上键入)
使用ufw命令在Debian/Ubuntu Linux上打开端口443:
$ sudo ufw allow proto tcp from any to 192.54.1.5 port 443 $ sudo ufw allow proto tcp from any to 192.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
步骤3:后端网路伺服器设定为192.168.1。{100,101}
您必须在生产现场使用真实/商业证书。
我将Nginx与免费的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 ######
保存并关闭文件。
创建一个名为/root/hook.sh的shell脚本,将/etc/nginx /配置从192.168.1.100复制到第二台服务器(192.168.1.101)并重新加载它。
这是一个示例脚本:
#!/bin/bash # Purpose: Replicate ssl and nginx settings/certs across all backends # Author: Hyman Gite {https://www.theitroad.local} # License: GPL v2.0+ # - # NOTE: SSH keys must be set between all hosts # The certificate information must be replicated on # every server. Modify script as per your needs. # -------------------------------------------------------------------- _rsync="/usr/bin/rsync" _ssh="/usr/bin/ssh" _lxc="/usr/bin/lxc" _rsync_opt='-az -H --delete --numeric-ids ' u="root" ## add all IPs/hostnames of backend here ## servers="192.168.1.101" S='/etc/nginx/' D=/etc/nginx ## Do it ## 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 ## above will renew certificate every 90 days ##