Cannot get websocket connection working with ec2 + application load balancer - amazon-web-services

I am having trouble establishing a websocket connection. I have an aws ec2 instance that is running an SSL websocket server on a subdomain: api.example.com, on port 9999. My client application is running at www.example.com, the client sets up a listener:
new WebSocket('wss://api.example.com:9999');
This results in the browser giving me:
net::ERR_CONNECTION_REFUSED
So my next idea was since my application load balancer already has an https listener setup on port 443 going to my api server, I changed my websocket listener setup to:
new WebSocket('wss://api.example.com/socket');
Then I made my nodejs (restify) webserver on the ec2 instance catch /socket with plans to redirect it to localhost:9999... However, I put a console.log in that /socket endpoint prior to redirecting, and there is no logging happening-- I also tried wss://api.example.com:443/socket, neither seems to hit the endpoint in my webserver.
Yet if I use curl, it works fine:
~>curl -i -N -H "Connection: Upgrade" -H "Upgrade: websocket" -H "Host: api.example.com" -H "Origin: https://www.example.com" https://api.example.com/socket
HTTP/2 301
date: Tue, 26 Jun 2018 02:27:07 GMT
content-type: application/json
content-length: 4
location: https://localhost:9999/localhost
server: restify
access-control-allow-origin: https://www.example.com
vary: origin
access-control-expose-headers: api-version, content-length, content-md5, content-type, date, request-id, response-time
although https://localhost:9999/localhost seems a little weird-- but regardless, when I use curl, it hits the endpoint and I see the log.

Related

Basic authentication through HTTPS reverse proxy works with curl, don't work with browser

In our GKE Kubernetes cluster we have a deployment running a pod with a third-party unmodifiable legacy application exposing an HTTP service (port :80) protected with based authentication. The cluster is exposed to the outside Internet through a GCP load balancer that takes care of terminating HTTPS connections.
When, from the Internet, I try to access the service using CURL, it works perfectly, I got an HTTP status 200.
curl -vvv 'https://username:password#portale-ambrogio-test.sigemi.cloud/admin'
* Trying 34.107.254.133...
* Connected to portale-ambrogio-test.sigemi.cloud (34.107.254.133) port 443 (#0)
* found 129 certificates in /etc/ssl/certs/ca-certificates.crt
* found 516 certificates in /etc/ssl/certs
* ALPN, offering http/1.1
* SSL connection using TLS1.2 / ECDHE_RSA_AES_128_GCM_SHA256
* server certificate verification OK
* server certificate status verification SKIPPED
* common name: *.sigemi.cloud (matched)
* server certificate expiration date OK
* server certificate activation date OK
* certificate public key: RSA
* certificate version: #3
* subject: CN=*.sigemi.cloud
* start date: Tue, 24 May 2022 00:00:00 GMT
* expire date: Wed, 24 May 2023 23:59:59 GMT
* issuer: C=GB,ST=Greater Manchester,L=Salford,O=Sectigo Limited,CN=Sectigo RSA Domain Validation Secure Server CA
* compression: NULL
* ALPN, server accepted to use http/1.1
* Server auth using Basic with user 'username'
> GET /admin HTTP/1.1
> Host: portale-ambrogio-test.sigemi.cloud
> Authorization: Basic aR.......................==
> User-Agent: curl/7.47.0
> Accept: */*
>
< HTTP/1.1 200 OK
< Ntrip-Version: Ntrip/2.0
< Access-Control-Allow-Origin: *
< Server: NTRIP BKG Caster/2.0.39
< Content-Type: text/html
< Date: Tue, 06 Sep 2022 15:53:09 GMT
< Via: 1.1 google
< Transfer-Encoding: chunked
< Alt-Svc: h3=":443"; ma=2592000,h3-29=":443"; ma=2592000
When I access the same resource through the browser, it fails instead.
Do you know why that could happen? I think it is something related to some security policy implemented by the browser but what?
[EDIT] Now with the browser I'm explicitly typing username and password in the authentication pop up to avoid the problem pointed out by #john-hanley
The problem was caused by few facts.
Our web application was not fully compliant with any of the HTTP specs (1.1, 2 and 3) regarding the name of the HTTP headers. In particular HTTP/1.1 states that header names should be considered case insensitive, while HTTP/2 and HTTP/3 states that headers should be lower case. Our application expected header names to be capitalized, so it always looked for the "Authentication" header.
When modern browsers connect to an HTTP web server, they usually use HTTP/1.1 and in this case, they tend to capitalize header names, so browsers actually send a header which name is spelled "Authorization".
However when modern browsers connect to HTTPS, they upgrade to HTTP/2 or HTTP/3 id supported by the web server. If they upgrade to such protocols, they obey it, so the send the authorization header in lower case, so "authorization".
Our reverse proxy is provided by GCP, that indeed supports HTTP/3. So, when the browser connects to our GCP reverse proxy it switches to HTTP/3 and start sending lower case headers.
The reverse proxy the forward the request to our application in lower case.
And because of 1) the app is unable to authenticate.
Hope this report can help, because I spend a whole day trying to figure it out (and I actually learnt about HTTP/2 and HTTP/3).
The solution was obviously to fix our application and made it fully HTTP compliant.
The CLI curl is converting username:password from the URI into Authorization: Basic ....
Chrome stopped supporting URI credentials in the address bar after version 52. Internally, this is still supported via JavaScript.

Set HTTP 1.1 for sam local start-api

I'm developing a lambda function and using AWS SAM to build my stack. I've noticed that when I test locally using sam local start-api, the API responds with HTTP 1.0 for HTTP 1.1 requests. Here's a sample output from curl:
* Trying 127.0.0.1:3000...
* TCP_NODELAY set
* Connected to 127.0.0.1 (127.0.0.1) port 3000 (#0)
> GET / HTTP/1.1
> Host: 127.0.0.1:3000
> User-Agent: curl/7.68.0
> Accept: */*
>
* Mark bundle as not supporting multiuse
* HTTP 1.0, assume close after body
< HTTP/1.0 403 FORBIDDEN
< Content-Type: application/json
< Content-Length: 43
< Server: Werkzeug/1.0.1 Python/3.7.10
< Date: Fri, 03 Dec 2021 04:21:40 GMT
<
{ [43 bytes data]
* Closing connection 0
{
"message": "Missing Authentication Token"
}
As you can see in the output above, an HTTP 1.1 request is sent to the API but the API responds with HTTP 1.0. This happens for all requests.
I assume that when I push this out to AWS, the API will also use HTTP 1.0. Does anyone know if I can configure which HTTP protocol version gets used for API gateway proxy to lambda function? Also, how do I set a minimum TLS version of 1.2?
Tell curl to use http 1.1:
curl http://api-url -vvv --http1.1

Bitbcuket server integration with AWS API gateway / Lamda

Problem:
Goal - Integrate Bitbucket server which is running in a container/EC2 from AWS-1 account with [ APIGateway-->Lambda-->S3-->Codepipeline ] in AWS-2 account for autodeploying of code whenever there is push in to the bitbucket.
I had setup the infra on AWS-2 account by running cloudforamtion. And while testing / invoking the API gateway from Bitbucket in webhook, it is giving the 'forbidden' error
[
Response details
HTTP status:403
Headers
x-amz-apigw-id: xxxxxxxxxxxxxx
Server: Server
Connection: keep-alive
x-amzn-RequestId: xxxxxxxxxxxxxxxxxxxxx
x-amzn-ErrorType: ForbiddenException
Content-Length: 23
Date: xxxxxxxxxxxxxx
Via: 1.1 localhost (Apache-HttpClient/4.5.5 (cache))
Content-Type: application/json
Body
**{"message":"Forbidden"}**
]
I have installed bitbucket server on my laptop to test.
However, when I invoke api gateurl from the postman or bitbucket server on my laptop I am getting expected exception from lambda/api gateway
[
Response details
HTTP status:502
Headers
x-amz-apigw-id: xxxxxxxxxxxxxxxxxxxxx
Connection: keep-alive
x-amzn-RequestId: xxxxxxxxxxxxxxxxxxxxx
x-amzn-ErrorType: InternalServerErrorException
Content-Length: 36
Date: Tue, 14 Jul 2020 16:25:21 GMT
X-Amzn-Trace-Id: Root=xxxxxxxxxxxxxxxxxxxxx
Via: 1.1 localhost (Apache-HttpClient/4.5.5 (cache))
Content-Type: application/json
Body
{"message": "Internal server error"}
]
The owner of AWSaccount-1 mentioning that resource policy for bit bucket allows all inbound and outbound calls. However he did run curl command from bitbucket hosting container/ec2, got same forbidden error.
I am so confused here, can you please help me or let me know I need to provide more information.
note - this is my first question in stackoverflow :)

Handshake error in Webservice

Our integration partner was using our Web service with http: 8090 and now we are moving to https: 8443 so they tried to update the WS URL but they are getting "handshake error". They are asking whether they can still use http 8090. If we route any traffic coming from http 8090 to https 8443 in the webserver config, will they still get handshake error?
When you create a redirect, the server sends a HTTP 302 which the client is obligated to follow, which means that they should still get the error. depending on your setup, and config, they may be able to send the request anyway, but if that works, then all your traffic is potentially insecure...

How does the web browser know if the url being requested is https or http

When I type google.com (note, I didn't specify it's http or https.)in the chrome, the chrome automatically goes to https://google.com, which is a secured socket connection that connect to port 443. So, my question is how does my browser know it should connect to 443 instead of 80? Or, to put it more simply, how does my browser know google.com use secured socket for http?
HTTP procotocol!
Chrome by default appends http:// prefix, and sends the http://google.com request to the HTTP port:
GET / HTTP/1.1
Host: google.com
...
Then google.com replies:
HTTP/1.1 301 Moved Permanently
Location: https://google.com
...
Notice the https in the Location header.
Then Chrome automatically handles redirections, and sends the second request to the HTTPS port.
GET / HTTP/1.1
Host: google.com
...
Which finally replies with the content displayed in the browser:
HTTP/1.1 200 OK
....
The browser usually tries HTTP first, then gets a redirect to HTTPS. That's the common case, but not the only one. Chrome and Firefox support the notion of HTTP Strict Transport Security Preload Lists which are lists of sites which should only be contacted via HTTPS, even if referenced with a HTTP URL.
You can learn more about HSTS here.
its not your browser doing it but google redirecting http://www.google.com to https://www.google.com.