简体   繁体   English

如何使Node.js express.js(代理)服务器仅可用于特定域?

[英]How can I make a Nodejs express.js (proxy) server available only for a specific domain?

I have developed a small images proxy in node.js (expressjs). 我在node.js(expressjs)中开发了一个小型图片代理。 This proxy should reduce all images, which come from my website "www.myUrl.com". 该代理应减少来自我的网站“ www.myUrl.com”的所有图像。 This also works well so far. 到目前为止,这也很好。 But I would like to protect the proxy against unauthorized access. 但是我想保护代理免受未经授权的访问。 That is, as soon as an image is loaded via the proxy from another url, an error message "unauthorized" or null ... is to be returned. 即,一旦通过代理从另一个URL加载了图像,将返回错误消息“未经授权”或null...。 I have already tried to read the header "origin" via req.headers.origin , but this was empty: 我已经尝试通过req.headers.origin读取标头“ origin”,但这是空的:

console.log(JSON.stringify(req.headers)) shows this: console.log(JSON.stringify(req.headers))显示如下:

{
"host":"myImageProxyUrl.com",
"user-agent":"Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko)Chrome/54.0.2840.100Safari/537.36","accept":"image/webp,image/*, */*; q=0.8",
"accept-encoding":"gzip, deflate, sdch, br",
"accept-language":"de-DE,de;q=0.8,en-US;q=0.6,en;q=0.4",
"connection":"keep-alive",
"referer":"https://myUrl.de/myPage",
"x-forwarded-for":"ip1,ip2",
"x-forwarded-proto":"https, https",
"x-mod-original-region":"joyent-eu-ams-1.onmodulus.net",
"x-mod-region":"aws-us-east-1a.onmodulus.net"
}

The proxy is hosted at modulus.io. 该代理托管在模数.io。 "www.myUrl.com" is a Meteor.js app. “ www.myUrl.com”是一个Meteor.js应用程序。

How can I make the proxy available only for the domain "www.myUrl.com"? 如何使代理仅可用于域“ www.myUrl.com”?

Thanks. 谢谢。

Update: 更新:

Images are simply loaded over an image tag in the client: 图像只是通过客户端中的图像标签加载:

<img src='http://myImageProxyUrl.com/imageXY.png' />

It seems like you'd be better off using nginx as a reverse proxy for that sort of work. 似乎最好将nginx用作此类工作的反向代理。

By blocking access at the app level, you are wasting resources that could be used by legit requests. 通过在应用程序级别阻止访问,您正在浪费合法请求可能使用的资源。 If you're looking for a production solution, avoid blocking requests after they have reached your app. 如果您正在寻找生产解决方案,请避免在请求到达您的应用后阻止请求。

A simple example would be an attempt at DoSing your site, all an attacker would have to to is spam requests to slow your app down to a crawl. 一个简单的例子就是尝试对您的站点进行DoSing,攻击者所要做的就是发送垃圾邮件请求,以使您的应用程序慢下来进行爬网。 Nginx allows you to use rate limiting and reduce the chances of this kind of things happening. Nginx允许您使用速率限制并减少发生这种情况的机会。

The technique would be the same with nginx, check the headers and block everything but the ones with the right referrer. 该技术与nginx相同,请检查标头并屏蔽除具有正确引荐来源网址之外的所有内容。

The config for referrer filtering would look something like : 引荐来源网址过滤的配置如下所示:

location / {
    if ($http_referer !~ "myurl.com"){
          return 403
    }

    proxy_pass http://127.0.0.1:3000;  #replace 3000 by the port your app runs on
    proxy_http_version 1.1;
    proxy_set_header X-NginX-Proxy true;
    proxy_set_header X-Real-IP $remote_addr;
    proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
    proxy_set_header Upgrade $http_upgrade;
    proxy_set_header Connection 'upgrade';
    proxy_set_header Host $host;
    proxy_cache_bypass $http_upgrade;       
}

There are a lot of resources on how to use nginx as a reverse proxy for express app, it's really simple. 关于如何将Nginx用作Express应用程序的反向代理,有很多资源,这很简单。 Good luck! 祝好运!

If I understand your question correctly (it is not very clear) then you want to disallow hot-linking of the images served by your proxy on other websites than your own. 如果我正确理解了您的问题(不是很清楚),那么您想禁止将代理服务器提供的图像热链接到您自己网站以外的其他网站。 If so then you need to check the Referer header. 如果是这样,那么您需要检查Referer标头。 If you have a route like this in your Express app: 如果您的Express应用中有这样的路线:

app.get('/something', function (req, res, next) {
    // some response
});

then you can change it to: 然后您可以将其更改为:

app.get('/something', function (req, res, next) {
  if ( checkReferer(req) ) {
    // respond normally
  } else {
    // respond with error
  }
});

Implementing checkReferer can be something like: 实现checkReferer可以像这样:

function checkReferer(req) {
  var url = 'http://good.url.com/';
  return req.get('Referer').indexOf(url) === 0;
}

Or, if you want to allow uses with no Referer header: 或者,如果您想允许不使用Referer标头使用:

function checkReferer(req) {
  var url = 'http://good.url.com/';
  return !req.get('Referer') || req.get('Referer').indexOf(url) === 0;
}

The above will work if there is no Referer header at all but if there is then it must start with the right URL. 如果根本没有Referer标头,则以上内容将起作用,但是如果存在Referer标头,则必须以正确的URL开头。 This function may need to get more complicated if you want to add more domains, or if you want to allow both example.com and www.example.com etc. What's important is that this function should return true if the Referer is ok for your requirements and false if it's not. 如果要添加更多域,或者要同时允许example.com和www.example.com等,此功能可能会变得更加复杂。重要的是,如果Referer适合您,则此函数应返回true 。要求,如果不是,则为false

A better way (thanks to xShirase for pointing it out in the comments) would be to add a middleware instead of modifying the route handlers. 更好的方法(感谢xShirase在注释中指出)是添加中间件而不是修改路由处理程序。 That way you don't have to duplicate that logic in many places. 这样,您不必在许多地方重复该逻辑。 For example: 例如:

app.use(function (req, res, next) {
  if ( checkReferer(req) )
    return next();
  res.status(403).send('Forbidden');
});

(the checkReferer is the same as above) and then the route handlers with no changes: checkReferer与上面的相同),然后路由处理程序保持不变:

app.get('/something', function (req, res, next) {
    // some response
});

app.get('/something/else', function (req, res, next) {
    // another response
});

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM