https, http両対応のproxyサーバー(ポートフォワード)

以前ポートフォーワードのhttpプロキシサーバーを作成。
今回はプログラムを改良してhttpsにも対応したときの備忘録。

過去の関連する投稿

'use strict';
var port1 = 80;
var port2 = 443;
var fs = require('fs');

var http = require('http');
var https = require('https');
var httpProxy = require('http-proxy');
// proxy server
var proxy = httpProxy.createProxyServer();

var key = fs.readFileSync('/etc/letsencrypt/live/hoge.com/privkey.pem', 'utf8');
var cert = fs.readFileSync('/etc/letsencrypt/live/hoge.com/cert.pem', 'utf8');
var options = {
  key : key,
  cert: cert
}
var iptables = function( req ){
  var opt = {target:""};
  if( req.headers.host == "www.hoge.com" ){
      opt.target = "http://www.hoge.com:8010";
  }else if( req.headers.host == "app.hoge.com" ){
      opt.target = "http://www.hoge.com:8011";
  }
  return opt;
}
var translate = function( proxy, opt, req, res ){
  console.log("target = " + opt.target );
  proxy.web( req, res, opt, function(err){
    console.log(" !! translate error. ");
    console.log(err);
    res.write("<p> Translate error.</p>" );
    res.write( "<p>Host name : "+req.headers.host+"</p>" );
    res.end();
    return;
  });
  return;
}
// http server
var httpServer = http.createServer(function(req, res){
  var opt = {target:""};
  opt = iptables( req );
  if( opt.target == "" ){
    res.write( "<p>Unknown host server</p>" );
    res.write( "<p>Host name : "+req.headers.host+"</p>" );
    res.end();
    return;
  }
  // translate
  translate( proxy, opt, req, res );
});
// https server
var httpsServer = https.createServer(options, function(req, res){
  var opt = {target:""};
  opt = iptables( req );
  if( opt.target == "" ){
    res.write( "<p>Unknown host server</p>" );
    res.write( "<p>Host name : "+req.headers.host+"</p>" );
    res.end();
    return;
  }
  // translate
  translate( proxy, opt, req, res );
});
httpServer.listen( port1, function(){
  console.log("-- start reverse proxy server(http) . listen "+ port1 + " port. --");
});
httpsServer.listen( port2, function(){
  console.log("-- start reverse proxy server(https) . listen "+ port2 + " port. --");
});

注意点としては、iptables関数内でチェックしているreq.headers.hostのドメイン名が、letsencryptコマンドで作成した証明書に含まれていないと、保護されていない危険なサイトと表示されてしまう。(表現は異なるかもしれないが、ほぼすべてのブラウザで)
入れ忘れた場合は、証明書を再発行する必要がある。

サンプルプログラムでは、www.hoge.comapp.hoge.comでアクセスしてきたときにそれぞれのサーバーに転送している。
ポイントは、各アプリケーションサーバーは修正せずに、httpsサーバー(443)を追加して、同じように転送しているだけでセキュアなサイトとしてもアクセスできるようになる。