express.jsでHTTPSを有効にする


408

ノードのexpress.jsでHTTPSを機能させようとしているのですが、理解できません。

これは私のapp.jsコードです。

var express = require('express');
var fs = require('fs');

var privateKey = fs.readFileSync('sslcert/server.key');
var certificate = fs.readFileSync('sslcert/server.crt');

var credentials = {key: privateKey, cert: certificate};


var app = express.createServer(credentials);

app.get('/', function(req,res) {
    res.send('hello');
});

app.listen(8000);

実行すると、HTTPリクエストにのみ応答するようです。

私は単純なバニラnode.jsベースのHTTPSアプリを書きました:

var   fs = require("fs"),
      http = require("https");

var privateKey = fs.readFileSync('sslcert/server.key').toString();
var certificate = fs.readFileSync('sslcert/server.crt').toString();

var credentials = {key: privateKey, cert: certificate};

var server = http.createServer(credentials,function (req, res) {
  res.writeHead(200, {'Content-Type': 'text/plain'});
  res.end('Hello World\n');
});

server.listen(8000);

私はこのアプリを実行すると、それはない HTTPSリクエストに応答します。fsの結果のtoString()は重要ではないことに注意してください。両方の組み合わせを使用していて、それでもes buenoは使用していません。


追加する編集:

本番システムでは、おそらくNginxまたはHAProxyを使用して、nodejsアプリへのリクエストをプロキシする方がよいでしょう。nginxを設定してsslリクエストを処理し、ノードのapp.jsにhttpを話すだけです。

追加して編集(2015年4月6日)

AWSを使用しているシステムでは、EC2 Elastic Load Balancerを使用してSSL終了を処理し、EC2 Webサーバーへの通常のHTTPトラフィックを許可する方がよいでしょう。セキュリティをさらに強化するには、ELBのみがHTTPトラフィックをEC2インスタンスに送信できるようにセキュリティグループを設定します。これにより、外部の暗号化されていないHTTPトラフィックがマシンに到達するのを防ぎます。




AWSに関する最後のコメントについて:httpsモジュールでサーバーを作成する必要がないということですか?私の証明書はJenkins経由でAWSにアップロードされ、ARNで処理されます。(httpsオプションで)使用するファイルパスがない
sqldoug

@sqldoug質問が理解できるかどうかわかりません。AWS ELBは、HTTPS接続を受け入れ、SSL終了ポイントとして機能するように構成できます。つまり、通常のHTTPを介してアプリサーバーと通信します。ELBレベルまたはHTTPプロキシレベルのいずれかでスタックを処理できる追加の処理オーバーヘッドであるため、nodejsでSSLを処理する理由は通常ありません。
2016

アラン、ありがとう。はい、AWS ELBをそのように構成できる場合、NodeはSSLを処理する必要がないことに気づきました。
sqldoug 2016年

回答:


672

express.js(バージョン3以降)では、次の構文を使用する必要があります。

var fs = require('fs');
var http = require('http');
var https = require('https');
var privateKey  = fs.readFileSync('sslcert/server.key', 'utf8');
var certificate = fs.readFileSync('sslcert/server.crt', 'utf8');

var credentials = {key: privateKey, cert: certificate};
var express = require('express');
var app = express();

// your express configuration here

var httpServer = http.createServer(app);
var httpsServer = https.createServer(credentials, app);

httpServer.listen(8080);
httpsServer.listen(8443);

このようにして、ネイティブのhttp / httpsサーバーに高速ミドルウェアを提供します

1024未満のポートでアプリを実行したい場合は、sudoコマンド(推奨されません)を使用するか、リバースプロキシ(nginx、haproxyなど)を使用する必要があります。


2
すべてはここに書かれています:github.com/visionmedia/express/wiki/Migrating-from-2.x-to-3.x Paragraph Application function
codename-

74
HTTPSのデフォルトポートは443ですが、ほとんどのシステムでは小さい番号のポートで非ルートリスナーを許可していないため、開発時にはおそらく8443のようなものを使用することに注意してください。
ebohlman 2012

1
男、それは魔法のように動作します:) .pemファイルも受け入れます。それはとにかく正常です
Marcelo Teixeira Ruggeri '

5
Express 4それは機能しません、それは機能しますlocalhost:80が機能しませんhttps://localhost:443
Muhammad Umer

13
リバースプロキシにnginxを使用する場合、ノードの代わりにssl証明書を処理できます
Gianfranco P.

48

まず、あなたが作成する必要がありselfsigned.keyselfsigned.crtファイルを。自己署名SSL証明書の作成に進むか、次の手順を実行します。

ターミナルに移動し、次のコマンドを実行します。

sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout ./selfsigned.key -out selfsigned.crt

  • その後、次の情報を入れてください
  • 国名(2文字のコード)[AU]:US
  • 都道府県名(フルネーム)[Some-State]:NY
  • 地域名(都市など)[]:NY
  • 組織名(例:会社)[Internet Widgits Pty Ltd]:xyz(あなた-組織)
  • 組織単位名(例:セクション)[]:xyz(あなたの単位名)
  • 一般名(例:サーバーのFQDNまたはあなたの名前)[]:www.xyz.com(あなたのURL)
  • メールアドレス[]:あなたのメールアドレス

作成後、キーと証明書ファイルをコードに追加し、オプションをサーバーに渡します。

const express = require('express');
const https = require('https');
const fs = require('fs');
const port = 3000;

var key = fs.readFileSync(__dirname + '/../certs/selfsigned.key');
var cert = fs.readFileSync(__dirname + '/../certs/selfsigned.crt');
var options = {
  key: key,
  cert: cert
};

app = express()
app.get('/', (req, res) => {
   res.send('Now using https..');
});

var server = https.createServer(options, app);

server.listen(port, () => {
  console.log("server starting on port : " + port)
});
  • 最後に、httpsを使用してアプリケーションを実行します

詳細情報https://github.com/sagardere/set-up-SSL-in-nodejs


必要でない限り、sudoの使用はお勧めできません。sudoを使用せずにこのプロセスを実行しましたが、マシンにadminとしてログインしました。
jhickok

27

SSLをポート443以外のポートで機能させることで同様の問題に遭遇しました。私の場合、バンドル証明書と証明書およびキーがありました。バンドル証明書は、複数の証明書を保持するファイルです。ノードでは、これらの証明書を配列の個別の要素に分割する必要があります。

    var express = require('express');
    var https = require('https');
    var fs = require('fs');

    var options = {
      ca: [fs.readFileSync(PATH_TO_BUNDLE_CERT_1), fs.readFileSync(PATH_TO_BUNDLE_CERT_2)],
      cert: fs.readFileSync(PATH_TO_CERT),
      key: fs.readFileSync(PATH_TO_KEY)
    };

    app = express()

    app.get('/', function(req,res) {
        res.send('hello');
    });

    var server = https.createServer(options, app);

    server.listen(8001, function(){
        console.log("server running at https://IP_ADDRESS:8001/")
    });

app.jsでは、httpsを指定し、それに応じてサーバーを作成する必要があります。また、使用しようとしているポートが実際に受信トラフィックを許可していることを確認してください。


私は、私はわからない、キーとバンドル証明書を持っているものCERT:fs.readFileSync(PATH_TO_CERT)は、だろうとuは私に言わせれば「休憩」同梱CERTに、:)証明書で20+キーなどがありますか
ムハンマドウマル

@MuhammadUmarバンドルを解除する必要はなく、バンドルがない場合は指定することもできます。該当する場合はバンドル証明書があり、cert(公開鍵)とkey(秘密鍵)
Hayden Thring

@eomotoありがとうバド!これが最高です。私が必要とする例を完全にくぎ付けにしました
Hayden Thring

11

ポイントを含む:

  1. SSLセットアップ
    1. config / local.js
    2. config / env / production.js

HTTPおよびWSの処理

  1. アプリは開発中にHTTPで実行する必要があるため、アプリを簡単にデバッグできます。
  2. セキュリティ上の理由から、本番環境ではアプリをHTTPSで実行する必要があります。
  3. アプリのプロダクションHTTPリクエストは常にhttpsにリダイレクトする必要があります。

SSL構成

Sailsjsでは、すべてのものを構成する方法が2つあります。1つは、configフォルダーで構成する方法です。それぞれに個別のファイルがあります(設定に関するデータベース接続はconnections.js内にあります)。2つ目は、環境の基本ファイル構造で構成することです。各環境ファイルはconfig/envフォルダーにあり、各ファイルには特定の環境の設定が含まれています。

帆は最初にconfig / envフォルダーを探し、次にconfig / * .jsを楽しみにします

でsslをセットアップしますconfig/local.js

var local = {
   port: process.env.PORT || 1337,
   environment: process.env.NODE_ENV || 'development'
};

if (process.env.NODE_ENV == 'production') {
    local.ssl = {
        secureProtocol: 'SSLv23_method',
        secureOptions: require('constants').SSL_OP_NO_SSLv3,
        ca: require('fs').readFileSync(__dirname + '/path/to/ca.crt','ascii'),
        key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key','ascii'),
        cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt','ascii')
    };
    local.port = 443; // This port should be different than your default port
}

module.exports = local;

別の方法として、config / env / production.jsにも追加できます。(このスニペットは、複数のCARoot証明書を処理する方法も示しています)

または、production.js

module.exports = {
    port: 443,
    ssl: {
        secureProtocol: 'SSLv23_method',
        secureOptions: require('constants').SSL_OP_NO_SSLv3,
        ca: [
            require('fs').readFileSync(__dirname + '/path/to/AddTrustExternalCARoot.crt', 'ascii'),
            require('fs').readFileSync(__dirname + '/path/to/COMODORSAAddTrustCA.crt', 'ascii'),
            require('fs').readFileSync(__dirname + '/path/to/COMODORSADomainValidationSecureServerCA.crt', 'ascii')
        ],
        key: require('fs').readFileSync(__dirname + '/path/to/jsbot.key', 'ascii'),
        cert: require('fs').readFileSync(__dirname + '/path/to/jsbot.crt', 'ascii')
    }
};

http / httpsおよびws / wssリダイレクト

ここでwsはWebソケットであり、wssはSecure Web Socketを表します。これは、sslをセットアップした後、httpとwsの両方の要求がセキュアになり、それぞれhttpsとwssに変換されるためです。

私たちのアプリからの多くのソースは、ブログ投稿、ソーシャルメディア投稿などのリクエストを受信しますが、サーバーはhttpsでのみ実行されるため、httpからのリクエストがあると、クライアントブラウザーで「このサイトにアクセスできません」エラーが発生します。そして、私たちはウェブサイトのトラフィックを失います。したがって、httpリクエストをhttpsにリダイレクトする必要があります。同じルールではwebsocketを許可します。そうしないと、ソケットが失敗します。

したがって、同じサーバーをポート80(http)で実行し、すべての要求をポート443(https)に転送する必要があります。帆は最初にサーバーを持ち上げる前にconfig / bootstrap.jsファイルをコンパイルします。ここでは、ポート80でExpressサーバーを起動できます。

config / bootstrap.js(httpサーバーを作成し、すべてのリクエストをhttpsにリダイレクトします)

module.exports.bootstrap = function(cb) {
    var express = require("express"),
        app = express();

    app.get('*', function(req, res) {  
        if (req.isSocket) 
            return res.redirect('wss://' + req.headers.host + req.url)  

        return res.redirect('https://' + req.headers.host + req.url)  
    }).listen(80);
    cb();
};

これでhttp://www.yourdomain.comにアクセスできるようになり、https://www.yourdomain.comにリダイレクトされます


8

greenlock-expressを使用:無料のSSL、自動HTTPS

Greenlockは、証明書の発行と更新(Let's Encryptを使用)とhttp => httpsリダイレクトをそのまま使用できます。

express-app.js

var express = require('express');
var app = express();

app.use('/', function (req, res) {
  res.send({ msg: "Hello, Encrypted World!" })
});

// DO NOT DO app.listen()
// Instead export your app:
module.exports = app;

server.js

require('greenlock-express').create({
  // Let's Encrypt v2 is ACME draft 11
  version: 'draft-11'
, server: 'https://acme-v02.api.letsencrypt.org/directory'

  // You MUST change these to valid email and domains
, email: 'john.doe@example.com'
, approveDomains: [ 'example.com', 'www.example.com' ]
, agreeTos: true
, configDir: "/path/to/project/acme/"

, app: require('./express-app.j')

, communityMember: true // Get notified of important updates
, telemetry: true       // Contribute telemetry data to the project
}).listen(80, 443);

スクリーンキャスト

クイックスタートのデモを見る:https : //youtu.be/e8vaR4CEZ5s

Localhostの場合

これはよくあるフォローアップの質問なので、事前に回答するだけです。

ローカルホストにSSL証明書を置くことはできません。ただし、Telebitのようなものを使用して、ローカルアプリを実際のアプリとして実行できます。

DNS-01チャレンジを介してGreenlockでプライベートドメインを使用することもできます。これは、READMEに記載されている、それをサポートするさまざまなプラグインと一緒に記載されています。

非標準ポート(つまり、80/443なし)

上記のlocalhostに関する注意をお読みください。Let's Encryptで非標準ポートを使用することもできません。

ただし、port-forward、sni-routeを使用して内部の非標準ポートを外部標準ポートとして公開したり、SNIルーティングやポート転送/リレーを行うTelebitなどを使用したりできます。

DNS-01チャレンジを使用することもできます。その場合、ポートを公開する必要はまったくなく、プライベートネットワーク上のドメインをこの方法で保護することもできます。


「ローカルホストにSSL証明書を置くことはできません。」-localhost上のReactアプリでSSLが機能しています。Expressで動作させる方法を探してここに来ました。Reactは私のフロントエンドで、Expressは私のバックエンドです。Stripeへの私の投稿はSSLである必要があるため、Stripeで機能する必要があります。明らかなはずですが、localhostではテストを行っていますが、サーバーでは本番環境になります。
19

修正:「localhostに有効な SSL証明書を設定することはできません」。
CoolAJ86

6

これは私にとってどのように機能するかです。使用されるリダイレクトは、通常のhttpもすべてリダイレクトします。

const express = require('express');
const bodyParser = require('body-parser');
const path = require('path');
const http = require('http');
const app = express();
var request = require('request');
//For https
const https = require('https');
var fs = require('fs');
var options = {
  key: fs.readFileSync('certificates/private.key'),
  cert: fs.readFileSync('certificates/certificate.crt'),
  ca: fs.readFileSync('certificates/ca_bundle.crt')
};

// API file for interacting with MongoDB
const api = require('./server/routes/api');

// Parsers
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// Angular DIST output folder
app.use(express.static(path.join(__dirname, 'dist')));

// API location
app.use('/api', api);

// Send all other requests to the Angular app
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
});
app.use(function(req,resp,next){
  if (req.headers['x-forwarded-proto'] == 'http') {
      return resp.redirect(301, 'https://' + req.headers.host + '/');
  } else {
      return next();
  }
});


http.createServer(app).listen(80)
https.createServer(options, app).listen(443);

0

これは、Express 4.0の私の動作コードです。

Express 4.0は3.0やその他のものとは大きく異なります。

4.0 / bin / wwwファイルがあり、ここにhttpsを追加します。

「npm start」は、Express 4.0サーバーを起動する標準的な方法です。

readFileSync()関数は__dirnameを使用して現在のディレクトリを取得する必要があります

require()は./使用し、現在のディレクトリを参照します。

まず、/ binフォルダの下にprivate.keyとpublic.certファイルを置きます、それはWWWファイルと同じフォルダです

弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.