Node.js serving over https - python

I'm testing Node.js application over https connection where I created certificates for localhost,
Certificate creation,
$ openssl genrsa -out localhost.key 2048
$ openssl req -new -x509 -key localhost.key -out localhost.cert -days 3650 -subj /CN=localhost
Use this in server,
var options = {
key: fs.readFileSync('./localhost.key'),
cert: fs.readFileSync('./localhost.cert'),
};
var http2 = require('http2');
var app = express();
const server = http2.createSecureServer( options, app);
server.listen({ host: app_host, port: port});
Start the node.js server as,
$ node server.js
Tested using simple curl command as,
$ curl -k https://localhost:9000/getcpuinfo
{"hw": ...}
"-k" option is to ignote certificate validation step.
But if I try to use pythons 'requests' module as shown below the request fails,
$ python
import requests
requests.get("https://localhost:9000/getcpuinfo")
requests.exceptions.SSLError: ("bad handshake: Error([('SSL routines', 'tls_process_server_certificate', 'certificate verify failed')],)",)
So I used 'verify' option to make the request, it still fails.
requests.get("https://localhost:9000/getcpuinfo", verify=False)
requests.exceptions.SSLError: ("bad handshake: SysCallError(-1, 'Unexpected EOF')",)
What am I doing wrong? How do I workaround this issue using 'requests' module'? Shouldn't 'verify' prevent the check?

You cant generate https certificates over localhost.

The Python requests module does not connect to HTTP/2 servers, it only supports up to HTTP/1.1:
Requests allows you to send organic, grass-fed HTTP/1.1 requests, without the need for manual labor. There's no need to manually add query strings to your URLs, or to form-encode your POST data. Keep-alive and HTTP connection pooling are 100% automatic, thanks to urllib3.
If you compile curl with HTTP/2 support, then it will work. The curl packages pre-installed on most Linux distros and MacOS aren't and probably won't work.
Since HTTP/2 support in Node is experimental and client support is pretty bad outside of modern web browsers, I would not suggest you use it at this time unless you're specifically targeting web browsers or want to use a HTTP/2-capable web server that can support both HTTP/2 and HTTPS.
If you do need to connect to HTTP/2 servers from Python, there is the (also unstable) hyper module that does connect to a node.js HTTP/2 server. It currently doesn't allow you to disable certificate verification, so it will not be a drop-in replacement for requests.

It seems that there is a utility as part of nghttp2 called 'h2load' which works out of box for both protocols (http/1 and http/2). Thanks for all the answers/hints.
https://nghttp2.org/documentation/h2load-howto.html#basic-usage

Related

Mutual TLS with self signed certificates, with requests in python

I created both client and server certificates:
# client
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out ssl/client.crt -keyout ssl/client.key
# server
openssl req -new -newkey rsa:4096 -x509 -sha256 -days 365 -nodes -out ssl/server.crt -keyout ssl/server
Then with python I have the following:
import requests
response = requests.get(
"https://localhost:8080/",
verify="ssl/server.crt",
cert=("ssl/client.crt", "ssl/client.key")
)
I also have a gunicorn server running with the server self signed certificate.
The code snippet is throwing me the following error:
requests.exceptions.SSLError: HTTPSConnectionPool(host='localhost', port=8080): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: TLSV1_ALERT_UNKNOWN_CA] tlsv1 alert unknown ca (_ssl.c:2633)')))
It is a self signed certificate so I am not sure what CA is it expecting.
tlsv1 alert unknown ca
The server is sending a TLS alert back since it cannot validate your client certificate - the certificate authority (ca) which signed the certificate is unknown to the server. You either need to disable client certificate validation in your server or (better) make the server trust your client certificate.
It is a self signed certificate so I am not sure what CA is it expecting.
A self-signed certificate is signed by itself, i.e. the CA is the certificate itself.
It looks like the server isn't able to validate your client certificate. If you're just using a pair of self-signed certificates for the client and server, then the server needs to also use the client's certificate as its CA, since it will attempt to validate it was signed by the CA - which in this case is the client.
I recently wrote a blog on deploying mTLS with self-signed certificates which might help you as it contains more details, specifically with how to configure the client and server. Check it out here: https://otterize.com/blog/so-you-want-to-deploy-mtls

Problem securing Dask connections with TLS

I am trying to secure a dask distributed system using TLS but the scheduler throws "TypeError: TLS expects a 'ssl_context' argument of type ssl.SSLContext (perhaps check your TLS configuration?) Instead got None" when I run dask-ssh over some local to the network machines.
This is for a dask distributed system that is created using dask-ssh to initialize it. All of the computers in the hostfile.txt are local to the network and file server. I use the same 2 files created with the openssl tool for all machines. Using default TCP there are no issues. I think I am either making the TLS certificates incorrectly, or assigning them in the Dask config incorrectly. I have done a fair amount of googling of this error and I have no idea what could be the issue
Here is how I am generating the certificates:
openssl req -newkey rsa:4096 -nodes -sha256 -x509 -days 3650 -nodes -out /MyFakeDirectory/certs/myca.pem -keyout /MyFakeDirectory/private/mykey.pem
Leaving every asked question after that blank.
Here are all the relevant assignments I have inside of my dask config located at: .config/dask/distributed:
default-scheme: tls
.
.
.
require-encryption: True
tls:
ca-file: /MyFakeDirectory/Certs/certs/myca.pem
scheduler:
key: /MyFakeDirectory/Certs/private/mykey.pem
cert: /MyFakeDirectory/Certs/certs/myca.pem
worker:
key: /MyFakeDirectory/Certs/private/mykey.pem
cert: /MyFakeDirectory/Certs/certs/myca.pem
client:
key: /MyFakeDirectory/Certs/private/mykey.pem
cert: /MyFakeDirectory/Certs/certs/myca.pem
ciphers:
ECDHE-ECDSA-AES128-GCM-SHA256

Proxy authentication using CA5 cert & http certificate authentication

I am new to Python, trying to read & parse logs of applications https url. My org has proxy setup. I am able to connect http url using basic_auth providing & & also by CA5 cert using below code
import urllib3
from urllib3 import ProxyManager, make_headers
# default_headers = make_headers(proxy_basic_auth='<username>:<password>')
# http = ProxyManager("http://<proxy_server>:<port>/", headers=default_headers)
http = ProxyManager("http://<proxy_server>:<port>/",cert_reqs='CERT_REQUIRED',ca_certs='<Windows path to .cer>')
r = http.request('GET','http://google.com')
print(r.data)
.pem certificate got saved as .cer on windows system.
This is working as excepted and returnign google data.
Now while trying to use same for HTTPS url using below,
r = http.request('GET','https://google.com',verify='<same as above i.e. Windows path to .cer>')
It is failing with below errors,
.
.
OSError: Tunnel connection failed: 502 notresolvable
.
.
.
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='google.com', port=443): Max retries exceeded with url: / (Caused by SSLError(SSLError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:749)'),))
As the log files are keeping updating, might need to stream it; Suggestion on this is highly appreciated.
Using Python 3.6.0 |Anaconda 4.3.1 (64-bit) on Windows 7.

Custom web server & self-signed certificate

First of all let me to say my knowledge of ssl and criptography protocols is very limited. Please be patient if I say something blatantly wrong :-) . Feel free to correct me!
I'm building a custom web server to be deployed inside an isolated local network; this is how I run my service (Python code):
ssl_context = ssl.create_default_context(ssl.Purpose.CLIENT_AUTH)
ssl_context.load_cert_chain(certfile='mykey.crt', keyfile='mykey.key')
... client connects to https port 443 ...
ssl_sock = ssl_context.wrap_socket(sock, server_side=True)
This is how I generated mykey.crt and mykey.key files:
$ openssl genrsa -des3 -out mykey.orig.key 2048
$ openssl rsa -in mykey.orig.key -out mykey.key
$ openssl req -new -key mykey.key -out mykey.csr
$ openssl x509 -req -days 3650 -in mykey.csr -signkey mykey.key -out mykey.crt
So far so good, my webserver works very well. But I have go past the "not secure" warning that Firefox rightfully shove in my face.
I'd like to install my self-signed certificate in the few clients that are going access my web server in order to permanently avoid the warning.
I followed every single certificate installation guide I was able to find but I absolutely cannot get Firefox (and Chrome) accept my certificate. And I get no error message whatsoever from the browsers.
I think I'm missing something in the certificate generation commands.
Somebody could help me?
Thanks a lot!
self-signed certificate can uses only for tests. You have to get the certificate from an 'Accredited certification authority'
2) check please : self-signed certificate need to has next data:
URL, address,
name,
email
3) you should use a certificate signed by a CA

Python SSL server gives me "501 Unsupported method GET"

I've followed this link to build a simple file server with SSL.
from http.server import HTTPServer, BaseHTTPRequestHandler
import ssl
httpd = HTTPServer(('localhost', 4443), BaseHTTPRequestHandler)
# openssl req -x509 -newkey rsa:2048 -keyout key.pem -out cert.pem -days 365
httpd.socket = ssl.wrap_socket (httpd.socket, keyfile="key.pem", certfile='cert.pem', server_side=True)
httpd.serve_forever()
I have created a certificate successfully, key.pem and cert.pem file paths are cool and I can start the server using python server.py. I am asked for a password, enter it, then it freezes for a bit and then it seems to run.
However, when I enter some URL such as https://localhost:4443/index.html I get 500 Unsupported method GET. Error code explanation: HTTPStatus.NOT_IMPLEMENTED - Server does not support this operation. Do I need to do something more to make my server serve the current directory? Until now I have just used python -m http.server 8000 (SimpleHTTPServer when on Mac.) I am using Python 3.
This is an will stay local so don't worry about the PEM files and the server script being exposed through it (if it worked!). I am also okay with the certificate being untrusted and instructed Chrome to visit the page anyway. I just need it to allow me to access camera without having to deploy my app somewhere with a legit cert.
From the docs:
class http.server.BaseHTTPRequestHandler(request, client_address, server)
This class is used to handle the HTTP requests that arrive at the server. By itself, it cannot respond to any actual HTTP requests; it must be subclassed to handle each request method (e.g. GET or POST).
Try using SimpleHTTPRequestHandler instead, eg,
httpd = socketserver.TCPServer(('localhost', 4443), SimpleHTTPRequestHandler)

Categories

Resources