Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

native ssl support #1252

Closed
totaam opened this issue Jul 12, 2016 · 19 comments
Closed

native ssl support #1252

totaam opened this issue Jul 12, 2016 · 19 comments

Comments

@totaam
Copy link
Collaborator

totaam commented Jul 12, 2016

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
@totaam
Copy link
Collaborator Author

totaam commented Jul 12, 2016

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.

@totaam
Copy link
Collaborator Author

totaam commented Jul 12, 2016

See also: #1255 for smartcard integration which is possible in openssl.

@totaam
Copy link
Collaborator Author

totaam commented Jul 23, 2016

2016-07-23 23:44:20: antoine uploaded file ssl-v4.patch (20.2 KiB)

work in progress - ugly but working

@totaam
Copy link
Collaborator Author

totaam commented Jul 23, 2016

The patch above needs work and testing, but kinda works.

  • generate a cert:
openssl req -new -x509 -nodes -out cert.pem -keyout cert.pem
  • start a server with an ssl socket:
xpra start --start=xterm --bind-ssl=0.0.0.0:10000 --ssl-cert=./cert.pem
  • start a client:
xpra attach ssl:127.0.0.1:10000 --ssl-server-verify-mode=none

Still todo:

  • python < 2.7.9 compat (no ciphers argument)
  • xpras://.../ url handler
  • ssl=on flag and divert ssl traffic to ssl handler from tcp sockets (same as html=on for http)

@totaam
Copy link
Collaborator Author

totaam commented Jul 27, 2016

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:

  • url handler
  • testing on osx / win32, centos6 (python 2.6)
  • testing with valid certs and ca chain
  • man page and wiki updates
  • use SSLContext to force compression off, etc..

@totaam
Copy link
Collaborator Author

totaam commented Jul 28, 2016

  • minor rpm packaging fix r13105
  • url handler and packaging updates added in r13106 (tested on Fedora and win32)
  • tested ssl/username:password@HOST:PORT client connection string from win32 and osx
  • man page updates in r13112
  • wiki updated: Encryption

Still todo:

  • sslcontext and handling for extra options

@totaam
Copy link
Collaborator Author

totaam commented Jul 28, 2016

sslcontext done in r13114.

That's enough for a first round of testing and feedback.

Still todo:

  • win32 / osx and certification authorities: do we ship the ca cert file?
  • better debug logging?
  • auto-upgrade for clients (specify tcp but get ssl if server supports it)

@totaam
Copy link
Collaborator Author

totaam commented Aug 1, 2016

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
```shell
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: [Encryption SSL](../wiki/Encryption-SSL). 

@totaam
Copy link
Collaborator Author

totaam commented Aug 9, 2016

  • more minor updates: r13285 + r13286 allow us to handle cadata using strings
  • r13288 does the same thing for the legacy python ssl module
  • r13287 makes it easier to test the legacy interface: XPRA_USE_SSL_CONTEXT=0 xpra attach ....
  • r13294 + r13295 fix some ssl bugs in the launcher

See Encryption SSL.

@totaam
Copy link
Collaborator Author

totaam commented Sep 5, 2016

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.

@totaam
Copy link
Collaborator Author

totaam commented Sep 8, 2016

The "ssl" config option can now contain the following values: "on", "off", "auto", "tcp", "www". See #1213#comment:5.

@totaam
Copy link
Collaborator Author

totaam commented Jun 3, 2017

2017-06-03 01:17:28: afarr commented


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:
http://blog.endpoint.com/2014/10/openssl-csr-with-alternative-names-one.html ... but to no avail (well, I was able to generate a .csr that had the subjectAltName, but never quite figured out how to then sign using -extfile {filename} appending along the lines of 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?

@totaam
Copy link
Collaborator Author

totaam commented Jun 3, 2017

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.

@totaam
Copy link
Collaborator Author

totaam commented Jun 7, 2017

2017-06-07 00:41:12: afarr commented


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 14780 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.

@totaam
Copy link
Collaborator Author

totaam commented Jun 8, 2017

2017-06-08 23:35:31: afarr commented


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.

  • Launching with
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.

@totaam
Copy link
Collaborator Author

totaam commented Jun 9, 2017

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.

@totaam totaam closed this as completed Jun 9, 2017
@totaam
Copy link
Collaborator Author

totaam commented Aug 3, 2017

See also #1213, #1504

@totaam
Copy link
Collaborator Author

totaam commented Aug 23, 2018

Addendum: Encryption SSL has been updated, here's the simplest way of using SSL safely without a CA:

  • generate the cert and start the server:
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
  • either copy the 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.

@totaam
Copy link
Collaborator Author

totaam commented Jul 8, 2024

See also: #3305, #3299, #4288, #3313

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant