I have a site where people can buy digital downloads
I was thinking of using S3 to store the downloads
I would email links to the downloads.
I have a bucket with the downloads inside
The links look something like
https://downloads.s3.amazonaws.com/download-1
all downloads are in the same bucket
If people see this link they could work out how to get download-2, download-3 etc
Is there a way to disguise these links so it doesn’t describe where the downloads are
2
Answers
The typical flow would be:
Your application can generate a pre-signed URL in a few lines of code without calling S3. There is no need to ‘disguise’ a URL. Instead, the user can only download if they have been use a pre-signed URL within the validity period.
Further to @John’s answer, I would suggest using CloudFront signed urls instead of S3 signed URLs for your use case. The key differences for you is Cloudfront will sit infront of the S3 bucket giving you a better default security stance(and hide the name of the s3 bucket your files are stored in S3), and a CDN’s benefits like reduced cost for you(cheaper data transfer etc) and likely improved download speed for your end users. By default CloudFront provides a random subdomain from cloudfront.net for your distribution, so hiding the name of your s3 bucket – this is probably a good enough "disguise" of S3?
In this configuration your S3 bucket permissions can remain private – only cloudfront is needed to be given permissions to your bucket using an Origin Access Identity. Creating the S3/CloudFront signed URL is essentially the same for either approach through the API or cli. You can set restrictions on the signed link such as an allowed IP address to download the file, and the date/time the link is accessible and other restrictions.
Doing this would "disguise" the s3 URL and give you good control of how long that link is active and who would be able to use it – also the bucket name would not be exposed, nor would there be any mention of S3 at all by accessing the cloudfront URL even though the files would actualy still be located in S3.
If you really really want to try and hide the origin of your downloads(it will still look like an s3 "compatible" url) for any reason it can be achieved with some reverse proxying
NOTE: If you really must try and disguise the url further, and accept this is a terible idea on many levels, you can use the following approach but it wipes out the cost & speed benefits and adds a single point of failure to your app…
If your app generates signed urls for an object in s3/cloundfront, then replaces just the domain(either s3/cloudfornt) with a different hostname you can add a layer of obscurity(which isnt really security!). This does mean you can host your downloads on any webserver(or some route from your existing app), and have it appear to be the origin of the request. e.g. if you generate signed urls for myexample.com, but modify the signed link to use mysneakyexample.com. Your DNS can point mysneakyexample.com to your/any webserver that can reverse proxy requests to to the real cloudfront domain(eg back to myexample.com) – this will work so long as your reverse proxy correctly re-assembles the original URL myexample.com so the signed url signature is still valid when it arrives at S3/CloudFront backend. The response would be returned to your reverse-proxy and then back to the client as if it came from mysneakyexample.com and not myexample.com. (like i said, this works, but it kinda sucks – it really depends on your goals – id suggest a vanilla cloudfront signed URL would be sufficient if you can live with the default cloudfront.net url for your downloads). Good luck!