使用 Nginx 在 Linux 上托管 ASP.NET CoreHost ASP.NET Core on Linux with Nginx

作者:Sourabh ShirhattiBy Sourabh Shirhatti

本指南介绍如何在 Ubuntu 16.04 服务器上设置生产就绪 ASP.NET Core 环境。This guide explains setting up a production-ready ASP.NET Core environment on an Ubuntu 16.04 server. 这些说明可能适用于较新版本的 Ubuntu,但尚未使用较新版本进行测试。These instructions likely work with newer versions of Ubuntu, but the instructions haven't been tested with newer versions.

有关 ASP.NET Core 支持的其他 Linux 分配的信息,请参阅 Linux 上 .NET Core 的先决条件For information on other Linux distributions supported by ASP.NET Core, see Prerequisites for .NET Core on Linux.

备注

对于 Ubuntu 14.04,建议进行监控,以此作为监视 Kestrel 进程的解决方案。For Ubuntu 14.04, supervisord is recommended as a solution for monitoring the Kestrel process. 在 Ubuntu 14.04 上不提供 systemd 。systemd isn't available on Ubuntu 14.04. 有关 Ubuntu 14.04 的说明,请参阅本主题的以前版本For Ubuntu 14.04 instructions, see the previous version of this topic.

本指南:This guide:

  • 将现有 ASP.NET Core 应用置于反向代理服务器后方。Places an existing ASP.NET Core app behind a reverse proxy server.
  • 设置反向代理服务器,以便将请求转发到 Kestrel Web 服务器。Sets up the reverse proxy server to forward requests to the Kestrel web server.
  • 确保 Web 应用在启动时作为守护程序运行。Ensures the web app runs on startup as a daemon.
  • 配置进程管理工具以帮助重新启动 Web 应用。Configures a process management tool to help restart the web app.

系统必备Prerequisites

  1. 使用具有 sudo 特权的标准用户帐户访问 Ubuntu 16.04 服务器。Access to an Ubuntu 16.04 server with a standard user account with sudo privilege.
  2. 在服务器上安装 .NET Core 运行时。Install the .NET Core runtime on the server.
    1. 访问下载 .NET Core 页面Visit the Download .NET Core page.
    2. 选择最新的 .NET Core 非预览版。Select the latest non-preview .NET Core version.
    3. 在“运行应用”-“运行时”下的表格中,下载最新的非预览版运行时 。Download the latest non-preview runtime in the table under Run apps - Runtime.
    4. 选择 Linux 包管理器说明链接,然后按照 Ubuntu 版本的 Ubuntu 说明进行操作 。Select the Linux Package manager instructions link and follow the Ubuntu instructions for your version of Ubuntu.
  3. 一个现有 ASP.NET Core 应用。An existing ASP.NET Core app.

升级共享框架后,可随时重启服务器托管的 ASP.NET Core 应用。At any point in the future after upgrading the shared framework, restart the ASP.NET Core apps hosted by the server.

通过应用发布和复制Publish and copy over the app

配置应用以进行依赖框架的部署Configure the app for a framework-dependent deployment.

如果应用在本地运行,且未配置为建立安全连接 (HTTPS),则采用以下任一方法:If the app is run locally and isn't configured to make secure connections (HTTPS), adopt either of the following approaches:

  • 配置应用,以处理安全的本地连接。Configure the app to handle secure local connections. 有关详细信息,请参阅 HTTPS 配置部分。For more information, see the HTTPS configuration section.
  • 从 Properties/launchSettings.json 文件中的 applicationUrl 属性中删除 https://localhost:5001(如果存在) 。Remove https://localhost:5001 (if present) from the applicationUrl property in the Properties/launchSettings.json file.

在开发环境中运行 dotnet publish,将应用打包到可在服务器上运行的目录中(例如 bin/Release/<target_framework_moniker>/publish) :Run dotnet publish from the development environment to package an app into a directory (for example, bin/Release/<target_framework_moniker>/publish) that can run on the server:

dotnet publish --configuration Release

如果不希望维护服务器上的 .NET Core 运行时,还可将应用发布为独立部署The app can also be published as a self-contained deployment if you prefer not to maintain the .NET Core runtime on the server.

使用集成到组织工作流的工具(例如 SCP、SFTP)将 ASP.NET Core 应用复制到服务器。Copy the ASP.NET Core app to the server using a tool that integrates into the organization's workflow (for example, SCP, SFTP). 通常可在 var 目录(例如 var/www/helloapp)下找到 Web 应用 。It's common to locate web apps under the var directory (for example, var/www/helloapp).

备注

在生产部署方案中,持续集成工作流会执行发布应用并将资产复制到服务器的工作。Under a production deployment scenario, a continuous integration workflow does the work of publishing the app and copying the assets to the server.

测试应用:Test the app:

  1. 在命令行中运行应用:dotnet <app_assembly>.dllFrom the command line, run the app: dotnet <app_assembly>.dll.
  2. 在浏览器中,导航到 http://<serveraddress>:<port> 以确认应用在 Linux 本地正常运行。In a browser, navigate to http://<serveraddress>:<port> to verify the app works on Linux locally.

配置反向代理服务器Configure a reverse proxy server

反向代理是为动态 Web 应用提供服务的常见设置。A reverse proxy is a common setup for serving dynamic web apps. 反向代理终止 HTTP 请求,并将其转发到 ASP.NET Core 应用。A reverse proxy terminates the HTTP request and forwards it to the ASP.NET Core app.

使用反向代理服务器Use a reverse proxy server

Kestrel 非常适合从 ASP.NET Core 提供动态内容。Kestrel is great for serving dynamic content from ASP.NET Core. 但是,Web 服务功能不像服务器(如 IIS、Apache 或 Nginx)那样功能丰富。However, the web serving capabilities aren't as feature rich as servers such as IIS, Apache, or Nginx. 反向代理服务器可以卸载 HTTP 服务器的工作负载,如提供静态内容、缓存请求、压缩请求和 HTTPS 终端。A reverse proxy server can offload work such as serving static content, caching requests, compressing requests, and HTTPS termination from the HTTP server. 反向代理服务器可能驻留在专用计算机上,也可能与 HTTP 服务器一起部署。A reverse proxy server may reside on a dedicated machine or may be deployed alongside an HTTP server.

鉴于此指南的目的,使用 Nginx 的单个实例。For the purposes of this guide, a single instance of Nginx is used. 它与 HTTP 服务器一起运行在同一服务器上。It runs on the same server, alongside the HTTP server. 根据要求,可以选择不同的设置。Based on requirements, a different setup may be chosen.

由于请求是通过反向代理转接的,因此使用 Microsoft.AspNetCore.HttpOverrides 包中的转接头中间件Because requests are forwarded by reverse proxy, use the Forwarded Headers Middleware from the Microsoft.AspNetCore.HttpOverrides package. 此中间件使用 X-Forwarded-Proto 标头来更新 Request.Scheme,使重定向 URI 和其他安全策略能够正常工作。The middleware updates the Request.Scheme, using the X-Forwarded-Proto header, so that redirect URIs and other security policies work correctly.

调用转接头中间件后,必须放置依赖于该架构的组件,例如身份验证、链接生成、重定向和地理位置。Any component that depends on the scheme, such as authentication, link generation, redirects, and geolocation, must be placed after invoking the Forwarded Headers Middleware. 作为一般规则,转接头中间件应在诊断和错误处理中间件以外的其他中间件之前运行。As a general rule, Forwarded Headers Middleware should run before other middleware except diagnostics and error handling middleware. 此顺序可确保依赖于转接头信息的中间件可以使用标头值进行处理。This ordering ensures that the middleware relying on forwarded headers information can consume the header values for processing.

在调用 UseAuthentication 或类似的身份验证方案中间件之前,调用 Startup.Configure 中的 UseForwardedHeaders 方法。Invoke the UseForwardedHeaders method in Startup.Configure before calling UseAuthentication or similar authentication scheme middleware. 配置中间件以转接 X-Forwarded-ForX-Forwarded-Proto 标头:Configure the middleware to forward the X-Forwarded-For and X-Forwarded-Proto headers:

app.UseForwardedHeaders(new ForwardedHeadersOptions
{
    ForwardedHeaders = ForwardedHeaders.XForwardedFor | ForwardedHeaders.XForwardedProto
});

app.UseAuthentication();

如果没有为中间件指定 ForwardedHeadersOptions,则要转接的默认标头为 NoneIf no ForwardedHeadersOptions are specified to the middleware, the default headers to forward are None.

默认情况下,在环回地址 (127.0.0.0/8, [::1])(包括标准 localhost 地址 (127.0.0.1))上运行的代理受信任。Proxies running on loopback addresses (127.0.0.0/8, [::1]), including the standard localhost address (127.0.0.1), are trusted by default. 如果组织内的其他受信任代理或网络处理 Internet 与 Web 服务器之间的请求,请使用 ForwardedHeadersOptions 将其添加到 KnownProxiesKnownNetworks 的列表。If other trusted proxies or networks within the organization handle requests between the Internet and the web server, add them to the list of KnownProxies or KnownNetworks with ForwardedHeadersOptions. 以下示例会将 IP 地址为 10.0.0.100 的受信任代理服务器添加到 Startup.ConfigureServices 中的转接头中间件 KnownProxiesThe following example adds a trusted proxy server at IP address 10.0.0.100 to the Forwarded Headers Middleware KnownProxies in Startup.ConfigureServices:

services.Configure<ForwardedHeadersOptions>(options =>
{
    options.KnownProxies.Add(IPAddress.Parse("10.0.0.100"));
});

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

安装 NginxInstall Nginx

使用 apt-get 安装 Nginx。Use apt-get to install Nginx. 安装程序将创建一个 systemd init 脚本,该脚本运行 Nginx,作为系统启动时的守护程序 。The installer creates a systemd init script that runs Nginx as daemon on system startup. 按照以下网站上的 Ubuntu 安装说明操作:Nginx:官方 Debian/Ubuntu 包Follow the installation instructions for Ubuntu at Nginx: Official Debian/Ubuntu packages.

备注

如果需要可选 Nginx 模块,则可能需要从源代码生成 Nginx。If optional Nginx modules are required, building Nginx from source might be required.

因为是首次安装 Nginx,通过运行以下命令显式启动:Since Nginx was installed for the first time, explicitly start it by running:

sudo service nginx start

确认浏览器显示 Nginx 的默认登陆页。Verify a browser displays the default landing page for Nginx. 可在 http://<server_IP_address>/index.nginx-debian.html 访问登陆页面。The landing page is reachable at http://<server_IP_address>/index.nginx-debian.html.

配置 NginxConfigure Nginx

若要将 Nginx 配置为反向代理以将请求转接到 ASP.NET Core 应用,请修改 /etc/nginx/sites-available/default 。To configure Nginx as a reverse proxy to forward requests to your ASP.NET Core app, modify /etc/nginx/sites-available/default. 在文本编辑器中打开它,并将内容替换为以下内容:Open it in a text editor, and replace the contents with the following:

server {
    listen        80;
    server_name   example.com *.example.com;
    location / {
        proxy_pass         http://localhost:5000;
        proxy_http_version 1.1;
        proxy_set_header   Upgrade $http_upgrade;
        proxy_set_header   Connection keep-alive;
        proxy_set_header   Host $host;
        proxy_cache_bypass $http_upgrade;
        proxy_set_header   X-Forwarded-For $proxy_add_x_forwarded_for;
        proxy_set_header   X-Forwarded-Proto $scheme;
    }
}

当没有匹配的 server_name 时,Nginx 使用默认服务器。When no server_name matches, Nginx uses the default server. 如果没有定义默认服务器,则配置文件中的第一台服务器是默认服务器。If no default server is defined, the first server in the configuration file is the default server. 作为最佳做法,添加指定默认服务器,它会在配置文件中返回状态代码 444。As a best practice, add a specific default server which returns a status code of 444 in your configuration file. 默认的服务器配置示例是:A default server configuration example is:

server {
    listen   80 default_server;
    # listen [::]:80 default_server deferred;
    return   444;
}

使用上述配置文件和默认服务器,Nginx 接受主机标头 example.com*.example.com 端口 80 上的公共流量。With the preceding configuration file and default server, Nginx accepts public traffic on port 80 with host header example.com or *.example.com. 与这些主机不匹配的请求不会转接到 Kestrel。Requests not matching these hosts won't get forwarded to Kestrel. Nginx 将匹配的请求转接到 http://localhost:5000 中的 Kestrel。Nginx forwards the matching requests to Kestrel at http://localhost:5000. 有关详细信息,请参阅 nginx 如何处理请求See How nginx processes a request for more information. 若要更改 Kestrel 的 IP/端口,请参阅 Kestrel:终结点配置To change Kestrel's IP/port, see Kestrel: Endpoint configuration.

警告

未能指定正确的 server_name 指令会公开应用的安全漏洞。Failure to specify a proper server_name directive exposes your app to security vulnerabilities. 如果可控制整个父域(区别于易受攻击的 *.com),则子域通配符绑定(例如,*.example.com)不具有此安全风险。Subdomain wildcard binding (for example, *.example.com) doesn't pose this security risk if you control the entire parent domain (as opposed to *.com, which is vulnerable). 有关详细信息,请参阅 rfc7230 第 5.4 条See rfc7230 section-5.4 for more information.

完成配置 Nginx 后,运行 sudo nginx -t 来验证配置文件的语法。Once the Nginx configuration is established, run sudo nginx -t to verify the syntax of the configuration files. 如果配置文件测试成功,可以通过运行 sudo nginx -s reload 强制 Nginx 选取更改。If the configuration file test is successful, force Nginx to pick up the changes by running sudo nginx -s reload.

要直接在服务器上运行应用:To directly run the app on the server:

  1. 请导航到应用目录。Navigate to the app's directory.
  2. 运行应用:dotnet <app_assembly.dll>,其中 app_assembly.dll 是应用的程序集文件名。Run the app: dotnet <app_assembly.dll>, where app_assembly.dll is the assembly file name of the app.

如果应用在服务器上运行,但无法通过 Internet 响应,请检查服务器的防火墙,并确认端口 80 已打开。If the app runs on the server but fails to respond over the Internet, check the server's firewall and confirm that port 80 is open. 如果使用 Azure Ubuntu VM,请添加启用入站端口 80 流量的网络安全组 (NSG) 规则。If using an Azure Ubuntu VM, add a Network Security Group (NSG) rule that enables inbound port 80 traffic. 不需要启用出站端口 80 规则,因为启用入站规则后会自动许可出站流量。There's no need to enable an outbound port 80 rule, as the outbound traffic is automatically granted when the inbound rule is enabled.

测试应用完成后,请在命令提示符处按 Ctrl+C 关闭应用。When done testing the app, shut the app down with Ctrl+C at the command prompt.

监视应用Monitor the app

服务器设置为将对 http://<serveraddress>:80 发起的请求转接到在 http://127.0.0.1:5000 中的 Kestrel 上运行的 ASP.NET Core 应用。The server is setup to forward requests made to http://<serveraddress>:80 on to the ASP.NET Core app running on Kestrel at http://127.0.0.1:5000. 但是,未将 Nginx 设置为管理 Kestrel 进程。However, Nginx isn't set up to manage the Kestrel process. systemd 可用于创建服务文件以启动和监视基础 Web 应用。systemd can be used to create a service file to start and monitor the underlying web app. systemd 是一个 init 系统,可以提供用于启动、停止和管理进程的许多强大的功能。systemd is an init system that provides many powerful features for starting, stopping, and managing processes.

创建服务文件Create the service file

创建服务定义文件:Create the service definition file:

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

以下是应用的一个示例服务文件:The following is an example service file for the app:

[Unit]
Description=Example .NET Web API App running on Ubuntu

[Service]
WorkingDirectory=/var/www/helloapp
ExecStart=/usr/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=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

如果配置未使用用户 www-data,则必须先创建此处定义的用户,并为该用户提供适当的文件所有权。If the user www-data isn't used by the configuration, the user defined here must be created first and given proper ownership for files.

使用 TimeoutStopSec 配置在收到初始中断信号后等待应用程序关闭的持续时间。Use TimeoutStopSec to configure the duration of time to wait for the app to shut down after it receives the initial interrupt signal. 如果应用程序在此时间段内未关闭,则将发出 SIGKILL 以终止该应用程序。If the app doesn't shut down in this period, SIGKILL is issued to terminate the app. 提供作为无单位秒数的值(例如,150)、时间跨度值(例如,2min 30s)或 infinity 以禁用超时。Provide the value as unitless seconds (for example, 150), a time span value (for example, 2min 30s), or infinity to disable the timeout. TimeoutStopSec 默认为管理器配置文件(systemd-system.confsystem.conf.dsystemd-user.confuser.conf.d)中 DefaultTimeoutStopSec 的值。TimeoutStopSec defaults to the value of DefaultTimeoutStopSec in the manager configuration file (systemd-system.conf, system.conf.d, systemd-user.conf, user.conf.d). 大多数分发版的默认超时时间为 90 秒。The default timeout for most distributions is 90 seconds.

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

Linux 具有区分大小写的文件系统。Linux has a case-sensitive file system. 将 ASPNETCORE_ENVIRONMENT 设置为“生产”会导致搜索配置文件 appsettings.Production.json ,而不是 appsettings.production.json 。Setting ASPNETCORE_ENVIRONMENT to "Production" results in searching for the configuration file appsettings.Production.json, not appsettings.production.json.

必须转义某些值(例如,SQL 连接字符串)以供配置提供程序读取环境变量。Some values (for example, SQL connection strings) must be escaped for the configuration providers to read the environment variables. 使用以下命令生成适当的转义值以供在配置文件中使用:Use the following command to generate a properly escaped value for use in the configuration file:

systemd-escape "<value-to-escape>"

环境变量名不支持冒号 (:) 分隔符。Colon (:) separators aren't supported in environment variable names. 使用双下划线 (__) 代替冒号。Use a double underscore (__) in place of a colon. 环境变量读入配置时,环境变量配置提供程序将双下划线转换为冒号。The Environment Variables configuration provider converts double-underscores into colons when environment variables are read into configuration. 以下示例中,连接字符串密钥 ConnectionStrings:DefaultConnectionConnectionStrings__DefaultConnection 形式设置到服务定义文件中:In the following example, the connection string key ConnectionStrings:DefaultConnection is set into the service definition file as ConnectionStrings__DefaultConnection:

Environment=ConnectionStrings__DefaultConnection={Connection String}

保存该文件并启用该服务。Save the file and enable the service.

sudo systemctl enable kestrel-helloapp.service

启用该服务,并确认它正在运行。Start the service and verify that it's running.

sudo systemctl start kestrel-helloapp.service
sudo systemctl status kestrel-helloapp.service

● kestrel-helloapp.service - Example .NET Web API App running on Ubuntu
    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 进行访问。With the reverse proxy configured and Kestrel managed through systemd, the web app is fully configured and can be accessed from a browser on the local machine at http://localhost. 也可以从远程计算机进行访问,同时限制可能进行阻止的任何防火墙。It's also accessible from a remote machine, barring any firewall that might be blocking. 检查响应标头,Server 标头显示由 Kestrel 所提供的 ASP.NET Core 应用。Inspecting the response headers, the Server header shows the ASP.NET Core app being served by 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

查看日志View logs

使用 Kestrel 的 Web 应用是通过 systemd 进行管理的,因此所有事件和进程都被记录到集中日志。Since the web app using Kestrel is managed using systemd, all events and processes are logged to a centralized journal. 但是,此日志包含由 systemd 管理的所有服务和进程的全部条目。However, this journal includes all entries for all services and processes managed by systemd. 若要查看特定于 kestrel-helloapp.service 的项,请使用以下命令:To view the kestrel-helloapp.service-specific items, use the following command:

sudo journalctl -fu kestrel-helloapp.service

有关进一步筛选,使用时间选项(如 --since today--until 1 hour ago)或这些选项的组合可以减少返回的条目数。For further filtering, time options such as --since today, --until 1 hour ago or a combination of these can reduce the amount of entries returned.

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

数据保护Data protection

ASP.NET Core 数据保护堆栈由多个 ASP.NET Core 中间件(包括 cookie 中间件等身份验证中间件)和跨站点请求伪造 (CSRF) 保护使用。The ASP.NET Core Data Protection stack is used by several ASP.NET Core middlewares, including authentication middleware (for example, cookie middleware) and cross-site request forgery (CSRF) protections. 即使用户代码不调用数据保护 API,也应该配置数据保护,以创建持久的加密密钥存储Even if Data Protection APIs aren't called by user code, data protection should be configured to create a persistent cryptographic key store. 如果不配置数据保护,则密钥存储在内存中。重启应用时,密钥会被丢弃。If data protection isn't configured, the keys are held in memory and discarded when the app restarts.

如果密钥环存储于内存中,则在应用重启时:If the key ring is stored in memory when the app restarts:

  • 所有基于 cookie 的身份验证令牌都无效。All cookie-based authentication tokens are invalidated.
  • 用户需要在下一次请求时再次登录。Users are required to sign in again on their next request.
  • 无法再解密使用密钥环保护的任何数据。Any data protected with the key ring can no longer be decrypted. 这可能包括 CSRF 令牌ASP.NET Core MVC TempData cookieThis may include CSRF tokens and ASP.NET Core MVC TempData cookies.

若要配置数据保护以持久保存并加密密钥环,请参阅:To configure data protection to persist and encrypt the key ring, see:

较长的请求标头字段Long request header fields

代理服务器默认设置通常将请求标头字段限制为 4 K 或 8 K,具体取决于平台。Proxy server default settings typically limit request header fields to 4 K or 8 K depending on the platform. 某些应用可能需要超过默认值的字段(例如,使用 Azure Active Directory 的应用)。An app may require fields longer than the default (for example, apps that use Azure Active Directory). 如果需要更长的字段,则代理服务器的默认设置需要进行调整。If longer fields are required, the proxy server's default settings require adjustment. 要应用的值具体取决于方案。The values to apply depend on the scenario. 有关详细信息,请参见服务器文档。For more information, see your server's documentation.

警告

除非必要,否则不要提高代理缓冲区的默认值。Don't increase the default values of proxy buffers unless necessary. 提高这些值将增加缓冲区溢出的风险和恶意用户的拒绝服务 (DoS) 攻击风险。Increasing these values increases the risk of buffer overrun (overflow) and Denial of Service (DoS) attacks by malicious users.

保护应用Secure the app

启用 AppArmorEnable AppArmor

Linux 安全模块 (LSM) 是一个框架,它是自 Linux 2.6 后的 Linux kernel 的一部分。Linux Security Modules (LSM) is a framework that's part of the Linux kernel since Linux 2.6. LSM 支持安全模块的不同实现。LSM supports different implementations of security modules. AppArmor 是实现强制访问控制系统的 LSM,它允许将程序限制在一组有限的资源内。AppArmor is a LSM that implements a Mandatory Access Control system which allows confining the program to a limited set of resources. 确保已启用并成功配置 AppArmor。Ensure AppArmor is enabled and properly configured.

配置防火墙Configure the firewall

关闭所有未使用的外部端口。Close off all external ports that are not in use. 通过为配置防火墙提供命令行接口,不复杂的防火墙 (ufw) 为 iptables 提供了前端。Uncomplicated firewall (ufw) provides a front end for iptables by providing a command line interface for configuring the firewall.

警告

如果未正确配置,防火墙将阻止对整个系统的访问。A firewall will prevent access to the whole system if not configured correctly. 在使用 SSH 进行连接时,未能指定正确的 SSH 端口最终会将你关在系统之外。Failure to specify the correct SSH port will effectively lock you out of the system if you are using SSH to connect to it. 默认端口为 22。The default port is 22. 有关详细信息,请参阅 ufw 简介手册For more information, see the introduction to ufw and the manual.

安装 ufw,并将其配置为允许所需任何端口上的流量。Install ufw and configure it to allow traffic on any ports needed.

sudo apt-get install ufw

sudo ufw allow 22/tcp
sudo ufw allow 80/tcp
sudo ufw allow 443/tcp

sudo ufw enable

保护 NginxSecure Nginx

更改 Nginx 响应名称Change the Nginx response name

编辑 src/http/ngx_http_header_filter_module.c :Edit src/http/ngx_http_header_filter_module.c:

static char ngx_http_server_string[] = "Server: Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: Web Server" CRLF;

配置选项Configure options

用其他必需模块配置服务器。Configure the server with additional required modules. 请考虑使用 ModSecurity 等 Web 应用防火墙来加强对应用的保护。Consider using a web app firewall, such as ModSecurity, to harden the app.

HTTPS 配置HTTPS configuration

配置应用,以进行安全的 (HTTPS) 本地连接 Configure the app for secure (HTTPS) local connections

dotnet run 命令使用应用的 Properties/launchSettings.json 文件,该文件将应用配置为侦听 applicationUrl 属性(例如 https://localhost:5001;http://localhost:5000)提供的 URL 。The dotnet run command uses the app's Properties/launchSettings.json file, which configures the app to listen on the URLs provided by the applicationUrl property (for example, https://localhost:5001;http://localhost:5000).

使用以下方法之一配置应用,使其在开发过程中将证书用于 dotnet run 命令或开发环境(Visual Studio Code 中的 F5 或 Ctrl+F5):Configure the app to use a certificate in development for the dotnet run command or development environment (F5 or Ctrl+F5 in Visual Studio Code) using one of the following approaches:

配置反向代理,以便进行安全 (HTTPS) 客户端连接 Configure the reverse proxy for secure (HTTPS) client connections

  • 通过指定由受信任的证书颁发机构 (CA) 颁发的有效证书来配置服务器,以侦听端口 443 上的 HTTPS 流量。Configure the server to listen to HTTPS traffic on port 443 by specifying a valid certificate issued by a trusted Certificate Authority (CA).

  • 通过采用以下“/etc/nginx/nginx.conf” 文件中所示的某些做法来增强安全保护。Harden the security by employing some of the practices depicted in the following /etc/nginx/nginx.conf file. 示例包括选择更强的密码并将通过 HTTP 的所有流量重定向到 HTTPS。Examples include choosing a stronger cipher and redirecting all traffic over HTTP to HTTPS.

  • 添加 HTTP Strict-Transport-Security (HSTS) 标头可确保由客户端发起的所有后续请求都通过 HTTPS。Adding an HTTP Strict-Transport-Security (HSTS) header ensures all subsequent requests made by the client are over HTTPS.

  • 如果以后会禁用 HTTPS,请勿添加 HSTS 头或选择相应的 max-ageDon't add the HSTS header or chose an appropriate max-age if HTTPS will be disabled in the future.

添加 /etc/nginx/proxy.conf 配置文件:Add the /etc/nginx/proxy.conf configuration file:

proxy_redirect          off;
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;
client_max_body_size    10m;
client_body_buffer_size 128k;
proxy_connect_timeout   90;
proxy_send_timeout      90;
proxy_read_timeout      90;
proxy_buffers           32 4k;

编辑 /etc/nginx/nginx.conf 配置文件。Edit the /etc/nginx/nginx.conf configuration file. 示例包含一个配置文件中的 httpserver 部分。The example contains both http and server sections in one configuration file.

http {
    include        /etc/nginx/proxy.conf;
    limit_req_zone $binary_remote_addr zone=one:10m rate=5r/s;
    server_tokens  off;

    sendfile on;
    keepalive_timeout   29; # Adjust to the lowest possible value that makes sense for your use case.
    client_body_timeout 10; client_header_timeout 10; send_timeout 10;

    upstream hellomvc{
        server localhost:5000;
    }

    server {
        listen     *:80;
        add_header Strict-Transport-Security max-age=15768000;
        return     301 https://$host$request_uri;
    }

    server {
        listen                    *:443 ssl;
        server_name               example.com;
        ssl_certificate           /etc/ssl/certs/testCert.crt;
        ssl_certificate_key       /etc/ssl/certs/testCert.key;
        ssl_protocols             TLSv1.1 TLSv1.2;
        ssl_prefer_server_ciphers on;
        ssl_ciphers               "EECDH+AESGCM:EDH+AESGCM:AES256+EECDH:AES256+EDH";
        ssl_ecdh_curve            secp384r1;
        ssl_session_cache         shared:SSL:10m;
        ssl_session_tickets       off;
        ssl_stapling              on; #ensure your cert is capable
        ssl_stapling_verify       on; #ensure your cert is capable

        add_header Strict-Transport-Security "max-age=63072000; includeSubdomains; preload";
        add_header X-Frame-Options DENY;
        add_header X-Content-Type-Options nosniff;

        #Redirects all traffic
        location / {
            proxy_pass http://hellomvc;
            limit_req  zone=one burst=10 nodelay;
        }
    }
}

保护 Nginx 免受点击劫持的侵害Secure Nginx from clickjacking

点击劫持(也称为 UI 伪装攻击)是一种恶意攻击,其中网站访问者会上当受骗,从而导致在与当前要访问的页面不同的页面上单击链接或按钮。Clickjacking, also known as a UI redress attack, is a malicious attack where a website visitor is tricked into clicking a link or button on a different page than they're currently visiting. 使用 X-FRAME-OPTIONS 可保护网站。Use X-FRAME-OPTIONS to secure the site.

缓解点击劫持攻击:To mitigate clickjacking attacks:

  1. 编辑 nginx.conf 文件:Edit the nginx.conf file:

    sudo nano /etc/nginx/nginx.conf
    

    添加行 add_header X-Frame-Options "SAMEORIGIN";Add the line add_header X-Frame-Options "SAMEORIGIN";.

  2. 保存该文件。Save the file.

  3. 重启 Nginx。Restart Nginx.

MIME 类型探查MIME-type sniffing

此标头可阻止大部分浏览器通过 MIME 方式探查来自已声明内容类型的响应,因为标头会指示浏览器不要替代响应内容类型。This header prevents most browsers from MIME-sniffing a response away from the declared content type, as the header instructs the browser not to override the response content type. 使用 nosniff 选项后,如果服务器认为内容是“文本/html”,则浏览器将其显示为“文本/html”。With the nosniff option, if the server says the content is "text/html", the browser renders it as "text/html".

编辑 nginx.conf 文件:Edit the nginx.conf file:

sudo nano /etc/nginx/nginx.conf

添加行 add_header X-Content-Type-Options "nosniff"; 并保存文件,然后重新启动 Nginx。Add the line add_header X-Content-Type-Options "nosniff"; and save the file, then restart Nginx.

其他 Nginx 建议Additional Nginx suggestions

在服务器上升级共享框架后,重启服务器托管的 ASP.NET Core 应用。After upgrading the shared framework on the server, restart the ASP.NET Core apps hosted by the server.

其他资源Additional resources