使用 Apache 在 Linux 上托管 ASP.NET Core 您所在的位置:网站首页 apache基于cookie转发 使用 Apache 在 Linux 上托管 ASP.NET Core

使用 Apache 在 Linux 上托管 ASP.NET Core

#使用 Apache 在 Linux 上托管 ASP.NET Core | 来源: 网络整理| 查看: 265

使用 Apache 在 Linux 上托管 ASP.NET Core 项目 05/05/2023

作者:Shayne Boyer

使用本指南,了解如何在 CentOS 7 上将 Apache 设置为反向代理服务器,以将 HTTP 流量重定向到在 Kestrel 服务器上运行的 ASP.NET Core Web 应用。 mod_proxy extension 和相关模块可创建服务器的反向代理。

先决条件 运行 CentOS 7 的服务器,使用具有 sudo 特权的标准用户帐户。 在服务器上安装 .NET Core 运行时。 访问下载 .NET Core 页面。 选择最新的 .NET Core 非预览版。 在“运行应用”-“运行时”下的表格中,下载最新的非预览版运行时 。 选择 Linux 包管理器说明链接,然后按照 CentOS 说明进行操作 。 一个现有 ASP.NET Core 应用。

升级共享框架后,可随时重启服务器托管的 ASP.NET Core 应用。

通过应用发布和复制

配置应用以进行依赖框架的部署。

如果应用在开发环境中本地运行,并且未被服务器配置为建立安全 HTTPS 连接,则采用以下任一方法:

配置应用,以处理安全的本地连接。 有关详细信息,请参阅 HTTPS 配置部分。

将应用配置为在不安全的终结点运行:

在开发环境 (Program.cs) 中停用 HTTPS 重定向中间件:

if (!app.Environment.IsDevelopment()) { app.UseHttpsRedirection(); }

有关详细信息,请参阅在 ASP.NET Core 中使用多个环境。

从 Properties/launchSettings.json 文件的 applicationUrl 属性中删除 https://localhost:5001(如果存在)。

有关按环境配置的详细信息,请参阅在 ASP.NET Core 中使用多个环境。

在开发环境中运行 dotnet publish,将应用打包到可在服务器上运行的目录(例如 bin/Release/{TARGET FRAMEWORK MONIKER}/publish,其中 {TARGET FRAMEWORK MONIKER} 占位符表示目标框架名字对象 (TFM))中:

dotnet publish --configuration Release

如果不希望维护服务器上的 .NET Core 运行时,还可将应用发布为独立部署。

使用集成到组织工作流的工具(例如 SCP、SFTP)将 ASP.NET Core 应用复制到服务器。 通常可在 var 目录(例如 var/www/helloapp)下找到 Web 应用 。

注意

在生产部署方案中,持续集成工作流会执行发布应用并将资产复制到服务器的工作。

配置代理服务器

反向代理是为动态 Web 应用提供服务的常见设置。 反向代理终止 HTTP 请求,并将其转发到 ASP.NET 应用。

代理服务器将客户端请求转发到另一个服务器,而不是自身实现这些请求。 反向代理转发到固定的目标,通常代表任意客户端。 在本指南中,Apache 被配置为反向代理,在 Kestrel 为 ASP.NET Core 应用提供服务的同一服务器上运行。

由于请求是通过反向代理转接的,因此使用 Microsoft.AspNetCore.HttpOverrides 包中的转接头中间件。 此中间件使用 X-Forwarded-Proto 标头来更新 Request.Scheme,使重定向 URI 和其他安全策略能够正常工作。

调用转接头中间件后,必须放置依赖于该架构的组件,例如身份验证、链接生成、重定向和地理位置。

转接头中间件应在其他中间件之前运行。 此顺序可确保依赖于转接头信息的中间件可以使用标头值进行处理。 若要在诊断和错误处理中间件后运行转接头中间件,请参阅转接头中间件顺序。

调用其他中间件之前,请先在 Startup.Configure 的基础上调用 UseForwardedHeaders 方法。 配置中间件以转接 X-Forwarded-For 和 X-Forwarded-Proto 标头:

// using Microsoft.AspNetCore.HttpOverrides; app.UseForwardedHeaders(new ForwardedHeadersOptions { ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto }); app.UseAuthentication();

如果没有为中间件指定 ForwardedHeadersOptions,则要转接的默认标头为 None。

默认情况下,在环回地址 (127.0.0.0/8, [::1])(包括标准 localhost 地址 (127.0.0.1))上运行的代理受信任。 如果组织内的其他受信任代理或网络处理 Internet 与 Web 服务器之间的请求,请使用 ForwardedHeadersOptions 将其添加到 KnownProxies 或 KnownNetworks 的列表。 以下示例会将 IP 地址为 10.0.0.100 的受信任代理服务器添加到 Startup.ConfigureServices 中的转接头中间件 KnownProxies:

// using System.Net; services.Configure(options => { options.KnownProxies.Add(IPAddress.Parse("10.0.0.100")); });

有关详细信息,请参阅配置 ASP.NET Core 以使用代理服务器和负载均衡器。

安装 Apache

将 CentOS 包更新为其最新稳定版本:

sudo yum update -y

使用单个 yum 命令在 CentOS 上安装 Apache Web 服务器:

sudo yum -y install httpd mod_ssl

运行该命令后的示例输出:

Downloading packages: httpd-2.4.6-40.el7.centos.4.x86_64.rpm | 2.7 MB 00:00:01 Running transaction check Running transaction test Transaction test succeeded Running transaction Installing : httpd-2.4.6-40.el7.centos.4.x86_64 1/1 Verifying : httpd-2.4.6-40.el7.centos.4.x86_64 1/1 Installed: httpd.x86_64 0:2.4.6-40.el7.centos.4 Complete!

注意

在此示例中,输出反映了 httpd.86_64,因为 CentOS 7 版本是 64 位的。 若要验证 Apache 的安装位置,请从命令提示符运行 whereis httpd。

配置 Apache

Apache 的配置文件位于 /etc/httpd/conf.d/ 目录内。 在 Ubuntu 上的 Apache 中,所有虚拟主机配置文件都存储在 /etc/apache2/sites-available 中。 除了 /etc/httpd/conf.modules.d/ 中的模块配置文件外(其中包含加载模块所需的任何配置文件),将对任何带 .conf 扩展名的文件按字母顺序进行处理。

为应用创建名为 helloapp.conf 的配置文件:

RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME}s ProxyPreserveHost On ProxyPass / http://127.0.0.1:5000/ ProxyPassReverse / http://127.0.0.1:5000/ ServerName www.example.com ServerAlias *.example.com ErrorLog ${APACHE_LOG_DIR}/helloapp-error.log CustomLog ${APACHE_LOG_DIR}/helloapp-access.log common

VirtualHost 块可以在服务器上的一个或多个文件中多次出现。 在前面的配置文件中,Apache 接受端口 80 上的公共流量。 正在向域 www.example.com 提供服务,*.example.com 别名解析为同一网站。 有关详细信息,请参阅基于名称的虚拟主机支持。 请求会通过代理从根位置转到 127.0.0.1 处的服务器的端口 5000。 对于双向通信,需要 ProxyPass 和 ProxyPassReverse。 要更改 Kestrel 的 IP/端口,请参阅 Kestrel:终结点配置。

VirtualHost 块可以在服务器上的一个或多个文件中多次出现。 在前面的配置文件中,Apache 接受端口 80 上的公共流量。 正在向域 www.example.com 提供服务,*.example.com 别名解析为同一网站。 有关详细信息,请参阅基于名称的虚拟主机支持。 请求会通过代理从根位置转到 127.0.0.1 处的服务器的端口 5000。 对于双向通信,需要 ProxyPass 和 ProxyPassReverse。 要更改 Kestrel 的 IP/端口,请参阅 Kestrel:终结点配置。

创建一个指向 /etc/apache2/sites-enabled 目录的符号链接,供 Apache 在启动期间读取:

sudo ln -s /etc/apache2/sites-available/helloapp.conf /etc/apache2/sites-enabled/

警告

未能指定 VirtualHost 块中的正确 ServerName 指令会公开应用的安全漏洞。 如果可控制整个父域(区别于易受攻击的 *.com),则子域通配符绑定(例如,*.example.com)不具有此安全风险。 有关详细信息,请参阅 RFC 9110:HTTP 语义(第 7.2 节:托管和授权)。

可以使用 ErrorLog 和 CustomLog 指令配置每个 VirtualHost 的日志记录。 ErrorLog 是服务器记录错误的位置,CustomLog 则设置文件名和日志文件的格式。 在这种情况下,这是记录请求信息的位置。 每个请求将各占一行。

保存文件,并测试配置。 如果一切正常,响应应为 Syntax [OK]。

sudo apachectl configtest

重新启动 Apache:

sudo systemctl restart httpd sudo systemctl enable httpd

有关标头指令值的详细信息,请参阅 Apache 模块 mod_headers。

监视应用

Apache 现在已设置为将对 http://localhost:80 发起的请求转发到在 http://127.0.0.1:5000 中的 Kestrel 上运行的 ASP.NET Core 应用。 但是,未将 Apache 设置为管理 Kestrel 进程。 使用 systemd ,并创建服务文件以启动和监视基础 Web 应用。 systemd 是一个 init 系统,可以提供用于启动、停止和管理进程的许多强大的功能。

创建服务文件

创建服务定义文件:

sudo nano /etc/systemd/system/kestrel-helloapp.service

应用的一个示例服务文件:

[Unit] Description=Example .NET Web API App running on CentOS 7 [Service] WorkingDirectory=/var/www/helloapp ExecStart=/usr/local/bin/dotnet /var/www/helloapp/helloapp.dll Restart=always # Restart service after 10 seconds if the dotnet service crashes: RestartSec=10 KillSignal=SIGINT SyslogIdentifier=dotnet-example User=apache Environment=ASPNETCORE_ENVIRONMENT=Production [Install] WantedBy=multi-user.target

在前面的示例中,管理服务的用户由 User 选项指定。 用户 (apache) 必须存在并且拥有正确应用文件的所有权。

使用 TimeoutStopSec 配置在收到初始中断信号后等待应用程序关闭的持续时间。 如果应用程序在此时间段内未关闭,则将发出 SIGKILL 以终止该应用程序。 提供作为无单位秒数的值(例如,150)、时间跨度值(例如,2min 30s)或 infinity 以禁用超时。 TimeoutStopSec 默认为管理器配置文件(systemd-system.conf、system.conf.d、systemd-user.conf、user.conf.d)中 DefaultTimeoutStopSec 的值。 大多数分发版的默认超时时间为 90 秒。

# The default value is 90 seconds for most distributions. TimeoutStopSec=90

必须转义某些值(例如,SQL 连接字符串)以供配置提供程序读取环境变量。 使用以下命令生成适当的转义值以供在配置文件中使用:

systemd-escape ""

环境变量名不支持冒号 (:) 分隔符。 使用双下划线 (__) 代替冒号。 环境变量读入配置时,环境变量配置提供程序将双下划线转换为冒号。 以下示例中,连接字符串密钥 ConnectionStrings:DefaultConnection 以 ConnectionStrings__DefaultConnection 形式设置到服务定义文件中:

环境变量名不支持冒号 (:) 分隔符。 使用双下划线 (__) 代替冒号。 环境变量读入配置时,环境变量配置提供程序将双下划线转换为冒号。 以下示例中,连接字符串密钥 ConnectionStrings:DefaultConnection 以 ConnectionStrings__DefaultConnection 形式设置到服务定义文件中:

Environment=ConnectionStrings__DefaultConnection={Connection String}

保存该文件并启用该服务:

sudo systemctl enable kestrel-helloapp.service

启动该服务,并确认它正在运行:

sudo systemctl start kestrel-helloapp.service sudo systemctl status kestrel-helloapp.service ◝ kestrel-helloapp.service - Example .NET Web API App running on CentOS 7 Loaded: loaded (/etc/systemd/system/kestrel-helloapp.service; enabled) Active: active (running) since Thu 2016-10-18 04:09:35 NZDT; 35s ago Main PID: 9021 (dotnet) CGroup: /system.slice/kestrel-helloapp.service └─9021 /usr/local/bin/dotnet /var/www/helloapp/helloapp.dll

在配置了反向代理并通过 systemd 管理 Kestrel 后,Web 应用现已完全配置,并能在本地计算机上的浏览器中从 http://localhost 进行访问。 检查响应标头,服务器标头表示 ASP.NET Core 应用由 Kestrel 提供服务:

HTTP/1.1 200 OK Date: Tue, 11 Oct 2016 16:22:23 GMT Server: Kestrel Keep-Alive: timeout=5, max=98 Connection: Keep-Alive Transfer-Encoding: chunked 查看日志

由于使用 Kestrel 的 Web 应用是通过 systemd 进行管理的,因此事件和进程将记录到集中日志。 但是,此日志包含由 systemd 管理的所有服务和进程的条目。 若要查看特定于 kestrel-helloapp.service 的项,请使用以下命令:

sudo journalctl -fu kestrel-helloapp.service

若要进行时间筛选,请使用命令指定时间选项。 例如,使用 --since today 筛选出当天或 --until 1 hour ago 来查看前一小时的条目。 有关详细信息,请参阅 journalctl 手册页。

sudo journalctl -fu kestrel-helloapp.service --since "2016-10-18" --until "2016-10-18 04:00" 数据保护

ASP.NET Core 数据保护堆栈由多个 ASP.NET Core 中间件(包括 cookie 中间件等身份验证中间件)和跨站点请求伪造 (CSRF) 保护使用。 即使用户代码不调用数据保护 API,也应该配置数据保护,以创建持久的加密密钥存储。 如果不配置数据保护,则密钥存储在内存中。重启应用时,密钥会被丢弃。

如果密钥环存储于内存中,则在应用重启时:

所有基于 cookie 的身份验证令牌都无效。 用户需要在下一次请求时再次登录。 无法再解密使用密钥环保护的任何数据。 这可能包括 CSRF 令牌和 ASP.NET Core MVC TempData cookie。

若要配置数据保护以持久保存并加密密钥环,请参阅:

ASP.NET Core 中的密钥存储提供程序 使用 ASP.NET Core 在 Windows 和 Azure 中实现密钥静态加密 保护应用 配置防火墙

Firewalld 是管理防火墙的动态守护程序,支持网络区域。 仍可以使用 iptable 管理端口和数据包筛选。 默认情况下应安装 Firewalld。 yum 可用于安装包或验证是否已安装。

sudo yum install firewalld -y

使用 firewalld 仅打开应用所需的端口。 本例中使用的是端口 80 和 443。 以下命令将端口 80 和 443 永久设置为打开:

sudo firewall-cmd --add-port=80/tcp --permanent sudo firewall-cmd --add-port=443/tcp --permanent

重新加载防火墙设置。 检查默认区域中可用的服务和端口。 通过检查 firewall-cmd -h 获取可用选项。

sudo firewall-cmd --reload sudo firewall-cmd --list-all public (default, active) interfaces: eth0 sources: services: dhcpv6-client ports: 443/tcp 80/tcp masquerade: no forward-ports: icmp-blocks: rich rules: HTTPS 配置

配置应用,以进行安全的 (HTTPS) 本地连接

dotnet run 命令使用应用的 Properties/launchSettings.json 文件,该文件将应用配置为侦听 applicationUrl 属性(例如 https://localhost:5001;http://localhost:5000)提供的 URL。

使用以下方法之一配置应用,使其在开发过程中将证书用于 dotnet run 命令或开发环境(Visual Studio Code 中的 F5 或 Ctrl+F5):

从配置中替换默认证书(推荐) KestrelServerOptions.ConfigureHttpsDefaults 从配置中替换默认证书(推荐) KestrelServerOptions.ConfigureHttpsDefaults

配置反向代理,以便进行安全 (HTTPS) 客户端连接

警告

本部分中的安全配置是一种常规配置,可以作为进一步进行自定义的起点。 我们无法为第三方工具、服务器和操作系统提供支持。 如果使用本部分中的配置,请自行承担风险。 有关更多信息,请访问以下资源:

Apache SSL/TLS 加密(Apache 文档) mozilla.org SSL Configuration Generator

若要为 Apache 配置 HTTPS,请使用 mod_ssl 模块。 安装了 httpd 模块时,也会安装了 mod_ssl 模块。 如果未安装,请使用 yum 将其添加到配置。

sudo yum install mod_ssl

若要强制使用 HTTPS,请安装 mod_rewrite 模块以启用 URL 重写:

sudo yum install mod_rewrite

修改 helloapp.conf 文件以在端口 443 上启用安全通信。

下面的示例未将服务器配置为重定向不安全的请求。 建议使用 HTTPS 重定向中间件。 有关详细信息,请参阅在 ASP.NET Core 中强制使用 HTTPS。

注意

对于由服务器配置(而非 HTTPS 重定向中间件)处理安全重定向的开发环境,建议使用临时重定向 (302) 替代永久性重定向 (301)。 链接缓存会导致开发环境中的行为不稳定。

添加 Strict-Transport-Security (HSTS) 标头可确保由客户端发起的所有后续请求都通过 HTTPS。 有关设置 Strict-Transport-Security 标头的指南,请参阅在 ASP.NET Core 中强制使用 HTTPS。

RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME} Protocols h2 http/1.1 ProxyPreserveHost On ProxyPass / http://127.0.0.1:5000/ ProxyPassReverse / http://127.0.0.1:5000/ ErrorLog /var/log/httpd/helloapp-error.log CustomLog /var/log/httpd/helloapp-access.log common SSLEngine on SSLProtocol all -SSLv3 -TLSv1 -TLSv1.1 SSLHonorCipherOrder off SSLCompression off SSLSessionTickets on SSLUseStapling off SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key SSLCipherSuite ECDHE-ECDSA-AES128-GCM-SHA256:ECDHE-RSA-AES128-GCM-SHA256:ECDHE-ECDSA-AES256-GCM-SHA384:ECDHE-RSA-AES256-GCM-SHA384:ECDHE-ECDSA-CHACHA20-POLY1305:ECDHE-RSA-CHACHA20-POLY1305:DHE-RSA-AES128-GCM-SHA256:DHE-RSA-AES256-GCM-SHA384

注意

此示例中使用了本地生成的证书。 SSLCertificateFile 应为域名的主证书文件。 SSLCertificateKeyFile 应为创建 CSR 时生成的密钥文件。 SSLCertificateChainFile 应为证书颁发机构提供的中间证书文件(如有)。

需要 Apache HTTP 服务器版本 2.4.43 或更高版本,才能使用 OpenSSL 1.1.1 运行 TLS 1.3 Web 服务器。

注意

上面的示例禁用了在线证书状态协议 (OCSP) 装订。 有关启用 OCSP 的更多信息和指南,请参阅 OCSP 装订(Apache 文档)。

保存文件,并测试配置:

sudo service httpd configtest

重新启动 Apache:

sudo systemctl restart httpd 其他 Apache 建议 通过共享框架更新重启应用

在服务器上升级共享框架后,重启服务器托管的 ASP.NET Core 应用。

其他标头

为了防止恶意攻击,应对一些标头进行修改或添加一些标头。 确保已安装 mod_headers 模块:

sudo yum install mod_headers 保护 Apache 免受点击劫持攻击

点击劫持(也称为 UI 伪装攻击)是一种恶意攻击,其中网站访问者会上当受骗,从而导致在与当前要访问的页面不同的页面上单击链接或按钮。 使用 X-FRAME-OPTIONS 可保护网站。

缓解点击劫持攻击:

编辑 httpd.conf 文件:

sudo nano /etc/httpd/conf/httpd.conf

添加行 Header append X-FRAME-OPTIONS "SAMEORIGIN"。

保存该文件。

重启 Apache。

MIME 类型探查

X-Content-Type-Options 标头阻止 Internet Explorer 进行 MIME 探查(从文件内容中确定文件的 Content-Type)。 如果服务器通过设置 nosniff 选项将 Content-Type 标头设置为 text/html,则不管文件内容为何,Internet Explorer 都会将内容呈现为 text/html。

编辑 httpd.conf 文件:

sudo nano /etc/httpd/conf/httpd.conf

添加行 Header set X-Content-Type-Options "nosniff"。 保存该文件。 重启 Apache。

负载平衡

此示例演示如何在同一实例计算机上的 CentOS 7 和 Kestrel 上设置和配置 Apache。 为了不出现单一故障点,使用 mod_proxy_balancer 并修改 VirtualHost 可实现在 Apache 代理服务器后方管理 Web 应用的多个实例。

sudo yum install mod_proxy_balancer

在下面所示的配置文件中,helloapp 的其他实例设置为在端口 5001 上运行。 “代理” 部分设置了具有两个成员的均衡器配置,以便对 byrequests 进行负载均衡。

RequestHeader set "X-Forwarded-Proto" expr=%{REQUEST_SCHEME} RewriteEngine On RewriteCond %{HTTPS} !=on RewriteRule ^/?(.*) https://%{SERVER_NAME}/$1 [R,L] ProxyPass / balancer://mycluster/ ProxyPassReverse / http://127.0.0.1:5000/ ProxyPassReverse / http://127.0.0.1:5001/ BalancerMember http://127.0.0.1:5000 BalancerMember http://127.0.0.1:5001 ProxySet lbmethod=byrequests SetHandler balancer ErrorLog /var/log/httpd/helloapp-error.log CustomLog /var/log/httpd/helloapp-access.log common SSLEngine on SSLProtocol all -SSLv2 SSLCipherSuite ALL:!ADH:!EXPORT:!SSLv2:!RC4+RSA:+HIGH:+MEDIUM:!LOW:!RC4 SSLCertificateFile /etc/pki/tls/certs/localhost.crt SSLCertificateKeyFile /etc/pki/tls/private/localhost.key 速率限制

使用 httpd 模块中包含的 mod_ratelimit ,客户端的带宽可以限制为:

sudo nano /etc/httpd/conf.d/ratelimit.conf

示例文件将根位置下的带宽限制为 600 KB/秒:

SetOutputFilter RATE_LIMIT SetEnv rate-limit 600 较长的请求标头字段

代理服务器默认设置通常将请求标头字段限制为 8190 字节。 某些应用可能需要超过默认值的字段(例如,使用 Azure Active Directory 的应用)。 如果需要更长的字段,则代理服务器的 LimitRequestFieldSize 指令需要进行调整。 要应用的值具体取决于方案。 有关详细信息,请参见服务器文档。

警告

除非必要,否则不要提高 LimitRequestFieldSize 的默认值。 提高该值将增加缓冲区溢出的风险和恶意用户的拒绝服务 (DoS) 攻击风险。

其他资源 Linux 上 .NET Core 的先决条件 ASP.NET Core 项目故障排除和调试 配置 ASP.NET Core 以使用代理服务器和负载均衡器


【本文地址】

公司简介

联系我们

今日新闻

    推荐新闻

    专题文章
      CopyRight 2018-2019 实验室设备网 版权所有