Bref: Url broken when using cloudfront in front of lambda

Created on 22 Jan 2020  路  11Comments  路  Source: brefphp/bref

Hi, great package.

Currently i am testing an app built with symfony but redirections/url generation are broken.

Redirecting to a non absolute url within the app, generates a url of the type

somerandom-url.execute.aws-region.com

67 seems to be related.

Any pointers on how to fix?

Thanks.

documentation

Most helpful comment

Right, sorry I wasn't a little more explicit.

Here is a solution to configure the CloudFront CDN in serverless.yml:

Origins:
  # The website (AWS Lambda)
  - Id: Website
    DomainName: '#{ApiGatewayRestApi}.execute-api.#{AWS::Region}.amazonaws.com'
    OriginPath: '/dev'
    CustomOriginConfig:
      OriginProtocolPolicy: 'https-only' # API Gateway only supports HTTPS
    OriginCustomHeaders:
      - HeaderName: 'X-Forwarded-Host'
        HeaderValue: 'your-domain-here.com'

Then you need to configure your framework to take the X-Forwarded-Host header into account.

For Symfony, have a look at https://symfony.com/doc/current/deployment/proxies.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly
Though it's interesting to see that Symfony mentions CloudFront, so maybe you can skip the configuration above and try this directly: https://symfony.com/doc/current/deployment/proxies.html#custom-headers-when-using-a-reverse-proxy (please report if it works)

For Laravel it seems that this package is now installed by default. You can configure it: https://github.com/fideloper/TrustedProxy#configure-trusted-proxies

In case you wonder if the CloudFront proxy has an IP address: no. This is why in those docs above you often need to use *.

Hope that helps, sorry I don't have more time at the moment, but please report whatever works or breaks.

All 11 comments

Hi, this is a limitation of CloudFront: the host header is not forwarded by CloudFront.

That means that the HTTP request landing in API Gateway does not contain the host from CloudFront, but instead contains the API Gateway URL.

Possible solutions:

  • force the HTTP header Host to a specific value (your domain name) in your CloudFront configuration
  • force your app/framework to use a specific domain name

Thanks for the proposed solutions.

Any doc that i can check to achieve properly?, i have tried to set up a lambda function to modify the header but it messes up the app, after setting up it returns a 403 forbidden, disabling it makes it work again - page loads (with broken urls)

Thanks.

Right, sorry I wasn't a little more explicit.

Here is a solution to configure the CloudFront CDN in serverless.yml:

Origins:
  # The website (AWS Lambda)
  - Id: Website
    DomainName: '#{ApiGatewayRestApi}.execute-api.#{AWS::Region}.amazonaws.com'
    OriginPath: '/dev'
    CustomOriginConfig:
      OriginProtocolPolicy: 'https-only' # API Gateway only supports HTTPS
    OriginCustomHeaders:
      - HeaderName: 'X-Forwarded-Host'
        HeaderValue: 'your-domain-here.com'

Then you need to configure your framework to take the X-Forwarded-Host header into account.

For Symfony, have a look at https://symfony.com/doc/current/deployment/proxies.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly
Though it's interesting to see that Symfony mentions CloudFront, so maybe you can skip the configuration above and try this directly: https://symfony.com/doc/current/deployment/proxies.html#custom-headers-when-using-a-reverse-proxy (please report if it works)

For Laravel it seems that this package is now installed by default. You can configure it: https://github.com/fideloper/TrustedProxy#configure-trusted-proxies

In case you wonder if the CloudFront proxy has an IP address: no. This is why in those docs above you often need to use *.

Hope that helps, sorry I don't have more time at the moment, but please report whatever works or breaks.

@mnapoli I can confirm that solution works with laravel. Maybe we should add your snippet to the documentation and close this issue?

@yangm97 yes I welcome a PR that adds this to the documentation.

Hello guys,

For me worked a Symfony 5.1 project with the first documentation link (https://symfony.com/doc/current/deployment/proxies.html#but-what-if-the-ip-of-my-reverse-proxy-changes-constantly) and the notes appointed by @mnapoli :

This is the final public/index.php (keep in mind that is a test website)

use App\Kernel;
use Symfony\Component\Dotenv\Dotenv;
use Symfony\Component\ErrorHandler\Debug;
use Symfony\Component\HttpFoundation\Request;

require dirname(__DIR__) . '/vendor/autoload.php';

(new Dotenv())->bootEnv(dirname(__DIR__) . '/.env');

if ($_SERVER['APP_DEBUG']) {
    umask(0000);

    Debug::enable();
}

// See https://github.com/brefphp/bref/issues/535#issuecomment-577158098
Request::setTrustedProxies(
    [ '127.0.0.1', 'REMOTE_ADDR' ],
    Request::HEADER_X_FORWARDED_ALL
);

if ($trustedHosts = $_SERVER['TRUSTED_HOSTS'] ?? false) {
    Request::setTrustedHosts([$trustedHosts]);
}

$kernel = new Kernel($_SERVER['APP_ENV'], (bool) $_SERVER['APP_DEBUG']);
$request = Request::createFromGlobals();
$response = $kernel->handle($request);
$response->send();
$kernel->terminate($request, $response);

I think that is important mention that in the Symony and Websites documentation:

  • in Symfony documentation at Bref (https://bref.sh/docs/frameworks/symfony.html) maybe I think that should be mentioned that if it is behind some proxy like CloudFront should read and apply the point in Symfony official documentation.
  • By other hand I think that in websites documentation (https://bref.sh/docs/websites.html#serving-php-and-static-files-via-cloudfront) should mention the importance of add the X-Forwarded-Header in Default Origin.

I can help you adding some of this points with my little english, but I can't help you adding the last point in Cloud Formation because I don't know the syntax. Please, if you consider that is interesting I can create you a PR.

I think Laravel still needs some more love.

While the CloudFront header setup does fix urls generated by the current request, I noticed that unless you set $APP_URL, mailables get generated with the wrong URL.

@yangm97 do you think that can be documented? Do you have an example of what needs to be changed in Laravel config?

@mnapoli I briefly reviewed my commits here and it seems like I did exactly as you described, no more and no less.

@yangm97 which commits are you talking about?

@mnapoli from the private project I applied your suggestion.

Was this page helpful?
0 / 5 - 0 ratings