Nginx 搭載の Linux で ASP.NET Core をホストするための環境をセットアップし、その環境に展開するSet up a hosting environment for ASP.NET Core on Linux with Nginx, and deploy to it

Sourabh Shirhatti による投稿By 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 14.04 の場合、Kestrel プロセスを監視するためのソリューションとして supervisord が推奨されます。Note: For Ubuntu 14.04, supervisord is recommended as a solution for monitoring the Kestrel process. systemd は Ubuntu 14.04 ではご利用いただけません。systemd is not available on Ubuntu 14.04. この文書の前のバージョンをご覧くださいSee previous version of this document

このガイドでは:This guide:

  • リバース プロキシ サーバーの後ろに既存の ASP.NET Core アプリケーションを配置しますPlaces an existing ASP.NET Core application 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 application runs on startup as a daemon
  • Web アプリケーションの再起動を支援するようにプロセス管理ツールを構成しますConfigures a process management tool to help restart the web application

必須コンポーネントPrerequisites

  1. Ubuntu 16.04 サーバーへのアクセスと sudo 特権が与えられた標準ユーザー アカウントAccess to an Ubuntu 16.04 Server with a standard user account with sudo privilege
  2. 既存の ASP.NET Core アプリケーションAn existing ASP.NET Core application

アプリをコピーするCopy over your app

開発環境から dotnet publish を実行し、サーバーで実行可能な自己完結型ディレクトリにアプリをパッケージ化します。Run dotnet publish from the dev environment to package an app into a self-contained directory that can run on the server.

ワークフローに統合されているツール (SCP や FTP など) を利用し、サーバーに ASP.NET Core アプリをコピーします。Copy the ASP.NET Core app to the server using whatever tool (SCP, FTP, etc.) integrates into your workflow. 次のようにアプリをテストします。Test the app, for example:

  • コマンド ラインから dotnet yourapp.dll を実行します。From the command line, run dotnet yourapp.dll
  • ブラウザーで、http://<serveraddress>:<port> に移動し、アプリが Linux で動作することを検証します。In a browser, navigate to http://<serveraddress>:<port> to verify the app works on Linux.

注: Yeoman を利用し、新しいプロジェクトのために新しい ASP.NET Core アプリを作成します。Note: Use Yeoman to create a new ASP.NET Core app for a new project.

リバース プロキシ サーバーを構成するConfigure a reverse proxy server

リバース プロキシは、動的 Web アプリケーションにサービスを提供するための一般的なしくみです。A reverse proxy is a common setup for serving dynamic web applications. リバース プロキシは HTTP 要求を終了させ、ASP.NET Core アプリケーションに転送します。A reverse proxy terminates the HTTP request and forwards it to the ASP.NET Core application.

リバース プロキシ サーバーを利用する理由Why use a reverse proxy server?

ASP.NET Core から動的コンテンツにサービスを提供することに関して、Kestrel は優れた Web ツールです。しかしながら、IIS、Apache、Nginx などのサーバーのように機能が豊富ではありません。Kestrel is great for serving dynamic content from ASP.NET Core; however, the web serving parts aren’t as feature rich as servers like IIS, Apache, or Nginx. リバース プロキシ サーバーは、静的コンテンツ サービス、要求のキャッシュ、要求の圧縮、HTTP サーバーからの SSL 終了などの作業の負荷を軽減します。A reverse proxy server can offload work like serving static content, caching requests, compressing requests, and SSL 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 your requirements, you may choose a different setup.

要求はリバース プロキシによって転送されるため、Microsoft.AspNetCore.HttpOverrides パッケージの ForwardedHeaders ミドルウェアを使用します。Because requests are forwarded by reverse proxy, use the ForwardedHeaders middleware from the Microsoft.AspNetCore.HttpOverrides package. このミドルウェアは X-Forwarded-Proto ヘッダーを利用して Request.Scheme を更新します。リダイレクト URI とその他のセキュリティ ポリシーが正しく機能します。This middleware updates Request.Scheme, using the X-Forwarded-Proto header, so that redirect URIs and other security policies work correctly.

リバース プロキシ サーバーを設定するとき、認証ミドルウェアで UseForwardedHeaders を先に実行する必要があります。When setting up a reverse proxy server, the authentication middleware needs UseForwardedHeaders to run first. この順序により、認証ミドルウェアは影響を受けた値を利用し、正しいリダイレクト URI を生成できます。This ordering ensures that the authentication middleware can consume the affected values and generate correct redirect URIs.

UseAuthentication や同様の認証スキーム ミドルウェアを呼び出す前に、UseForwardedHeaders メソッドを呼び出します (Startup.csConfigure メソッド)。Invoke the UseForwardedHeaders method (in the Configure method of Startup.cs) before calling UseAuthentication or similar authentication scheme middleware:

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

app.UseAuthentication();

Nginx をインストールするInstall Nginx

sudo apt-get install nginx

注意

オプションの Nginx モジュールをインストールする場合、ソースから Nginx をビルドしなければならないことがあります。If you plan to install optional Nginx modules, you may be required to build Nginx from source.

apt-get を利用し、Nginx をインストールします。Use apt-get to install Nginx. インストーラーにより System V init スクリプトが作成されます。このスクリプトがシステム起動時に Nginx をデーモンとして実行します。The installer creates a System V init script that runs Nginx as daemon on system startup. 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.

Nginx を構成するConfigure Nginx

Nginx をリバース プロキシとして構成し、ASP.NET Core アプリケーションに要求を転送するには、/etc/nginx/sites-available/default を変更します。To configure Nginx as a reverse proxy to forward requests to our ASP.NET Core application, modify /etc/nginx/sites-available/default. テキスト エディターで開き、中身を次のものに変更します。Open it in a text editor, and replace the contents with the following:

server {
    listen 80;
    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;
    }
}

この Nginx 構成ファイルは、ポート 80 から入ってくるパブリック トラフィックをポート 5000 に転送します。This Nginx configuration file forwards incoming public traffic from port 80 to port 5000.

Nginx 構成の変更が終わったら、sudo nginx -t を実行し、構成ファイルの構文を検証します。Once you have completed making changes to your Nginx configuration, you can run sudo nginx -t to verify the syntax of your configuration files. 構成ファイル テストが合格の場合、sudo nginx -s reload を実行し、変更を反映するように Nginx に要求できます。If the configuration file test is successful, you can ask Nginx to pick up the changes by running sudo nginx -s reload.

アプリケーションの監視Monitoring our application

これで、http://yourhost:80 に対して行われた要求を Kestrel で実行されている ASP.NET Core アプリケーション (http://127.0.0.1:5000) に転送するように Nginx が設定されました。Nginx is now setup to forward requests made to http://yourhost:80 on to the ASP.NET Core application running on Kestrel at http://127.0.0.1:5000. ただし、Nginx は Kestrel プロセスを管理するようには設定されていません。However, Nginx is not set up to manage the Kestrel process. systemd を利用し、基礎 Web アプリを起動し、監視するサービス ファイルを作成できます。You can use systemd and 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-hellomvc.service

次はアプリケーションのサービス ファイルの例です。The following is an example service file for our application:

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

[Service]
WorkingDirectory=/var/aspnetcore/hellomvc
ExecStart=/usr/bin/dotnet /var/aspnetcore/hellomvc/hellomvc.dll
Restart=always
RestartSec=10  # Restart service after 10 seconds if dotnet service crashes
SyslogIdentifier=dotnet-example
User=www-data
Environment=ASPNETCORE_ENVIRONMENT=Production
Environment=DOTNET_PRINT_TELEMETRY_MESSAGE=false

[Install]
WantedBy=multi-user.target

注: ユーザー www-data が構成で利用されない場合、ここで定義するユーザーを先に作成し、ファイルの適切な所有権を与える必要があります。Note: If the user www-data is not used by your configuration, the user defined here must be created first and given proper ownership for files.

ファイルを保存し、サービスを有効にします。Save the file, and enable the service.

systemctl enable kestrel-hellomvc.service

サービスを起動し、動作していることを確認します。Start the service and verify that it is running.

systemctl start kestrel-hellomvc.service
systemctl status kestrel-hellomvc.service

● kestrel-hellomvc.service - Example .NET Web API Application running on Ubuntu
    Loaded: loaded (/etc/systemd/system/kestrel-hellomvc.service; enabled)
    Active: active (running) since Thu 2016-10-18 04:09:35 NZDT; 35s ago
Main PID: 9021 (dotnet)
    CGroup: /system.slice/kestrel-hellomvc.service
            └─9021 /usr/local/bin/dotnet /var/aspnetcore/hellomvc/hellomvc.dll

リバース プロキシを構成し、Kestrel を systemd で管理している状態で、Web アプリケーションは完全に構成されたことになり、http://localhost でローカル コンピューター上のブラウザーからアクセスできます。With the reverse proxy configured and Kestrel managed through systemd, the web application is fully configured and can be accessed from a browser on the local machine at http://localhost. 妨げとなるファイアウォールを禁止すれば、リモート コンピューターからもアクセスできます。It is also accessible from a remote machine, barring any firewall that might be blocking. 応答ヘッダーを調べるとき、Kestrel がサービスを提供している ASP.NET Core アプリケーションが Server ヘッダーに表示されます。Inspecting the response headers, the Server header shows the ASP.NET Core application 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

ログの表示するViewing logs

Kestrel を利用する Web アプリケーションは systemd で管理されるため、すべてのイベントとプロセスが記録され、中心的ジャーナルが生成されます。Since the web application 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-hellomvc.service 固有の項目を表示するには、次のコマンドを使用します。To view the kestrel-hellomvc.service-specific items, use the following command:

sudo journalctl -fu kestrel-hellomvc.service

さらに絞り込むには、時間オプションとして --since today--until 1 hour ago、あるいはこの 2 つの組み合わせを利用すれば、返されるエントリの数を減らすことができます。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-hellomvc.service --since "2016-10-18" --until "2016-10-18 04:00"

アプリケーションのセキュリティ強化Securing our application

AppArmor を有効にするEnable AppArmor

Linux Security Modules (LSM) は、Linux 2.6 以降の Linux カーネルに含まれるフレームワークです。Linux Security Modules (LSM) is a framework that is part of the Linux kernel since Linux 2.6. LSM は、セキュリティ モジュールのさまざまな実装に対応しています。LSM supports different implementations of security modules. AppArmor は Mandatory Access Control システムを実装する 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.

ファイアウォールの構成Configuring our firewall

使用されていないすべての外部ポートを閉じます。Close off all external ports that are not in use. ufw (uncomplicated firewall/複雑ではないファイアウォール) は iptables のフロント エンドとなり、ファイアウォールを構成するためのコマンド ライン インターフェイスを提供します。Uncomplicated firewall (ufw) provides a front end for iptables by providing a command line interface for configuring the firewall. 必要なあらゆるポートでトラフィックを許可するように ufw が設定されていることを確認します。Verify that ufw is configured to allow traffic on any ports you need.

sudo apt-get install ufw
sudo ufw enable

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

Nginx のセキュリティを強化するSecuring Nginx

Nginx の既定のディストリビューションでは SSL が有効になっていません。The default distribution of Nginx doesn't enable SSL. 追加のセキュリティ機能を有効にするには、ソースからビルドします。To enable additional security features, build from source.

ソースをダウンロードし、ビルド依存関係をインストールするDownload the source and install the build dependencies

# Install the build dependencies
sudo apt-get update
sudo apt-get install build-essential zlib1g-dev libpcre3-dev libssl-dev libxslt1-dev libxml2-dev libgd2-xpm-dev libgeoip-dev libgoogle-perftools-dev libperl-dev

# Download nginx 1.10.0 or latest
wget http://www.nginx.org/download/nginx-1.10.0.tar.gz
tar zxf nginx-1.10.0.tar.gz

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: Your Web Server" CRLF;
static char ngx_http_server_full_string[] = "Server: Your Web Server" CRLF;

オプションを構成し、ビルドするConfigure the options and build

正規表現には PCRE ライブラリが必要です。The PCRE library is required for regular expressions. 正規表現は、ngx_http_rewrite_module の場所ディレクティブで使用されます。Regular expressions are used in the location directive for the ngx_http_rewrite_module. http_ssl_module により HTTPS プロトコル サポートが追加されます。The http_ssl_module adds HTTPS protocol support.

ModSecurity など、Web アプリケーション ファイアウォールを利用してアプリケーションの防護を検討してください。Consider using a web application firewall like ModSecurity to harden your application.

./configure
--with-pcre=../pcre-8.38
--with-zlib=../zlib-1.2.8
--with-http_ssl_module
--with-stream
--with-mail=dynamic

SSL を構成するConfigure SSL

  • ポート 443 で HTTPS トラフィックを待ち受けるようにサーバーを構成します。信頼されている証明書機関 (CA) が発行した有効な証明書を指定します。Configure your 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 your 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 only.

  • Strict-Transport-Security ヘッダーは追加しないでください。あるいは、今後、SSL を無効にすることがあれば、適切な max-age を選択してください。Do not add the Strict-Transport-Security header or chose an appropriate max-age if you plan to disable SSL 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. この例では、1 つの構成ファイルに http セクションと server セクションの両方が含まれています。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;
        }
    }
}

Nginx をクリックジャッキングから守るSecure Nginx from clickjacking

クリックジャッキングは、感染したユーザーのクリックを集めるという悪意のある手法です。Clickjacking is a malicious technique to collect an infected user's clicks. クリックジャッキングは被害者 (訪問者) をだまし、感染したサイトでクリックさせます。Clickjacking tricks the victim (visitor) into clicking on an infected site. X-FRAME-OPTIONS を利用し、サイトのセキュリティを強化します。Use X-FRAME-OPTIONS to secure your site.

nginx.conf ファイルを編集します。Edit the nginx.conf file:

sudo nano /etc/nginx/nginx.conf

add_header X-Frame-Options "SAMEORIGIN"; を追加し、ファイルを保存し、Nginx を再起動します。Add the line add_header X-Frame-Options "SAMEORIGIN"; and save the file, then 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 オプションを指定すると、サーバーがコンテンツを "text/html" と読むとき、ブラウザーはそれを "text/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.