I already implemented a nice http:// and ws:/ based application using flask-socket.io and now I need do secure the system with SSL client certificate authentication. For https I could use a fastCGI configuration with flask-only funktionality. In order to bring back the web socket part, I will also need wss.
Do you have support for wss:// or can you propose a configuration for my use case?
What web server are you using? If you are using nginx, then you can let nginx handle the SSL communication with clients, but then when nginx connects to your Flask application using regular http:// and ws://.
I have lighttpd running the http part with fastCGI configuration. This is part of the handler:
from flup.server.fcgi import WSGIServer
if __name__ == '__main__':
WSGIServer(app).run()
I tested the socket system running with standalone:
wsapp = Flask(__name__+"ws")
app.config['SECRET_KEY'] = 'secret!'
socket = sio.SocketIO(app)
#=======RUN standalone================
if __name__ == '__main__':
app.debug = True
socket.run(app, host='0.0.0.0', port=8001)
I guess, I need nginx instead of lighttpd.
Thanks so far.
I like lighttpd a lot, but unfortunately it has no support for WebSockets. I believe there is an unofficial plugin that can do this, but I can't comment on it as I haven't used it.
So yes, my recommendation is that you give nginx a try.
If you are using nginx, then you can let nginx handle the SSL communication with clients, but then when nginx connects to your Flask application using regular http:// and ws://.
@miguelgrinberg I'm using the webserver included with socketio. From your comment, it sounds like this does not support SSL (I want to use it for encryption to the client)? I will need to use nginx as a front end?
I successfully used nginx with reverse proxy as external ssl secured access point, internally flask is running on as gevent. like described here: https://flask-socketio.readthedocs.org/en/latest/
@hackscribble I haven't tried, but I believe you can pass your SSL options (see http://www.gevent.org/gevent.server.html) directly into the socketio.run(), as these should make it up to the appropriate base class within gevent.
My recommendation, however, is to use nginx and terminate the SSL connection before it reaches the Python server, that is a simpler set up in my opinion.
Thank you @miguelgrinberg and @pokulo. Based on your comments and the nginx configuration file in post https://github.com/miguelgrinberg/Flask-SocketIO/issues/22, I have now got nginx and SSL working. Http requests get redirected as https, and both static pages and sockets are forwarded to gevent to be served.
As suggested in the other post, I had to upgrade nginx to a more recent version - could not get pre-built versions working so compiled version 1.8.0 from source.
In case it helps anyone, my nginx site file is ...
server {
listen 80;
server_name hackscribble.net;
return 301 https://$server_name$request_uri;
}
server {
listen 443;
server_name hackscribble.net;
access_log /var/log/nginx/test-mqtt;
ssl on;
ssl_certificate /etc/nginx/ssl/server.crt;
ssl_certificate_key /etc/nginx/ssl/server.key;
ssl_session_timeout 5m;
ssl_protocols SSLv3 TLSv1;
ssl_ciphers ALL:!ADH:!EXPORT56:!RC4+RSA:+HIGH:+MEDIUM:+LOW:+SSLv3:+EXP;
ssl_prefer_server_ciphers on;
location /socket.io {
proxy_pass http://127.0.0.1:5000/socket.io;
proxy_redirect off;
proxy_buffering off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
proxy_http_version 1.1;
proxy_set_header Upgrade $http_upgrade;
proxy_set_header Connection "Upgrade";
}
location / {
proxy_pass http://127.0.0.1:5000;
proxy_redirect off;
proxy_set_header Host $host;
proxy_set_header X-Real-IP $remote_addr;
proxy_set_header X-Forwarded-For $proxy_add_x_forwarded_for;
}
}
I was also trying to implement socketio over https. But the problem is that I am using apache2, so any connection that is not on htttps is termed as unsafe. I read the link you posted for gevent ssl certificate, but I couldn't understand that which instanct should I pass in ssl.wrap_socket(), the first argument should be a socket object which will be encrypted. If I pass socketio instance, it is not working
@deveshaggrawal19 I don't have any supported configuration for Flask-SocketIO with Apache2, at least not when using mod_wsgi. You may have better luck if you use Apache2 as a HTTP reverse proxy, and in that case, the same recommendation I made above applies, just terminate the SSL with Apache, and let the SocketIO server run w/o encryption.
Most helpful comment
Thank you @miguelgrinberg and @pokulo. Based on your comments and the nginx configuration file in post https://github.com/miguelgrinberg/Flask-SocketIO/issues/22, I have now got nginx and SSL working. Http requests get redirected as https, and both static pages and sockets are forwarded to gevent to be served.
As suggested in the other post, I had to upgrade nginx to a more recent version - could not get pre-built versions working so compiled version 1.8.0 from source.
In case it helps anyone, my nginx site file is ...