運行工作結(jié)構(gòu)原理:
Nginx監(jiān)聽127.0.0.1:80和127.0.0.1:443
Apache監(jiān)聽127.0.0.2:80和127.0.0.2:443
HAProxy偵聽公用IP地址的端口80和443。 它將HTTP請求從端口80重定向到端口443。當(dāng)請求到達(dá)端口443時,它將通過分析HTTPS請求中的SNI標(biāo)頭在Nginx和Apache后端之間進行選擇。
實際上,Cloudflare(CDN提供商)還使用SNI標(biāo)頭來確定如何將HTTPS請求路由到原始服務(wù)器。
一、停用Nginx和Apache
要在Debian、Ubuntu和centos上停用Nginx,請運行:
sudo systemctl stop nginx
停用Debian/Ubuntu上的Apache:
sudo systemctl stop apache2
停用CentOS上的Apache:
sudo systemctl stop httpd
二、在Nginx中更改監(jiān)聽端口
我們需要讓Nginx監(jiān)聽127.0.0.1:80。 在/etc/nginx/conf.d/或/etc/nginx/sites-enabled/中打開您的Nginx配置文件,并找到以下命令行。
listen 80;
更改為:
listen 127.0.0.1:80;
如果在Nginx服務(wù)器上啟用了https,則還要查找
listen 443 ssl;
更改為:
listen 127.0.0.1:443 ssl;
Nginx主配置文件/etc/nginx/nginx.conf可能包括偵聽端口80或443的默認(rèn)虛擬主機,因此您可能也需要編輯此文件。
重新啟動Nginx以使更改生效。
sudo systemctl restart nginx
三、在Apache中更改監(jiān)聽端口
我們需要讓Apache在127.0.0.2:80上監(jiān)聽。
Debian / Ubuntu
在Debian和Ubuntu上,編輯/etc/apache2/ports.conf文件。
sudo nano /etc/apache2/ports.conf
更改:
Listen 80
Listen 443
為:
Listen 127.0.0.2:80
Listen 127.0.0.2:443
保存并關(guān)閉文件。 同時轉(zhuǎn)到/etc/apache2/sites-enabled /目錄,編輯虛擬主機文件。 更改:
<VirtualHost *:80>
為:
<VirtualHost 127.0.0.2:80>
如果有SSL虛擬主機,則也要更改
<VirtualHost *:443>
為
<VirtualHost 127.0.0.2:443>
重啟Apache
sudo systemctl restart apache2
CentOS
CentOS上編輯/etc/httpd/conf/httpd.conf
sudo nano /etc/httpd/conf/httpd.conf
找到
Listen 80
更改為
Listen 127.0.0.2:80
保存并關(guān)閉然后轉(zhuǎn)向/etc/httpd/conf.d/ 更改:
<VirtualHost *:80>
為
<VirtualHost 127.0.0.2:80>
SSL更改
<VirtualHost *:443>
為
<VirtualHost 127.0.0.2:443>
在/etc/httpd/conf.d/ssl.conf里找到
Listen 443 https
更改為:
Listen 127.0.0.2:443 https
保存、關(guān)閉并重啟服務(wù)器:
sudo systemctl restart httpd
四、配置HAProxy
安裝HAProxy
Debian/Ubuntu
sudo apt install haproxy
CentOS
sudo dnf install haproxy
編輯HAProxy配置文件
sudo nano /etc/haproxy/haproxy.cfg
在文件末尾添加以下代碼段,這將使HAPorxy偵聽公用IP地址的端口80,并將HTTP請求從端口80重定向到端口443。將12.34.56.78替換為服務(wù)器的公用IP地址。
frontend http
bind 12.34.56.78:80
mode http
redirect scheme https code 301
SSL
frontend https
bind 12.34.56.78:443
mode tcp
tcp-request inspect-delay 5s
tcp-request content accept if { req_ssl_hello_type 1 }
然后定義Nginx和Apache后端。
backend nginx
mode tcp
option ssl-hello-chk
server nginx 127.0.0.1:443 check
backend apache
mode tcp
option ssl-hello-chk
server apache 127.0.0.2:443 check
您可以恢復(fù)默認(rèn)定義為:
default_backend nginx
我們將在HTTPS請求中使用SNI標(biāo)頭重定向到正確的后端。 例如,如果Nginx服務(wù)于domain1.com,而Apache服務(wù)于domain2.com,則添加以下兩行。
use_backend nginx if { req_ssl_sni -i domain1.com }
use_backend apache if { req_ssl_sni -i domain2.com }
如果客戶端未在TLS客戶端Hello中指定服務(wù)器名稱,則HAproxy將使用默認(rèn)后端(nginx)。
保存并關(guān)閉文件。 然后重新啟動HAproxy。
sudo systemctl restart haproxy
現(xiàn)在,Apache、Nginx和HAProxy可以在同一服務(wù)器上運行。
如何將客戶的IP地址轉(zhuǎn)發(fā)到后端
默認(rèn)情況下,Apache和Nginx只能看到HAProxy的IP地址。 要獲取客戶端的真實IP地址,請確保已在HAProxy的后端定義中添加了“ send-proxy-v2”選項,如下所示。
server nginx 127.0.0.1:443 send-proxy-v2 check
server apache 127.0.0.2:443 send-proxy-v2 check
我們還需要在Nginx和Apache中添加一些配置。
Nginx
如下所示,在Nginx監(jiān)聽指令中添加proxy_protocol。
listen 127.0.0.2:443 ssl http2 proxy_protocol;
然后在Nginx http {}塊中添加以下兩個指令。
set_real_ip_from 127.0.0.1;
real_ip_header proxy_protocol;
保存關(guān)閉然后重啟Nginx.
sudo systemctl reload nginx
Apache
如果您在Debian / Ubuntu上使用Apache,則需要啟用遠(yuǎn)程模塊。 (默認(rèn)情況下,此模塊已在CentOS上啟用。)
sudo a2enmod remoteip
然后在Apache虛擬主機配置文件中添加以下3行。
RemoteIPProxyProtocol On
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1
有如:
<VirtualHost 127.0.0.2:443>
ServerName www.example.com
RemoteIPProxyProtocol On
RemoteIPHeader X-Forwarded-For
RemoteIPTrustedProxy 127.0.0.1
保存并關(guān)閉文件。 然后我們還需要更改組合日志格式。 編輯Apache主配置文件。
sudo nano /etc/apache2/apache2.conf
或者
sudo nano /etc/httpd/conf/httpd.conf
找到以下信息:
LogFormat "%h %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined
更換為:
LogFormat "%a %l %u %t "%r" %>s %O "%{Referer}i" "%{User-Agent}i"" combined
保存并關(guān)閉文件。 然后重新啟動Apache,以使更改生效。
sudo systemctl restart apache2
或者
sudo systemctl restart httpd
請注意,RemoteIPProxyProtocolOn指令僅在Apache 2.4.31及更高版本中可用。 要檢查您的Apache版本,請運行
sudo apache2 -v
或者
sudo httpd -v
Ubuntu 18.04隨Apache 2.4.29一起提供。 如果您的Apache版本不符合此要求,則應(yīng)刪除HAProxy后端定義中的send-proxy-v2。 CentOS 8附帶了Apache 2.4.37。
最后,重新啟動HAProxy。
sudo systemctl restart haproxy