Search code examples
amazon-web-servicessslamazon-ec2amazon-cloudfront

No way to get CloudFront working with my dynamic website


I have a hard time to get CloudFront running in front of our dynamic PHP website running on an EC2 instance (PHP with Nginx Webserver - but that should not matter).

The site is running on www.example.com (just an example obviously ;-). The webserver listens on example.com, www.example.com and public.example.com on ports 80 (HTTP) and 443 (HTTPS). It is configured to forward example.com and public.example.com to www.example.com and HTTP to HTTPS. HTTPS uses a Let's Encrypt certificate issued for public.example.com and www.example.com.

Using the following settings in CloudFront:

  • Distribution
    • Price class: Use only North America and Europe
    • AWS WAF web ACL: None
    • Alternate domain name (CNAME): www.example.com
    • Custom SSL certificate: a AWS Certificate Manager issued RSA 2048 certificate for www.example.com
    • Legacy clients support: no enabled
    • Security policy: TLSv1.2_2021 (recommended)
    • Supported HTTP versions: HTTP/2 (no HTTP/3)
    • Default root object: empty
    • Standard logging: On
    • S3 bucket: an existing S3 bucket (logging is working)
    • Log prefix: empty
    • Cookie logging: Off
    • IPv6: On
  • Origin
    • Origin domain: www.example.com
    • Protocol: HTTPS only
    • HTTPS port: 443
    • Minimum origin SSL protocol: TLSv1.2
    • Origin path: empty
    • Add custom header: none
    • Enable Origin Shield: No
    • Additional settings: unchanged/default
  • Behaviors
    • Path pattern: Default (*)
    • Origin and origin groups: www.example.com
    • Compress objects automatically: Yes
    • Viewer protocol policy: Redirect HTTP to HTTPS
    • Allowed HTTP methods: GET, HEAD, OPTIONS, PUT, POST, PATCH, DELETE
    • Restrict viewer access: No
    • Cache policy and origin request policy
    • Cache policy: CachingDisabled
    • Origin request policy: AllViewer
    • Response headers policy: none
    • Smooth streaming: No
    • Field-level encryption: empty
    • Enable real-time logs: No
    • Function associations: none

and the following Route 53 setup for example.com:

  • Apex Domain: example.com
  • example.com A >>public IP of EC2 instance running the website<<
  • example.com CAA 0 issue "letsencrypt.org" 0 issue "amazonaws.com"
  • example.com MX some MX configuration
  • example.com NS AWS nameserver list
  • example.com SOA default AWS entry
  • example.com TXT SPF, domain validation, etc.
  • archive.example.com A >>public IP of a separate EC2 instance running a different application<<
  • internal.example.com A >>public IP of a separate EC2 instance running a different application<<
  • intranet.example.com A >>public IP of a separate EC2 instance running a different application<<
  • public.example.com A >>public IP of EC2 instance running the website<<
  • www.example.com A ALIAS to CloudFront distribution www.example.com

I thought this would be a pretty straight forward standard CloudFront configuration with caching disabled (for now). But no matter what I do, every request to www.example.com results in a 403 error Bad Request from CloudFront immediately. CloudFront not even tries to connect the EC2 instance (at least there's nothing the logs). Error rate is 100% and the CloudFront logs do not provide any additional information. I'm not sure what to look for, what settings to change, basically what to do.

What can I do to debug the issue? Is there any obvious configuration mistake?


Solution

  • Thanks Mark B! It is indeed a problem when the CloudFront domain - in this case www.example.com - is the same as the origin address - again www.example .com. Thinking about it, it may be absolutely clear that this cannot work because there's an infinite loop between a request to the CloudFront distribution and the subsequent call to the origin. I just thought that the Route 53 Alias DNS record somehow deals with this magically.

    The solution is to use a different domain for the origin. So in the example case the steps to solve the issue are:

    • allow the EC2 instance (Nginx) to serve content from public.example.com, instead of redirecting to www.example.com
    • change the CloudFron origin address from www.example.com to public.example.com

    This way requests to www.example.com go to the CloudFront distribution which then requests data from public.example.com. And now everything works perfectly - and, I have to admit, as easy I'd have imagined it to work.