我正在使用vhost
和express
来管理两个子域。一切正常,但我想按 ip 过滤其中一个子域的请求。你知道是否有可能吗?
我尝试在我的子域站点的应用程序.js中管理它,但req.connection.remoteAddress
和req.ip
给了我服务器的 ip。
当我只有一个子域并且不使用 vhost 时,我有正确的 ip,但由于我使用了 vhost,我得到了我的服务器的 ip......
这是我之前的文件夹结构:
-- subdomain1/
-- app.js
-- views/
这是我的新结构:
-- subdomain1/
-- app.js
-- views/
-- subdomain2/
-- app.js
-- views/
-- manageSubdomain/
-- app.js
这是我在使用vhost之前工作时的代码,并且仅适用于一个子域:
子域 1/应用.js :
var express = require('express');
var path = require('path');
var logger = require('morgan');
var cookieParser = require('cookie-parser');
var bodyParser = require('body-parser');
require('body-parser-xml')(bodyParser);
var routes = require('./routes/index');
var app = express();
// view engine setup
app.set('views', path.join(__dirname, 'views'));
app.set('view engine', 'jade');
// uncomment after placing your favicon in /public
app.use(logger('dev'));
app.use(bodyParser.json());
app.use(bodyParser.urlencoded({ extended: false }));
app.use(cookieParser());
app.use(express.static(path.join(__dirname, 'public')));
// Example middleware to get ip
app.use(function (req, res) {
console.log(req.ip); // it give me the correct IP
});
app.use('/', routes);
module.exports = app;
以及之前管理服务器的文件:
#!/usr/bin/env node
/**
* Module dependencies.
*/
var app = require('../app');
var debug = require('debug')('webservicePrestashop:server');
var https = require('https');
var fs = require('fs');
/**
* Get port from environment and store in Express.
*/
var port = normalizePort(process.env.PORT || '443');
app.set('port', port);
/**
* Create HTTP server.
*/
//var server = http.createServer(app);
var options = {
key: fs.readFileSync('/path/to/privkey.pem'),
cert: fs.readFileSync('/path/to/fullchain.pem'),
ca: fs.readFileSync('/path/to/chain.pem')
}
var server = https.createServer(options, app);
// 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);
/**
* Listen on provided port, on all network interfaces.
*/
server.listen(port);
/**
* Event listener for HTTP server "listening" event.
*/
function onListening() {
var addr = server.address();
var bind = typeof addr === 'string'
? 'pipe ' + addr
: 'port ' + addr.port;
debug('Listening on ' + bind);
}
这是我管理子域的代码:
管理子域/应用程序.js :
var express = require('express');
var vhost = require('vhost');
var http = require('http');
var https = require('https');
var fs = require('fs');
var tls = require('tls');
// Gestions des sites
const subdomain1 = {
app: require('../subdomain1/app'),
context: tls.createSecureContext({
key: fs.readFileSync('path/to/privkey.pem').toString(),
cert: fs.readFileSync('path/to/privkey.pem/fullchain.pem').toString(),
ca: fs.readFileSync('path/to/privkey.pem/chain.pem').toString()
}).context
};
const subdomain2 = {
app: require('../subdomain2/app'),
context: tls.createSecureContext({
key: fs.readFileSync('path/to/privkey.pem/privkey.pem').toString(),
cert: fs.readFileSync('path/to/privkey.pem/fullchain.pem').toString(),
ca: fs.readFileSync('path/to/privkey.pem/chain.pem').toString()
}).context
};
var sites = {
"my.subdomain1.com": subdomain1,
"my.subdomain2.com": subdomain2
};
var exp = express();
for (let s in sites) {
exp.use(vhost(s, sites[s].app));
}
// Redirect du http to https
http.createServer(function (req, res) {
res.writeHead(301, { "Location": "https://" + req.headers['host'] + req.url });
res.end();
}).listen(80);
var secureOpts = {
SNICallback: function (domain, cb) {
if (typeof sites[domain] === "undefined") {
cb(new Error("domain not found"), null);
console.log("Error: domain not found: " + domain);
} else {
cb(null, sites[domain].context);
}
},
key: fs.readFileSync('path/to/privkey.pem/privkey.pem').toString(),
cert: fs.readFileSync('path/to/privkey.pem/fullchain.pem').toString()
};
// Création du serveur https
var httpsServer = https.createServer(secureOpts, exp);
httpsServer.listen(443);
现在我的子域 1/app.js 和以前一样
你试过req.ip
属性吗?
快递文档 说:
包含请求的远程 IP 地址。
当信任代理设置的计算结果未为 false 时,值 此属性派生自 X 转发标头。此标头可以由客户端设置,也可以由 代理。
若要调试代码,请在将任何应用添加到 express 对象之前添加日志记录中间件:
var exp = express();
// ip logging middleware
app.use(function (req, res, next) {
console.log(req.ip);
next();
});
for (let s in sites) {
exp.use(vhost(s, sites[s].app));
}
然后,添加与子应用的第一个中间件相同的中间件。通过这种方式,您可以确定问题是由vhost
模块引起的。