Repository: urllib3/urllib3

Issue:
SSLV3_ALERT_HANDSHAKE_FAILURE after upgrading to v1.25.x
SSL handshake failure after upgrading from 1.24.2 to 1.25 or 1.25.1.
Travis link: https://travis-ci.org/h3llrais3r/Auto-Subliminal/jobs/524114951
Downgrading to version 1.24.2 fixes the problem.
Travis link: https://travis-ci.org/h3llrais3r/Auto-Subliminal/builds/524029312

```
Traceback (most recent call last):
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/urllib3/connectionpool.py", line 603, in urlopen
    chunked=chunked)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/urllib3/connectionpool.py", line 344, in _make_request
    self._validate_conn(conn)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/urllib3/connectionpool.py", line 843, in _validate_conn
    conn.connect()
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/urllib3/connection.py", line 350, in connect
    ssl_context=context)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/urllib3/util/ssl_.py", line 369, in ssl_wrap_socket
    return context.wrap_socket(sock)
  File "/opt/python/3.6.3/lib/python3.6/ssl.py", line 407, in wrap_socket
    _context=self, _session=session)
  File "/opt/python/3.6.3/lib/python3.6/ssl.py", line 814, in __init__
    self.do_handshake()
  File "/opt/python/3.6.3/lib/python3.6/ssl.py", line 1068, in do_handshake
    self._sslobj.do_handshake()
  File "/opt/python/3.6.3/lib/python3.6/ssl.py", line 689, in do_handshake
    self._sslobj.do_handshake()
ssl.SSLError: [SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:777)
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/requests/adapters.py", line 449, in send
    timeout=timeout
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/urllib3/connectionpool.py", line 641, in urlopen
    _stacktrace=sys.exc_info()[2])
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/urllib3/util/retry.py", line 399, in increment
    raise MaxRetryError(_pool, url, error or ResponseError(cause))
urllib3.exceptions.MaxRetryError: HTTPSConnectionPool(host='v2.sg.media-imdb.com', port=443): Max retries exceeded with url: /suggests/s/Southpaw.json (Caused by SSLError(SSLError(1, '[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:777)'),))
During handling of the above exception, another exception occurred:
Traceback (most recent call last):
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/autosubliminal/indexer.py", line 351, in get_imdb_id_and_year
    api_obj = self._search(title, year)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/autosubliminal/indexer.py", line 273, in _search
    search_results = ImdbFacade().search_for_title(title)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/imdbpie/facade.py", line 87, in search_for_title
    for result in self._client.search_for_title(query):
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/imdbpie/imdbpie.py", line 182, in search_for_title
    search_results = self._suggest_search(title)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/imdbpie/imdbpie.py", line 160, in _suggest_search
    search_results = self._get(url=url, query=query_encoded)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/imdbpie/imdbpie.py", line 308, in _get
    resp = self.session.get(url, headers=headers, params=params)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/requests/sessions.py", line 546, in get
    return self.request('GET', url, **kwargs)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/requests/sessions.py", line 533, in request
    resp = self.send(prep, **send_kwargs)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/requests/sessions.py", line 646, in send
    r = adapter.send(request, **kwargs)
  File "/home/travis/build/h3llrais3r/Auto-Subliminal/lib/requests/adapters.py", line 514, in send
    raise SSLError(e, request=request)
requests.exceptions.SSLError: HTTPSConnectionPool(host='v2.sg.media-imdb.com', port=443): Max retries exceeded with url: /suggests/s/Southpaw.json (Caused by SSLError(SSLError(1, '[SSL: SSLV3_ALERT_HANDSHAKE_FAILURE] sslv3 alert handshake failure (_ssl.c:777)'),))
```


Discussion:
Are you providing a proper CA cert for that ConnectionPool? One of the changes in 1.25 is that `cert_reqs` defaults to `CERT_REQUIRED`.
I'm not using a CA cert. I'm using your `urllib3` lib via the `requests` lib and up until now I didn't had to provide any certificate at all. Any idea on how to fix this without a CA cert except reverting to previous release? Or perhaps this is rather an issue for `requests` to be compatible with the version 1.25.x?
I figured out this issue. It's detecting the hostname `v2.sg.media-imdb.com` as an "IP address" due to the hostname matching the IPvFuture specification in RFC 3986. That hostname is technically a valid IPvFuture address and we don't send SNI for IP addresses. Maybe we need to change that behavior to only include IPv4 and IPv6 addresses.

In the past we would have used SNI for this hostname because we didn't detect IPvFuture addresses. I think I'm going to change `is_ipaddress()` to only detect IPv4 and IPv6 addresses. Thank you so much for reporting this issue. :)

Resolving patch:
diff --git a/src/urllib3/util/ssl_.py b/src/urllib3/util/ssl_.py
--- a/src/urllib3/util/ssl_.py
+++ b/src/urllib3/util/ssl_.py
@@ -44,11 +44,10 @@ def _const_compare_digest_backport(a, b):
 # Borrow rfc3986's regular expressions for IPv4
 # and IPv6 addresses for use in is_ipaddress()
 _IP_ADDRESS_REGEX = re.compile(
-    r'^(?:%s|%s|%s|%s)$' % (
+    r'^(?:%s|%s|%s)$' % (
         abnf_regexp.IPv4_RE,
         abnf_regexp.IPv6_RE,
-        abnf_regexp.IPv6_ADDRZ_RE,
-        abnf_regexp.IPv_FUTURE_RE
+        abnf_regexp.IPv6_ADDRZ_RFC4007_RE
     )
 )
 
@@ -370,7 +369,8 @@ def ssl_wrap_socket(sock, keyfile=None, certfile=None, cert_reqs=None,
 
 
 def is_ipaddress(hostname):
-    """Detects whether the hostname given is an IP address.
+    """Detects whether the hostname given is an IPv4 or IPv6 address.
+    Also detects IPv6 addresses with Zone IDs.
 
     :param str hostname: Hostname to examine.
     :return: True if the hostname is an IP address, False otherwise.


Test patch:
diff --git a/test/test_ssl.py b/test/test_ssl.py
--- a/test/test_ssl.py
+++ b/test/test_ssl.py
@@ -5,11 +5,21 @@
 
 
 @pytest.mark.parametrize('addr', [
+    # IPv6
     '::1',
     '::',
+    'FE80::8939:7684:D84b:a5A4%251',
+
+    # IPv4
     '127.0.0.1',
     '8.8.8.8',
-    b'127.0.0.1'
+    b'127.0.0.1',
+
+    # IPv6 w/ Zone IDs
+    'FE80::8939:7684:D84b:a5A4%251',
+    b'FE80::8939:7684:D84b:a5A4%251',
+    'FE80::8939:7684:D84b:a5A4%19',
+    b'FE80::8939:7684:D84b:a5A4%19'
 ])
 def test_is_ipaddress_true(addr):
     assert ssl_.is_ipaddress(addr)
@@ -17,7 +27,9 @@ def test_is_ipaddress_true(addr):
 
 @pytest.mark.parametrize('addr', [
     'www.python.org',
-    b'www.python.org'
+    b'www.python.org',
+    'v2.sg.media-imdb.com',
+    b'v2.sg.media-imdb.com'
 ])
 def test_is_ipaddress_false(addr):
     assert not ssl_.is_ipaddress(addr)