Reputation: 263
I have developed a small images proxy in node.js (expressjs). This proxy should reduce all images, which come from my website "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.
I have already tried to read the header "origin" via req.headers.origin
, but this was empty:
console.log(JSON.stringify(req.headers))
shows this:
{
"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. "www.myUrl.com" is a Meteor.js app.
How can I make the proxy available only for the domain "www.myUrl.com"?
Thanks.
Update:
Images are simply loaded over an image tag in the client:
<img src='http://myImageProxyUrl.com/imageXY.png' />
Upvotes: 2
Views: 1635
Reputation: 111336
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. If you have a route like this in your Express app:
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:
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:
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. 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.
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. 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:
app.get('/something', function (req, res, next) {
// some response
});
app.get('/something/else', function (req, res, next) {
// another response
});
Upvotes: 1
Reputation: 12399
It seems like you'd be better off using nginx as a reverse proxy for that sort of work.
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. Nginx allows you to use rate limiting and reduce the chances of this kind of things happening.
The technique would be the same with nginx, check the headers and block everything but the ones with the right referrer.
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. Good luck!
Upvotes: 2