As the title states, I'd like to figure out how to use SNI (server name indication) with the tornado webserver.
I'd like to be able to present a particular certificate based on the hostname of the given request.
After looking more into this I found the solution using a sni_callback from ssl.SSLContext.
That will give you a method that contains the hostname before a TLS handshake is established.
Within the servername_callback method you can then chose what certificate to load based on the hostname.
Working solution
import tornado.ioloop
import tornado.web
import tornado.httpserver
import ssl
class MainHandler(tornado.web.RequestHandler):
def get(self):
self.write('Hello, world')
application = tornado.web.Application([
(r'/', MainHandler)
])
def servername_callback(sock, hostname, cb_context):
# hostname contains the hostname that the client is requesting
print("hostname", hostname)
# now that we have the hostname we can dynamically pick the correct certificate
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
# this part is up to you to store via a config file or even in a database
ssl_context.load_cert_chain(certfile="/path/to/cert", keyfile="/path/to/key")
sock.context = ssl_context
if __name__ == '__main__':
ssl_context = ssl.SSLContext(ssl.PROTOCOL_TLSv1_2)
ssl_context.sni_callback = servername_callback
http_server = tornado.httpserver.HTTPServer(application, ssl_options=ssl_context)
http_server.listen(443)
tornado.ioloop.IOLoop.instance().start()
Related
I am using UAExpert application and i am connecting to my machine with these settings:
I want to connect to my device with python.
I have this code but it doesn't work.
from opcua import Client
client = Client("opc.tcp://<ip>:4840")
client.set_user("username")
client.set_password("password")
client.set_security_string("Basic256Sha256,Sign,cert.der,key.pem")
client.connect()
I am getting this error:
raise ua.UaError("No matching endpoints: {0}, {1}".format(security_mode, policy_uri))
opcua.ua.uaerrors._base.UaError: No matching endpoints: 2, http://opcfoundation.org/UA/SecurityPolicy#Basic256Sha256
UPDATE:
I think it's the issue of the certificate. So i found from UAExpert settings where it gets the certificate from.
I use the same path for cert.der but i don't know where i can find the key.pem
Ok so i made it work. This is my current code:
import asyncio
import opcua
async def main():
client = opcua.Client("opc.tcp://<ip>:4840", timeout=60)
client.application_uri = "urn:<ip>:UPS1600" # Should match in your certificate
client.set_user("username")
client.set_password("password")
client.set_security_string("Basic256Sha256,SignAndEncrypt,<path_to_certificate.pem>,<path_to_key.pem")
client.connect()
struct = client.get_node("ns=3;i=100191")
value= struct.get_value()
print(value)
if __name__ == '__main__':
asyncio.run(main())
Where certificate.pem and key.pem i have created them from
here
I'm trying to make a simple program that checks if a connection (to localhost) is HTTP, Socks4 or Socks5.
(I mean connection in the sense of a proxy connection)
import waitress
import flask
app = flask.Flask(__name__)
#app.route("/")
def use_proxy():
# check proxy connection type as string
return string
if __name__ == "__main__":
print("Serving server on 8888.")
waitress.serve(app, host="localhost", port=8888)
How can I get this string?, I'm guessing it could be through the headers.
I have python_socketio 5.0.4 on client and Flask-SocketIO 5.0.1 on server. When client connects to server, I would like to synchronize client's SID between client and server. However, when I print SID on client, it's different from SID printed on server.
Is there any way to make SID of client same on server as on client?
Here is code for client:
import socketio
sio = socketio.Client()
sio.connect("http://localhost:5000")
print(sio.sid) # czNJ6NXIAXP9-vgmAAAK
sio.emit("test_event")
And here for server:
from flask import Flask, request
from flask_socketio import SocketIO
app = Flask(__name__)
sio = SocketIO(app)
#sio.on("test_event")
def test_event():
print(request.sid) # ukJhK9ZIiXY_gTMAAAL <--- this is different SID
sio.run(app)
The problem is that in the client you are accessing your sid as sio.sid. The sid property of the Socket.IO client is private, it is not supposed to be used.
Instead, use the sio.get_sid() method to obtain the sid. This used to not be a problem, but in the latest revision of the Socket.IO protocol each namespace is required to have a different sid, so the get_sid() method should be used to obtain the correct one for your namespace.
If you were using a non-default namespace you can pass it as an argument as follows: sio.get_sid(namespace='/my-namespace').
I'm trying to write a twisted https client, that uses a client certificate for authentication. This is the example from the twisted docs for making a simple https request:
from __future__ import print_function
from twisted.internet import reactor
from twisted.web.client import Agent
from twisted.web.http_headers import Headers
agent = Agent(reactor)
d = agent.request(
b'GET',
b'https://127.0.0.1:8880/test',
Headers({'User-Agent': ['Twisted Web Client Example']}),
None)
def cbResponse(ignored):
print('Response received')
d.addCallback(cbResponse)
def cbShutdown(ignored):
reactor.stop()
d.addBoth(cbShutdown)
reactor.run()
I've found this explanation on how to use a client with ssl certificates. I have no idea though, how I can tell the agent to use a certificate for authentication. Any ideas?
Construct Agent with an IPolicyForHTTPS which can create a contextFactory to provide a client certificate to the TLS connection.
certData = getModule(__name__).filePath.sibling('public.pem').getContent()
authData = getModule(__name__).filePath.sibling('server.pem').getContent()
clientCertificate = ssl.PrivateCertificate.loadPEM(authData)
authority = ssl.Certificate.loadPEM(certData)
options = ssl.optionsForClientTLS(u'example.com', authority,
clientCertificate)
class SinglePolicy(object):
def creatorForNetloc(self, hostname, port):
return options
agent = Agent(reactor, SinglePolicy())
we have this mockserver that is now serving https:// requests, and if we remove the ssl wrapping (ssl.wrap_socket(myServer.socket,keyfile='key.pem',certfile= 'cert.pem', server_side=True), the server only serves http:// requests. Is there any way where we can make this server to support both requests. Our objective is when the server receives an http:// request, it will automatically convert it as https:// and process the request.
Thanks in advance for the support
from http.server import HTTPServer, BaseHTTPRequestHandler
import ssl
class Mock(BaseHTTPRequestHandler):
-------------------
-------------------
def main():
global hostname, port
hostname = "127.0.0.1"
port = 8000
myServer = HTTPServer((hostname, port), Mock)
myServer.socket = ssl.wrap_socket(myServer.socket,keyfile='key.pem',certfile= 'cert.pem', server_side=True)
myServer.serve_forever()
if __name__ =="__main__":
main()
If the HTTP and HTTPS servers need different functionality, then it makes sense to make them two different instances. Why not make a second HTTPServer that is only HTTP that simply returns a 302 status with the Location header pointing to the HTTPS mock server (but using the same path).