The python ssl module makes it trivial to wrap tcp sockets.
As part of fixing websockify + ssl (#1213), it would be nice to re-use the same code for supporting SSL natively in our TCP sockets and the websockify code.
Something like:
xpra start --bind-ssl=IP:PORT
And client side:
xpra attach ssl:HOST:PORT
Other arguments we will need for configuring SSL, mirroring websockify and the ssl module but with a "ssl" prefix:
--ssl-cert=CERT
--ssl-key=KEY
--ssl-version=VERSION
--ssl-cert-reqs=REQS
--ssl-ca-certs=FILE
--ssl-ciphers=CIPHERS
Or maybe we can support ssl on all tcp server sockets with a --ssl=on
switch in the same way that we support websockets for --html=on
.
Milestone renamed
See also: #1255 for smartcard integration which is possible in openssl.
work in progress - ugly but working
The patch above needs work and testing, but kinda works.
openssl req -new -x509 -nodes -out cert.pem -keyout cert.pem
xpra start --start=xterm --bind-ssl=0.0.0.0:10000 --ssl-cert=./cert.pem
xpra attach ssl:127.0.0.1:10000 --ssl-server-verify-mode=none
Still todo:
xpras://.../
url handler
Mostly done in r13100 + r13101, this includes the ssl
flag (defaults to "auto") for multiplexing ssl traffic through the same tcp socket.
So this is now enough to start a server with both TCP and SSL support on the same port:
xpra start --start=xterm --bind-tcp=0.0.0.0:10000 --ssl-cert=`pwd`/cert.pem
Still todo:
ssl/username:password@HOST:PORT
client connection string from win32 and osx
Still todo:
sslcontext done in r13114.
That's enough for a first round of testing and feedback.
Still todo:
Some more minor tweaks: r13151, r13152, r13155, r13156, r13157, r13160.
Tested the latest beta on centos 6.x and 7.x, without problems.
But on centos6, you need one more thing configured to workaround the limitations of the old / narrower API: unless the client provides a certificate, add --ssl-client-verify=none
to prevent the server from trying to load the CA certs used to validate the client connection (and failing).
Some notes on interoperability with stunnel. You can easily wrap a regular TCP server with stunnel:
xpra start --start=xterm --bind-tcp=0.0.0.0:10000
cat > stunnel.conf <<EOF [xpra] accept = 10001 connect = 10000 cert = cert.pem verify = 0 EOF
You can then connect to the SSL server on port 10001 using the connection string ssl:127.0.0.1:10001
Or you could start another stunnel instance at the client end, and connect to that via TCP.
The SSL wiki page has been moved here: wiki/Encryption/SSL.
XPRA_USE_SSL_CONTEXT=0 xpra attach ...
.
See wiki/Encryption/SSL.
r13544 allows us to use "xor" authentication mode with ssl connections, so now we can also use the "sys" authentication modules (pam / win32) with ssl.
The "ssl" config option can now contain the following values: "on", "off", "auto", "tcp", "www". See ticket:1213#comment:5.
Hmm, trying with a self-signed cert as mentioned above, with a 1.0.7 r16004 fedora 25 server, I keep getting an SSL socket create error.
[jimador@Fedora25-Server-415 ~]$ xpra --no-daemon --bind-tcp=0.0.0.0:1234 --ssl-cert=/home/jimador/cert/jimador.pem --ssl=on --start-child=xterm start :13 using systemd-run to wrap 'start' server command 'systemd-run' '--description' 'xpra-start' '--scope' '--user' '/usr/bin/xpra' '--bind-tcp=0.0.0.0:1234' '--ssl-cert=/home/jimador/cert/jimador.pem' '--ssl=on' '--start-child=xterm' 'start' ':13' '--daemon=no' '--systemd-run=no' Running scope as unit: run-r31c9b2bc84104066ab6bf45382d4e6f9.scope xpra initialization error: cannot create SSL socket (check your certificate paths): [SSL] PEM lib (_ssl.c:2718)
The absolute path is correct though.
[jimador@Fedora25-Server-415 ~]$ ls /home/jimador/cert/ csr-maker jimador.key jimador.pem simple-jimador
I'm getting the same error even when the absolute path is wrong, however, so I feel like maybe there's a detail I overlooked in enabling the ssl on this VM?
I dnf installed mod_ssl openssl, and restarted /bin/systemctl httpd.service, but saw no sign of anything else that looked required.
Thinking that the above method of generating certs might be the issue, since I took so long to find time to test this and as of Chrome 58 subjectAltName is required for the browser to deem a cert as secure (I'm having the problems just launching, so it seemed unlikely, but just in case) I also tried a number of experiments along the lines of the following: https://serverfault.com/questions/707458/self-signed-cert-with-subject-alternative-names).
Is there something I'm missing in the fedora 25 to enable the handling of ssl?
I dnf installed mod_ssl openssl, and restarted /bin/systemctl httpd.service, but saw no sign of anything else that looked required.
We don't use apache or mod ssl at all.
I followed the steps in comment:3 and it worked fine. Tested with both 1.0 branch and trunk.
Here it is again, fully scripted:
cat > cert-params.conf <<EOF [req] default_bits = 2048 prompt = no default_md = sha256 distinguished_name = dn [ dn ] C=US O=End Point OU=Testing Domain CN = localhost EOF openssl req -new -x509 -nodes -out cert.pem -keyout cert.pem -config ./cert-params.conf xpra start --start=xterm --bind-ssl=0.0.0.0:10000 --ssl-cert=./cert.pem --no-daemon
(PS: ssl does support relative paths - I had fixed that already)
Note: if you want to connect with a browser rather than the client in ssl mode, see comment:10.
The cert-params.cnf that I generated using your example still shows no sujectAltName in the cert that is generated, but I just gave up and re-installed chrome 57.
As long as I read the instructions and use --ssl=www, rather than =on, that worked with the html5 client (against the same 1.0.7 r16004 fedora 25 server).
Likewise, as long as I use the --ssl-server-verify-mode=none
parameter with the 1.0.2 r14780 windows client, the client connects with --ssl=on (attempts to import the .pem created with your instructions fail with windows 7, it insists that 'This file is invalid for use as the following: Security Certificate', but I was able to import it with a 10.12 OSX client to go with the chrome 57 connection).
At this point I suspect that the issues I'm seeing are more related to my lack of knowledge of the fine points of cert generation/installation rather than with the xpra use of the certs... so I think this can probably be closed and new tickets opened for any issues that come up.
Since I seem to have forgotten to re-assign this back to you to close, I figured I'd try some of the less obvious combinations you'd listed before correcting that oversight.
xpra --no-daemon --bind-ssl=0.0.0.0:1234 --ssl-cert=/home/jimador/cert/jimador.pem --ssl=off --start-child=xterm start :13
... and then trying to connect with
./xpra attach tcp:10.0.32.138:1234 -d auth
The client fails to connect with the following message:
2017-06-08 15:00:29,775 Error: failed to receive anything, not an xpra server? 2017-06-08 15:00:29,775 could also be the wrong protocol, username, password or port 2017-06-08 15:00:29,775 Connection lost
... and trying to connect instead with ./xpra attach ssl:10.0.32.138:1234 -d auth
, I get a cert error - connection failed: [SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed (_ssl.c:661)
.
This isn't really very surprising, but it does make me wonder what the --ssl=off
flag is meant to do? (Maybe just a warning about bind-ssl use in conjunction with --ssl=off?).
Seeing the same behavior with bind-ssl and ssl=tcp
, just in case that strange combination ought to be accounted for.
And, as one last interesting note - it looks like the bind-tcp with --ssl=www works for both the client and the html client (to my mild surprise, that was the only combination that allowed me, with the client, to connect without using the --ssl-server-verify-mode=none
client-side flag).
And, with those last details, I'll pass this back to you to (probably) close.
This isn't really very surprising, but it does make me wonder what the --ssl=off flag is meant to do?
The ssl flag is fully documented in the man page:
--ssl=on|auto|off|tcp|www Whether to enable SSL on TCP sockets and for what purpose. The TCP sockets will automatically be upgraded to SSL when SSL packets are received. * auto: The server will try to guess what protocol to use for each new SSL connection: either xpra's native protocol or https / websocket (wss) * tcp: The SSL sockets will only be used for xpra's native protocol * www: The SSL sockets will only be used for https and websocket (wss)
it looks like the bind-tcp with --ssl=www works for both the client and the html client (to my mild surprise, that was the only combination that allowed me, with the client, to connect without using the --ssl-server-verify-mode=none client-side flag
Then my guess is that you connected with a plain tcp client connection string, not an ssl one.
Addendum: wiki/Encryption/SSL has been updated, here's the simplest way of using SSL safely without a CA:
openssl req -new -x509 -days 365 -nodes -out cert.pem -keyout key.pem -sha256 cat key.pem cert.pem > ssl-cert.pem xpra start --start=xterm --bind-tcp=0.0.0.0:10000 --ssl-cert=ssl-cert.pem -d ssl #this is equivalent to #xpra start --start=xterm --bind-tcp=0.0.0.0:10000 --ssl-cert=cert.pem --ssl-key=key.pem -d ssl
cert.pem
to the client and run:
xpra attach ssl://server:10000 --ssl-ca-certs=./cert.pem -d ssl
OR convert this cert data into a string and use that:
CADATA=`python -c "import sys,base64;print(base64.b64encode(open(sys.argv[1]).read()))" cert.pem` xpra attach ssl://server:10000 --ssl-ca-data=$CADATA -d ssl
This option is much more useful for using SSL with xpra URLs (#1894) or .xpra
connection files.
We now generate split cert and key: r20177.
this ticket has been moved to: https://github.com/Xpra-org/xpra/issues/1252