Jason McFarlane
Jason McFarlane

Reputation: 2175

S3 Bucket not found behind cloudflare CNAME

Problem: Using my CNAME on cloudflare (assets.my-site.com) I am trying to point to a public AWS S3 bucket. If I navigate to the AWS hostname I can clearly see it working in multiple browsers (public read access is correct) however when I try to access via assets.my-site.com (cloudflare CNAME) I get the error

<Code>NoSuchBucket</Code>
<Message>The specified bucket does not exist</Message>
<BucketName>assets.my-site.com</BucketName>

Im pretty sure the issue is with this <BucketName>assets.my-site.com</BucketName> that somehow amazon is picking up assets.my-site.com as the hostname of the bucket instead of the correct S3 target

enter image description here

Upvotes: 0

Views: 1133

Answers (3)

Nathan Cobb
Nathan Cobb

Reputation: 53

I managed to get this working with a little finessing.

You'll need to name your bucket after your cdn url. cdn.yourdomain.com for example.

Amazon bucket urls have two forms:

  • your-bucket.s3.amazonaws.com
  • s3.amazonaws.com/your-bucket

The second form is used whenever your bucket name has dots in it, so it doesn't interfere with the amazon url. This may be possible with the first url form but I haven't been able to get it to work yet.

You'll need two things:

  1. a CNAME record to proxy the connection to s3.amazonaws.com

  2. A cloudflare worker script to set the HOSTNAME of the request to s3.amazonaws.com. Amazon forbids using their services with other hostnames, so without this the proxied connection is forbidden.

    addEventListener('fetch', event => {
        event.respondWith(handleRequest(event.request));
    });
    
    async function handleRequest(request) {
        const url = new URL(request.url);
        // Rewrite the URL to point to your S3 bucket
        const s3Url = `https://s3.amazonaws.com/cdn.your-domain.com${url.pathname}`;
    
        // Create a new request with the Host header set to your S3 bucket's hostname
        const modifiedRequest = new Request(s3Url, {
            method: request.method,
            headers: {
                ...request.headers,
                'Host': 's3.amazonaws.com'
            },
            body: request.body
        });
    
        // Fetch from S3
        const s3Response = await fetch(modifiedRequest);
    
        if (!s3Response.ok) {
            return new Response('Error fetching from S3', { status: s3Response.status });
        }
    
        return new Response(s3Response.body, {
            headers: s3Response.headers
        });
    }
    

Workers do not belong to websites in Cloudflare, so you'll need to

add a trigger. You can find this on the new worker's settings page under triggers. Just add your cdn url as the route for the trigger (e.g. c

dn.your-domain.com)

To test, just find a document in your bucket, for example:

https://s3.amazonaws.com/cdn.your-domain.com//foo/bar.json

And format your new cdn url like this:

https://cdn.your-domain.com//foo/bar.json

Upvotes: 0

drussey
drussey

Reputation: 713

The other answers and comments have basically answered this, but to answer this clearly your bucket needs to be named assets.my-site.com. From the error it's fairly clear my-bucket is a different value than assets.my-site.com.

I have posted a similar answer that shows how to serve a static bucket using Cloudflare to dramatically reduce bandwidth usage here.

Upvotes: 0

nmishin
nmishin

Reputation: 3064

I believe yes, you need to rewrite host header here, you can do that for example via Cloudflare Page Rules, you need to put your CNAME to the URL (required) field, and name of the bucket to the value, it should looks like: enter image description here

Upvotes: 3

Related Questions