如何在一个Ubuntu18.04服务器上将Nginx配置为Web服务器和Apache的反向代理

来自菜鸟教程
跳转至:导航、​搜索

作为 Write for DOnations 计划的一部分,作者选择了 Electronic Frontier Foundation 来接受捐赠。

介绍

Apache 和 Nginx 是两种流行的开源 Web 服务器,通常与 PHP 一起使用。 当托管具有不同要求的多个网站时,在同一虚拟机上运行它们会很有用。 在单个系统上运行两个 Web 服务器的一般解决方案是使用多个 IP 地址或不同的端口号。

可以将同时具有 IPv4 和 IPv6 地址的服务器配置为在一个协议上为 Apache 站点提供服务,在另一个协议上为 Nginx 站点提供服务,但这目前并不实用,因为 ISP 采用 IPv6 仍然没有普及。 为第二个 Web 服务器使用不同的端口号,例如 818080 是另一种解决方案,但使用端口号(例如 http://example.com:81)共享 URL 并不总是合理的,或者理想的。

在本教程中,您将把 Nginx 配置为 Web 服务器和 Apache 的反向代理——所有这些都在单个服务器上。

根据 Web 应用程序,可能需要更改代码以保持 Apache 反向代理感知,尤其是在配置 SSL 站点时。 为避免这种情况,您将安装一个名为 mod_rpaf 的 Apache 模块,该模块会重写某些环境变量,因此 Apache 似乎是直接处理来自 Web 客户端的请求。

我们将在一台服务器上托管四个域名。 Nginx 将提供两个服务:example.com(默认虚拟主机)和 sample.org。 剩下的两个,foobar.nettest.io,将由 Apache 提供服务。 我们还将配置 Apache 以使用 PHP-FPM 为 PHP 应用程序提供服务,它提供比 mod_php 更好的性能。

先决条件

要完成本教程,您需要以下内容:

  • 按照使用Ubuntu 18.04的初始服务器设置配置的新Ubuntu 18.04服务器。 这包括 sudo 非 root 用户和防火墙。
  • 四个完全限定的域名配置为指向您的服务器的 IP 地址。 有关如何执行此操作的示例,请参阅 如何使用 DigitalOcean 设置主机名的第 3 步。 如果您在其他地方托管您的域的 DNS,则应改为在那里创建适当的 A 记录。

第 1 步 — 安装 Apache 和 PHP-FPM

让我们从安装 Apache 和 PHP-FPM 开始。

除了 Apache 和 PHP-FPM,我们还将安装 PHP FastCGI Apache 模块 libapache2-mod-fastcgi,以支持 FastCGI Web 应用程序。

首先,更新您的软件包列表以确保您拥有最新的软件包。

sudo apt update

接下来,安装 Apache 和 PHP-FPM 软件包:

sudo apt install apache2 php-fpm

FastCGI Apache 模块在 Ubuntu 的存储库中不可用,因此请从 kernel.org 下载它并使用 dpkg 命令安装它。

wget https://mirrors.edge.kernel.org/ubuntu/pool/multiverse/liba/libapache-mod-fastcgi/libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb
sudo dpkg -i libapache2-mod-fastcgi_2.4.7~0910052141-1.2_amd64.deb

接下来,让我们将 Apache 的默认配置更改为使用 PHP-FPM。

第 2 步 — 配置 Apache 和 PHP-FPM

在这一步中,我们将 Apache 的端口号更改为 8080 并使用 mod_fastcgi 模块将其配置为与 PHP-FPM 一起使用。 重命名 Apache 的 ports.conf 配置文件:

sudo mv /etc/apache2/ports.conf /etc/apache2/ports.conf.default

创建一个新的 ports.conf 文件,并将端口设置为 8080

echo "Listen 8080" | sudo tee /etc/apache2/ports.conf

注意: Web 服务器在配置反向代理时通常设置为侦听 127.0.0.1:8080,但这样做会将 PHP 的环境变量 SERVER_ADDR 的值设置为环回 IP 地址而不是服务器的公共 IP。 我们的目标是设置 Apache,使其网站在其前面看不到反向代理。 因此,我们将其配置为侦听所有 IP 地址上的 8080


接下来,我们将为 Apache 创建一个虚拟主机文件。 此文件中的 <VirtualHost> 指令将设置为仅在端口 8080 上服务站点。

禁用默认虚拟主机:

sudo a2dissite 000-default

然后使用现有的默认站点创建一个新的虚拟主机文件:

sudo cp /etc/apache2/sites-available/000-default.conf /etc/apache2/sites-available/001-default.conf

现在打开新的配置文件:

sudo nano /etc/apache2/sites-available/001-default.conf

将监听端口改为8080

/etc/apache2/sites-available/000-default.conf

<VirtualHost *:8080>
    ServerAdmin webmaster@localhost
    DocumentRoot /var/www/html
    ErrorLog ${APACHE_LOG_DIR}/error.log
    CustomLog ${APACHE_LOG_DIR}/access.log combined
</VirtualHost>

保存文件并激活新的配置文件:

sudo a2ensite 001-default

然后重新加载 Apache:

sudo systemctl reload apache2

验证 Apache 现在正在侦听 8080

sudo netstat -tlpn

输出应类似于以下示例,其中 apache2 正在侦听 8080

OutputActive Internet connections (only servers)
Proto Recv-Q Send-Q Local Address     Foreign Address      State    PID/Program name
tcp        0      0 0.0.0.0:22        0.0.0.0:*            LISTEN   1086/sshd
tcp6       0      0 :::8080           :::*                 LISTEN   4678/apache2
tcp6       0      0 :::22             :::*                 LISTEN   1086/sshd

一旦您确认 Apache 正在侦听正确的端口,您就可以配置对 PHP 和 FastCGI 的支持。

第 3 步 — 配置 Apache 以使用 mod_fastcgi

Apache 默认使用 mod_php 提供 PHP 页面,但它需要额外的配置才能使用 PHP-FPM。

注意: 如果您在使用 mod_php 的现有 LAMP 安装上尝试本教程,请先使用 sudo a2dismod php7.2 禁用它。


我们将为 mod_fastcgi 添加一个配置块,它依赖于 mod_actionmod_action默认是禁用的,所以我们首先需要启用它:

sudo a2enmod actions

重命名现有的 FastCGI 配置文件:

sudo mv /etc/apache2/mods-enabled/fastcgi.conf /etc/apache2/mods-enabled/fastcgi.conf.default

创建一个新的配置文件:

sudo nano /etc/apache2/mods-enabled/fastcgi.conf

将以下指令添加到文件中,以将对 .php 文件的请求传递到 PHP-FPM UNIX 套接字:

/etc/apache2/mods-enabled/fastcgi.conf

<IfModule mod_fastcgi.c>
  AddHandler fastcgi-script .fcgi
  FastCgiIpcDir /var/lib/apache2/fastcgi
  AddType application/x-httpd-fastphp .php
  Action application/x-httpd-fastphp /php-fcgi
  Alias /php-fcgi /usr/lib/cgi-bin/php-fcgi
  FastCgiExternalServer /usr/lib/cgi-bin/php-fcgi -socket /run/php/php7.2-fpm.sock -pass-header Authorization
  <Directory /usr/lib/cgi-bin>
    Require all granted
  </Directory>
</IfModule>

保存更改并进行配置测试:

sudo apachectl -t

如果显示 Syntax OK,则重新加载 Apache:

sudo systemctl reload apache2

如果您看到警告 Could not reliably determine the server's fully qualified domain name, using 127.0.1.1. Set the 'ServerName' directive globally to suppress this message.,您现在可以放心地忽略它。 稍后我们将配置服务器名称。

现在让我们确保我们可以从 Apache 提供 PHP。

第 4 步 — 验证 PHP 功能

让我们通过创建一个 phpinfo() 文件并从 Web 浏览器访问它来确保 PHP 正常工作。

创建包含对 phpinfo 函数的调用的文件 /var/www/html/info.php

echo "<?php phpinfo(); ?>" | sudo tee /var/www/html/info.php

请注意,如果您遵循 Prerequisites 部分中的初始服务器设置,那么您可能启用了 Apache 防火墙。 让我们继续并确保我们可以在端口 8080 上访问我们的 IP,该端口当前无法访问。 我们将在 Step 10 中限制对该端口的公共访问。

首先允许端口8080通过防火墙:

sudo ufw allow 8080

由于我们要保护我们的 Apache 域,让我们继续确保端口 443 上的 TLS 流量可以进入。

允许 Apache Full 允许端口 80443 上的流量:

sudo ufw allow "Apache Full"

现在检查您的防火墙状态:

sudo ufw status

如果您遵循了先决条件,那么输出将如下所示:

OutputTo                         Action      From
--                         ------      ----
OpenSSH                    ALLOW       Anywhere
Apache Full                ALLOW       Anywhere
8080                       ALLOW       Anywhere
OpenSSH (v6)               ALLOW       Anywhere (v6)
Apache Full (v6)           ALLOW       Anywhere (v6)
8080 (v6)                  ALLOW       Anywhere (v6)

您将看到端口 8080Apache Full 与任何其他防火墙规则一起被允许。 现在让我们查看我们的 info.php 页面。

要在浏览器中查看文件,请转到 http://your_server_ip:8080/info.php。 这将为您提供 PHP 正在使用的配置设置列表。

在页面顶部,检查 Server API 是否显示 FPM/FastCGI。 在页面向下大约三分之二的地方,PHP 变量 部分将告诉您 SERVER_SOFTWARE 是 Ubuntu 上的 Apache。 这些确认 mod_fastcgi 处于活动状态并且 Apache 正在使用 PHP-FPM 处理 PHP 文件。

第 5 步 — 为 Apache 创建虚拟主机

让我们为域 foobar.nettest.io 创建 Apache 虚拟主机文件。 为此,我们将首先为两个站点创建文档根目录,并在这些目录中放置一些默认文件,以便我们可以轻松地测试我们的配置。

首先,创建文档根目录:

sudo mkdir -v /var/www/foobar.net /var/www/test.io

然后为每个站点创建一个 index 文件:

echo "<h1 style='color: green;'>Foo Bar</h1>" | sudo tee /var/www/foobar.net/index.html
echo "<h1 style='color: red;'>Test IO</h1>" | sudo tee /var/www/test.io/index.html

然后为每个站点创建一个 phpinfo() 文件,以便我们可以测试 PHP 是否配置正确。

echo "<?php phpinfo(); ?>" | sudo tee /var/www/foobar.net/info.php
echo "<?php phpinfo(); ?>" | sudo tee /var/www/test.io/info.php

现在为 foobar.net 域创建虚拟主机文件:

sudo nano /etc/apache2/sites-available/foobar.net.conf

将以下代码添加到文件中以定义主机:

/etc/apache2/sites-available/foobar.net.conf

    <VirtualHost *:8080>
        ServerName foobar.net
        ServerAlias www.foobar.net
        DocumentRoot /var/www/foobar.net
        <Directory /var/www/foobar.net>
            AllowOverride All
        </Directory>
    </VirtualHost>

AllowOverride All 行启用 .htaccess 支持。

这些只是最基本的指令。 有关在 Apache 中设置虚拟主机的完整指南,请参阅 如何在 Ubuntu 16.04 上设置 Apache 虚拟主机。

保存并关闭文件。 然后为 test.io 创建一个类似的配置。 首先创建文件:

sudo nano /etc/apache2/sites-available/test.io.conf

然后将配置添加到文件中:

/etc/apache2/sites-available/test.io.conf

    <VirtualHost *:8080>
        ServerName test.io
        ServerAlias www.test.io
        DocumentRoot /var/www/test.io
        <Directory /var/www/test.io>
            AllowOverride All
        </Directory>
    </VirtualHost>

保存文件并退出编辑器。

现在两个 Apache 虚拟主机都设置好了,使用 a2ensite 命令启用站点。 这会在 sites-enabled 目录中创建一个指向虚拟主机文件的符号链接:

sudo a2ensite foobar.net
sudo a2ensite test.io

再次检查 Apache 的配置错误:

sudo apachectl -t

如果没有错误,您将看到 Syntax OK 显示。 如果您看到其他任何内容,请查看配置并重试。

一旦您的配置没有错误,重新加载 Apache 以应用更改:

sudo systemctl reload apache2

要确认站点是否正常工作,请在浏览器中打开 http://foobar.net:8080http://test.io:8080 并验证每个站点是否显示其 index.html 文件。

您将看到以下结果:

此外,通过访问每个站点的 info.php 文件来确保 PHP 正常工作。 在浏览器中访问 http://foobar.net:8080/info.phphttp://test.io:8080/info.php

您将在每个站点上看到与第 4 步中相同的 PHP 配置规范列表。

我们现在有两个网站托管在 Apache 的端口 8080 上。 接下来我们来配置 Nginx。

第 6 步 — 安装和配置 Nginx

在这一步中,我们将安装 Nginx 并将域 example.comsample.org 配置为 Nginx 的虚拟主机。 有关在 Nginx 中设置虚拟主机的完整指南,请参阅 如何在 Ubuntu 18.04 上设置 Nginx 服务器块(虚拟主机)。

使用包管理器安装 Nginx:

sudo apt install nginx

然后删除默认虚拟主机的符号链接,因为我们将不再使用它:

sudo rm /etc/nginx/sites-enabled/default

稍后我们将创建自己的默认站点 (example.com)。

现在我们将使用与 Apache 相同的过程为 Nginx 创建虚拟主机。 首先为两个网站创建文档根目录:

sudo mkdir -v /usr/share/nginx/example.com /usr/share/nginx/sample.org

我们会将 Nginx 网站保存在 /usr/share/nginx 中,这是 Nginx 默认需要它们的地方。 您可以将它们与 Apache 站点放在 /var/www/html 下,但这种分离可能有助于您将站点与 Nginx 关联。

正如您对 Apache 的虚拟主机所做的那样,在设置完成后创建 indexphpinfo() 文件进行测试:

echo "<h1 style='color: green;'>Example.com</h1>" | sudo tee /usr/share/nginx/example.com/index.html
echo "<h1 style='color: red;'>Sample.org</h1>" | sudo tee /usr/share/nginx/sample.org/index.html
echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/example.com/info.php
echo "<?php phpinfo(); ?>" | sudo tee /usr/share/nginx/sample.org/info.php

现在为域 example.com 创建一个虚拟主机文件:

sudo nano /etc/nginx/sites-available/example.com

Nginx 调用配置文件 服务器块server {. . .} 区域。 为主要虚拟主机 example.com 创建一个服务器块。 default_server 配置指令使它成为默认虚拟主机,它处理与任何其他虚拟主机不匹配的 HTTP 请求。

/etc/nginx/sites-available/example.com

server {
    listen 80 default_server;

    root /usr/share/nginx/example.com;
    index index.php index.html index.htm;

    server_name example.com www.example.com;
    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        include snippets/fastcgi-php.conf;
    }
}

保存并关闭文件。 现在为 Nginx 的第二个域 sample.org 创建一个虚拟主机文件:

sudo nano etc/nginx/sites-available/sample.org

将以下内容添加到文件中:

/etc/nginx/sites-available/sample.org

server {
    root /usr/share/nginx/sample.org;
    index index.php index.html index.htm;

    server_name sample.org www.sample.org;
    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        fastcgi_pass unix:/run/php/php7.2-fpm.sock;
        include snippets/fastcgi-php.conf;
    }
}

保存并关闭文件。

然后通过创建指向 sites-enabled 目录的符号链接来启用这两个站点:

sudo ln -s /etc/nginx/sites-available/example.com /etc/nginx/sites-enabled/example.com
sudo ln -s /etc/nginx/sites-available/sample.org /etc/nginx/sites-enabled/sample.org

然后测试 Nginx 配置,确保没有配置问题:

sudo nginx -t

如果没有错误则重新加载 Nginx:

sudo systemctl reload nginx

现在通过访问 http://example.com/info.phphttp://sample.org/ 在 Web 浏览器中访问 Nginx 虚拟主机的 phpinfo() 文件info.php。 再次查看 PHP 变量部分。

[“SERVER_SOFTWARE”] 应该是 nginx,表示这些文件是由 Nginx 直接提供的。 [“DOCUMENT_ROOT”] 应该指向您在此步骤之前为每个 Nginx 站点创建的目录。

至此,我们已经安装好 Nginx 并创建了两个虚拟主机。 接下来,我们将配置 Nginx 以代理针对托管在 Apache 上的域的请求。

第 7 步 — 为 Apache 的虚拟主机配置 Nginx

让我们在 server_name 指令中创建一个具有多个域名的附加 Nginx 虚拟主机。 对这些域名的请求将被代理到 Apache。

创建一个新的 Nginx 虚拟主机文件以将请求转发给 Apache:

sudo nano /etc/nginx/sites-available/apache

添加以下代码块,指定两个 Apache 虚拟主机域的名称并将它们的请求代理到 Apache。 记得在proxy_pass中使用公网IP地址:

/etc/nginx/sites-available/apache

server {
    listen 80;
    server_name foobar.net www.foobar.net test.io www.test.io;

    location / {
        proxy_pass http://your_server_ip:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }
}

保存文件并通过创建符号链接启用这个新的虚拟主机:

sudo ln -s /etc/nginx/sites-available/apache /etc/nginx/sites-enabled/apache

测试配置以确保没有错误:

sudo nginx -t

如果没有错误,重新加载 Nginx:

sudo systemctl reload nginx

打开浏览器并在浏览器中访问 URL http://foobar.net/info.php。 向下滚动到 PHP 变量 部分并检查显示的值。

变量 SERVER_SOFTWAREDOCUMENT_ROOT 确认此请求已由 Apache 处理。 变量 HTTP_X_REAL_IPHTTP_X_FORWARDED_FOR 由 Nginx 添加,应显示您用于访问 URL 的计算机的公共 IP 地址。

我们已成功设置 Nginx 将特定域的请求代理到 Apache。 接下来,让我们配置 Apache 以设置 REMOTE_ADDR 变量,就好像它直接处理这些请求一样。

第 8 步 — 安装和配置 mod_rpaf

在这一步中,您将安装一个名为 mod\_rpaf 的 Apache 模块,它会根据提供的值重写 REMOTE_ADDRHTTPSHTTP_PORT 的值通过反向代理。 如果没有这个模块,一些 PHP 应用程序需要更改代码才能在代理后面无缝工作。 该模块在 Ubuntu 的存储库中以 libapache2-mod-rpaf 的形式存在,但已过时并且不支持某些配置指令。 相反,我们将从源代码安装它。

安装构建模块所需的包:

sudo apt install unzip build-essential apache2-dev

从 GitHub 下载最新的稳定版本:

wget https://github.com/gnif/mod_rpaf/archive/stable.zip

提取下载的文件:

unzip stable.zip

切换到包含文件的新目录:

cd mod_rpaf-stable

编译并安装模块:

make
sudo make install

接下来,在 mods-available 目录中创建一个文件,该文件将加载 rpaf 模块:

sudo nano /etc/apache2/mods-available/rpaf.load

将以下代码添加到文件中以加载模块:

/etc/apache2/mods-available/rpaf.load

LoadModule rpaf_module /usr/lib/apache2/modules/mod_rpaf.so

保存文件并退出编辑器。

在此目录中创建另一个名为 rpaf.conf 的文件,其中将包含 mod_rpaf 的配置指令:

sudo nano /etc/apache2/mods-available/rpaf.conf

添加以下代码块来配置 mod_rpaf,确保指定服务器的 IP 地址:

/etc/apache2/mods-available/rpaf.conf

    <IfModule mod_rpaf.c>
        RPAF_Enable             On
        RPAF_Header             X-Real-Ip
        RPAF_ProxyIPs           your_server_ip 
        RPAF_SetHostName        On
        RPAF_SetHTTPS           On
        RPAF_SetPort            On
    </IfModule>

以下是每个指令的简要说明。 有关详细信息,请参阅 mod_rpaf README 文件。

  • RPAF_Header - 用于客户端真实 IP 地址的标头。
  • RPAF_ProxyIPs - 用于调整 HTTP 请求的代理 IP。
  • RPAF_SetHostName - 更新虚拟主机名,以便 ServerNameServerAlias 工作。
  • RPAF_SetHTTPS - 根据 X-Forwarded-Proto 中包含的值设置 HTTPS 环境变量。
  • RPAF_SetPort - 设置 SERVER_PORT 环境变量。 当 Apache 位于 SSL 代理之后时很有用。

保存 rpaf.conf 并启用模块:

sudo a2enmod rpaf

这将在 mods-enabled 目录中创建文件 rpaf.loadrpaf.conf 的符号链接。 现在做一个配置测试:

sudo apachectl -t

如果没有错误,请重新加载 Apache:

sudo systemctl reload apache2

在浏览器中访问 phpinfo() 页面 http://foobar.net/info.phphttp://test.io/info.php 并检查 PHP 变量 部分。 REMOTE_ADDR 变量现在也将是您本地计算机的公共 IP 地址的变量。

现在让我们为每个站点设置 TLS/SSL 加密。

第 9 步 — 使用 Let's Encrypt 设置 HTTPS 网站(可选)

在这一步中,我们将为托管在 Apache 上的两个域配置 TLS/SSL 证书。 我们将通过 [Let's Encrypt](https://letsencrypt.org] 获取证书。 Nginx 支持 SSL 终止,因此我们可以在不修改 Apache 的配置文件的情况下设置 SSL。 mod_rpaf 模块确保在 Apache 上设置所需的环境变量,以使应用程序在 SSL 反向代理后面无缝工作。

首先,我们将两个域的 server {...} 块分开,以便每个域都可以拥有自己的 SSL 证书。 在编辑器中打开文件 /etc/nginx/sites-available/apache

sudo nano /etc/nginx/sites-available/apache

修改文件,使其看起来像这样,在它们自己的 server 块中包含 foobar.nettest.io

/etc/nginx/sites-available/apache

    server {
        listen 80;
        server_name foobar.net www.foobar.net;
    
        location / {
            proxy_pass http://your_server_ip:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }
    server {
        listen 80;
        server_name test.io www.test.io;
    
        location / {
            proxy_pass http://your_server_ip:8080;
            proxy_set_header Host $host;
            proxy_set_header X-Real-IP $remote_addr;
            proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
            proxy_set_header X-Forwarded-Proto $scheme;
        }
    }

我们将使用 Certbot 来生成我们的 TLS/SSL 证书。 它的 Nginx 插件将负责重新配置 Nginx 并在必要时重新加载配置。

首先,添加官方 Certbot 存储库:

sudo add-apt-repository ppa:certbot/certbot

当提示您确认要添加新存储库时,按 ENTER。 然后更新包列表以获取新存储库的包信息:

sudo apt update

然后用 apt 安装 Certbot 的 Nginx 包:

sudo apt install python-certbot-nginx

安装后,使用 certbot 命令生成 foobar.netwww.foobar.net 的证书:

sudo certbot --nginx -d foobar.net -d www.foobar.net

此命令告诉 Certbot 使用 nginx 插件,使用 -d 指定我们希望证书有效的名称。

如果这是您第一次运行 certbot,系统将提示您输入电子邮件地址并同意服务条款。 完成此操作后,certbot 将与 Let's Encrypt 服务器通信,然后运行质询以验证您是否控制了要为其请求证书的域。

接下来,Certbot 将询问您希望如何配置 HTTPS 设置:

OutputPlease choose whether or not to redirect HTTP traffic to HTTPS, removing HTTP access.
-------------------------------------------------------------------------------
1: No redirect - Make no further changes to the webserver configuration.
2: Redirect - Make all requests redirect to secure HTTPS access. Choose this for
new sites, or if you're confident your site works on HTTPS. You can undo this
change by editing your web server's configuration.
-------------------------------------------------------------------------------
Select the appropriate number [1-2] then [enter] (press 'c' to cancel):

选择您的选择,然后按 ENTER。 配置将被更新,Nginx 将重新加载以获取新设置。

现在为第二个域执行命令:

sudo certbot --nginx -d test.io -d www.test.io

使用 https:// 前缀在浏览器中访问 Apache 的域之一; 访问 https://foobar.net/info.php 你会看到这个:

查看 PHP 变量 部分。 变量 SERVER_PORT 已设置为 443 并且 HTTPS 设置为 on,就好像 Apache 是通过 HTTPS 直接访问的一样。 设置这些变量后,PHP 应用程序不必专门配置为在反向代理后面工作。

现在让我们禁用对 Apache 的直接访问。

第 10 步 — 阻止对 Apache 的直接访问(可选)

由于 Apache 正在侦听公共 IP 地址上的端口 8080,因此每个人都可以访问它。 可以通过在防火墙规则集中使用以下 IPtables 命令来阻止它。

sudo iptables -I INPUT -p tcp --dport 8080 ! -s your_server_ip -j REJECT --reject-with tcp-reset

请务必使用您的服务器的 IP 地址代替红色示例。 一旦端口 8080 在您的防火墙中被阻止,请测试 Apache 在其上是否无法访问。 打开您的 Web 浏览器并尝试在端口 8080 上访问 Apache 的域名之一。 例如:http://example.com:8080

浏览器应显示“无法连接”或“网页不可用”错误消息。 使用 IPtables tcp-reset 选项,局外人会发现端口 8080 和没有任何服务的端口之间没有区别。

注意: 默认情况下,IPtables 规则不会在系统重新启动后继续存在。 有多种方法可以保留 IPtables 规则,但最简单的方法是使用 Ubuntu 存储库中的 iptables-persistent。 浏览 这篇文章 以了解有关如何配置 IPTables 的更多信息。


现在让我们配置 Nginx 为 Apache 站点提供静态文件。

第 11 步 — 使用 Nginx 提供静态文件(可选)

当 Nginx 代理对 Apache 域的请求时,它会将对该域的每个文件请求发送到 Apache。 Nginx 在提供静态文件(如图像、JavaScript 和样式表)方面比 Apache 更快。 因此,让我们配置 Nginx 的 apache 虚拟主机文件以直接提供静态文件,但将 PHP 请求发送到 Apache。

在编辑器中打开文件 /etc/nginx/sites-available/apache

sudo nano /etc/nginx/sites-available/apache

您需要向每个服务器块添加两个额外的 location 块,并修改现有的 location 部分。 此外,您需要告诉 Nginx 在哪里可以找到每个站点的静态文件。

如果您决定不使用 SSL 和 TLS 证书,请修改您的文件,使其如下所示:

/etc/nginx/sites-available/apache

server {
    listen 80;
    server_name test.io www.test.io;
    root /var/www/test.io;
    index index.php index.htm index.html;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        proxy_pass http://your_server_ip:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location ~ /\.ht {
        deny all;
    }
}

server {
    listen 80;
    server_name foobar.net www.foobar.net;
    root /var/www/foobar.net;
    index index.php index.htm index.html;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        proxy_pass http://your_ip_address:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location ~ /\.ht {
        deny all;
    }
}

如果您还希望 HTTPS 可用,请改用以下配置:

/etc/nginx/sites-available/apache

server {
    listen 80;
    server_name test.io www.test.io;
    root /var/www/test.io;
    index index.php index.htm index.html;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        proxy_pass http://your_server_ip:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location ~ /\.ht {
        deny all;
    }

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/test.io/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/test.io/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

server {
    listen 80;
    server_name foobar.net www.foobar.net;
    root /var/www/foobar.net;
    index index.php index.htm index.html;

    location / {
        try_files $uri $uri/ /index.php;
    }

    location ~ \.php$ {
        proxy_pass http://your_ip_address:8080;
        proxy_set_header Host $host;
        proxy_set_header X-Real-IP $remote_addr;
        proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header X-Forwarded-Proto $scheme;
    }

    location ~ /\.ht {
        deny all;
    }

    listen 443 ssl;
    ssl_certificate /etc/letsencrypt/live/foobar.net/fullchain.pem;
    ssl_certificate_key /etc/letsencrypt/live/foobar.net/privkey.pem;
    include /etc/letsencrypt/options-ssl-nginx.conf;
    ssl_dhparam /etc/letsencrypt/ssl-dhparams.pem;
}

try_files 指令使 Nginx 在文档根目录中查找文件并直接提供它们。 如果文件具有 .php 扩展名,则将请求传递给 Apache。 即使在文档根目录中找不到该文件,请求也会传递给 Apache,以便永久链接等应用程序功能正常工作。

警告: location ~ /\.ht指令很重要; 这可以防止 Nginx 提供包含敏感信息的 Apache 配置文件的内容,例如 .htaccess.htpasswd


保存文件并执行配置测试:

sudo nginx -t

如果测试成功则重新加载 Nginx:

sudo service nginx reload

要验证一切是否正常,您可以检查 /var/log/apache2 中的 Apache 日志文件并查看 GETtest.io 和 文件的 info.php 文件的请求X154X]。 使用 tail 命令查看文件的最后几行,并使用 -f 开关查看文件的更改:

sudo tail -f /var/log/apache2/other_vhosts_access.log

现在在浏览器中访问 http://test.io/info.php,然后查看日志的输出。 您会看到 Apache 确实在回复:

Output    test.io:80 your_server_ip - - [01/Jul/2016:18:18:34 -0400] "GET /info.php HTTP/1.0" 200 20414 "-" "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_10_5) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/47.0.2526.111 Safari/537.36"

然后访问每个站点的 index.html 页面,您将看不到任何来自 Apache 的日志条目。 Nginx 正在为他们服务。

观察完日志文件后,按 CTRL+C 停止拖尾。

使用此设置,Apache 将无法限制对静态文件的访问。 静态文件的访问控制需要在 Nginx 的 apache 虚拟主机文件中配置,但这超出了本教程的范围。

结论

您现在拥有一台 Ubuntu 服务器,其中 Nginx 服务 example.comsample.org,Apache 服务 foobar.nettest.io。 尽管 Nginx 充当 Apache 的反向代理,但 Nginx 的代理服务是透明的,与 Apache 域的连接似乎是直接从 Apache 本身提供的。 您可以使用此方法为安全和静态站点提供服务。