How to call cloudfront distribution with wrong Host header - ssl

Prerequisites
I have configured a custom domain for an API Gateway. The endpoint type is edge, as the API Gateway (RestApi) is edge.
I also issued a certificate through cdk. This is some of the code used:
const zone = route53.HostedZone.fromLookup(stack, 'Z0557019************', {
domainName: 'sub.example.com' // changed for SO post
})
const certificate = new DnsValidatedCertificate(stack, 'lws-api-certificate', {
domainName: 'mysub.sub.example.com', // changed for SO post
region: 'us-east-1',
hostedZone: zone
})
const api = new apigateway.RestApi(stack, 'legacy-wrapper-api', {
restApiName: 'My API',
domainName: {
domainName: 'mysub.sub.example.com',
certificate: certificate,
endpointType: EndpointType.EDGE
},
policy: apiResourcePolicy
})
new route53.ARecord(stack, 'ApiGatewayAliasRecord', {
zone: zone,
recordName: 'mysub',
target: route53.RecordTarget.fromAlias(new targets.ApiGateway(api))
})
So, I understand that a Cloudfront distribution is created. However, it is not listed in CloudFront.
In ApiGateway console:
What works
The custom domain was successfully created and applied and I am able to access my API gateway through mysub.sub.example.com.
What is not working
My issue is the following. I have clients which send a wrong Host Header. We can call our api fine when Host Header is mysub.sub.example.com. However, one client sends erroneously sub.another-example.com.
I know that this is a wrong header. But there is nothing we can do about this client sending the wrong header. Unfortunately!
What are my options?
switch to http
add foreign Host to allowed Hosts (certificate)?
Create some sort of proxy instance which allows incoming traffic from sub.another-example.com and redirect to
Regarding 1.
How can I allow http? I am seeing an option to set a minimum security level, but the minimum is TSL1.0. Can I even create a CloudFront distribution that accepts http? Again, in console I cannot see the distribution so I have to do it via CDK.
Regarding 2.
How can I do that, specifically in CDK?
Regarding 3.
Any creative ideas?
Help is much appreciated.
Additional resource:
A curl call to the custom domain with wrong header brings this:
$ curl --header "Authorization: Bearer 9c904d3##########################" --header "Host: sub.another-example.com" -v https://mysub.sub.example.com/v2.2/api/posts/list
* TCP_NODELAY set
* Connected to mysub.sub.example.com (18.66.###########) port 443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
* successfully set certificate verify locations:
* CAfile: /etc/ssl/certs/ca-certificates.crt
CApath: /etc/ssl/certs
* TLSv1.3 (OUT), TLS handshake, Client hello (1):
* TLSv1.3 (IN), TLS handshake, Server hello (2):
* TLSv1.3 (IN), TLS handshake, Encrypted Extensions (8):
* TLSv1.3 (IN), TLS handshake, Certificate (11):
* TLSv1.3 (IN), TLS handshake, CERT verify (15):
* TLSv1.3 (IN), TLS handshake, Finished (20):
* TLSv1.3 (OUT), TLS change cipher, Change cipher spec (1):
* TLSv1.3 (OUT), TLS handshake, Finished (20):
* SSL connection using TLSv1.3 / TLS_AES_128_GCM_SHA256
* ALPN, server accepted to use h2
* Server certificate:
* subject: CN=mysub.sub.example.com
* start date: May 27 00:00:00 2022 GMT
* expire date: Jun 25 23:59:59 2023 GMT
* subjectAltName: host "mysub.sub.example.com" matched cert's "mysub.sub.example.com"
* issuer: C=US; O=Amazon; OU=Server CA 1B; CN=Amazon
* SSL certificate verify ok.
* Using HTTP2, server supports multi-use
* Connection state changed (HTTP/2 confirmed)
* Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0
* Using Stream ID: 1 (easy handle 0x5627934cd8c0)
> GET /v2.2/api/posts/list HTTP/2
> Host: sub.another-example.com <----------------- This is the problematic value
> user-agent: curl/7.68.0
> accept: */*
> authorization: Bearer 9c904d3##########################
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Connection state changed (MAX_CONCURRENT_STREAMS == 128)!
< HTTP/2 403
< server: CloudFront
< date: Mon, 30 May 2022 11:21:50 GMT
< content-type: text/html
< content-length: 915
< x-cache: Error from cloudfront
< via: 1.1 f7d063##########################.cloudfront.net (CloudFront)
< x-amz-cf-pop: FRA56-P5
< x-amz-cf-id: _KTRiNK8z74PB4qCwS##################################################==
<
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN" "http://www.w3.org/TR/html4/loose.dtd">
<HTML><HEAD><META HTTP-EQUIV="Content-Type" CONTENT="text/html; charset=iso-8859-1">
<TITLE>ERROR: The request could not be satisfied</TITLE>
</HEAD><BODY>
<H1>403 ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
Bad request.
We can't connect to the server for this app or website at this time. There might be too much traffic or a configuration error. Try again later, or contact the app or website owner.
<BR clear="all">
If you provide content to customers through CloudFront, you can find steps to troubleshoot and help prevent this error by reviewing the CloudFront documentation.
<BR clear="all">
<HR noshade size="1px">
<PRE>
Generated by cloudfront (CloudFront)
Request ID: _KTRiNK8z74PB4qCwS##################################################==
</PRE>
<ADDRESS>
</ADDRESS>
* Connection #0 to host mysub.sub.example.com left intact
</BODY></HTML>

As often when the questions are so specific I found a solution myself.
It is option 2! All with CDK.
Those are the steps:
As I mentioned the Cloudfront distribution created for the custom domain is hidden in console, so you need to create an new one.
you want an "Alternate domain name" with the value of "sub.another-example.com" to be appearing on the distributions settings
In order for that to work, you will need to create a certificate which also includes the foreign domain
for that certificate to validate you will need to put a CNAME to the DNS settings of that domain (so you need to be able to do that).
your certificate will not auto-validate by DNS of course! I found a hack for that which requires deploying two times.
Cloudfront distribution with alternate domain and cert
This is the final code.
import { CloudFrontToApiGateway } from '#aws-solutions-constructs/aws-cloudfront-apigateway'
let certificate
if (buildConfig.isFirstDeploy) {
// This is a helper for an otherwise manual step. Unfortunately, there is no better fix for foreign host certs.
// The first deploy will fail with message '*.another-example.com. is not permitted in zone *.sub.example.com
// However, you can then manually validate the *.another-example.com domain and use the ARN for following deploys
// https://stackoverflow.com/questions/58101817/cdk-dnsvalidatedcertificate-can-create-a-certificate-in-a-linked-aws-account-w
certificate = new DnsValidatedCertificate(stack, 'api-certificate', {
domainName: `mysub.sub.example.com`,
region: 'us-east-1', // required for edge https://docs.aws.amazon.com/acm/latest/userguide/acm-services.html
hostedZone: zone,
subjectAlternativeNames: ['*.another-example.com']
})
} else {
certificate = Certificate.fromCertificateArn(
stack,
'api-certificate',
'arn:aws:acm:us-east-1:#############:certificate/#################' // you only know that after first deploy, copy from console
)
}
const cloudfront = new CloudFrontToApiGateway(stack, 'MyCloudFrontDistribution', {
existingApiGatewayObj: api,
cloudFrontDistributionProps: {
certificate: certificate,
domainNames: [
`mysub.sub.example.com`,
'*.another-example.com'
]
}
})

Related

Wallet pass push notifications APNs

So I have completed all the signing and compressing process for Apple passes and have been able to connect the pass to my server for updating. The only problem I have left to solve is implementing push notifications.
I have been trying for a couple of days now but just can't seem to manage and I think I am missing something really simple. I am not too proficient with networking so I would really appreciate the help.
This is the log I get from guzzle with my best try.
Trying 17.188.136.150:443... * TCP_NODELAY set * Connected to api.push.apple.com (17.188.136.150) port 443 (#0) * ALPN, offering h2 * ALPN, offering http/1.1 * successfully set certificate verify locations: * CAfile: /usr/local/etc/openssl/cert.pem CApath: /usr/local/etc/openssl#1.1/certs * SSL connection using TLSv1.2 / ECDHE-RSA-CHACHA20-POLY1305 * ALPN, server accepted to use h2 * Server certificate: * subject: CN=api.push.apple.com; OU=management:idms.group.533599; O=Apple Inc.; ST=California; C=US * start date: Mar 14 17:50:10 2019 GMT * expire date: Apr 12 17:50:10 2021 GMT * subjectAltName: host "api.push.apple.com" matched cert's "api.push.apple.com" * issuer: CN=Apple IST CA 2 - G1; OU=Certification Authority; O=Apple Inc.; C=US * SSL certificate verify ok. * Using HTTP2, server supports multi-use * Connection state changed (HTTP/2 confirmed) * Copying HTTP/2 data in stream buffer to connection buffer after upgrade: len=0 * Failed sending HTTP POST request * Connection #0 to host api.push.apple.com left intact
I am using the same certificate I used for the pass I am trying to update and am sending the device token I received upon registering the pass. This is my php code.
$client = new Client();
try {
$result = $client->post('https://api.push.apple.com:443', [
'headers' => ['apns-id' => <pass_type_id> , ':path' => '/3/device/<device_id_received_upon_registration>'],
'json' => ['apns'=>''],
'debug'=>true,
'version'=>2.0,
'ssl_key' => [<path_to_key>, <key_password>],
'cert' => [<path_to_certificate (same one used for signing pass)>, <certificate_password>]]);
}
catch (GuzzleHttp\Exception\ClientException $e) {
dd($e);
}
I am really lost with this one. Please help me out. I also tried connecting to port 1295 with some other code I copy pasted but it wasn't working as it should and had even more difficulty debugging as I am more familiar with port 443.
It works for me, with small changes:
$pem_file = '<path_to_your_pem_file_including_private_key>';
$pem_secret = '<private_key_password>';
$url = "https://api.push.apple.com/3/device/" . $device_push_token;
$response = $client->post($url, [
'headers' => ['apns-topic' => $pass_type_id],
'json' => json_decode('{}'),
'debug' => true,
'version' => 2.0,
'cert' => [$pem_file, $pem_secret]
]);
var_dump($response->getStatusCode());
var_dump($response->getReasonPhrase());
What is changed is the payload that needs to be empty JSON object (but present) and the header name for the topic, it is apns-topic not apns-id. I also constructed the URL directly, not via the headers and used a pem file with private key included in it, not sure if those matter.
Maybe you should also check what you pass at the end of the URL, it is not the device_id, but the device_push_token.
NB: remember to always send the wallet push notification to the production apple endpoint, not the sandbox!

HTTPS requests to paypal sandbox fail

I can't currently use the PayPal Sandbox to test my shopping-cart integrations. When i access the sandbox in a browser or via curl, all i get is connection errors.
Here's an example curl-session:
curl -v "https://api-3t.sandbox.paypal.com/nvp?user=test"
* Trying 173.0.82.83...
* TCP_NODELAY set
* Connected to api-3t.sandbox.paypal.com (173.0.82.83) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_AES_256_CBC_SHA256
* Server certificate: api-3t.sandbox.paypal.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> GET /nvp?user=test HTTP/1.1
> Host: api-3t.sandbox.paypal.com
> User-Agent: curl/7.51.0
> Accept: */*
>
* SSLRead() return error -9806
* Curl_http_done: called premature == 1
* Closing connection 0
curl: (56) SSLRead() return error -9806
Any hints if this is a serverside issue or something i can work around?
Thanks!
Looks like the NVP/SOAP integration method of Paypal Express Checkout is deprecated as of January 1, 2017. The live URL (https://api-3t.paypal.com/nvp) seems to work for now, but this might be why the sandbox doesn't work anymore.
I don't exactly understand why, but using POST instead of GET when submitting data to the PayPal Sandbox solves the problem nicely. No more weird SSL-errors.
Found below answer to curl 56 error . Hope that could help work out of the problem.
curl (56) Recv failure
PHP CURL Error - curl: (56) Recv failure: Connection reset by peer

Proxy request through Apache host to docker container

I have an Ubuntu server host running an Apache web server. Running on this host is a docker container serving Geoserver (via Tomcat) (built from this image) with a port configuration as such: 0.0.0.0:32770->8080/tcp
I can access Geoserver just fine using http://my.domain:32770/geoserver
I have a redirect configured in Apache on the host to serve all requests over HTTPS (see code snippet below), which does not play nicely with the port in requests like this(ie. https://my.domain:32770/geoserver)
<VirtualHost *:80>
# sending http requests to https
ServerName data.nrri.umn.edu
Redirect permanent / https://data.nrri.umn.edu/
</VirtualHost>
My attempt at a workaround for this is to use the ProxyPass directive in an Apache config file:
ProxyRequests Off
ProxyPreserveHost On
ProxyPass /my-geoserver http://127.0.0.1:32770/geoserver
ProxyPassReverse /my-geoserver http://127.0.0.1:32770/geoserver
When I use the URL that I would expect would get me to the Geoserver home page like the one above does (ie. http://my.domain/my-geoserver) I am redirected to
https://my.domain/geoserver/index.html and presented with 404 Not Found.
I should also note that both http://my.domain:32770/geoserver and http://my.domain:32770/geoserver/index.html resolve to http://my.domain:32770/geoserver/web/
What am I doing wrong here?
Edit
Output from curl -L -v -o /dev/null data.nrri.umn.edu/nra-geoserver
* Hostname was NOT found in DNS cache
% Total % Received % Xferd Average Speed Time Time Time Current
Dload Upload Total Spent Left Speed
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0* Trying 131.212.123.7...
* Connected to data.nrri.umn.edu (131.212.123.7) port 80 (#0)
> GET /nra-geoserver HTTP/1.1
> User-Agent: curl/7.35.0
> Host: data.nrri.umn.edu
> Accept: */*
>
< HTTP/1.1 302 Found
< Date: Fri, 19 May 2017 15:28:35 GMT
* Server Apache-Coyote/1.1 is not blacklisted
< Server: Apache-Coyote/1.1
< Location: /geoserver/index.html
< Content-Length: 0
< Set-Cookie: JSESSIONID=DFECFFB91353A34C407488EAAF70A2B4; Path=/geoserver; HttpOnly
<
0 0 0 0 0 0 0 0 --:--:-- --:--:-- --:--:-- 0
* Connection #0 to host data.nrri.umn.edu left intact
* Issue another request to this URL: 'HTTP://data.nrri.umn.edu/geoserver/index.html'
* Found bundle for host data.nrri.umn.edu: 0x95b8c0
* Re-using existing connection! (#0) with host data.nrri.umn.edu
* Connected to data.nrri.umn.edu (131.212.123.7) port 80 (#0)
> GET /geoserver/index.html HTTP/1.1
> User-Agent: curl/7.35.0
> Host: data.nrri.umn.edu
> Accept: */*
>
< HTTP/1.1 301 Moved Permanently
< Date: Fri, 19 May 2017 15:28:35 GMT
* Server Apache/2.4.7 (Ubuntu) is not blacklisted
< Server: Apache/2.4.7 (Ubuntu)
< Location: https://data.nrri.umn.edu/geoserver/index.html
< Content-Length: 336
< Content-Type: text/html; charset=iso-8859-1
<
* Ignoring the response-body
{ [data not shown]
100 336 100 336 0 0 38536 0 --:--:-- --:--:-- --:--:-- 38536
* Connection #0 to host data.nrri.umn.edu left intact
* Issue another request to this URL: 'https://data.nrri.umn.edu/geoserver/index.html'
* Found bundle for host data.nrri.umn.edu: 0x95b8c0
* Hostname was NOT found in DNS cache
* Trying 131.212.123.7...
* Connected to data.nrri.umn.edu (131.212.123.7) port 443 (#1)
* successfully set certificate verify locations:
* CAfile: none
CApath: /etc/ssl/certs
* SSLv3, TLS handshake, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Server hello (2):
{ [data not shown]
* SSLv3, TLS handshake, CERT (11):
{ [data not shown]
* SSLv3, TLS handshake, Server key exchange (12):
{ [data not shown]
* SSLv3, TLS handshake, Server finished (14):
{ [data not shown]
* SSLv3, TLS handshake, Client key exchange (16):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
} [data not shown]
* SSLv3, TLS handshake, Finished (20):
} [data not shown]
* SSLv3, TLS change cipher, Client hello (1):
{ [data not shown]
* SSLv3, TLS handshake, Finished (20):
{ [data not shown]
* SSL connection using ECDHE-RSA-AES256-GCM-SHA384
* Server certificate:
* subject: C=US; ST=MN; L=Minneapolis; O=University of Minnesota; OU=Natural Resources Research Institute; CN=data.nrri.umn.edu
* start date: 2017-04-18 00:00:00 GMT
* expire date: 2020-04-17 23:59:59 GMT
* subjectAltName: data.nrri.umn.edu matched
* issuer: C=US; ST=MI; L=Ann Arbor; O=Internet2; OU=InCommon; CN=InCommon RSA Server CA
* SSL certificate verify ok.
> GET /geoserver/index.html HTTP/1.1
> User-Agent: curl/7.35.0
> Host: data.nrri.umn.edu
> Accept: */*
>
< HTTP/1.1 404 Not Found
< Date: Fri, 19 May 2017 15:28:35 GMT
* Server Apache/2.4.7 (Ubuntu) is not blacklisted
< Server: Apache/2.4.7 (Ubuntu)
< Content-Length: 301
< Content-Type: text/html; charset=iso-8859-1
<
{ [data not shown]
100 301 100 301 0 0 4404 0 --:--:-- --:--:-- --:--:-- 4404
* Connection #1 to host data.nrri.umn.edu left intact
OK, so there are two redirects happening. I am not sure of a good way to solve the first one (and it is possible the solution solves it as well as the second one). But the second one, you should be able to add a trailing / to the paths. The resulting proxy directives would be:
ProxyPass /my-geoserver/ http://127.0.0.1:32770/geoserver/
ProxyPassReverse /my-geoserver/ http://127.0.0.1:32770/geoserver/
Give this a try first at http://data.nrri.umn.edu/geoserver/index.html and then with http://data.nrri.umn.edu/nra-geoserver and see where it fails next. If the former works but the latter fails, we'll probably need to edit some Tomcat configuration as well (to enable the remote IP valve https://tomcat.apache.org/tomcat-7.0-doc/api/org/apache/catalina/valves/RemoteIpValve.html).

Heroku ssl certficate not switched with custom domain

I have a heroku app (whatever-app-11123) and I want to use a custom domain through ssl (https://myapp.co).
I have bought the certificate and followed all the instructions provided by heroku.
Strange thing is that https://whatever-app-11123 is displaying the myapp.co certificate and https://myapp.co is displaying the *.herokuapp.com certificate.
I need this to be the other way around : myapp.co with the myapp.co certificat.
Any hints on how achieving this?
Results of different commands :
herok:certs
Endpoint Common Name(s) Expires Trusted
--------------------------------- ---------------------------------------- -------------------- -------
whatever-app-11123.herokuapp.com myapp.co, www.myapp.co 2017-02-12 23:59 UTC True
curl -kvI https://www.myapp.co
* Adding handle: conn: 0x7fbd03804000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fbd03804000) send_pipe: 1, recv_pipe: 0
* About to connect() to www.myapp.co port 443 (#0)
* Trying 46.132.168.142...
* Connected to www.myapp.co (46.132.168.142) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: *.herokuapp.com
* Server certificate: DigiCert SHA2 High Assurance Server CA
* Server certificate: DigiCert High Assurance EV Root CA
> HEAD / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: www.myapp.co
> Accept: */*
>
< HTTP/1.1 302 Found
HTTP/1.1 302 Found
* Server Cowboy is not blacklisted
<
* Connection #0 to host www.myapp.co left intact
Here's the answer: check your DNS redirection. Make sure it is a CNAME type and MOST OF ALL (what I did wrong) the redirection should be :
www.myapp.co -> whatever-app-11123.herokuapp.com
myapp.co -> whatever-app-11123.herokuapp.com
and not
www.myapp.co -> myapp.co
myapp.co -> whatever-app-11123.herokuapp.com

Golang issue x509: cannot verify signature: algorithm unimplemented on net/http

I was writing a very simple Golang script and use this library golang-jenkins to connect with our internal HTTPS server. But I face the following x509 cert issue and wasn't sure what to do with the x509 cert problem. Our team has zero access to Jenkins and would like to know what else we can do to dig more about the issue.
$ go run jenkins.go
2014/07/28 22:00:29 [] Get https://jenkins.mydomain.com/api/json: x509: certificate signed by unknown authority (possibly because of "x509: cannot verify signature: algorithm unimplemented" while trying to verify candidate authority certificate "MyDomain Internal Root CA")
using curl:
$ curl -v "https://jenkins.mydomain.com/api/json"
* Adding handle: conn: 0x7f8469004000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f8469004000) send_pipe: 1, recv_pipe: 0
* About to connect() to jenkins.mydomain.com port 443 (#0)
* Trying 10.38.8.70...
* Connected to jenkins.mydomain.com (10.38.8.70) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256
* Server certificate: jenkins.mydomain.com
* Server certificate: MyDomain Server CA - 2014
* Server certificate: MyDomain Internal Root CA
> GET /api/json HTTP/1.1
> User-Agent: curl/7.30.0
> Host: jenkins.mydomain.com
> Accept: */*
>
< HTTP/1.1 200 OK
* Server nginx is not blacklisted
< Server: nginx
< Date: Tue, 29 Jul 2014 05:03:45 GMT
< Content-Type: application/json;charset=UTF-8
< Transfer-Encoding: chunked
< Connection: keep-alive
< Set-Cookie: JSESSIONID.214ca1a4=1ry000odf815goiv7vl8tr627;Path=/;Secure
< Expires: Thu, 01 Jan 1970 00:00:00 GMT
< X-Jenkins: 1.554.3
< X-Jenkins-Session: c660ff91
TLS_ECDHE_RSA_WITH_AES_128_CBC_SHA256 is currently broken in Go, it will be supported in v1.4, the only workaround is to downgrade the TLS MaxVersion.
A quick look at golang-jenkins, it doesn't allow specifying the http.Client to use and just uses http.DefaultClient, the only ugly way to downgrade TLS's MaxVersion is to override http.DefaultClient.Transport.
You should be able to do something like this in func init() before you try to connect to anything:
cfg := &tls.Config{
MaxVersion: tls.VersionTLS11, // try tls.VersionTLS10 if this doesn't work
PreferServerCipherSuites: true,
}
http.DefaultClient.Transport = &http.Transport{
TLSClientConfig: cfg,
}
Keep in mind this will set the transport for anything that uses http.DefaultClient directly, like http.Get, however if you use your own instance, you will be fine.
Discussion about the bug: https://groups.google.com/forum/#!topic/golang-nuts/oK3EBAY2Uig