如何使用 TCP 负载平衡配置 Nginx SSL/TLS 直通
通常,SSL 终止发生在负载均衡器上,未加密的流量发送到后端 Web 服务器。所有 HTTPS/SSL/TLS 和 HTTP 请求都在 Nginx 服务器本身上终止。Nginx 服务器使用 HTTP 协议与后端服务器通信。您必须非常小心,确保没有人窥探您的专用网络之间的流量。在共享环境中,专用网络可能不安全,或者您可能无法为专用网络获取 VLAN 和 VPN。在这种情况下,您可以配置 Nginx 以将所有加密流量直接传递到后端 Web 服务器。所有后端 Web 服务器之间的流量保持加密:
请注意,您必须在所有后端服务器(例如 192.168.1.100 和 192.168.1.101)上安装 SSL/TLS。
向流模块问好
您需要使用 ngx_stream_core_module 模块来实现 TCP 负载平衡,该模块自 1.9.0 版起可用。Debian/Ubuntu 或任何其他发行版上默认不内置此模块,应使用配置参数启用它--with-stream。但是,您可以安装官方 Nginx 软件包并使用此模块。
步骤1:安装Nginx LB
根据您的 Linux 发行版运行命令:
Ubuntu Linux 16.04 LTS 服务器
首先使用wget 命令获取 PGP 密钥:使用apt-get 命令
安装:
创建配置文件:
附加以下代码:
保存并关闭文件。更新 repo 并安装 nginx:
$ cd /tmp/
$ wget https://nginx.org/keys/nginx_signing.key
$ 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
$ sudo apt-get update
$ sudo apt-get install nginx
Debian Linux 9.x 服务器
首先使用wget 命令获取 PGP 密钥:使用apt-get 命令
安装:
创建配置文件:
附加以下代码:
保存并关闭文件。更新 repo 并安装 nginx:
$ cd /tmp/
$ wget http://nginx.org/keys/nginx_signing.key
$ 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
$ 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
图 01:从官方仓库安装 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 examplebizapache { 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.example.com_access.log basic; error_log /var/log/nginx/wwww.example.com_error.log; server { listen 443; proxy_pass examplebizapache; proxy_next_upstream on; } }
保存并关闭文件。测试一下:
$ nginx -t
重启或者重新加载 nginx 服务器,运行:
$ sudo systemctl reload nginx
或者
$ sudo /etc/init.d/nginx reload
打开端口443和80(必须在公网IP上运行的nginx服务器上输入)
在 Debian/Ubuntu Linux 上使用ufw 命令打开端口 443:
您可以在 CentOS7/RHEL7 上使用以下命令打开端口 80/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
# 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}
您必须为您的生产站点使用真实/商业证书。我将使用带有免费 Let's Encrypt SSL 证书的 Nginx:
编辑 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.example.com'
# 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
## START: SSL/HTTPS www.example.com ### server { #------- Start SSL config with http2 support ----# listen 443 http2; server_name www.example.com; ssl on; ssl_certificate /etc/nginx/ssl/www.example.com/www.example.com.cer; ssl_certificate_key /etc/nginx/ssl/www.example.com/www.example.com.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.example.com/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.example.com ######
保存并关闭文件。创建一个名为 /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: Vivek Gite {https://www.example.com} # 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
输入以下命令: cron
# acme.sh --installcert -d $DOM --keypath /etc/nginx/ssl/$DOM/$DOM.key --fullchainpath /etc/nginx/ssl/$DOM/$DOM.in.cer --reloadcmd '/root/hook.sh'
作业现在将自动创建证书并每次运行 /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 ##
结论
您应该能够使用 nginx 作为负载均衡器并将所有 SSL 流量传递到后端服务器。您的 SSL/TSL 证书将在 192.168.1.100 和 192.168.1.101 后端服务器上终止,而不是在托管在公共 IP 地址上的负载均衡器上终止。请注意,您无法修改 HTTP 标头或获取客户端的 IP 地址,即存储在 X-Forwarded* 标头中的信息。这是 Nginx 作为 SSL 直通方法的唯一缺点。有关更多信息,请参阅以下网址: