diff options
| author | Tomasz Barański <yubizume@gmail.com> | 2018-07-04 11:06:57 +0200 |
|---|---|---|
| committer | Tomasz Barański <yubizume@gmail.com> | 2018-07-05 21:55:29 +0200 |
| commit | 7c816eb2077465a61cc2a94a950217b4635fa632 (patch) | |
| tree | fc0423c3a6b145fa527eedfce031ee891f64be7f | |
| parent | 51ad14d16c81a68c804cf094760a3fc3f32131a5 (diff) | |
| download | websockify-7c816eb2077465a61cc2a94a950217b4635fa632.tar.gz | |
Added command line options for minum SSL version and SSL ciphers
--ssl-version takes two possible values (tlsv1_1, tlsv1_2). Defaults
to tlsv1_1.
--ssl-ciphers takes allowed ciphers in the same format as
`openssl ciphers`.
Added options for 1.3 and the default ssl config
| -rw-r--r-- | websockify/websocketproxy.py | 58 |
1 files changed, 57 insertions, 1 deletions
diff --git a/websockify/websocketproxy.py b/websockify/websocketproxy.py index b8e3d99..a28542f 100644 --- a/websockify/websocketproxy.py +++ b/websockify/websocketproxy.py @@ -11,7 +11,7 @@ as taken from http://docs.python.org/dev/library/ssl.html#certificates ''' -import signal, socket, optparse, time, os, sys, subprocess, logging, errno +import signal, socket, optparse, time, os, sys, subprocess, logging, errno, ssl try: from socketserver import ForkingMixIn except ImportError: @@ -382,6 +382,53 @@ def _subprocess_setup(): signal.signal(signal.SIGPIPE, signal.SIG_DFL) +try : + # First try SSL options for Python 3.4 and above + SSL_OPTIONS = { + 'default': ssl.OP_ALL, + 'tlsv1_1': ssl.PROTOCOL_TLS | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | + ssl.OP_NO_TLSv1, + 'tlsv1_2': ssl.PROTOCOL_TLS | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | + ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1, + 'tlsv1_3': ssl.PROTOCOL_TLS | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | + ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1 | ssl.OP_NO_TLSv1_2, + } +except AttributeError: + try: + # Python 3.3 uses a different scheme for SSL options + # tlsv1_3 is not supported on older Python versions + SSL_OPTIONS = { + 'default': ssl.OP_ALL, + 'tlsv1_1': ssl.PROTOCOL_TLSv1 | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | + ssl.OP_NO_TLSv1, + 'tlsv1_2': ssl.PROTOCOL_TLSv1 | ssl.OP_NO_SSLv2 | ssl.OP_NO_SSLv3 | + ssl.OP_NO_TLSv1 | ssl.OP_NO_TLSv1_1, + } + except AttributeError: + # Python 2.6 does not support TLS v1.2, and uses a different scheme + # for SSL options + SSL_OPTIONS = { + 'default': ssl.PROTOCOL_SSLv23, + 'tlsv1_1': ssl.PROTOCOL_TLSv1, + } + +def select_ssl_version(version): + """Returns SSL options for the most secure TSL version available on this + Python version""" + if version in SSL_OPTIONS: + return SSL_OPTIONS[version] + else: + # It so happens that version names sorted lexicographically form a list + # from the least to the most secure + keys = list(SSL_OPTIONS.keys()) + keys.sort() + fallback = keys[-1] + logger = logging.getLogger(WebSocketProxy.log_prefix) + logger.warn("TLS version %s unsupported. Falling back to %s", + version, fallback) + + return SSL_OPTIONS[fallback] + def websockify_init(): # Setup basic logging to stderr. logger = logging.getLogger(WebSocketProxy.log_prefix) @@ -430,6 +477,12 @@ def websockify_init(): help="file of concatenated certificates of authorities trusted " "for validating clients (only effective with --verify-client). " "If omitted, system default list of CAs is used.") + parser.add_option("--ssl-version", type="choice", default="default", + choices=["default", "tlsv1_1", "tlsv1_2", "tlsv1_3"], action="store", + help="minimum TLS version to use (default, tlsv1_1, tlsv1_2, tlsv1_3)") + parser.add_option("--ssl-ciphers", action="store", + help="list of ciphers allowed for connection. For a list of " + "supported ciphers run `openssl ciphers`") parser.add_option("--unix-target", help="connect to unix socket target", metavar="FILE") parser.add_option("--inetd", @@ -480,6 +533,9 @@ def websockify_init(): (opts, args) = parser.parse_args() + opts.ssl_options = select_ssl_version(opts.ssl_version) + del opts.ssl_version + if opts.log_file: # Setup logging to user-specified file. opts.log_file = os.path.abspath(opts.log_file) |
