How to use Azure Application Gateway's rewrite rules feature to rewrite the hostname of a website? - url-rewriting

I have a website called oldcompany.com. Our product name changed, and I would like to use Azure Application Gateway in front of the website, in order to rewrite the URL, i.e. access the website using the newcompany.com hostname.
There is a feature of Azure Application Gateway, called rewrite rules, that allows to modify request and response headers, documented here: https://github.com/MicrosoftDocs/azure-docs/blob/master/articles/application-gateway/rewrite-http-headers-url.md#rewrite-http-headers-and-url-with-application-gateway. The reason I want to use this feature is that it allows specifying complex conditions to rewrite a header. So I don't want to be using the Override with new host name switch on the HTTP setting, but rather overwrite the Host header of all requests going through the application gateway.
I have defined:
the listener to listen on HTTPS, port 443, hostname newcompany.com
the backend pool pointing to oldcompany.com
the rule binding the listener to the backend pool
With this configuration only, accessing https://newcompany.com results in Azure Application Gateway's 502 error page, which is expected, because the Host header in the request is still newcompany.com, which is not a virtual host recognized by the server (which is only serving requests for oldcompany.com).
So, in order to set the Host header, I have configured a rewrite ruleset associated to my routing rule. This ruleset has a rule that changes the request's Host header to oldcompany.com.
However, I still get the same 502 error page when accessing https://newcompany.com. I have pulled the request from my application gateway's access logs, and the request shows the following fields:
host_s: oldcompany.com
originalHost_s: newcompany.com
httpStatus_d: 502
which seems like the correct values for the original and rewritten hosts.
What am I missing to make this work?

Related

How to access host in lambda behind both API gateway and cloudfront?

I have a lambda function being executed by an API gateway. I have cloudfront pointing traffic to the API gateway endpoint.
How do I access the host/domain the client is on in my lambda function?
Can I move the Host header to X-Forwarded-Host?
e.g.
abc.com (cloudfront) -> API gateway -> lambda (Host: abc.com)
In order to propagate Host header through Cloudfront and API Gateway, follow these steps:
Configure Cloudfront to forward Host header
Step-by-step guide
Key points:
Choose the Behaviors tab, and then choose the path that you want to forward the Host header to.
Choose Edit.
Under Cache key and origin requests, confirm that Legacy cache settings is selected. If it's not selected, then follow the steps in the preceding section to create a cache policy. If Legacy cache settings is selected, then complete the following:
For Headers, select Include the following headers.
From the Add header dropdown list, select Host.
Configure API Gateway request to relay Host header
Detailed docs here
Key point:
Edit your API Gateway resource(s) and for each method you need the Host header edit the Method Request by adding Host header in the HTTP Request Headers list.
You can also move the Host header to X-Forwarded-Host using a Cloudfront function but you would still need to follow the steps above to propagate X-Forwarded-Host header. You can try this out starting with this sample function.

Laravel Vapor deploys and then fails to respond to requests

I just deployed a Laravel App using Vapor, and received the following message. I don't believe that I changed anything (a few html blade lines).
Caching Laravel configuration{"message":"Argument 1 passed to
Symfony\Component\HttpKernel\Exception\HttpException::__construct()
must be of the type int, string given, called in
/var/task/vendor/laravel/framework/src/Illuminate/Foundation/Application.php
on line
1014","context":{"exception":{"class":"Symfony\Component\Debug\Exception\FatalThrowableError","message":"Argument
1 passed to
Symfony\Component\HttpKernel\Exception\HttpException::__construct()
must be of the type int, string given, called in
/var/task/vendor/laravel/framework/src/Illuminate/Foundation/Application.php
on line
1014","code":0,"file":"/var/task/vendor/symfony/http-kernel/Exception/HttpException.php:24"},"aws_request_id":null},"level":400,"level_name":"ERROR","channel":"production","datetime":"2019-09-27T13:18:45.338555+00:00","extra":{}}
The website now just shows {"message": "Internal server error"}
Did I do this, or is this a Laravel/Vapor bug?
This happens when you use gateway_version 2. As per vapors documentation, you need to use an external DNS like Cloudflare for HTTPS redirection. https://docs.vapor.build/1.0/projects/environments.html#gateway-versions
If you choose to use API Gateway 2.0 and would like to support HTTP to
HTTPS redirection, we currently suggest using Cloudflare as an
external DNS provider for your Vapor application. Cloudflare not only
provides DNS, but serves as a reverse proxy to your application and
features an option for automatic HTTP to HTTPS redirection.
After a Vapor deployment is completed, Vapor will provide you with
CNAME records for the domain(s) associated with your environment.
These records will point the domain to your Lambda application. You
should manually add these values as CNAME records within the
Cloudflare DNS dashboard.
In addition, when using Cloudflare, you should set your Cloudflare SSL
/ TLS mode to "Full". The "Always Use HTTPS" configuration option may
be found under the SSL / TLS menu's "Edge Certificates" tab.
A simple solution would be to use Gateway Version 1.

URL rewrite is working for http but not for https

We want to display content of "https" site under my "http" site so, we are using IIS Rewrite module. (Same as CNAME)
We have created Inbound rules for same. However we are facing below error.
HTTP Error 502.3 - Bad Gateway
A connection with the server could not be established
If I use same rule in http site than it is working. Means We are able to display any http site content under my http site.
It is also working when we use "Redirect" action type but Here we want "Rewrite" action in rule because we do'not want to display another site Url
Inbound Rules and further details are here

Get CloudFront custom domain in the headers of a request

I have a CloudFront distribution abcd1234.cloudfront.net and I've added a custom domain of mysite.com to the distribution.
The CloudFront distribution's origin: aaabbbccc.execute-api.us-east-1.amazonaws.com
When I load the page mysite.com/hello/world, CloudFront is then consuming API Gateway aaabbbccc.execute-api.us-east-1.amazonaws.com/prod/{proxy+}
the API Gateway path endpoint is invoking a Lambda Function that calls a function like getPageContent(customDomainName, pagePath) which should be mysite.com and /hello/world respectively.
However, inside that function, the Host header that eventually makes it into the function's event.headers.Host value is never the custom domain. Instead, the Host header is always aaabbbccc.execute-api.us-east-1.amazonaws.com.
I want headers.Host to equal mysite.com (or another header to show that the request comes from mysite.com, but no matter what I do, the Host value is always just the origin url.
Edit: I tried whitelisting Host and it caused the site to break completely, with the error about not being able to reach the CloudFront distribution.

Capture HTTPS request to nonexistent server with FiddlerCore

I am trying to send a response to an HTTPS request, using FiddlerCore.
I need things to work like this: I put some fake URL in browser, like https://my_url_that_doesnt_exist.com/, then I intercept this request with FiddlerCore and respond to it with my data. But I only see a CONNECT and the host URL. I know this is because of HTTPS and Fiddler being a proxy. But is there a way to get the real full URL and be able to respond to HTTPS request, using FiddlerCore?
Also I use this code to create a root certificate if it's missing:
if (!Fiddler.CertMaker.rootCertExists())
{
if (!Fiddler.CertMaker.createRootCert())
{
throw new Exception("Could not create a certificate.");
}
}
also, I use these startup settings:
FiddlerCoreStartupFlags fcsf = FiddlerCoreStartupFlags.Default | FiddlerCoreStartupFlags.DecryptSSL|FiddlerCoreStartupFlags.AllowRemoteClients;
and CONFIG.IgnoreServerCertErrors = true;
This HTTPS request is not visible in Fiddler itself. I mean when I try some non-existent URL to which I'd like my app to respond with some custom content. It's also HTTP, not HTTPS, and Fiddler itself contains the following in response:
[Fiddler] DNS Lookup for "my_url_that_doesnt_exist.com" failed. The requested name is valid, but no data of the requested type was found
But if I use some existing HTTPS URL, like google plus or anything like that, I can see the HTTPS and all the request details.
So the question follows: How can I intercept HTTPS request to a non-existent URL and serve my content instead?
I can provide any additional details if needed.
Also makecert.exe is in the same folder where all my binaries are.
The problem is that HTTPS traffic flows through a CONNECT tunnel, and by default that secure traffic won't be sent if creating the CONNECT tunnel to the target server doesn't first succeed. Of course, if that target server doesn't exist, you end up with a DNS error in creating the tunnel, so the secure requests are never sent.
The workaround is to tell Fiddler to tell the client that the CONNECT tunnel was created, without even trying to contact the server. Do so by adding this inside the BeforeRequest handler:
if (oSession.HTTPMethodIs("CONNECT"))
{
oSession.oFlags["x-replywithtunnel"] = "GenerateTunnel";
return;
}

Resources