{ "info": { "author": "Yulian Oifa, Baranov Volodymyr", "author_email": "vladimir.baranov@mobius-software.com", "bugtrack_url": null, "classifiers": [ "Development Status :: 5 - Production/Stable", "Intended Audience :: Developers", "License :: OSI Approved :: Apache Software License", "Operating System :: Microsoft :: Windows", "Operating System :: POSIX :: Linux", "Programming Language :: Python :: 3.5", "Topic :: Security :: Cryptography", "Topic :: Software Development :: Libraries :: Python Modules" ], "description": "Datagram Transport Layer Security for Python\n============================================\n\nPyDTLS brings Datagram Transport Layer Security (DTLS - RFC 6347:\nhttp://tools.ietf.org/html/rfc6347) to the Python environment. In a\nnutshell, DTLS brings security (encryption, server authentication, user\nauthentication, and message authentication) to UDP datagram payloads in\na manner equivalent to what SSL/TLS does for TCP stream content.\n\nDTLS is now very easy to use in Python. If you're familiar with the ssl\nmodule in Python's standard library, you already know how. All it takes\nis passing a datagram/UDP socket to the *wrap\\_socket* function instead\nof a stream/TCP socket. Here's how one sets up the client side of a\nconnection:\n\n::\n\n import ssl\n from socket import socket, AF_INET, SOCK_DGRAM\n from dtls import do_patch\n do_patch()\n sock = ssl.wrap_socket(socket(AF_INET, SOCK_DGRAM))\n sock.connect(('foo.bar.com', 1234))\n sock.send('Hi there')\n\nAs of version 1.2.0, PyDTLS supports DTLS version 1.2 in addition to\nversion 1.0. This version also introduces forward secrecy using elliptic\ncurve cryptography and more fine-grained configuration options.\n\nInstallation\n------------\n\nTo install from PyPI, on any supported platform enter:\n\n::\n\n pip install python3-dtls\n\nDesign Goals\n------------\n\nThe primary design goal of PyDTLS is broad availability. It has\ntherefore been built to be widely compatible with the following:\n\n- Operating systems: apart from the Python standard library, PyDTLS\n relies on the OpenSSL library only. OpenSSL is widely ported, and in\n fact the Python standard library's *ssl* module also uses it.\n- Python runtime environments: PyDTLS is a package consisting of pure\n Python modules only. It should therefore be portable to many\n interpreters and runtime environments. It interfaces with OpenSSL\n strictly through the standard library's *ctypes* foreign function\n library.\n- The Python standard library: the standard library's *ssl* module is\n Python's de facto interface to SSL/TLS. PyDTLS aims to be compatible\n with the full public interface presented by this module. The ssl\n module ought to behave identically with respect to all of its\n functions and options when used in conjunction with PyDTLS and\n datagram sockets as when used without PyDTLS and stream sockets.\n- Connection-based protocols: as outlined below, layering security on\n top of datagram sockets requires introducing certain connection\n constructs normally absent from datagram sockets. These constructs\n have been added in such a way as to be compatible with code that\n expects to interoperate with connection-oriented stream sockets. For\n example, code that expects to go through server-side\n bind/listen/accept connection establishment should be reusable with\n PyDTLS sockets.\n\nDistributions\n-------------\n\nPyDTLS requires version 1.1.0 or higher of the OpenSSL library. Earlier\nversions are reported not to offer stable DTLS support. Since packaged\ndistributions of this version of OpenSSL are available for many popular\noperating systems, OpenSSL-1.1.0 is an installation requirement before\nPyDTLS functionality can be called.\n\nIn comparison, installation of OpenSSL on Microsoft Windows operating\nsystems is inconvenient. For this reason, source distributions of PyDTLS\nare available that include OpenSSL dll's for 32-bit and 64-bit Windows.\nAll dll's have been linked with the Visual Studio 2008 version of the\nMicrosoft C runtime library, msvcr90.dll, the version used by CPython\n3.5. Installation of Microsoft redistributable runtime packages should\ntherefore not be required on machines with CPython 3.5.\n\nThe OpenSSL version used by PyDTLS can be determined from the values of\n*sslconnection's* DTLS\\_OPENSSL\\_VERSION\\_NUMBER,\nDTLS\\_OPENSSL\\_VERSION, and DTLS\\_OPENSSL\\_VERSION\\_INFO. These\nvariables are available through the *ssl* module also if *do\\_patch* has\nbeen called (see below). Note that the OpenSSL version used by PyDTLS\nmay differ from the one used by the *ssl* module.\n\nInterfaces\n----------\n\nPyDTLS' top-level package, *dtls*, provides DTLS support through the\n**SSLConnection** class of its *sslconnection* module. **SSLConnection**\nis in-line documented, and dtls/test/echo\\_seq.py demonstrates how to\ntake a simple echo server through a listen/accept/echo/shutdown sequence\nusing this class. The corresponding client side can look like the\nsnippet at the top of this document, followed by a call to the *unwrap*\nmethod for shutdown (or a call to the **SSLConnection** *shutdown*\nmethod, if an instance of this class is used for the client side also).\nNote that the *dtls* package does not depend on the standard library's\n*ssl* module, and **SSLConnection** can therefore be used in\nenvironments where *ssl* is unavailable or incompatible.\n\nIt is expected that with the *ssl* module being an established, familiar\ninterface to TLS, it will be the preferred module through which to\naccess DTLS. To do so, one must call the *dtls* package's *do\\_patch*\nfunction before passing sockets of type SOCK\\_DGRAM to either *ssl's*\n*wrap\\_socket* function, or *ssl's* **SSLSocket** constructor.\n\nIt should be noted that once *do\\_patch* is called, *dtls* will raise\nexceptions of type **ssl.SSLError** instead of its default\n**dtls.err.SSLError**. This allows users' error handling code paths to\nremain identical when interfacing with *ssl* across stream and datagram\nsockets.\n\nConnection Handling\n-------------------\n\nThe DTLS protocol implies a connection as an association between two\nnetwork peers where the overall association state is characterized by\nthe handshake status of each peer endpoint (see RFC 6347). The OpenSSL\nlibrary records this handshake status in \"SSL\" type instances (a.k.a.\nstruct ssl\\_st). Datagrams can be securely sent and received by\nreferring to a unique \"SSL\" instance after handshaking has been\ncompleted with this instance and its network peer. A connection is\nimplied in that traffic may be directed to or received from only that\nnetwork peer with whose \"SSL\" instance the handshake has been completed.\nThe fact that the underlying network protocol, UDP in most cases, is\nitself connectionless is immaterial.\n\nFurther, in order to prevent denial-of-service attacks on UDP DTLS\nservers, clients must undergo a cookie exchange phase early in the\nhandshaking protocol, and before server-side resources are committed to\na particular client (see section 4.2.1 of RFC 6347). The cookie exchange\nproves to the server that a client can indeed receive IP traffic at the\nsource IP address with which its handshake-initiating ClientHello\ndatagram is marked.\n\nPyDTLS implements this connection establishment through the *connect*\nmethod on the client side, and the *accept* method on the server side.\nThe latter returns a new **dtls.SSLConnection** or **ssl.SSLSocket**\nobject (depending on which interface is used, see above), which is\n\"connected\" to its peer. In addition to the *read* and *write* methods\n(at both interface levels), **SSLSocket's** *send* and *recv* methods\ncan be used; use of *sendto* and *recvfrom* on connected sockets is\nprohibited by *ssl*. *accept* returns peer address information, as\nexpected. Note that when using the *ssl* interface to *dtls*, *listen*\nmust be called before calling *accept*.\n\nDemultiplexing\n--------------\n\nAt the network io layer, only datagrams from its connected peer must be\npassed to a **SSLConnection** or **SSLSocket** object (unless the object\nis unconnected on the server-side, in which case it can be in listening\nmode, the initial server-side socket whose role it is to listen for\nincoming client connection requests).\n\nThe initial server-side listening socket is not useful for performing\nthis datagram routing function. This is because it must remain\nunconnected and ready to receive additional connection requests from\nnew, unknown clients.\n\nThe function of passing incoming datagrams to the proper connection is\nperformed by the *dtls.demux* package. **SSLConnection** requests a new\nconnection from the demux when a handshake has cleared the cookie\nexchange phase. An efficient implementation of this request is provided\nby the *osnet* module of the demux package: it creates a new socket that\nis bound to the same network interface and port as the listening socket,\nbut connected to the peer. UDP stacks such as the one included with\nLinux route incoming datagrams to such a connected socket in preference\nto an unconnected socket bound to the same port.\n\nUnfortunately such is not the behavior on Microsoft Windows. Windows UDP\nroutes datagrams to whichever currently existing socket bound to the\nparticular port the earliest (and whether or not that socket is\nunconnected, or connected to the datagram's peer, or a different peer).\nOther sockets bound to the same port will not receive traffic, if and\nuntil they become the earliest bound socket because another socket is\nclosed.\n\nThe demux package therefore provides and automatically selects the\nmodule *router* on Windows platforms. This module also creates a new\nsocket when receiving a new connection request; but instead of binding\nthis socket to the same port as the listening socket, it binds to a new\nephemeral port. *router* then forwards datagrams originating from the\npeer for which a connection was requested to the corresponding socket.\n\nFor efficiency's sake, no forwarding is performed on outgoing traffic.\nInstead, **SSLConnection** directs outgoing traffic from the original\nlistening socket, using *sendto*. At the OpenSSL level this requires\nseparate read and write datagram BIO's for an \"SSL\" instance, one in\n\"connected\" state and one in \"peer set\" state, respectively, and\nassociated with two separate network sockets.\n\nFrom the perspective of a PyDTLS user, this selection of and difference\nbetween demux implementations should be transparent, with the possible\nexception of performance deviation. This transparency does however have\nsome limits: for example, when *router* is in use, the *accept* methods\ncan return *None*. This happens when **SSLConnection** detects that the\ndemux has forwarded a datagram to a known connection instead of\ninitiating a connection to a new peer through *accept*. Returning *None*\nin this case is important whenever non-blocking sockets or sockets with\ntimeouts are used, since another socket might now be readable as a\nresult of the forwarded datagram. *accept* must return so that the\napplication can iterate on its asynchronous *select* loop.\n\nShutdown and Unwrapping\n-----------------------\n\nPyDTLS implements the SSL/TLS shutdown protocol as it has been adapted\nfor DTLS. **SSLConnection's** *shutdown* and **SSLSocket's** *unwrap*\ninvoke this protocol. As is the case with DTLS handshaking in general,\napplications must be prepared to use the *get\\_timeout* and\n*handle\\_timeout* methods in addition to re-invoking *shutdown* or\n*unwrap* when sockets become readable and an exception carried\nSSL\\_ERROR\\_WANT\\_READ. (See more on asynchronous IO in the Testing\nsection.)\n\n**SSLConnection's** *shutdown* and **SSLSocket's** *unwrap* return a\n(possibly new) socket that can be used for unsecured communication with\nthe peer, as set forth by the *ssl* module. The demux infrastructure\nremains in use for this communication until the returned socket is\ncleaned up. Note that when the *router* demux is in use, the object\nreturned will be one derived from *socket.socket*. This is because the\nsend and recv paths must still be directed to two different OS sockets.\nIn addition, the right thing happens if secured communication is resumed\nover such a socket by passing it to *ssl.wrap\\_socket* or the\n**SSLConnection** constructor. If *osnet* is used, an actual\n*socket.socket* instance is returned.\n\nFramework Compatibility\n-----------------------\n\nPyDTLS sockets have been tested under the following usage modes:\n\n- Using blocking sockets and sockets with timeouts in multi-threaded\n UDP servers\n- Using non-blocking sockets, and in conjunction with the asynchronous\n socket handler, asyncore\n- Using blocking sockets, and in conjunction with the network server\n framework SocketServer - ThreadingTCPServer (this works because of\n PyDTLS's emulation of connection-related calls)\n\nMulti-thread Support\n--------------------\n\nUsing multiple threads with OpenSSL requires implementing a locking\ncallback. PyDTLS does implement this, and therefore multi-threaded\nprogramming with PyDTLS is safe in any environment. However, being a\npure Python library, these callbacks do carry some overhead. The *ssl*\nmodule implements an equivalent locking callback in its C extension\nmodule. Not requiring interpreter re-entry, this approach can be\nexpected to perform better. PyDTLS therefore queries OpenSSL as to\nwhether a locking callback is already in place, and does not overwrite\nit if there is. Loading *ssl* can therefore improve performance, even\nwhen only the *sslconnection* interface is used.\n\nNote that loading order does not matter: to obtain the performance\nbenefit, *ssl* can be loaded before or after the dtls package. This is\nbecause *ssl* does not do an equivalent existing locking callback check,\nand will simply overwrite the PyDTLS callback if it has already been\ninstalled. But *ssl* should not be loaded while *dtls* operation is\nalready in progress, when some locks may be in their acquired state.\n\nAlso note that this performance enhancement is available only on\nplatforms where PyDTLS loads the same OpenSSL shared object as *ssl*. On\nUbuntu 12.04, for example, this is the case, but on Microsoft Windows it\nis not.\n\nTesting\n-------\n\nA simple echo server is available to be executed from the project root\ndirectory with ``python3 -m dtls.test.echo_seq``. The echo server is\nreachable using the code snippet at the top of this document, using port\n28000 at \"localhost\".\n\nUnit test suites can be executed from the project root directory with\n``python3 -m dtls.test.unit [-v]`` and\n``python3 -m dtls.test.unit_wrapper`` (for the client and server\nwrappers)\n\nAlmost all of the Python standard library's *ssl* unit tests from the\nmodule *test\\_ssl.py* have been ported to *dtls.test.unit.py*. All tests\nhave been adjusted to operate with datagram sockets. On Linux, each test\nis executed four times, varying the address family among IPv4 and IPv6\nand the demux among *osnet* and *router*. On Windows, where *osnet* is\nunavailable, each test is run twice, once with IPv4 and once with IPv6.\n\nThe unit test suite includes tests for each of the above-mentioned\ncompatible frameworks. The class **AsyncoreEchoServer** serves as an\nexample of how to use non-blocking datagram sockets and implement the\nresulting timeout detection requirements. DTLS in general and OpenSSL in\nparticular require being called back when used with non-blocking sockets\n(or sockets with timeout option) after DTLS timeouts expire to handle\npacket loss using re-transmission during a handshake. Handshaking may\noccur during any read or write operation, even after an initial\nhandshake completes successfully, in case renegotiation is requested by\na peer.\n\nRunning with the -v switch executes all unit tests in verbose mode.\n\ndtls/test/test\\_perf.py implements an interactive performance test suite\nthat compares the raw throughput of TCP, UDP, SSL, and DTLS. It can be\nexecuted locally through the loopback interface, or between remote\nclients and servers. In the latter case, test jobs are sent to remote\nconnected clients whenever a suite run is initiated through the\ninteractive interface. Run test\\_perf.py -h for more information.\n\nIt should be noted that comparing the performance of protocols that\ndon't offer congestion control (UDP and DTLS) with those that do (TCP\nand SSL) is a difficult undertaking. Raw throughput even across gigabit\nnetwork links can be expected to suffer without congestion control and\npeers that generate data as fast as possible without throttling (as this\ntest does): the link's throughput will drop significantly as it enters\ncongestion collapse. Similarly, loopback is an imperfect test interface\nsince it rarely drops packets, and never duplicates or reorders them\n(thus negating the relative performance benefits of DTLS over SSL).\nNevertheless, some useful insights can be gained by observing the\noperation of test\\_perf.py, including software stack behavior in the\npresence of some amount of packet loss.\n\nLogging\n-------\n\nThe *dtls* package and its sub-packages log various occurrences,\nprimarily events that can aid debugging. Especially *router* emits many\nmessages when the logging level is set to at least *logging.DEBUG*.\ndtls/test/echo\\_seq.py activates this logging level during its\noperation.\n\n\n", "description_content_type": "", "docs_url": null, "download_url": "", "downloads": { "last_day": -1, "last_month": -1, "last_week": -1 }, "home_page": "https://github.com/mobius-software-ltd/pyton3-dtls", "keywords": "", "license": "Apache-2.0", "maintainer": "", "maintainer_email": "", "name": "python3-dtls", "package_url": "https://pypi.org/project/python3-dtls/", "platform": "", "project_url": "https://pypi.org/project/python3-dtls/", "project_urls": { "Homepage": "https://github.com/mobius-software-ltd/pyton3-dtls" }, "release_url": "https://pypi.org/project/python3-dtls/1.0.3/", "requires_dist": null, "requires_python": "", "summary": "Python Datagram Transport Layer Security", "version": "1.0.3" }, "last_serial": 4594154, "releases": { "1.0.2": [ { "comment_text": "", "digests": { "md5": "a90a1aad350ed886a7d2157ae9ababd9", "sha256": "ed9594da8553bc069609bc805a16f5ff02e04a3a25a95d17dabb435b643d3932" }, "downloads": -1, "filename": "python3_dtls-1.0.2-py3-none-any.whl", "has_sig": false, "md5_digest": "a90a1aad350ed886a7d2157ae9ababd9", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 99376, "upload_time": "2018-12-11T11:11:46", "url": "https://files.pythonhosted.org/packages/ba/89/c49fe7257aa544003a2b1b1da970a59291fec50ee97d4c06077fb138d7ed/python3_dtls-1.0.2-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "47621219c4ad639d7a4a134f56c42582", "sha256": "b2e2814c92fb2f02dc587a69467c3a54430c01abeff3a20eea7eafe6abc21c05" }, "downloads": -1, "filename": "python3-dtls-1.0.2.tar.gz", "has_sig": false, "md5_digest": "47621219c4ad639d7a4a134f56c42582", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 86726, "upload_time": "2018-12-11T11:11:48", "url": "https://files.pythonhosted.org/packages/21/aa/f32ccd58828bf34980eb545dc0b1d1643fd62e287a85f3fba6858e83b102/python3-dtls-1.0.2.tar.gz" } ], "1.0.3": [ { "comment_text": "", "digests": { "md5": "452532f3f78198d6f889f28773693a36", "sha256": "d3ea7865d718fefb2c445897514e5208a22888b1878eef991c76936d027583b6" }, "downloads": -1, "filename": "python3_dtls-1.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "452532f3f78198d6f889f28773693a36", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 99245, "upload_time": "2018-12-13T12:13:34", "url": "https://files.pythonhosted.org/packages/01/6c/22b421f665f9013ef6271dd8121ac63c6b7e48ffbab47fb2cc399d5ea6b6/python3_dtls-1.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4ed7b8c96e90e82e77cf93a3a95714db", "sha256": "eebda42739dc686411383320ed7ac59af02b71158cbf5d1b718edd9e80fe521c" }, "downloads": -1, "filename": "python3-dtls-1.0.3.tar.gz", "has_sig": false, "md5_digest": "4ed7b8c96e90e82e77cf93a3a95714db", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 86600, "upload_time": "2018-12-13T12:13:35", "url": "https://files.pythonhosted.org/packages/84/9e/1b3bd414d90f358b887bd1a1e7a7b1bb1a88d5a2017eb98b18d922192799/python3-dtls-1.0.3.tar.gz" } ] }, "urls": [ { "comment_text": "", "digests": { "md5": "452532f3f78198d6f889f28773693a36", "sha256": "d3ea7865d718fefb2c445897514e5208a22888b1878eef991c76936d027583b6" }, "downloads": -1, "filename": "python3_dtls-1.0.3-py3-none-any.whl", "has_sig": false, "md5_digest": "452532f3f78198d6f889f28773693a36", "packagetype": "bdist_wheel", "python_version": "py3", "requires_python": null, "size": 99245, "upload_time": "2018-12-13T12:13:34", "url": "https://files.pythonhosted.org/packages/01/6c/22b421f665f9013ef6271dd8121ac63c6b7e48ffbab47fb2cc399d5ea6b6/python3_dtls-1.0.3-py3-none-any.whl" }, { "comment_text": "", "digests": { "md5": "4ed7b8c96e90e82e77cf93a3a95714db", "sha256": "eebda42739dc686411383320ed7ac59af02b71158cbf5d1b718edd9e80fe521c" }, "downloads": -1, "filename": "python3-dtls-1.0.3.tar.gz", "has_sig": false, "md5_digest": "4ed7b8c96e90e82e77cf93a3a95714db", "packagetype": "sdist", "python_version": "source", "requires_python": null, "size": 86600, "upload_time": "2018-12-13T12:13:35", "url": "https://files.pythonhosted.org/packages/84/9e/1b3bd414d90f358b887bd1a1e7a7b1bb1a88d5a2017eb98b18d922192799/python3-dtls-1.0.3.tar.gz" } ] }