How to exclude a path from the context path of a deployment? - jetty

I use Jetty 11. I have two context files in /opt/web/mybase/webapps, one for Certbot (Let's Encrypt) and another one for the web app context at the root. The first context file must not redirect from HTTP to HTTPS in order to let Certbot work when the SSL certificate has just been revoked, its context path is /.well-known/acme-challenge. The second context file must redirect from HTTP to HTTPS (by forcing the transport type "confidential" in web.xml), the context path is /, it's similar to this context file. Certbot writes something in /.well-known/acme-challenge and expects to see it at http://example.org/.well-known/acme-challenge.
How can I indicate in the second context file that everything except the stuff in /.well-known/acme-challenge must be handled by the servlet of the WAR in this context file?

You need to put your trust into the servlet spec request path mapping rules, and things will get really easy.
For context paths, the longest match is used.
So for contexts /foo and /, and a request of /foo/example.txt, the longest match is context /foo
Lets take a look at this example ${jetty.base}
certbot-example/
├── etc/
│   └── keystore.p12
├── start.d/
│   ├── deploy.ini
│   ├── http.ini
│   ├── https.ini
│   ├── server.ini
│   └── ssl.ini
└── webapps/
├── ROOT/
│   ├── index.html
│   └── WEB-INF/
│   └── web.xml
├── well-known/
│   └── certbot.txt
└── well-known.xml
It has the following configuration ...
$ java -jar ${JETTY_HOME}/start.jar --list-config
Enabled Modules:
----------------
0) resources transitive provider of resources for logging-jetty
1) logging/slf4j transitive provider of logging/slf4j for logging-jetty
dynamic dependency of logging-jetty
2) logging-jetty transitive provider of logging for threadpool
transitive provider of logging for bytebufferpool
transitive provider of logging for server
3) bytebufferpool transitive provider of bytebufferpool for server
init template available with --add-module=bytebufferpool
4) threadpool transitive provider of threadpool for server
init template available with --add-module=threadpool
5) server ${jetty.base}/start.d/server.ini
6) security transitive provider of security for webapp
7) servlet transitive provider of servlet for webapp
8) webapp transitive provider of webapp for deploy
init template available with --add-module=webapp
9) deploy ${jetty.base}/start.d/deploy.ini
10) http ${jetty.base}/start.d/http.ini
11) ssl ${jetty.base}/start.d/ssl.ini
12) https ${jetty.base}/start.d/https.ini
...(snip)...
Jetty Environment:
-----------------
jetty.version = 10.0.6
jetty.tag.version = jetty-10.0.6
jetty.build = 37e7731b4b142a882d73974ff3bec78d621bd674
jetty.home = /home/joakim/code/jetty/distros/jetty-home-10.0.6
jetty.base = /home/joakim/code/jetty/distros/bases/certbot-example
...(snip)...
Properties:
-----------
...(snip)...
jetty.httpConfig.securePort = 8443
With the following content in ${jetty.base}/webapps/ ...
[certbot-example]$ cat webapps/ROOT/WEB-INF/web.xml
<web-app xmlns="http://xmlns.jcp.org/xml/ns/javaee"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xsi:schemaLocation="http://xmlns.jcp.org/xml/ns/javaee
http://xmlns.jcp.org/xml/ns/javaee/web-app_3_1.xsd"
version="3.1">
<display-name>Example WebApp</display-name>
<security-constraint>
<web-resource-collection>
<web-resource-name>securedapp</web-resource-name>
<url-pattern>/*</url-pattern>
</web-resource-collection>
<user-data-constraint>
<transport-guarantee>CONFIDENTIAL</transport-guarantee>
</user-data-constraint>
</security-constraint>
</web-app>
[certbot-example]$ cat webapps/ROOT/index.html
<html><body><h2>Hello World!</h2></body></html>
[certbot-example]$ cat webapps/well-known/certbot.txt
example-cert-bot
[certbot-example]$ cat webapps/well-known.xml
<?xml version="1.0"?>
<!DOCTYPE Configure PUBLIC "-//Jetty//Configure//EN" "https://www.eclipse.org/jetty/configure_10_0.dtd">
<Configure class="org.eclipse.jetty.webapp.WebAppContext">
<Set name="contextPath">/.well-known</Set>
<Set name="war"><Property name="jetty.webapps" default="." />/well-known</Set>
</Configure>
Once we start jetty, we can see that 2 webapps contexts are deployed ...
[certbot-example]$ java -jar ../../jetty-home-10.0.6/start.jar
2021-08-06 08:29:27.121:INFO :oejs.Server:main: jetty-10.0.6; built: 2021-06-29T15:28:56.259Z; git: 37e7731b4b142a882d73974ff3bec78d621bd674; jvm 11.0.12+7
2021-08-06 08:29:27.151:INFO :oejdp.ScanningAppProvider:main: Deployment monitor [file:///home/joakim/code/jetty/distros/bases/certbot-example/webapps/]
2021-08-06 08:29:27.227:INFO :oejw.StandardDescriptorProcessor:main: NO JSP Support for /.well-known, did not find org.eclipse.jetty.jsp.JettyJspServlet
2021-08-06 08:29:27.234:INFO :oejss.DefaultSessionIdManager:main: Session workerName=node0
2021-08-06 08:29:27.253:INFO :oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext#30bce90b{/.well-known,file:///home/joakim/code/jetty/distros/bases/certbot-example/webapps/well-known/,AVAILABLE}{/home/joakim/code/jetty/distros/bases/certbot-example/webapps/well-known}
2021-08-06 08:29:27.264:INFO :oejw.StandardDescriptorProcessor:main: NO JSP Support for /, did not find org.eclipse.jetty.jsp.JettyJspServlet
2021-08-06 08:29:27.269:INFO :oejsh.ContextHandler:main: Started o.e.j.w.WebAppContext#10cf09e8{Example WebApp,/,file:///home/joakim/code/jetty/distros/bases/certbot-example/webapps/ROOT/,AVAILABLE}{/home/joakim/code/jetty/distros/bases/certbot-example/webapps/ROOT}
2021-08-06 08:29:27.432:INFO :oejus.SslContextFactory:main: x509=X509#57abad67(mykey,h=[localhost],a=[],w=[]) for Server#584f54e6[provider=null,keyStore=file:///home/joakim/code/jetty/distros/bases/certbot-example/etc/keystore.p12,trustStore=null]
2021-08-06 08:29:27.515:INFO :oejs.AbstractConnector:main: Started ServerConnector#1af687fe{HTTP/1.1, (http/1.1)}{0.0.0.0:8080}
2021-08-06 08:29:27.522:INFO :oejs.AbstractConnector:main: Started ServerConnector#70efb718{SSL, (ssl, http/1.1)}{0.0.0.0:8443}
2021-08-06 08:29:27.534:INFO :oejs.Server:main: Started Server#1e16c0aa{STARTING}[10.0.6,sto=5000] #1071ms
The two entries of note ...
Started o.e.j.w.WebAppContext#30bce90b{/.well-known, file:///.../certbot-example/webapps/well-known/, AVAILABLE}
Started o.e.j.w.WebAppContext#10cf09e8{Example WebApp, /, file:///.../certbot-example/webapps/ROOT/, AVAILABLE}
This means that we have 2 contexts defined,
one for serving requests to path http://<machine>/.well-known/
and another for http://<machine>/
If we make a few requests you'll see the behavior ...
Make a request to the context /.well-known (notice that http and https works)
$ curl -vvv http://localhost:8080/.well-known/certbot.txt
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET /.well-known/certbot.txt HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Last-Modified: Fri, 06 Aug 2021 13:11:32 GMT
< Content-Type: text/plain
< Accept-Ranges: bytes
< Content-Length: 17
< Server: Jetty(10.0.6)
<
example-cert-bot
$ curl -k -vvv https://localhost:8443/.well-known/certbot.txt
* Trying 127.0.0.1:8443...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8443 (#0)
* ALPN, offering h2
* ALPN, offering http/1.1
...(snip)...
* SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET /.well-known/certbot.txt HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.68.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Last-Modified: Fri, 06 Aug 2021 13:11:32 GMT
< Content-Type: text/plain
< Accept-Ranges: bytes
< Content-Length: 17
< Server: Jetty(10.0.6)
<
example-cert-bot
But if we request something from the context / we can only do so with https.
$ curl -k -L -vvv http://localhost:8080/
* Trying 127.0.0.1:8080...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8080 (#0)
> GET / HTTP/1.1
> Host: localhost:8080
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
< HTTP/1.1 303 See Other
< Location: https://localhost:8443/
< Content-Length: 0
< Server: Jetty(10.0.6)
<
* Connection #0 to host localhost left intact
* Issue another request to this URL: 'https://localhost:8443/'
* Trying 127.0.0.1:8443...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 8443 (#1)
* ALPN, offering h2
* ALPN, offering http/1.1
..(snip)...
* SSL certificate verify result: self signed certificate (18), continuing anyway.
> GET / HTTP/1.1
> Host: localhost:8443
> User-Agent: curl/7.68.0
> Accept: */*
>
* TLSv1.3 (IN), TLS handshake, Newsession Ticket (4):
* Mark bundle as not supporting multiuse
< HTTP/1.1 200 OK
< Last-Modified: Fri, 06 Aug 2021 13:08:50 GMT
< Content-Type: text/html
< Accept-Ranges: bytes
< Content-Length: 48
< Server: Jetty(10.0.6)
<
<html><body><h2>Hello World!</h2></body></html>
* Connection #1 to host localhost left intact

Related

AWS EC2 can't access my ec2 public domain, tried many web solutions none worked

I don't this is a very common question, I'm only asking it because I've already started some ec2 instances using the method I'll explain bellow and I succed, maybe EC2 changed something the right away to connect it by HTTP using public dns. Here are the steps I've always done and I don't know why it isn't working anymore.
public dns: ec2-23-22-52-143.compute-1.amazonaws.com
1 - Settup the default security group, that is oppened for every traffic
2 - Add IAM policity to this ec2, as you can see IAM function bellow
3 - Access SSH and configure nginx, I used putty and could enter on the instance. The configuration for nginx is /etc/nginx/sites-avaiable/default
## default nginx config
server {
listen 80 default_server;
server_name _;
# front-end
location / {
root /var/www/html;
try_files $uri /index.html;
}
# node api
location /api/ {
proxy_pass http://localhost:3000/;
}
}
4 - Clone both my front-end and back-end repositories from github
5 - build production and move to /var/www/html all frontend dist files
6 - Start my node.js server using pm2
7 - Start nginx
sudo nginx -t
sudo systemctl start nginx
sudo netstat -plant | grep 80
tcp 0 0 0.0.0.0:80 0.0.0.0:* LISTEN 21159/nginx: master
As you can see the port:80 is being listening by nginx
Guys I have no ideia why I can't access the public dns of this instance, I made everything identical as I've done in the past, It has always been working doing these steps, anything has changed using AWS EC2 ubuntu 20 instance, let me know. Thanks a lot, I'm headaching trying to figure this out.
Last steps to try to solve it is check nginx logs
cd /var/log/nginx
2022/04/05 09:42:02 [error] 8216#8216: *1 directory index of "/var/www/html/" is forbidden, client: 103.178.236.40, server: _, request: "GET http://example.>
But even doing this, it has not solved the issue:
sudo chmod -R 777 /var/www/html
You are accessing the site via https (443) while it's running on http (80).
Here is the result of curl.
root#MSI:~# curl -vk https://ec2-23-22-52-143.compute-1.amazonaws.com
* Rebuilt URL to: https://ec2-23-22-52-143.compute-1.amazonaws.com/
* Trying 23.22.52.143...
* TCP_NODELAY set
* connect to 23.22.52.143 port 443 failed: Connection refused
* Failed to connect to ec2-23-22-52-143.compute-1.amazonaws.com port 443: Connection refused
* Closing connection 0
curl: (7) Failed to connect to ec2-23-22-52-143.compute-1.amazonaws.com port 443: Connection refused
root#MSI:~# curl -vk http://ec2-23-22-52-143.compute-1.amazonaws.com
* Rebuilt URL to: http://ec2-23-22-52-143.compute-1.amazonaws.com/
* Trying 23.22.52.143...
* TCP_NODELAY set
* Connected to ec2-23-22-52-143.compute-1.amazonaws.com (23.22.52.143) port 80 (#0)
> GET / HTTP/1.1
> Host: ec2-23-22-52-143.compute-1.amazonaws.com
> User-Agent: curl/7.58.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Server: nginx/1.18.0 (Ubuntu)
< Date: Tue, 05 Apr 2022 13:02:08 GMT
< Content-Type: text/html
< Content-Length: 1676
< Last-Modified: Tue, 05 Apr 2022 09:54:30 GMT
< Connection: keep-alive
< ETag: "624c11d6-68c"
< Accept-Ranges: bytes
<
* Connection #0 to host ec2-23-22-52-143.compute-1.amazonaws.com left intact
<!DOCTYPE html><html class="bg-image" lang="en"><head><meta charset="utf-8"><meta http-equiv="X-UA-Compatible" content="IE=edge"><meta name="viewport" content="width=device-width,initial-scale=1"><link rel="my icon" href="/assets/icone.ico" type="image/x-icon"><title>Lab301mktdigital</title><link rel="preconnect" href="https://fonts.googleapis.com"><link rel="preconnect" href="https://fonts.gstatic.com" crossorigin><link href="https://fonts.googleapis.com/css2?family=Comfortaa:wght#300;400;500;600;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Dancing+Script:wght#400;500;600;700&display=swap" rel="stylesheet"><link href="https://fonts.googleapis.com/css2?family=Playfair+Display:ital,wght#0,400;0,500;0,600;0,700;0,800;0,900;1,400;1,500;1,600;1,700;1,800;1,900&display=swap" rel="stylesheet"><link rel="stylesheet" href="https://cdn.jsdelivr.net/npm/#mdi/font#latest/css/materialdesignicons.min.css"><link rel="stylesheet" href="./assets/styles/general.css"><link href="/css/app.9ba0b389.css" rel="preload" as="style"><link href="/css/chunk-vendors.f754c4c0.css" rel="preload" as="style"><link href="/js/app.5380592f.js" rel="preload" as="script"><link href="/js/chunk-vendors.1ab5dd1a.js" rel="preload" as="script"><link href="/css/chunk-vendors.f754c4c0.css" rel="stylesheet"><link href="/css/app.9ba0b389.css" rel="stylesheet"></head><body><noscript><strong>We're sorry but freelancer-front-end doesn't work properly without JavaScript enabled. Please enable it to continue.</strong></noscript><div id="app"></div><script src="/js/chunk-vendors.1ab5dd1a.js"></script><script src="/js/app.5380592f.js"></script></body></html>
From browser :

firefox does not allow CORS request

vuejs is running inside a docker container served by:
CMD [ "http-server", "dist" ]
when using axios inside Vue.js mounted() to do a GET request against a flask api it shows "blocked" in the network tab, accessing other REST-API's works fine.
testing with curl (localhost:6000 being the flask server):
- curl is running from my real host and conneting to the container
curl -H "Origin: http://localhost:5000"
-H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Requested With"
-X OPTIONS --verbose http://localhost:6000/todo/api/v1.0/wheel/40
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 6000 (#0)
> OPTIONS /todo/api/v1.0/wheel/40 HTTP/1.1
> Host: localhost:6000
> User-Agent: curl/7.58.0
> Accept: */*
> Origin: http://localhost:5000
> Access-Control-Request-Method: GET
> Access-Control-Request-Headers: X-Requested-With
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: text/html; charset=utf-8
< Allow: OPTIONS, GET, HEAD
< Access-Control-Allow-Origin: http://localhost:5000
< Access-Control-Allow-Headers: X-Requested-With
< Access-Control-Allow-Methods: DELETE, GET, HEAD, OPTIONS, PATCH, POST, PUT
< Vary: Origin
< Content-Length: 0
< Server: Werkzeug/1.0.0 Python/3.8.2
< Date: Sun, 15 Mar 2020 15:43:44 GMT
<
* Closing connection 0
from what ive read so far, for example here: 1, for a unauthorized GET request the headers look ok.
This one gets the real data:
curl -H "Origin: http://l:5000" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Requested-With" -v http://localhost:6000/todo/api/v1.0/wheel/40
* Trying 127.0.0.1...
* TCP_NODELAY set
* Connected to localhost (127.0.0.1) port 6000 (#0)
> GET /todo/api/v1.0/wheel/40 HTTP/1.1
> Host: localhost:6000
> User-Agent: curl/7.58.0
> Accept: */*
> Origin: http://l:5000
> Access-Control-Request-Method: GET
> Access-Control-Request-Headers: X-Requested-With
>
* HTTP 1.0, assume close after body
< HTTP/1.0 200 OK
< Content-Type: application/json
< Content-Length: 39
< Access-Control-Allow-Origin: http://l:5000
< Vary: Origin
< Server: Werkzeug/1.0.0 Python/3.8.2
< Date: Sun, 15 Mar 2020 15:56:43 GMT
<
{"result":{"model 1":0,"model 2":150}}
* Closing connection 0
Manipulating -H "Origin..." to this:
-H "Origin: http://l:5000"
also shows a normal reply. Isn't that a good test?
As it turns out mozilla allows certain ports for certain protocols as shown here:
https://developer.mozilla.org/en-US/docs/Mozilla/Mozilla_Port_Blocking
6000 is the "x11" port and on that list - As port for x11 and not to be used for xhr. So every port not on that list should do the trick.
reason:
Cert issued a Vulnerability Note VU#476267 for a "Cross-Protocol" scripting attack, known as the HTML Form Protocol Attack
In your app's __init__.py file add these lines and you'll be good to go.
$ pip install flask-cors
from flask_cors import CORS
app = Flask(__name__)
CORS(app)
Read more about CORS here-- MDN CORS

CORS for AWS API Gateway return HTTP 500

I've a simple API Gateway, that sends the data to an HTTP endpoint (Express/Node).
For testing, I'm using curl, which is great. Sending the curl request without CORS works like a charm, however if I try to mimic CORS in curl, I get a HTTP 500 and have no idea why. These are both requests:
curl -v -H "X-Api-Key: myapikey" -H "Origin: example.com" "https://apigatewayid.execute-api.us-west-2.amazonaws.com/dev/path/prettyParam?anotherParam=1"
* Trying x.x.x.x...
* TCP_NODELAY set
* Connected to apigatewayid.execute-api.us-west-2.amazonaws.com (x.x.x.x) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.execute-api.us-west-2.amazonaws.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> GET /dev/path/prettyParam?anotherParam=1 HTTP/1.1
> Host: apigatewayid.execute-api.us-west-2.amazonaws.com
> User-Agent: curl/7.51.0
> Accept: */*
> X-Api-Key: myapikey
> Origin: example.com
>
< HTTP/1.1 200 OK
< Content-Type: application/json
< Content-Length: 64
< Connection: keep-alive
< Date: Fri, 21 Jul 2017 00:28:50 GMT
< x-amzn-RequestId: numbers-6dab-11e7-b411-b7f8fd6c0cc3
< Access-Control-Allow-Origin: *
< X-Amzn-Trace-Id: Root=1-5morenumbersletters3e8be5c86a2c72781a0b356
< X-Cache: Miss from cloudfront
< Via: 1.1 numbersletters7a8621aabe6b30d2f5a48.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: numberslettersUk3Bs9dL4KJR4QccPmILA4tJUjO0X_h7cQc9DxA==
<
* Curl_http_done: called premature == 0
* Connection #0 to host apigatewayid.execute-api.us-west-2.amazonaws.com left intact
{"resultDataFromServer":"dataReceived!"}
curl -H "Origin: example.com" -H "X-Api-Key: myapikey" -H "Access-Control-Request-Method: GET" -H "Access-Control-Request-Headers: X-Requested-With" -X OPTIONS --verbose "https://apigatewayid.execute-api.us-west-2.amazonaws.com/dev/path/prettyParam?anotherParam=1"
* Trying x.x.x.x...
* TCP_NODELAY set
* Connected to apigatewayid.execute-api.us-west-2.amazonaws.com (x.x.x.x) port 443 (#0)
* TLS 1.2 connection using TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256
* Server certificate: *.execute-api.us-west-2.amazonaws.com
* Server certificate: Symantec Class 3 Secure Server CA - G4
* Server certificate: VeriSign Class 3 Public Primary Certification Authority - G5
> OPTIONS /dev/path/prettyParam?anotherParam=1 HTTP/1.1
> Host: apigatewayid.execute-api.us-west-2.amazonaws.com
> User-Agent: curl/7.51.0
> Accept: */*
> X-Api-Key: myapikey
> Access-Control-Request-Method: GET
> Access-Control-Request-Headers: X-Requested-With
>
< HTTP/1.1 500 Internal Server Error
< Content-Type: application/json
< Content-Length: 36
< Connection: keep-alive
< Date: Fri, 21 Jul 2017 00:29:07 GMT
< x-amzn-RequestId: numbers-6dab-11e7-b411-b7f8fd6c0cc3
< Access-Control-Allow-Origin: *
< Access-Control-Allow-Headers: Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token
< Access-Control-Allow-Methods: GET,OPTIONS
< X-Cache: Miss from cloudfront
< Via: 1.1 numbersletters7a8621aabe6b30d2f5a48.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: numberslettersUk3Bs9dL4KJR4QccPmILA4tJUjO0X_h7cQc9DxA==
<
* Curl_http_done: called premature == 0
* Connection #0 to host apigatewayid.execute-api.us-west-2.amazonaws.com left intact
{"message": "Internal server error"}
I really don't understand what I'm doing wrong. I enabled CORS in the API Gateway, and in Express CORS is enabled also, so not sure what is going on.
#Raul, did you test your API method via API Gateway? Try deploying your API again and test it from the APIGateway itself by providing the URL param. If you get the same {"message": "Internal server error"} there is a problem with the code. Sometimes it might look like a CORS issue, but actually it could be a lambda logic error.

CloudFront error when serving over HTTPS using SNI

Amazon recently rolled out a new feature on CloudFront that supports custom SSL certificates at no charge using SNI (Server Name Indication).
I got my distribution set up with a free Class 1 certificate from StartSSL and everything was working when I was noticing that the site would go down a short time after it's deployed. Running SSL Checker returns that my certificate is working properly:
But then I would hit this error page when trying to access the site via HTTPS (it would work for the first request then go down in subsequent attempts to connect).
Here's a verbose output when accessing with ssl (succeeds on index):
$ curl -I -v -ssl https://wikichen.is
* Adding handle: conn: 0x7f9f82804000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7f9f82804000) send_pipe: 1, recv_pipe: 0
* About to connect() to wikichen.is port 443 (#0)
* Trying 54.230.141.222...
* Connected to wikichen.is (54.230.141.222) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_RC4_128_MD5
* Server certificate: www.wikichen.is (6w984WNu7vM5OrdU)
* Server certificate: StartCom Class 1 Primary Intermediate Server CA
* Server certificate: StartCom Certification Authority
> HEAD / HTTP/1.1
> User-Agent: curl/7.30.0
> Host: wikichen.is
> Accept: */*
>
< HTTP/1.1 200 OK
HTTP/1.1 200 OK
< Content-Type: text/html; charset=utf-8
Content-Type: text/html; charset=utf-8
< Content-Length: 1153
Content-Length: 1153
< Connection: keep-alive
Connection: keep-alive
< Date: Sun, 09 Mar 2014 16:09:54 GMT
Date: Sun, 09 Mar 2014 16:09:54 GMT
< Cache-Control: max-age=120
Cache-Control: max-age=120
< Content-Encoding: gzip
Content-Encoding: gzip
< Last-Modified: Wed, 05 Mar 2014 20:40:48 GMT
Last-Modified: Wed, 05 Mar 2014 20:40:48 GMT
< ETag: "34685bc45353d1030d3a515ddba78f3e"
ETag: "34685bc45353d1030d3a515ddba78f3e"
* Server AmazonS3 is not blacklisted
< Server: AmazonS3
Server: AmazonS3
< Age: 4244
Age: 4244
< X-Cache: Hit from cloudfront
X-Cache: Hit from cloudfront
< Via: 1.1 4f672256eaca5524999342dc8678cdd2.cloudfront.net (CloudFront)
Via: 1.1 4f672256eaca5524999342dc8678cdd2.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: h4TEULH44TCi7m2lL42A8lO-5-Gmx8iY2M2C1AOmRlK543zFN6jCtQ==
X-Amz-Cf-Id: h4TEULH44TCi7m2lL42A8lO-5-Gmx8iY2M2C1AOmRlK543zFN6jCtQ==
<
* Connection #0 to host wikichen.is left intact
Then fails on other pages:
$ curl -i -v https://wikichen.is/writing/index.html
* Adding handle: conn: 0x7fa153804000
* Adding handle: send: 0
* Adding handle: recv: 0
* Curl_addHandleToPipeline: length: 1
* - Conn 0 (0x7fa153804000) send_pipe: 1, recv_pipe: 0
* About to connect() to wikichen.is port 443 (#0)
* Trying 54.230.140.160...
* Connected to wikichen.is (54.230.140.160) port 443 (#0)
* TLS 1.2 connection using TLS_RSA_WITH_RC4_128_MD5
* Server certificate: www.wikichen.is (6w984WNu7vM5OrdU)
* Server certificate: StartCom Class 1 Primary Intermediate Server CA
* Server certificate: StartCom Certification Authority
> GET /writing/index.html HTTP/1.1
> User-Agent: curl/7.30.0
> Host: wikichen.is
> Accept: */*
>
< HTTP/1.1 502 Bad Gateway
HTTP/1.1 502 Bad Gateway
< Content-Type: text/html
Content-Type: text/html
< Content-Length: 472
Content-Length: 472
< Connection: keep-alive
Connection: keep-alive
* Server CloudFront is not blacklisted
< Server: CloudFront
Server: CloudFront
< Date: Sun, 09 Mar 2014 17:54:41 GMT
Date: Sun, 09 Mar 2014 17:54:41 GMT
< Age: 6
Age: 6
< X-Cache: Error from cloudfront
X-Cache: Error from cloudfront
< Via: 1.1 9096435f28f91f92bacdf76122de09ee.cloudfront.net (CloudFront)
Via: 1.1 9096435f28f91f92bacdf76122de09ee.cloudfront.net (CloudFront)
< X-Amz-Cf-Id: iAUOQbP8O4A0pI9KGvVz0VgBT1TW-j0yVDa7vdSvIAuxnKOyQghtnw==
X-Amz-Cf-Id: iAUOQbP8O4A0pI9KGvVz0VgBT1TW-j0yVDa7vdSvIAuxnKOyQghtnw==
<
<!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>ERROR</H1>
<H2>The request could not be satisfied.</H2>
<HR noshade size="1px">
</BODY></HTML>
<BR clear="all">
<HR noshade size="1px">
<ADDRESS>
Generated by cloudfront (CloudFront)
</ADDRESS>
* Connection #0 to host wikichen.is left intact
</BODY></HTML>%
Would love some pointers as to where to start troubleshooting.
A kind rep by the name of Alastair#AWS from the AWS CloudFront forums solved this for me:
I have identified your CloudFront distribution and the S3 bucket
acting as the origin for this distribution.
I can re-create and explain the intermittent '502 Bad Gateway'
response you are receiving.
This response is returned by CloudFront when you attempt to access a
URL using the HTTPS protocol that is not currently cached by
CloudFront. The reason for this error is CloudFront is attempting to
contact your origin using the HTTPS protocol, and this is failing.
The reason for this failure is you have configured your origin as an
S3 bucket, but you are using the "Custom Origin" type and directing to
the S3 website URL for this bucket. If you attempt to hit your S3
website URL using HTTPS, you will note this does not work. S3 website
hosting only supports serving content using the HTTP protocol
(http://docs.aws.amazon.com/AmazonS3/latest/dev/WebsiteEndpoints.html#WebsiteRestEndpointDiff).
Now, the intermittent page load behavior you are seeing is due to
CloudFront returning the pages it currently has in its cache. You
should be able to re-create this scenario as follows:
Hit a page on your site using HTTPS. You should get a '502 Bad Gateway' error back.
Hit the same page using HTTP. You should see the page.
Hit the page again using HTTPS. You should now get the expected result, as CF has served the content from its cache rather than
attempting to contact your origin.
To resolve this issue, please try the following:
Open the CloudFront Management Console and open your distribution.
Navigate to the Origins tab, select your origin and click "Edit"
Modify the "Origin Protocol Policy" to "HTTP Only".
Save the changes and wait about 15 minutes for the change to take effect.
Test
My expectation is this will force CloudFront to contact your origin
using HTTP only. I have tested this in my environment with an S3
Website hosted bucket and I can successfully load content via both
HTTP and HTTPS.
Here's the link to the original forum thread.
I had a similar issue to this and, as #Michael-sqlbot suggested, switched from custom origin to S3. That did not, by itself, resolve the issue.
In addition to switching the origin, Andrew from AWS support said that aliases work better than CNAMEs. I had been using CNAMEs. When I switched to aliases (one for IPv4 and one for IPv6) it worked. Here is the Route 53 documentation for CloudFront that shows how to setup aliases for CloudFront.
I was struggling a bit with having proper setup with own SSL Certificate, but this article was most helpful. Just pay attention to details:
https://docs.aws.amazon.com/Route53/latest/DeveloperGuide/tutorial-redirecting-dns-queries.html

Firefox WebFont 403 Despite S3 CORS Rules

I'm trying to host and serve webfonts (specifically, fontawesome) to my django project on heroku from AWS S3, and I'm having difficulty overcoming the dreaded firefox cross-domain font-loading issue. I've tried all the documented, accepted solutions and none of them are working for me.
The recommended solution I keep seeing is to edit CORS configs on my S3 bucket:
<?xml version="1.0" encoding="UTF-8"?>
<CORSConfiguration xmlns="http://s3.amazonaws.com/doc/2006-03-01/">
<CORSRule>
<AllowedOrigin>https://myapp.herokuapp.com</AllowedOrigin>
<AllowedOrigin>https://www.myapp.herokuapp.com</AllowedOrigin>
<AllowedOrigin>https://myapp.com</AllowedOrigin>
<AllowedOrigin>https://www.myapp.com</AllowedOrigin>
<AllowedMethod>GET</AllowedMethod>
<MaxAgeSeconds>3000</MaxAgeSeconds>
<AllowedHeader>Authorization</AllowedHeader>
</CORSRule>
</CORSConfiguration>
I've tried different variations of these settings and firefox is still giving me an HTTP 403 forbidden from https://www.myapp.com:
Request URL: https://my_bucket.s3.amazonaws.com/css/fontawesome-webfont-webfont.ttf
Request Method: GET
Status Code: HTTP/1.1 403 Forbidden
With that HTTP request I'm getting "Access-Control-Allow-Credentials:true" in response headers.
Is there another CORS rule I need to declare for firefox to accept the fonts from S3? When I curl font-awesome I don't get/see anything helpful for troubleshooting this:
> https://s3.amazonaws.com/my_bucket/font/fontawesome-webfont.eot
* About to connect() to s3.amazonaws.com port 443 (#0)
* Trying xxx.xx.xx.xxxx... connected
* Connected to s3.amazonaws.com (xxx.xx.xx.xxx) port 443 (#0)
* SSLv3, TLS handshake, Client hello (1):
* SSLv3, TLS handshake, Server hello (2):
* SSLv3, TLS handshake, CERT (11):
* SSLv3, TLS handshake, Server finished (14):
* SSLv3, TLS handshake, Client key exchange (16):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSLv3, TLS change cipher, Client hello (1):
* SSLv3, TLS handshake, Finished (20):
* SSL connection using DES-CBC3-SHA
* Server certificate:
* subject: C=US; ST=Washington; L=Seattle; O=Amazon.com Inc.; CN=s3.amazonaws.com
* start date: 2010-10-08 00:00:00 GMT
* expire date: 2013-10-07 23:59:59 GMT
* common name: s3.amazonaws.com (matched)
* issuer: C=US; O=VeriSign, Inc.; OU=VeriSign Trust Network; OU=Terms of use at https://www.verisign.com/rpa (c)09; CN=VeriSign Class 3 Secure Server CA - G2
* SSL certificate verify ok.
> GET /my_bucket/font/fontawesome-webfont.eot HTTP/1.1
> User-Agent: curl/7.21.4 (universal-apple-darwin11.0) libcurl/7.21.4 OpenSSL/0.9.8r zlib/1.2.5
> Host: s3.amazonaws.com
> Accept: */*
> Origin: https://www.myapp.com
>
< HTTP/1.1 200 OK
< x-amz-id-2: XxMCWhqMsTGMMmAQnSHT/+RO7aluQSRyZ5wTAseMKM5cpavE+NkBQCuD8ykiIIDE
< x-amz-request-id: 90FF2C1C85254815
< Date: Mon, 22 Jul 2013 01:54:53 GMT
< Access-Control-Allow-Origin: https://www.myapp.com
< Access-Control-Allow-Methods: GET
< Access-Control-Max-Age: 3000
< Access-Control-Allow-Credentials: true
< Vary: Origin, Access-Control-Request-Headers, Access-Control-Request-Method
< Last-Modified: Mon, 22 Jul 2013 01:44:31 GMT
< ETag: "455808250694e5760bd92b3ce1f070b6"
< Accept-Ranges: bytes
< Content-Type: application/octet-stream
< Content-Length: 25395
< Server: AmazonS3
<
3cOb?LP&?S~FontAwesomeRegular"Version 1.00 2012&FontAwesome RegularBSGPɴbGbKV?????Y?D
Is there another way to set Access-Control-Allow-Origin that might get this working?
If you are restricting access to specific HTTP referrers in your bucket policy, add your bucket url also in referer list. For example:
"Condition": {
"StringLike": {
"aws:Referer": [
"http://my_bucket.s3.amazonaws.com/*",
"https://my_bucket.s3.amazonaws.com/*",
"http://www.example.com/*",
"https://www.example.com/*",
]
}
}
Check the response headers in Firefox. Turns out that referer for font is your CSS file, which is hosted on s3 bucket, not your domain.