6

Включение HTTPS в express.js

34

Я пытаюсь настроить HTTPS на express.js для Node.js, но не могу разобраться, как это сделать.

Вот мой код из файла 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-запросы. Обратите внимание, что я не думаю, что вызов .toString() на результате fs имеет значение, так как я перепробовал разные комбинации и в любом случае ничего не работает.


Редактирование:

Для производственных систем, возможно, лучше использовать Nginx или HAProxy для проксирования запросов к вашему приложению Node.js. Вы можете настроить Nginx для обработки SSL-запросов и просто общаться с вашим приложением на http.


Редактирование (04/06/2015):

Для систем, использующих AWS, лучше воспользоваться ELB (Elastic Load Balancers) для обработки SSL-терминации и позволить обычный HTTP-трафик вашим веб-серверам EC2. Для дополнительной безопасности настройте вашу группу безопасности так, чтобы только ELB мог отправлять HTTP-трафик на экземпляры EC2, что предотвратит попадание внешнего незащищенного HTTP-трафика на ваши машины.

4 ответ(ов)

9

В 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();

// здесь ваша конфигурация express

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

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

Таким образом, вы передаете middleware Express в родной HTTP/HTTPS сервер.

Если вы хотите, чтобы ваше приложение работало на портах ниже 1024, вам нужно будет использовать команду sudo (что не рекомендуется) или использовать обратный прокси (например, nginx или haproxy).

0

Я столкнулся с похожей проблемой при настройке SSL на порту, отличном от порта 443. В моем случае у меня был пакетный сертификат, а также отдельный сертификат и ключ. Пакетный сертификат — это файл, содержащий несколько сертификатов, и Node.js требует, чтобы эти сертификаты были разбиты на отдельные элементы массива.

Вот пример кода:

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("Сервер запущен по адресу https://IP_ADDRESS:8001/");
});

В файле app.js вам нужно использовать HTTPS и создать сервер соответствующим образом. Также убедитесь, что порт, который вы пытаетесь использовать, действительно позволяет входящий трафик.

0

Включение SSL:

  1. Настройка SSL
    1. В файле config/local.js
    2. В файле config/env/production.js

Обработка HTTP и WS

  1. Приложение должно работать по HTTP в режиме разработки, чтобы мы могли легко отлаживать его.
  2. Приложение должно работать по HTTPS в продакшене для обеспечения безопасности.
  3. HTTP-запросы в продакшене должны всегда перенаправляться на HTTPS.

Конфигурация SSL

В Sails.js есть два способа конфигурации: первый — это настройка в папке config, где у каждого компонента есть свой отдельный файл (например, настройки подключения базы данных находятся в файле connections.js). Второй способ — это конфигурация на основе файлов окружения, где каждый файл содержит настройки для конкретного окружения и находится в папке config/env.

Sails сначала проверяет папку 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; // Этот порт должен отличаться от вашего порта по умолчанию
}

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 — это WebSocket, а wss — это защищённый WebSocket. После настройки SSL как HTTP, так и WS становятся безопасными и преобразуются в HTTPS и WSS соответственно.

Наше приложение может получать запросы из различных источников, таких как блоги или посты в социальных сетях, но сервер должен работать только по HTTPS. В противном случае, когда приходят HTTP-запросы, пользователи получат ошибку "Этот сайт недоступен". В результате мы теряем трафик на сайте. Поэтому необходимо перенаправлять HTTP-запросы на HTTPS, и те же правила должны применяться для веб-сокетов, иначе сокеты будут неработоспособными.

Таким образом, нам нужно запустить тот же сервер на порту 80 (HTTP) и перенаправить все запросы на порт 443 (HTTPS). Sails сначала компилирует файл config/bootstrap.js перед запуском сервера. Здесь мы можем запустить наш сервер Express на порту 80.

В 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.

0

Вот как это работает для меня. Используемое перенаправление будет перенаправлять весь обычный 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');
// Для 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 файл для взаимодействия с MongoDB
const api = require('./server/routes/api');

// Парсеры
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));

// Папка с выходными данными Angular
app.use(express.static(path.join(__dirname, 'dist')));

// Место расположения API
app.use('/api', api);

// Перенаправляем все остальные запросы на приложение Angular
app.get('*', (req, res) => {
  res.sendFile(path.join(__dirname, 'dist/index.html'));
});

// Промежуточное ПО для перенаправления HTTP на HTTPS
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 сервера
http.createServer(app).listen(80)
// Создание HTTPS сервера
https.createServer(options, app).listen(443);

Здесь используется x-forwarded-proto заголовок, чтобы проверить, идет ли запрос через HTTP, и, если да, перенаправить его на HTTPS. Обратите внимание, что этот код предназначен для работы как с HTTP, так и с HTTPS.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь