在同一服务器(Debian,Ubuntu,CentOS)上运行Apache,Nginx和HAProxy

如果您是服务器管理员,则可能选择了一个Web服务器,例如Apache或Nginx。 自1990年代以来,Apache是​​著名的Web服务器。 Nginx于2004年首次开发,由于其轻巧的内存占用和对静态HTML文件的快速处理速度而迅速受到关注。

Apache和Nginx都支持虚拟托管,这意味着您可以在同一服务器上托管多个网站或Web应用程序。 但是,您将遇到正在运行现有Web服务器但特定Web应用程序需要使用其他Web服务器的情况。 公用IP地址上的端口80或443只能由一个进程使用。 如果Apache使用的是端口,则Nginx不能使用(或绑定)该端口。 所以,你可以做什么?

您可以将Nginx配置为Apache的反向代理,因此Nginx可以将HTTP请求重定向到Apache。 以我的经验,我发现这并不总是最好的方法,因为它曾经引起了我无法解决的怪异问题。 相反,我更喜欢将HAProxy用作Nginx和Apache的反向代理。 HAProxy是一个免费的开源高可用性负载平衡器和代理服务器,用于基于TCP和HTTP的应用程序。

在同一服务器上运行Apache,Nginx和HAProxy

运作方式如下。

  • Nginx监听127.0.0.1:80和127.0.0.1:443
  • Apache监听127.0.0.2:80和127.0.0.2:443
  • HAProxy侦听公用IP地址的端口80和443。 它将HTTP请求从端口80重定向到端口443。当请求到达端口443时,它将通过分析HTTPS请求中的SNI(服务器名称指示)标头在Nginx和Apache后端之间进行选择。

实际上,Cloudflare(CDN提供程序)还使用SNI标头来确定如何将HTTPS请求路由到原始服务器。

步骤1:停止Nginx和Apache

要在Debian,Ubuntu和CentOS上停止Nginx,请运行

sudo systemctl stop nginx

要在Debian / Ubuntu上停止Apache,请运行

sudo systemctl stop apache2

要在CentOS上停止Apache,请运行

sudo systemctl stop httpd

步骤2:在Nginx中更改监听端口

我们需要让Nginx监听127.0.0.1:80。 在以下位置打开您的Nginx配置文件 /etc/nginx/conf.d/ 要么 /etc/nginx/sites-enabled/ 并找到以下行。

listen 80;

更改为

listen 127.0.0.1:80;

如果在Nginx服务器块上启用了https,则还要查找

listen 443 ssl;

并将其更改为

listen 127.0.0.1:443 ssl;

Nginx主配置文件 /etc/nginx/nginx.conf 可能包括侦听端口80或443的默认虚拟主机,因此您可能也需要编辑此文件。

重新启动Nginx以使更改生效。

sudo systemctl restart nginx

步骤3:在Apache中更改监听端口

我们需要让Apache在127.0.0.2:80上监听。

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

保存并关闭文件。 也去 /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

保存并关闭文件。 然后去 /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

保存并关闭文件。 重新启动Apache,以使更改生效。

sudo systemctl restart httpd

步骤4:配置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替换为服务器的公用IP地址。

frontend http
    bind 12.34.56.78:80
    mode http
    redirect scheme https code 301

现在,我们还需要添加一个HTTPS前端。

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

您可以使用以下方法定义默认后端:

default_backend nginx

我们将在HTTPS请求中使用SNI标头重定向到正确的后端。 例如,如果Nginx正在投放 domain1.com Apache正在提供服务 domain2.com,然后添加以下两行。

use_backend nginx if { req_ssl_sni -i domain1.com }
use_backend apache if { req_ssl_sni -i domain2.com }

请注意 default_backenduse_backend 指令应放在后端定义之上。

在上面的配置中,我们利用TLS中的SNI(服务器名称指示)功能来区分HTTPS流量。

  • 当domain1.com在TLS客户端Hello中时,HAProxy会将流量重定向到 nginx 后端。
  • 当domain2.com位于TLS客户端Hello中时,HAProxy会将流量重定向到 apache 后端。

如果客户端未在TLS客户端Hello中指定服务器名称,则HAproxy将使用默认后端(nginx)。

保存并关闭文件。 然后重新启动HAproxy。

sudo systemctl restart haproxy

现在,Apache,Nginx和HAProxy可以在同一服务器上运行。

如何将客户端的IP地址转发到后端

默认情况下,Apache和Nginx只能看到HAProxy的IP地址。 要获取客户端的真实IP地址,请确保您添加了 send-proxy-v2 如下所示在HAProxy的后端定义中选择选项。

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的

proxy_protocol 在Nginx中 listen 指令如下。

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;

保存并关闭文件。 然后重新加载Nginx。

sudo systemctl reload nginx

阿帕奇

如果在Debian / Ubuntu上使用Apache,则需要启用remoteip模块。 (默认情况下,此模块在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

保存并关闭文件。 然后我们还需要更改 combined 日志格式。 编辑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

保存并关闭文件。 然后重新启动Apache,以使更改生效。

sudo systemctl restart apache2

要么

sudo systemctl restart httpd

注意RemoteIPProxyProtocol On 指令仅在Apache 2.4.31及更高版本中可用。 要检查您的Apache版本,请运行

sudo apache2 -v

要么

sudo httpd -v

Ubuntu 18.04随Apache 2.4.29一起提供。 如果您的Apache版本不符合此要求,则应删除 send-proxy-v2 在HAProxy后端定义中。 CentOS 8附带了Apache 2.4.37。

最后,重新启动HAProxy。

sudo systemctl restart haproxy

获取新的加密我们的SSL证书

要获得虚拟主机/服务器块的新的“加密”证书,我发现我只能使用 dns-01 挑战类型。 http-01tls-alpn-01 挑战是行不通的。

首先,您需要安装Certbot DNS插件。 它们是Debian和Ubuntu软件存储库中提供的几个DNS插件,您可以从中找到

apt search python3-certbot-dns

输出:

python3-certbot-dns-cloudflare/bionic,bionic 0.23.0-1 all
Cloudflare DNS plugin for Certbot

python3-certbot-dns-digitalocean/bionic,bionic 0.23.0-1 all
DigitalOcean DNS plugin for Certbot

python3-certbot-dns-dnsimple/bionic,bionic 0.23.0-1 all
DNSimple DNS plugin for Certbot

python3-certbot-dns-google/bionic,bionic 0.23.0-1 all
Google DNS plugin for Certbot

python3-certbot-dns-rfc2136/bionic,bionic 0.23.0-1 all
RFC 2136 DNS plugin for Certbot

python3-certbot-dns-route53/bionic,bionic 0.23.0-1 all
Route53 DNS plugin for Certbot

在CentOS 8上,您可以从EPEL存储库中找到Certbot DNS插件。 请注意,您需要从默认的CentOS存储库安装Certbot。

sudo dnf install certbot

从EPEL存储库中查找DNS插件。

sudo dnf install epel-release
dnf search certbot-dns

输出:

python3-certbot-dns-ovh.noarch : OVH DNS Authenticator plugin for Certbot
python3-certbot-dns-nsone.noarch : NS1 DNS Authenticator plugin for Certbot
python3-certbot-dns-gehirn.noarch : Gehirn Infrastructure Service DNS Authenticator plugin for Certbot
python3-certbot-dns-google.noarch : Google Cloud DNS Authenticator plugin for Certbot
python3-certbot-dns-linode.noarch : Linode DNS Authenticator plugin for Certbot
python3-certbot-dns-luadns.noarch : LuaDNS Authenticator plugin for Certbot
python3-certbot-dns-rfc2136.noarch : RFC 2136 DNS Authenticator plugin for Certbot
python3-certbot-dns-route53.noarch : Route53 DNS Authenticator plugin for Certbot
python3-certbot-dns-cloudxns.noarch : CloudXNS DNS Authenticator plugin for Certbot
python3-certbot-dns-dnsimple.noarch : DNSimple DNS Authenticator plugin for Certbot
python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot
python3-certbot-dns-cloudflare.noarch : Cloudflare DNS Authenticator plugin for Certbot
python3-certbot-dns-dnsmadeeasy.noarch : DNS Made Easy DNS Authenticator plugin for Certbot
python3-certbot-dns-sakuracloud.noarch : Sakura Cloud DNS Authenticator plugin for Certbot

根据您使用的DNS托管服务安装这些插件之一。 我正在使用Cloudflare,因此我将以Cloudflare为例。 运行以下命令以安装 python3-certbot-dns-cloudflare 在Debian / Ubuntu上打包。

sudo apt install python3-certbot-dns-cloudflare

然后为Cloudflare创建配置文件。

sudo nano /etc/letsencrypt/cloudflare.ini

我们需要在此文件中添加Cloudflare帐户的电子邮件地址和API密钥。

# Cloudflare API credentials used by Certbot
dns_cloudflare_email = [email protected]
dns_cloudflare_api_key = 0123456789abcdef0123456789abcdef01234567

您可以在https://dash.cloudflare.com/profile中找到您的Cloudflare API密钥。 请注意,Certbot Cloudflare插件当前不支持Cloudflare的“ API令牌”,因此请确保使用“全局API密钥”进行身份验证。

保存并关闭文件。 API密钥会绕过Cloudflare的两因素身份验证,因此您应仅允许root用户读取此文件。

sudo chmod 600 /etc/letsencrypt/cloudflare.ini

现在运行certbot。

sudo certbot --agree-tos -a dns-cloudflare -i nginx --redirect --hsts --staple-ocsp --email [email protected] -d www.your-domain.com,your-domain.com

在上面的命令中,我们指定将使用 dns-cloudflare 作为身份验证者以获取新的TLS证书并使用 nginx 用于创建HTTPS服务器块的插件。 如果使用Apache,则替换 nginxapache

此命令将要求您输入 .ini 文件,所以输入 /etc/letsencrypt/cloudflare.ini 然后按Enter键。

certbot dns cloudflare

获取SSL证书并将其安装在Web服务器配置文件中之后。 您需要使其在127.0.0.1:443或127.0.0.2:443上侦听。 例如,如果您使用Nginx,则查找

listen 443 ssl

并将其更改为

listen 127.0.0.1:443 ssl http2

另外,将端口80更改为

listen 127.0.0.1:80;

保存并关闭文件。 然后重新启动您的Web服务器。

常见错误

如果服务器上有多个Nginx虚拟主机,并且键入一个域名,则Web浏览器会将您带到同一服务器上托管的另一个域名,则可能是您的Nginx虚拟主机文件名没有结尾与 .conf 文件扩展名,因此Nginx不会加载该虚拟主机。 也可能是您已经为域名设置了AAAA记录,但是没有将Nginx配置为在IPv6中提供域名。

上面的内容也适用于Apache Web服务器。

包起来

我希望本教程可以帮助您在同一服务器上运行Apache,Nginx和HAProxy。 与往常一样,如果您发现这篇文章很有用,请订阅我们的免费新闻通讯以获取更多提示和技巧。 保重🙂

Sidebar