How can I implement a secure WebSocket (wss://) server in Python? - python

I want to serve a real-time stream that has to be securely encrypted due to sensitive data.
I've successfully got normal WebSockets streaming using both gevent and gunicorn as direct frontends, but now I need to make it secure, and am looking for either of these:
A server that can serve secure WebSocket connections that are proxied to (for example) gunicorn which listens for non-secure WebSocket connections.
A framework that can serve secure WebSocket connections directly. I've been looking at Tornado and believe it can handle it, but I'm still open to suggestions.
I use ZeroMQ for the PUB/SUB pattern. If there is a good WebSocket protocol implementation for ZeroMQ, that would be great.
Speed is not super important here as the number of connections will be low. However, the integrity of the data is important.

Assuming that you have your app running correctly over non-SSL Tornado WebSockets, change the listen call from:
app.listen(args.listen_port, args.listen_interface)
to:
app.listen(args.listen_port, args.listen_interface, ssl_options={
"certfile": os.path.join(lib_dir, "mydomain.crt"),
"keyfile": os.path.join(lib_dir, "mydomain.key"),
})
where "mydomain.crt" and "mydomain.key" are your usual SSL certificate files, and lib_dir is the directory they live in.
Don't forget to change the client to use "wss:"
Also note that the port you specify in the listen call will still be used if you specify ssl_options. i.e. it will not revert to listening on port 443.

You can check out the websockify project. Websockify is a proxy that allows a WebSockets capable browser to communicate with a raw binary TCP server. It does this by base64 encoding all traffic to/from the browser. However, the project is modular and the websocket.py file is a general WebSocket server that is designed to be extended (and there a couple of included tests that show how this works). It would be fairly easy to disable the base64 encoding if that is not needed for you project.
Websockify also includes a Javascript library 'websock.js' which is designed to interact with websockify. It will transparently fallback to using web-socket-js (Flash based) if the browser does not have native WebSocket support.
Websockify supports secure (TLS/wss) connections and also is able to answer Flash security policy requests inline on the same port.
Disclaimer: I made websockify.

Take a look at the standalone websockets server of the pywebsocket project supported by Google.
Note that this Python module uses CGIHTTPServer so you need to tweak it to make it secure. I had a similar requirement for a project I was involved in some months ago, so I forked the standalone.py module and removed the dependencies with CGI stuff but I haven't tested secure connections very much.
Maybe you can import OpenSSL.SSL and set up a WebSocketServer as it is in my script. It should use a WebSocketRequestHandler with the proper configuration of use_tls, private_key and certificate in order to implement TLS (Transport Layer Security).
Read the source code. I think you can extend it to meet your needs.

We use Tornado and Tornadio for our realtime app, and I just switched on SSL for websockets, as well as all the other realtime socket.io protocols. It took me just over an hour! more info here:
http://devblog.resolversystems.com/?p=1084

In server side add this to Tornado:
tornadio2.server.SocketServer(application, ssl_options={
"certfile": "server.crt",
"keyfile": "server.key",
})
In client side, refer to this link:
wss://www.example.com:2201/ws, where the 2201 is the secure Websocket's TLS port.

Related

issue in sending realtime data from esp32 to Django webpage

I am having trouble in sending data from tcp client in my esp32 board to my python django server,I am not familiar with setting channels in Django ,is there a way so that i can send the data and display in my page?
in order for your microcontroller (esp32) communicate with your own server side code first you need to define protocol you're going to use:
A. TCP:
TCP relies on IP which provides address to communicate between computers. TCP/IP is a basis for internet and other networks.
B. HTTP:
HTTP mostly used by browser (IE, Google Chrome). It rides on top of TCP which provides a safe and reliable link between two computers because if packet get lost - it can be safely re-transmitted.
After deciding protocol that you're going to use now you need suitable server side code. In python there are several library / framework that you can use:
A. HTTP:
Django, Flask, AIOHTTP (all of this supports sending and receiving JSON (REST)), I preferably use one of this framework for my IoT Projects.
B. TCP: If your microcontroller is very minimal and doesn't support HTTP/JSON, you can use a simple SocketServer or Tornado TCP Server. Don't worry even though communication between your board and server done through TCP you can still import django's libraries and use django's ORM.

How do I use a browser as a client in python sockets?

I tried to search in the internet for this subject, But I didn't found some answers.
If some know how can I use a browser as a client in python sockets it will be very good.
To use the browser as a client to a python (server) socket, you simply need to point it to the right endpoint.
Assuming you are running the browser and the python server on the same machine, and that you're opening port 1234 on the server socket, you simply need to open the localhost:1234 URL in your browser.
Of course, what happens next is entirely dependent on how you handle the communication in your program. Most browsers will understand plain text put directly on the socket, but you probably want to talk HTTP.
It's worth mentioning that using a plain socket to communicate with a browser is, at best, uncommon. There may be better solutions, depending on what, exactly, you want to do:
If you just want to quickly serve a few files from a directory (i.e.: often
called a "directory listing"), you can use SimpleHTTPServer
If you're trying to build a website, you should look into a web framework, such as Django, Flask or CherryPy
If you want a lower-level highly asynchronous scalable communication, Tornado is a popular choice
You might want to consider using websockets. They essentially function like regular TCP sockets, but are initiated with a HTTP handshake, making them suitable for browsers. They are supported in recent versions of all major browsers. There are many libraries available that adapt common python webservers to serve websockets as well, for example:
https://pypi.python.org/pypi/gevent-websocket/
if you like gevent.
They also support an SSL layer, which is called using a url starting with "wss://" on the browser side. More information here:
https://www.websocket.org/

High level Python library for using Websocket and Comet "fallback" transparently

I'm looking for a High Level Python library for establishing HTTP connections to a Web server.
The connections should ideally remain open (persistant) for sending and receiving two-ways messages, so Websocket are great to me.
As I want it to be compatible will most HTTP proxies, I think about a "fallback" mode with HTTP polling (Comet style).
My problem is I can't find a library for managing these two kinds of connections transparently. Ideally, I would establish the connection to the server with one of the techniques (Websocket or Comet), then simply send/receive messages using the same functions for both types of connections.
I found many Python servers and some Js clients for that purpose, but not in Python.
I looked at : Twisted, Tornado, ZeroMQ, py4ws
Have you taken a look at socket.io? It mainly works with websockets but has plenty of fallbacks and is thus supposed to be supported by all browsers.
For the server side, I've used flask together with gevent-socketio. Miquel Gringberg has recently released flask-socketio extension which is a nice abstraction for working with flask and gevent-socketio. Gevent-socketio is built on the nice gevent library.
gevent-socketio should work fine with other Python frameworks, such as Django and Bottle.
I'm not entirely sure if this fits your bill but probably worth a look.
I think Python Socket-IO client could be a good solution :
https://github.com/invisibleroads/socketIO-client
He can interact easily with a Socket.io NodeJs server, with same paradigms.
I tested it and it can default with Websocket connection and fallbacks to xhr-polling, which is great (I actually tested this features through a proxy).
Example :
with SocketIO('http://127.0.0.1', 7777, Namespace, transports=["websocket", "xhr-polling"], proxies={'http': 'http://localhost:8888'}) as socketIO:
socketIO.on('foo',some_callback_function)
socketIO.emit('bar')
socketIO.wait()

How can I setup an Autobahn Pub/Sub Server and a Autobahn Webserver listening on the same port

I recently discovered autobahn python and js as a comfortable method to establish a pub/sub server and corresponding client even with rpc-calls.
After looking through the tutorials, I set up a test version with a websocket server and a webserver running on the same port. The server sends periodically data to the client via websockets. The html the user gets lies on the localhost root. All that works fine.
However, what I want to accomplish is: Setup a pub/sub server and a webserver listening on the same port.
The tutorials show only how to setup these on two different ports (as shown at http://autobahn.ws/python/tutorials/pubsub).
Im very new to python in general and autobahn and twisted especially.
Any advice would be really nice!
Thanks very much!
Marc
Sure. You can run a WAMP/WebSocket server and a plain old Web server on one port using Autobahn. Here is an example for pure WebSocket and here is one for WAMP.
Disclaimer: I am author of Autobahn and work for Tavendo.
When using WAMP while having HTTP and WS servers listening on the same port you will need to start your instance of WampServerFactory manually as explained here.
factory = WampServerFactory("ws://localhost:8080")
factory.protocol = YourServerProtocolClass
factory.startFactory() # <--- need to call this manually
resource = WebSocketResource(factory)
root = File(".")
root.putChild("ws", resource)
For more details please see this complete example.
I would put nginx as a frontend that forwards each call either to pubsub or to web... Recent Nginx supports WebSocket forwarding.
Or you man write something similar with Twisted :)
Another alternative would be to adapt autobahn.websocket.WebSocketServerProtocol and its subclass autobahn.wamp.WampServerProtocol to Twisted.web. It should be possible.

Implement a Web based Client that interacts with a TCP Server

EDIT:Question Updated. Thanks Slott.
I have a TCP Server in Python.
It is a server with asynchronous behaviour. .
The message format is Binary Data.
Currently I have a python client that interacts with the code.
What I want to be able to do eventually implement a Web based Front End to this client.
I just wanted to know , what should be correct design for such an application.
Start with any WSGI-based web server. werkzeug is a choice.
The Asynchronous TCP/IP is a seriously complicated problem. HTTP is synchronous. So using the synchronous web server presenting some asynchronous data is always a problem. Always.
The best you can do is to buffer things and have two processes in your web application.
TCP/IP process that collects data from the remove server and buffers it in a file (or files) somewhere.
WSGI web process which handles GET/POST processing.
GET requests will fetch some or all of the buffer and display it.
POST requests will send a message to the TCP/IP server.
For Web-based, talk HTTP. Use JSON or XML as data formats.
Be standards-compliant and make use of the vast number of libraries out there. Don't reinvent the wheel. This way you have less headaches in the long run.
if you need to maintain a connection to a backend server across multiple HTTP requests, Twisted's HTTP server is an ideal choice, since it's built to manage multiple connections easily.

Categories

Resources