I am trying to have Cloudflare to act as CDN for files hosted on S3, in a way that nobody can access the files directly. For example:
S3 bucket: cdn.mydomain.com.s3.amazonaws.com
CDN (Cloudflare): cdn.mydomain.com
What I want is to be able to access cdn.mydomain.com/file.jpg
(Cloudflare) but not cdn.mydomain.com.s3.amazonaws.com/file.jpg
(S3).
Right now I have a CNAME configured on Cloudflare that points to my bucket, and the following CORS:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>*</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
If I try to access any file, via S3 or CDN, I get permission denied. If I make a file public (aka grantee Everyone), I can then access that file via S3 and CDN.
I have tried changing the AllowedOrigin
with *.mydomain.com
, but no luck.
I found the solution. The article at CloudFlare's support center doesn't mention this.
You have to edit the bucket policy, not the CORS. And instead of allowing your domain, like that article says, to have access to the bucket, you have to allow CloudFlare IP's. For the reference, here is the list of IP's: https://www.cloudflare.com/ips
Here is the bucket policy sample to work with CloudFlare:
{
"Sid": "SOME_STRING_ID_HERE",
"Effect": "Allow", // or deny
"Principal": {"AWS": "*"}, // or whatever principal you want
"Action": "s3:GetObject", // or whatever action you want
"Resource": "arn:aws:s3:::cdn.mydomain.com/*", // or whatever resource you want
"Condition": {
"IpAddress": {
"aws:SourceIp": [
"103.21.244.0/22",
"103.22.200.0/22",
"103.31.4.0/22",
"104.16.0.0/12",
"108.162.192.0/18",
"131.0.72.0/22",
"141.101.64.0/18",
"162.158.0.0/15",
"172.64.0.0/13",
"173.245.48.0/20",
"188.114.96.0/20",
"190.93.240.0/20",
"197.234.240.0/22",
"198.41.128.0/17",
"199.27.128.0/21"
]
}
}
}
The accepted solution doesn't exactly work. It just allows access to CloudFlare. For that solution to work, you must explicitly deny everything elsewhere in the policy. This bucket policy is updated for Cloudflare's most recent IP addresses (including IPv6) and it also denies all access not from a Cloudflare IP address out of the box.
{
"Id": "Policy1517260196123",
"Version": "2012-10-17",
"Statement": [
{
"Sid": "A string ID here",
"Action": "s3:*",
"Effect": "Deny",
"Resource": "arn:aws:s3:::yourbucket.example.com/*",
"Condition": {
"NotIpAddress": {
"aws:SourceIp": [
"103.21.244.0/22",
"103.22.200.0/22",
"103.31.4.0/22",
"104.16.0.0/12",
"108.162.192.0/18",
"131.0.72.0/22",
"141.101.64.0/18",
"162.158.0.0/15",
"172.64.0.0/13",
"173.245.48.0/20",
"188.114.96.0/20",
"190.93.240.0/20",
"197.234.240.0/22",
"198.41.128.0/17",
"2400:cb00::/32",
"2405:8100::/32",
"2405:b500::/32",
"2606:4700::/32",
"2803:f800::/32",
"2c0f:f248::/32",
"2a06:98c0::/29"
]
}
},
"Principal": {
"AWS": "*"
}
}
]
}
It's better to use your domain name as the entry guard to s3, rather than a list of IPs.
Go to your site's S3 Console
Select the Properties Panel
Under Permission
Choose Add CORS Configuration
Add your CORSRules for your domain names
More CORS configuration can be found here
Kinda a mistake, but this answer only forbid other sites from referencing you assets, not from the original endpoint S3 generate for you...
来源:https://stackoverflow.com/questions/39731914/s3-with-cloudflare-disallow-direct-access