WebSocket connection failed: Error during WebSocket handshake: Unexpected response code: 502 - python

We have host python service on the server (no public accessible) which allows HTTPS and Web Socket requests on 4431.To connect to the python service, we have implemented an Azure App Gateway (bind with the domain) with rule - domain:4431 and which will be redirected to the server.
So, the problem is we are facing the following error
502 Bad Gateway - Microsoft-Azure-Application-Gateway/v2
We have observed that request from the browser comes to the AppGW but on server, we are receiving request intermittently.
socketio.run(app, host='0.0.0.0', port=4431, certfile=certs["crt"], keyfile=certs["key"], ssl_version=ssl.PROTOCOL_TLSv1_2)
Our Architecture
Error

Found out, what was causing the issue, we haven't provided root CA Certificate to run server.
socketio.run(app, host='0.0.0.0', port=4431, certfile=certs["crt"], keyfile=certs["key"], ca_certs=certs["CA crt"], ssl_version=ssl.PROTOCOL_TLSv1_2)

Related

Cannot reach "worker" process in Heroku from web process: `ConnectionRefusedError`

I have a web process and an api process (a "worker" process similar to what is described in the docs and these other docs). However, I don't understand how the networking between different processes works.
Both processes are listening on 0.0.0.0, and the worker process is bound to port 5000. However, when I try to make a request from the web process, I get a ConnectionRefusedError:
ConnectionError: HTTPConnectionPool(host='0.0.0.0', port=5000): Max retries exceeded with url: /tokenize?sentence=hello (Caused by NewConnectionError('<urllib3.connection.HTTPConnection object at 0x7fd307019dc0>: Failed to establish a new connection: [Errno 111] Connection refused'))
Am I supposed to figure out the IP of the other process? Am I doing something wrong here?
Procfile:
api: python app.py
web: voila UI.ipynb --port $PORT --Voila.ip=0.0.0.0
app.py:
from flask import Flask, request
from ie_utils import tokenize
app = Flask(__name__)
#app.route("/")
def home():
return {
"message": "Hello world!",
"version": "0.1",
}
if __name__ == "__main__":
import os
port = 5000
app.run(host="0.0.0.0", port=port)
Relevant code in UI.ipynb:
import requests
requests.get("http://0.0.0.0:5000/")
Full source code: https://github.com/astrojuanlu/ie-titanic-utils-a/tree/test-procfile
I don't understand how the networking between different processes works
Unless you are using Private Spaces (part of Heroku's enterprise offering), it doesn't:
The Common Runtime provides strong isolation by firewalling all dynos off from one another. The only traffic that can reach a dyno is web requests forwarded from the router to web processes listening on the port number specified in the $PORT environment variable. Worker and one-off dynos cannot receive inbound requests.
I'm not totally clear what you're trying to do here, but you won't be able to do it by making an HTTP request to localhost. You might have better luck running this as two separate apps—in that case your API could be its own web process and your Voilà app could make requests to the API app's hostname.
Side note: even on a system where this is permitted your request should not go to 0.0.0.0. That isn't a real IP address.
Telling Flask to bind to 0.0.0.0 really means that it should listen on all available IP addresses. When you want to make a request you should use one of the real hostnames or IP addresses that your system is using, e.g. localhost or 127.0.0.1 or one of its public IP addresses or hostnames.

Disable Client Authentication for python HTTPS requests

Currently my client side HTTPS request code looks like this:
resp = requests.post(endpoint_predict_v100, files={'image': open(file_path, 'rb')}, verify=client_auth,
cert=(client_cert_path, client_secret_path))
This is an HTTPS request, the server root CA is client_auth and the client certificate and key are client_cert_path and client_secret_path.
because my server code is deployed and I cannot change much on that side, I am wondering if I can do the following on the client side:
enable server authentication only when the server root CA is provided by the client
enable client authentication only when the client cert and key are provided by the client.
I have found out that I am able to do the first thing, "enable server authentication only when the server root CA is provided by the client", by passing verify=False if the server root CA is not presented on the client side., referring to the Python requests docs. However, when I try to remove the cert=(client_cert_path, client_secret_path), the request will fail, throwing this error:
ssl.SSLError: [SSL] tlsv13 alert certificate required (_ssl.c:2570)
It seems that this error is suggesting I must pass in the client cert and key to make the server accept my request. but is there a way to disable client authentication on the client side, when the client cert and key are not present?
ssl.SSLError: [SSL] tlsv13 alert certificate required (_ssl.c:2570)
... is there a way to disable client authentication on the client side, when the client cert and key are not present?
The alert you get is because the server is requiring the client certificate. Since it is required by the server it is not sufficient to change some client side behavior only. This is similar to a server requesting authentication by password - this cannot be simply skipped in the client too.
With many servers there is a way to have client certificates optional, i.e. request a client certificate but don't insist that one is sent. How to do this with your specific server and if it is supported by your server at all is unknown though.

flask server with ssl_context freezes if it receives http request

I'm trying to create a simple flask server that redirects any http requests to https. I've created a certificate and key file and registered a before_request hook to see if the request is secure and redirect appropriately, following advise this SO answer.
The flask server responds to https requests as expected. However, when I send an http request, the before_request hook never gets called and ther server hangs forever. If I send the http request from the browser, I see an "ERR_EMPTY_RESPONSE". The server doesn't even respond to https requests afterwards. No logs are printed either.
Running the app with gunicorn didn't help either. The only difference was that gunicorn is able to detect that the worker is frozen and eventually kills and replaces it. I've also tried using flask-talisman, with the same results.
Below is the code I'm running
### server.py
from flask import Flask, request, redirect
def verify_https():
if not request.is_secure:
url = request.url.replace("http://", "https://", 1)
return redirect(url, 301)
def create_flask_app():
app = Flask(__name__)
app.before_request(verify_https)
app.add_url_rule('/', 'root', lambda: "Hello World")
return app
if __name__ == '__main__':
app = create_flask_app()
app.run(
host="0.0.0.0",
port=5000,
ssl_context=('server.crt', 'server.key')
)
Running it with either python3.8 server.py or gunicorn --keyfile 'server.key' --certfile 'server.crt' --bind '0.0.0.0:5000' 'server:create_flask_app()' and opening a browser window to localhost:5000 causes the server to hang.
Talking about freezes, its not. Flask and gunicorn can serve only one variant of connection. So it's not freezing because your browser canceled the request and is idling.
I think it is better to use a faster web server, for example, Nginx, if you want to change HTTP to HTTPS. I would recommend it to you.
But it's possible to trigger your verify_https function if you run multiple instances of gunicorn at the same time.
I took your example, generated a certificate, and then run this script in my console (it contains a background job and can be runned in twoo separate ter)
gunicorn --bind '0.0.0.0:80' 'server:create_flask_app()' & gunicorn --certfile server.crt --keyfile server.key --bind '0.0.0.0:443' 'server:create_flask_app()'
now chrome goes to the secure page as expected.
Typically servers don't listen for both http and https on the same port. I have a similar requirement for my personal portfolio, but I use nginx to forward http requests (port 80) to https (port 443) and then the https server passes it off to my uwsgi backend, which listens on port 3031. That's probably more complex than you need, but a possible solution. If you go that route I would recommend letsencrypt for your certificate needs. It will set up the certificates AND the nginx.conf for you.
If you don't want to go the full nginx/apache route I think your easiest solution is the one suggested here on that same thread that you linked.

AWS ELB http works, but https not working

I requested a SSL certificate in AWAS Certificate Manager with my own domain, then setup an Elastic Load Balancer forwarding to an EC2 instance which has a Python API running on port 5070.
Load Balancer
443 Rule
Target Group
I can get response from http URL, but https is not working, got the below error
The requested URL can’t provide a secure connection
The URL sent an invalid response.
Learn more about this problem.
net::ERR_SSL_PROTOCOL_ERROR
Any idea on this problem?

Why python post request with nordvpn socks proxy doesn't work on distant hosted server while working on local windows?

On a python app, i send a request post through a socks proxy of nordvpn :
(los-angeles.us.socks.nordhold.net)
prox = {'https':'socks5://user:pass#host:port'}
requests.post(url, proxies=prox, data=data)
While this code works on my local windows environnement, the request been sent and received, the code gets an error when the app is hosted on a shared server.
socks.ProxyConnectionError: Error connecting to SOCKS5 proxy los-angeles.us.socks.nordhold.net:1080:
[Errno 111] Connection refused
Hoster says i need a root ssh access from a dedidated server. But how would it help ?
amsterdam.nl.socks.nordhold.net
atlanta.us.socks.nordhold.net
dallas.us.socks.nordhold.net
dublin.ie.socks.nordhold.net
ie.socks.nordhold.net
los-angeles.us.socks.nordhold.net
nl.socks.nordhold.net
se.socks.nordhold.net
stockholm.se.socks.nordhold.net
us.socks.nordhold.net
Port is 1080
your username is manually setup credentials and passwords too.
Dont try to use ur login data for it because it will never work.
Try with closing the connection.

Categories

Resources