是否有可以转换端口(例如将端口 8001 转换为端口 80)的 Amazon Web Services 服务?
我喜欢在单个静态 IP 地址后托管多个网站,并使用端口转发将不同的端口路由到防火墙后面执行端口转发的各个 Web 服务器。
如果我可以在 AWS 服务中的某个地方实现这样的表就太好了:
客户端请求mydomain.com:80
-> AWS Route 53 转换为123.123.123.123:8001
-> 我的防火墙端口转发8001
到 LAN 内的 Web 服务器。
如果 AWS 不提供这项服务,那么还有其他现成的解决方案吗?我可以编写自己的应用程序来执行此操作并在 EC2 实例上运行它,但如果有可用的工具,我更喜欢使用现有工具。
答案1
当然,AWS白蛋白可以做到这一点。此外,它现在支持基于主机的路由,因此您可以将多个名称指向 ALB,并将其配置为分别路由每个名称。
注意:ALB 只能将请求负载平衡到以下后端服务器:之内AWS。它不是可以在任何地方使用的通用负载平衡服务。通常,您会在 VPC 的私有子网中部署后端服务器,然后在它们前面部署 ALB 以接受客户端请求。
客户端请求 mydomain.com:80 -> AWS Route 53 转换为 123.123.123.123:8001 -> 我的防火墙端口将 8001 转发到 LAN 内的 Web 服务器。
我认为您对 DNS 的作用感到困惑。DNS 对端口一无所知。为了发布网站,DNS仅有的将名称映射到一个或多个 IP 地址。就是这样。没有办法让 DNS“重定向”到端口或类似的东西。
答案2
我用 NodeJS 编写了自己的端口转换器,我在这里提交了代码,以防其他人想要使用它。它使用 https 证书以及纯文本端口 80 进行加密连接。我在 EC2 t2.micro 实例上运行它,每月收费 10 美元,运行良好。
唯一的缺点是它需要浏览器支持 SNICallback,以便代理服务器可以动态地使用所请求域的正确证书。
下面这个小应用程序利用了http-proxy 库对于 NodeJS。
var proxyTable = {
'mydomain.com': 'http://localhost:8001',
'demo1.mydomain.com': 'https://localhost:8002', // https after proxy
'demo2.mydomain.com': 'https://localhost:8005', // https after proxy
'demo3.mydomain.com': 'https://localhost:8006', // https after proxy
'demo4.mydomain.com': 'https://localhost:8007', // https after proxy
'demo5.mydomain.com': 'https://localhost:8008', // https after proxy
}
http.createServer(function(req, res) {
var hostname = req.headers.host.replace(/^www\./, ''); // remove www. subdomain prefix
if (proxyTable[hostname]) {
if (-1 != httpsDomains.indexOf(hostname)) { // redirect to https for httpsDomains
redirectToHttps(req, res); // res.redirect() not available here
} else {
proxy.web(req, res, {target: proxyTable[hostname]});
}
} else {
displayError(res, hostname)
}
}).listen(80);
// Use SNICallback to dynamically use various SSL certificates depending upon hostname.
// To add a new SSL domain, add to secureContext AND proxyTable
const efboKey = fs.readFileSync(global.appRootPath + '/../mydomain.com.key', 'utf8');
const efboCert = fs.readFileSync(global.appRootPath + '/../mydomain.com.crt', 'utf8');
const efboCaBundleArray = makeCertificateAuthorityArray(global.appRootPath + '/../mydomain.com.ca-bundle', 'utf8');
const efboHttpsComponents = {
key: efboKey,
cert: efboCert,
ca: efboCaBundleArray,
};
var secureContext = {
'mydomain.com': tls.createSecureContext(efboHttpsComponents),
'demo1.mydomain.com': tls.createSecureContext(efboHttpsComponents),
'demo2.mydomain.com': tls.createSecureContext(efboHttpsComponents),
'demo3.mydomain.com': tls.createSecureContext(efboHttpsComponents),
'demo4.mydomain.com': tls.createSecureContext(efboHttpsComponents),
'demo5.mydomain.com': tls.createSecureContext(efboHttpsComponents),
}
try {
var options = {
SNICallback: function (hostname, cb) {
if (secureContext[hostname]) {
if (cb) {
cb(null, secureContext[hostname]);
} else {
return secureContext[hostname]; // compatibility for older versions of node
}
} else {
throw new Error('No keys/certificates for hostname requested');
}
},
// must list a key and cert because required by tls.createServer()
key: efboKey,
cert: efboCert,
ca: efboCaBundleArray,
}
https.createServer(options, function (req, res) {
var hostname = req.headers.host.replace(/^www\./, ''); // remove www. subdomain prefix
proxy.web(req, res, {target: proxyTable[hostname], secure: false}); // proxy https to http
}).listen(443);
} catch (err){
console.error(err.message);
console.error(err.stack);
}