[node.js] node.js / express와의 자동 HTTPS 연결 / 리디렉션

작업중 인 node.js 프로젝트로 HTTPS를 설정하려고했습니다. 필자는 이 예제 에서 본질적으로 node.js 문서 를 따랐습니다 .

// curl -k https://localhost:8000/
var https = require('https');
var fs = require('fs');

var options = {
  key: fs.readFileSync('test/fixtures/keys/agent2-key.pem'),
  cert: fs.readFileSync('test/fixtures/keys/agent2-cert.pem')
};

https.createServer(options, function (req, res) {
  res.writeHead(200);
  res.end("hello world\n");
}).listen(8000);

이제 내가 할 때

curl -k https://localhost:8000/

나는 얻다

hello world

예상대로. 하지만 내가하면

curl -k http://localhost:8000/

나는 얻다

curl: (52) Empty reply from server

돌이켜 보면 이것이 이런 식으로 작동한다는 것이 명백해 보이지만 동시에 내 프로젝트를 방문하는 사람들은 https : // yadayada 를 입력하지 않을 것이며 모든 트래픽이 히트 한 순간부터 https가되기를 바랍니다. 사이트.

모든 수신 트래픽을 지정했는지 여부에 관계없이 모든 들어오는 트래픽을 https로 전달하기 위해 노드 (및 사용중인 프레임 워크이므로 Express)를 얻는 방법은 무엇입니까? 이 문제를 해결 한 문서를 찾을 수 없습니다. 또는 프로덕션 환경에서 노드가 이런 종류의 리디렉션을 처리하는 노드 (예 : nginx) 앞에있는 것으로 가정합니까?

이것은 웹 개발에 대한 첫 번째 길이므로, 이것이 분명하다면 내 무지를 용서하십시오.



답변

라이언, 올바른 방향으로 나를 찾아 주셔서 감사합니다. 나는 약간의 코드로 당신의 대답 (두 번째 단락)을 약간 만들어 내고 작동합니다. 이 시나리오에서 이러한 코드 스 니펫은 빠른 앱에 포함됩니다.

// set up plain http server
var http = express.createServer();

// set up a route to redirect http to https
http.get('*', function(req, res) {  
    res.redirect('https://' + req.headers.host + req.url);

    // Or, if you don't want to automatically detect the domain name from the request header, you can hard code it:
    // res.redirect('https://example.com' + req.url);
})

// have it listen on 8080
http.listen(8080);

https 익스프레스 서버는 3000에서 ATM을 수신합니다. 노드가 루트로 실행될 필요가 없도록 iptables 규칙을 설정했습니다.

iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 3000

모두 함께, 이것은 내가 원하는대로 정확하게 작동합니다.


답변

HTTP가 기본적으로 포트 80을 시도하고 HTTPS가 기본적으로 포트 443을 시도하기 때문에 일반적인 포트를 따르는 경우 동일한 시스템에 두 개의 서버가있을 수 있습니다. 코드는 다음과 같습니다.

var https = require('https');

var fs = require('fs');
var options = {
    key: fs.readFileSync('./key.pem'),
    cert: fs.readFileSync('./cert.pem')
};

https.createServer(options, function (req, res) {
    res.end('secure!');
}).listen(443);

// Redirect from http port 80 to https
var http = require('http');
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
    res.end();
}).listen(80);

https로 테스트하십시오.

$ curl https://127.0.0.1 -k
secure!

http로 :

$ curl http://127.0.0.1 -i
HTTP/1.1 301 Moved Permanently
Location: https://127.0.0.1/
Date: Sun, 01 Jun 2014 06:15:16 GMT
Connection: keep-alive
Transfer-Encoding: chunked

자세한 내용 : 동일한 포트를 통한 Nodejs HTTP 및 HTTPS


답변

이 사람 덕분에 :
https://www.tonyerwin.com/2014/09/redirecting-http-to-https-with-nodejs.html

app.use (function (req, res, next) {
        if (req.secure) {
                // request was via https, so do no special handling
                next();
        } else {
                // request was via http, so redirect to https
                res.redirect('https://' + req.headers.host + req.url);
        }
});


답변

Nginx를 사용하면 “x-forwarded-proto”헤더를 활용할 수 있습니다 :

function ensureSec(req, res, next){
    if (req.headers["x-forwarded-proto"] === "https"){
       return next();
    }
    res.redirect("https://" + req.headers.host + req.url);
}


답변

0.4.12 현재 Node의 HTTP / HTTPS 서버를 사용하여 동일한 포트에서 HTTP 및 HTTPS를 청취하는 확실한 방법은 없습니다.

일부 사람들은 Node의 HTTPS 서버 (Express.js와 함께 작동)가 443 (또는 다른 포트)을 수신하고 작은 http 서버가 80에 바인딩되고 사용자를 보안 포트로 리디렉션하도록하여이 문제를 해결했습니다.

단일 포트에서 두 프로토콜을 모두 처리 할 수 ​​있어야하는 경우 해당 포트에 nginx, lighttpd, apache 또는 다른 웹 서버를 배치하고 노드의 역방향 프록시로 작동해야합니다.


답변

express-force-https 모듈을 사용할 수 있습니다 .

npm install --save express-force-https

var express = require('express');
var secure = require('express-force-https');

var app = express();
app.use(secure);


답변

Basarat에서 제안한 솔루션을 사용하지만 HTTP 및 HTTPS 프로토콜에 2 개의 다른 포트가 있었기 때문에 포트를 덮어 써야합니다.

res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(http_port,https_port) + req.url });

루트 권한없이 nodejs를 시작하려면 표준 포트가 아닌 것을 선호합니다. 나는 바람둥이에 대한 다년간의 프로그래밍에서 왔기 때문에 8080과 8443을 좋아합니다.

완성 된 파일이됩니다

var fs = require('fs');
var http = require('http');
var http_port    =   process.env.PORT || 8080;
var app = require('express')();

// HTTPS definitions
var https = require('https');
var https_port    =   process.env.PORT_HTTPS || 8443;
var options = {
   key  : fs.readFileSync('server.key'),
   cert : fs.readFileSync('server.crt')
};

app.get('/', function (req, res) {
   res.send('Hello World!');
});

https.createServer(options, app).listen(https_port, function () {
   console.log('Magic happens on port ' + https_port);
});

// Redirect from http port to https
http.createServer(function (req, res) {
    res.writeHead(301, { "Location": "https://" + req.headers['host'].replace(http_port,https_port) + req.url });
    console.log("http request, will go to >> ");
    console.log("https://" + req.headers['host'].replace(http_port,https_port) + req.url );
    res.end();
}).listen(http_port);

그런 다음 HTTP 및 HTTPS 포트에서 80 및 443 트래픽을 forwording하기 위해 iptable을 사용합니다.

sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 80 -j REDIRECT --to-port 8080
sudo iptables -t nat -A PREROUTING -i eth0 -p tcp --dport 443 -j REDIRECT --to-port 8443