Error messages
(env) ➜ test $ python download.py
Traceback (most recent call last):
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 595, in urlopen
chunked=chunked)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 352, in _make_request
self._validate_conn(conn)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 831, in _validate_conn
conn.connect()
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/packages/urllib3/connection.py", line 289, in connect
ssl_version=resolved_ssl_version)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/packages/urllib3/util/ssl_.py", line 308, in ssl_wrap_socket
return context.wrap_socket(sock, server_hostname=server_hostname)
File "/usr/lib/python3.5/ssl.py", line 377, in wrap_socket
_context=self)
File "/usr/lib/python3.5/ssl.py", line 752, in __init__
self.do_handshake()
File "/usr/lib/python3.5/ssl.py", line 988, in do_handshake
self._sslobj.do_handshake()
File "/usr/lib/python3.5/ssl.py", line 633, in do_handshake
self._sslobj.do_handshake()
ssl.SSLEOFError: EOF occurred in violation of protocol (_ssl.c:645)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/adapters.py", line 423, in send
timeout=timeout
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/packages/urllib3/connectionpool.py", line 621, in urlopen
raise SSLError(e)
requests.packages.urllib3.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
File "download.py", line 17, in <module>
main()
File "download.py", line 14, in main
download('https://www.kmac.co.kr/inc/mailfiledownload.asp?mode=notice&idx=6770&gubun=filename')
File "download.py", line 8, in download
res = requests.get(url, stream=True)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/api.py", line 70, in get
return request('get', url, params=params, **kwargs)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/api.py", line 56, in request
return session.request(method=method, url=url, **kwargs)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/sessions.py", line 475, in request
resp = self.send(prep, **send_kwargs)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/sessions.py", line 596, in send
r = adapter.send(request, **kwargs)
File "/home/dev2/test/env/lib/python3.5/site-packages/requests/adapters.py", line 497, in send
raise SSLError(e, request=request)
requests.exceptions.SSLError: EOF occurred in violation of protocol (_ssl.c:645)
My environment
(env) ➜ test $ python -V
Python 3.5.2
(env) ➜ test $ python -c "import ssl; print(ssl.OPENSSL_VERSION)"
OpenSSL 1.0.2g 1 Mar 2016
(env) ➜ test $ cat /etc/os-release
NAME="Ubuntu"
VERSION="16.04.1 LTS (Xenial Xerus)"
ID=ubuntu
ID_LIKE=debian
PRETTY_NAME="Ubuntu 16.04.1 LTS"
VERSION_ID="16.04"
HOME_URL="http://www.ubuntu.com/"
SUPPORT_URL="http://help.ubuntu.com/"
BUG_REPORT_URL="http://bugs.launchpad.net/ubuntu/"
(env) ➜ test $ pip list
pip (8.1.2)
requests (2.11.1)
setuptools (28.0.0)
wheel (0.30.0a0)
Test code
#!/usr/bin/env python3
# -*- coding: utf-8 -*-
import requests
def download(url):
with open('output.dat', "wb") as f:
res = requests.get(url, stream=True)
for chunk in res.iter_content(8192):
f.write(chunk)
print(filename + ' download complete!')
def main():
download('https://www.kmac.co.kr/inc/mailfiledownload.asp?mode=notice&idx=6770&gubun=filename')
if __name__ == "__main__":
main()
So the problem here is that your security configuration is sufficiently high that you cannot connect to the remote peer. Specifically, Requests has a very restrictive set of ciphers: it only uses ciphers that are not known to be flawed. That means that in recent releases the set is quite restricted: in the release you're on that means AES and 3DES are the only supported ciphers. In an upcoming release that'll be further restricted to just AES due to known flaws in 3DES on large files.
The problem here is that the server only seems to support _utterly abominable_ ciphers. Check this out:
openssl s_client -connect www.kmac.co.kr:443
...
New, TLSv1/SSLv3, Cipher is RC4-MD5
...
That cipher there? That's a _terrible_ cipher. RC4 is known-broken, as is MD5. Either of these _by themselves_ would be a reason not to use the cipher suite, combining them is the height of absurdity. That made me want to check this server in SSLLabs: the result is here, but let me show you the highlights:
TLS_RSA_WITH_3DES_EDE_CBC_SHA, it's the weakest on our current list, and it's going away in the next major release of Requests.The pièce de résistance on this sandwich of terribleness is that, in fact, there's no reason Requests and this server shouldn't be able to speak. We do have a protocol overlap (we both allow TLSv1.0), and we do have a cipher suite overlap. However, it seems like the server has a _maximum number of cipher suites_ it will look through in a handshake before it gives up. You can actually test this by taking the full Requests cipher suite string ('ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:!eNULL:!MD5') and passing it to the OpenSSL command-line tool and attempting to connect. Each time you fail, remove one element from the front. Eventually, this will _start to work_.
The TL;DR here is that this server is terrible, it only supports terribly weak TLS, and if at all possible you should _avoid using it_. I strongly recommend not speaking to this server in any way, shape, or form. If you _absolutely must_, you can set requests.packages.urllib.util.ssl_.DEFAULT_CIPHERS = 'RSA+3DES', and that will allow your connection to succeed. But I strongly discourage doing that.
Most helpful comment
So the problem here is that your security configuration is sufficiently high that you cannot connect to the remote peer. Specifically, Requests has a very restrictive set of ciphers: it only uses ciphers that are not known to be flawed. That means that in recent releases the set is quite restricted: in the release you're on that means AES and 3DES are the only supported ciphers. In an upcoming release that'll be further restricted to just AES due to known flaws in 3DES on large files.
The problem here is that the server only seems to support _utterly abominable_ ciphers. Check this out:
That cipher there? That's a _terrible_ cipher. RC4 is known-broken, as is MD5. Either of these _by themselves_ would be a reason not to use the cipher suite, combining them is the height of absurdity. That made me want to check this server in SSLLabs: the result is here, but let me show you the highlights:
TLS_RSA_WITH_3DES_EDE_CBC_SHA, it's the weakest on our current list, and it's going away in the next major release of Requests.The pièce de résistance on this sandwich of terribleness is that, in fact, there's no reason Requests and this server shouldn't be able to speak. We do have a protocol overlap (we both allow TLSv1.0), and we do have a cipher suite overlap. However, it seems like the server has a _maximum number of cipher suites_ it will look through in a handshake before it gives up. You can actually test this by taking the full Requests cipher suite string (
'ECDH+AESGCM:DH+AESGCM:ECDH+AES256:DH+AES256:ECDH+AES128:DH+AES:ECDH+HIGH:DH+HIGH:ECDH+3DES:DH+3DES:RSA+AESGCM:RSA+AES:RSA+HIGH:RSA+3DES:!aNULL:!eNULL:!MD5') and passing it to the OpenSSL command-line tool and attempting to connect. Each time you fail, remove one element from the front. Eventually, this will _start to work_.The TL;DR here is that this server is terrible, it only supports terribly weak TLS, and if at all possible you should _avoid using it_. I strongly recommend not speaking to this server in any way, shape, or form. If you _absolutely must_, you can set
requests.packages.urllib.util.ssl_.DEFAULT_CIPHERS = 'RSA+3DES', and that will allow your connection to succeed. But I strongly discourage doing that.