開発におけるHTTPS実用的ガイド


Firefoxのテレメトリによると76% of web pages are loaded with HTTPS , そして、この数は成長している.
遅かれ早かれ、ソフトウェアエンジニアはHTTPSに対処しなければなりません.なぜ、あなたの開発環境でhttpsを使用してJavaScriptアプリケーションを提供する方法を知って読んでください.


開発環境でHTTPSを使う理由は?
まず、すべてのHTTPSを介して生産のウェブサイトを提供する必要がありますか?あなたが本当に何をしているかを知らない限り.the default answer is yes . それは非常に多くのレベルであなたのウェブサイトを向上させます:セキュリティ、パフォーマンス、SEOなど.
どのようにセットアップHTTPSは、しばしば最初のリリース中に遵守され、他の多くの質問をもたらします.トラフィックは終わりから終わりまで暗号化されるべきです、あるいは、逆のプロキシまでの暗号化は十分ですか?どのように証明書が生成されるか?どこに保管してください.アバウトHSTS ?
開発チームはこれらの質問に早く答えることができるはずです.そうすることができないならend up like Stack Overflow wasting a lot of time .
そのうえ、生産からできるだけ近い開発環境を持つことはバグが生産環境に達する危険を減らして、また、それらのバグをデバッグするために時間を減らす傾向があります.また、エンドツーエンドのテストにも該当します.
また、Httpsによって提供されるページでのみ動作する機能がありますService Workers .
しかし、HTTPSは遅いです!多くの人々は暗号化が複雑であると信じています、そして、ある方法では、効率的に遅くなければなりません.しかし、現代のハードウェアとプロトコルでthis is not true anymore .

開発環境の有効な証明書を生成する方法は?
生産システムでは、TLS証明書を得るのは簡単ですLet's Encrypt または有料プロバイダから1つを購入する.
開発環境のために、それはトリッキーなようですが、それは難しいことではない.

MKCert :ノーブレ
Filippo Valsorda 最近出版された mkcert , ローカルで信頼できる開発証明書を生成する単純なCLI.ただ一つの行コマンドを実行しなければなりません.
mkcert -install
mkcert example.com
完全にサポートされている証明書は、あなたがコマンドを実行した場所、すなわち./example.com-key.pem .

OpenSSLによる手動インストールmkcert あなたの同僚と同じ証明書を共有しなければならない限り、またはあなたのローカルのenvより他のシステムを通してあなたのニーズの全てを満たすべきです.その場合、独自の証明書を生成することができますopenssl .
openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout server.key -out server.crt
証明書server.crt ) とそのキーserver.key ) 有効ですが、自己署名されます.この証明書は何も知らないCertificate Authority . しかし、すべてのブラウザは、暗号化された接続を受け入れるために証明書を検証するために、よく知られた証明書当局に尋ねます.自己署名証明書については、検証できません.

あなたはその不便を受け入れることができます手動で警告を無視するたびに表示されます.しかし、それは非常に面倒です、そして、CI環境でE 2 Eテストをブロックするかもしれません.より良い解決策は、独自のローカル認証局を作成し、あなたのブラウザにこのカスタム権限を追加し、それから証明書を生成することです.
それでmkcert フードの下であなたのために、しかし、あなたがそれをあなた自身でやりたいならば、私はあなたを助けるかもしれないGISTを書きました:Kmaschta/205a67e42421e779edd3530a0efe5945 .

逆プロキシまたはサードパーティのアプリケーションからのHTTPS
通常、エンドユーザーは直接アプリケーションサーバーに到達しません.代わりに、ユーザ要求はバックバランサまたは逆のプロキシによって扱われます.そして、バックエンドの上で要求を分配して、キャッシュを保存して、不要な要求から保護します.これらのプロキシが要求を解読して、レスポンスを暗号化する役割をするのを見ることは、珍しくありません.
開発環境では、リバースプロキシも使えます.

TraefikとDocker構成による暗号化
Traefik 開発者にとって多くの利点があるリバースプロキシです.中で、それは構成するのが簡単です、そして、それはGUIとともに来ます.また、公式のDocker画像がありますavailable on docker hub .
では、内部でそれを使いましょうdocker-compose.yml 静的ファイルのみを提供する仮想アプリケーションの
version: '3.4'

services:
    reverse-proxy:
        image: traefik # The official Traefik docker image
        command: --docker --api # Enables the web UI and tells Traefik to listen to docker
        ports:
            - '3000:443'  # Proxy entrypoint
            - '8000:8080' # Dashboard
        volumes:
            - /var/run/docker.sock:/var/run/docker.sock # So that Traefik can listen to the Docker events
            - ./certs/server.crt:/sslcerts/server.crt
            - ./certs/server.key:/sslcerts/server.key
            - ./traefik.toml:/traefik.toml # Traefik configuration file (see below)
        labels:
            - 'traefik.enable=false'
        depends_on:
            - static-files
    static-files:
        image: halverneus/static-file-server
        volumes:
            - ./static:/web
        labels:
            - 'traefik.enable=true'
            - 'traefik.frontend.rule=Host:localhost'
            - 'traefik.port=8080'
            - 'traefik.protocol=http'
        ports:
            - 8080:8080
この例では、静的なファイルサーバはポート8080を聞き、HTTPでファイルを提供します.この設定はtraefikにHTTPSリクエストを処理するように伝えますhttps://localhost とプロキシの各http://localhost:8080 静的ファイルを提供する.
また、Aを追加する必要がありますtraefik.toml traefikエントリポイントを設定するには、次の手順に従います.
debug = false

logLevel = "ERROR"
defaultEntryPoints = ["https","http"]

[entryPoints]
  [entryPoints.http]
  address = ":80"
    [entryPoints.http.redirect]
    entryPoint = "https"
  [entryPoints.https]
  address = ":443"
  [entryPoints.https.tls]
      [[entryPoints.https.tls.certificates]]
      certFile = "/sslcerts/server.crt"
      keyFile = "/sslcerts/server.key"

ここで二つのエントリポイントがあります.http and https , ポート80,443のそれぞれを聞く.最初のものはHTTPSにリダイレクトします、そして、2番目は指定されたTLS証明書のおかげで要求を暗号化するように構成されます.


NGinxを介してDockerからの暗号化
明らかに、我々は全くNGNXリバースプロキシと全く同じことができます.nginxも直接静的ファイル自体を提供することができます、セットアップは簡単です.再び、最初のステップはdocker-compose.yml :
version: '3'

services:
    web:
        image: nginx:alpine
        volumes:
            - ./static:/var/www
            - ./default.conf:/etc/nginx/conf.d/default.conf
            - ../../certs/server.crt:/etc/nginx/conf.d/server.crt
            - ../../certs/server.key:/etc/nginx/conf.d/server.key
        ports:
            - "3000:443"
とnginxの設定default.conf :
server {
    listen 80 default_server;
    listen [::]:80 default_server;
    return 301 https://$server_name$request_uri;
}

server {
    listen 443 ssl;

    server_name ~.;

    ssl_certificate /etc/nginx/conf.d/server.crt;
    ssl_certificate_key /etc/nginx/conf.d/server.key;

    location / {
        root /var/www;
    }

    ## If the static server was another docker service,
    ## It is possible to forward requests to its port:
    # location / {
    #     proxy_set_header Host $host;
    #     proxy_set_header X-Real-IP $remote_addr;
    #     proxy_pass http://web:3000/;
    # }
}

アプリケーションから直接httpsを提供する
時にはセキュリティ要件がエンドツーエンドの暗号化を要求したり、逆プロキシを持っているだけで開発環境でオーバーキルになるかもしれません.ほとんどの場合、それは直接あなたの毎日の開発環境からHTTPSを提供することが可能です.
一般的なスタックの例を見てみましょうexpress .

を使用して反応アプリやwebpack devのサーバー
あなたの平均反応アプリはcreate-react-app . このものすごいツールはビルトイン機能の多くが来て、箱からHTTPSを扱うことができます.そのためには、HTTPS=true アプリケーションを起動するときに環境変数
HTTPS=true npm run start
# or
HTTPS=true yarn start
このコマンドはあなたからのアプリケーションに役立つhttps://localhost:3000 の代わりにhttp://localhost:3000 自動生成された証明書.しかし、それは自己署名証明書ですので、開発者の経験は貧しいです.
あなた自身のHTTPS証明書(あなたのブラウザーが信頼する権威で署名される)を使用するならば、create-react-app アプリケーションをエミュレートせずに設定することはできませんnpm run eject ).
Edit : dev . to readerに、デフォルトのhttps証明書を置き換えます.
  "scripts": {
    "prestart": "(cat ../../certs/server.crt ../../certs/server.key > ./node_modules/webpack-dev-server/ssl/server.pem) || :",
    "start": "react-scripts start",
  },
幸いにも、craを吐き出したり、プロジェクトがwebpackにバンドルされている場合は、webpack-dev-server と同じくらい簡単ですcreate-react-app ときに、HTTPSを提供する!WebPack設定で2行のカスタムHTTPS証明書を設定することができます.
const fs = require('fs');
const path = require('path');

module.exports = {
    mode: 'production',
    // ...
    devServer: {
        https: {
            key: fs.readFileSync(path.resolve(__dirname, '../../certs/server.key')),
            cert: fs.readFileSync(path.resolve(__dirname, '../../certs/server.crt')),
        },
        port: 3000,
    },
};
あなたが走る次の時間webpack-dev-server , これはHTTPS要求を処理しますhttps://localhost:3000 .


暗号化されたHTTP
今我々はHTTPSを介して提供されるアプリのフロントエンドの一部を持って、我々は我々のバックエンドと同じように行う必要があります.
この目的のために、使用しましょうexpress and spdy . これらの2つのライブラリ名がなぜ速度についてであるのか不思議ではありません.
const fs = require('fs');
const path = require('path');
const express = require('express');
const spdy = require('spdy');

const CERTS_ROOT = '../../certs/';

const app = express();

app.use(express.static('static'));

const config = {
    cert: fs.readFileSync(path.resolve(CERTS_ROOT, 'server.crt')),
    key: fs.readFileSync(path.resolve(CERTS_ROOT, 'server.key')),
};

spdy.createServer(config, app).listen(3000, (err) => {
    if (err) {
        console.error('An error occured', error);
        return;
    }

    console.log('Server listening on https://localhost:3000.')
});
HTTP/2はHTTPSを提供する必要はありません.it's possible to serve encrypted content with HTTP first of the name , しかし、我々がHTTPSを提供している間、我々はHTTPプロトコルをアップグレードすることができます.あなたがhttp/2の利点についてもっと知りたいならば、あなたは読むことができますthis quick FAQ .

結論
現代のツーリングは、エンドユーザーのためにより安全でより速いアプリケーションを構築することができます、そして、現在、簡単にブートストラップ.私は、あなたが彼らがまだインストールするためにまだ安いとき、あなたのプロジェクト開始から始まるこれらの図書館とテクノロジーを使用するように確信していたことを望みます.
私がこのブログ記事で使用したすべての例は以下のrepoに集められます.marmelab/https-on-dev . お気軽に再生し、独自のHTTPS開発体験を追加!