Best way to redirect non-CloudFront requests to CloudFront

A summary of what I want to do is to redirect requests for image URL’s
that don’t come from Amazon’s CloudFront service to CloudFront. This is
because I’m using origin pull, but what the redirect to be done at the
nginx level.

Obviously this won’t work:

rewrite ^/(.*).(png|gif|jpg) http://abc.cloudfront.net/$1.$2

because CloudFront’s original requests will be redirected to itself, and
also because I’ve got some further rewriting going on for WordPress
image uploads (such that /files/myimage.png will be redirected to a PHP
script for some sites, so I need that redirect to still happen and the
one above to be bypassed in those instances when CloudFront is trying to
do it’s original lookup).

What I want to do is basically say:

if ($remote_addr !~ “abc.cloudfront.net”) {
rewrite ^/(.*).(png|gif|jpg) http://abc.cloudfront.net/$1.$2
}

but this isn’t possible (as remote_addr is an IP that may change) and is
probably inefficient. Is there a correct way to redirect everything to a
hostname that doesn’t come from the hostname itself efficiently?

Posted at Nginx Forum:

A summary of what I want to do is to redirect requests for image URL’s
that don’t come from Amazon’s CloudFront service to CloudFront. This is

but this isn’t possible (as remote_addr is an IP that may change) and is
probably inefficient. Is there a correct way to redirect everything to a
hostname that doesn’t come from the hostname itself efficiently?

Check its user agent instead.

Would a regex match in an if statement on the user agent string still be
efficient in nginx? Presumably this is the only way to do it.

Posted at Nginx Forum:

OK, in the end I went with:

if ($http_user_agent !~ “Amazon CloudFront”) {
rewrite ^/(.*).(png|gif|jpg) http://abc.cloudfront.net/$1.$2
}

which seems to do the trick. Seems like there should be a better way of
doing what must be quite a common form of rewrite though? (Or is this
the fast alternative to Apache’s REWRITE_COND?)

Posted at Nginx Forum:

On 8 May 2012 10:53, WheresWardy [email protected] wrote:

OK, in the end I went with:

if ($http_user_agent !~ “Amazon CloudFront”) {
rewrite ^/(.*).(png|gif|jpg) http://abc.cloudfront.net/$1.$2
}

which seems to do the trick. Seems like there should be a better way of
doing what must be quite a common form of rewrite though? (Or is this
the fast alternative to Apache’s REWRITE_COND?)

This is an example of the more general “has my request been /from/ the
CDN I’m using, or has it bypassed it?” problem.

The solution is never to leak the un-CDN’d URIs, and enforce that only
the CDN can access them (perhaps via basic auth; perhaps via UA
blocking; perhaps via IP restrictions).

If you’ve already missed that opportunity, and also don’t have a
dedicated static-assets domain you can CNAME to the CDN, then you
could look at using their published list of cloudfront IPs along with
http://wiki.nginx.org/HttpGeoModule and do something like

location ~ \.(png|gif|jpg)$ {
  if ($request_not_from_cloudfront_netblocks) {
    rewrite ^/(.*)$ http://abc.cloudfront.net/$1;
  }
}

Yes, it’s not massively different from what you’ve got, but I’d
personally prefer it as it doesn’t involve a string-based regex only
invokes the geo/map evaluation for those image suffixes, and isn’t
externally gameable. Unless “cloudfront netblocks” == “EC2 netblocks”,
of course, in which case Amazon have been daft.

Yes, it also requires keeping this geo map IP list up to date. Still
preferable to my mind.

J

Jonathan M.
Oxford, London, UK
http://www.jpluscplusm.com/contact.html