我的设置是这样的:
[Apache running on port 80]
http://domain1/ ---> https://domain1/ (redirect using apache)
http://domain2/ ---> Hosted on apache.
和
[Nodejs running on port 443]
https://domain1/ ---> App on Express.js/Node.js
我现在想要的是,任何对https://domain2/的请求都应该被拒绝连接。
我的ssl证书仅对domain1有效。所以,我做不到这样的事情:
var vhostController = express.createServer({key:privateKey,cert:certificate});
vhostController.use(express.vhost('domain1',mainApp));
vhostController.use(express.vhost('domain2',function(req, res) {res.end();}));
vhostController.listen(443);
上面的代码适用于http,但不适用于https,因为它会在传递给处理返回内容的函数之前尝试验证服务器证书。
所以,是否有一些方法可以在证书错误之前检查请求是针对domain2,还是拒绝/关闭连接。
答案 0 :(得分:3)
在大多数情况下,没有。在发送 HTTP请求之前发生SSL握手(实际上HTTP请求是通过已建立的SSL通道发送的)。 TLS 1.0协议指定了特殊的TLS扩展,它允许客户端告诉服务器,证明哪个主机要呈现。不幸的是,并非所有(我会说很少)客户都支持此扩展,因此您的问题没有通用解决方案。
答案 1 :(得分:1)
这个问题有两个解决方案:
使用不同的IP:
我最终使用了这种方法。示例代码:
var app = express.createServer({key:privateKey,cert:certificate});
// setup app..
app.listen(443,IP1);
我在端口443上没有在IP2上运行任何东西。因此,任何与IP2的连接都被拒绝。
使用SNI:
如果有人想使用SNI,可以在此处找到有关将其与nodejs一起使用的详细信息:
http://nodejs.org/docs/latest/api/tls.html#event_secureConnection_
在tls服务器的secureConnection
事件中,传递一个cleartextStream变量,其中,如果客户端支持SNI,cleartextStream.servername
将提供客户端所需的服务器域。可以在这里查看,并采取适当的措施。
答案 2 :(得分:0)
一种优雅的方法是创建一个中间件函数,如下所示:
function kill_it(res) {
res.end(); // empty response
}
module.exports = function denyVhost(vhostArray) {
return function(req, res, next) {
var host;
if (req.headers.host) {
host = req.headers.host.split(':')[0];
if (vhostArray.indexOf(host) > -1) {
next(); // the host is found
} else {
kill_it(res);
}
} else {
// the host isn't found in the request headers
kill_it(res);
}
}
};
然后在您的快速配置中,您可以像这样使用它:
deny_by_vhost = require('./example_above');
app.configure(function() {
...
app.use(deny_by_vhost(["example.com", "foo.example.com"]));
...
});