Does it can visit with IPV6 successfully without hard code interface name in urllib3/util/connection.py - create_connection ?

Dear Requests

My OS is CentOS 72, with requests 2.27.1, Python3.9.0, I want to visit my page by Ipv6, but it return 400 - Bad Request

Code is
```
>>> import requests
>>> requests.packages.urllib3.disable_warnings()
>>> url = 'https://[fe80::2ac1:3cff:fe89:a728%enp0s3]/#login'
>>> res = requests.get(url, verify=False)
>>> res.status_code
400
```

Then I change url to https://[fe80::2ac1:3cff:fe89:a728]/#login, urllib3 will raise OSError: [Errno 22] Invalid argument

So I hard code interface name in urllib3/util/connection.py - create_connection like this
```
    family = allowed_gai_family()
    print('Before Change: {0}'.format(host))
    host = '{0}%enp0s3'.format(host)
    print('After Change: {0}'.format(host))
```

It can visit successfully
```
>>> import requests
>>> requests.packages.urllib3.disable_warnings()
>>> url = 'https://[fe80::2ac1:3cff:fe89:a728]/#login'
>>> res = requests.get(url, verify=False)
Before Change: fe80::2ac1:3cff:fe89:a728
After Change: fe80::2ac1:3cff:fe89:a728%enp0s3
>>> res.status_code
200
```

Does it can work without hard code interface name in create_connect ??

Thanks and best regard.

Hi @k870611, it sounds like you're attempting to use an ipv6 address with a zone identifier? This is currently missing functionality in urllib3 (and Requests). I'm going to resolve this in favor of the upstream tracking issue (urllib3/urllib3#1641). It's currently providing a $500 bounty for an accepted contribution, if you'd like to give it a try.

Hi @nateprewitt 

- [ ] Research and document why urllib3<1.25 worked while urllib3>=1.25 doesn't work in this issue

    For this request I have test requests 2.27.1 + urllib3 1.24.3 & requests 2.22.0 + urllib3 1.24.3, so I don't know how does it can use with urllib3 with version less then 1.25.0.

    And I have read with 1.23, 1.22, 1.21, they are all similar, so I feel they can't work too, there is the code I try.
```
import urllib3
import requests

try:    
    print(urllib3.__version__)
    print(requests.__version__)
    
    url = 'https://[fe80::2ac1:3cff:fe89:a728%enp0s3]/#login'
    res = requests.get(url, verify=False) 
    
    print(res.ok)
    print(res.status_code)
    # print(res.text)
    
except Exception as e:
    print(e)

[root@localhost web_test]# /usr/local/bin/python3.9 /root/ipv6.py
1.24.3
2.22.0
False
400

[root@localhost web_test]# /usr/local/bin/python3.9 /root/ipv6.py
1.24.3
2.27.1
False
400
```

My Code is: 
```
import unittest
import sys
import os
import socket
from ipaddress import ip_address, IPv6Address

import requests
import requests.packages.urllib3.util.connection as urllib3_cn

allowed_gai_family = urllib3_cn.allowed_gai_family
_set_socket_options = urllib3_cn._set_socket_options

def create_connection(
    address,
    timeout=socket._GLOBAL_DEFAULT_TIMEOUT,
    source_address=None,
    socket_options=None,
):
    """Connect to *address* and return the socket object.

    Convenience function.  Connect to *address* (a 2-tuple ``(host,
    port)``) and return the socket object.  Passing the optional
    *timeout* parameter will set the timeout on the socket instance
    before attempting to connect.  If no *timeout* is supplied, the
    global default timeout setting returned by :func:`get_default_timeout`
    is used.  If *source_address* is set it must be a tuple of (host, port)
    for the socket to bind as a source address before making the connection.
    An host of '' or port 0 tells the OS to use the default.
    """
        
    host, port = address
    if host.startswith("["):
        host = host.strip("[]")
        
    err = None

    # Using the value from allowed_gai_family() in the context of getaddrinfo lets
    # us select whether to work with IPv4 DNS records, IPv6 records, or both.
    # The original create_connection function always returns all records.
    family = allowed_gai_family()
    
    if isinstance(ip_address(host), IPv6Address) and os.path.exists('/sys/class/net'):
        all_interface = os.listdir('/sys/class/net')
        hosts = ['{0}%{1}'.format(host, interface) for interface in all_interface]
        
    else:
        hosts = [host]
        
    for host in hosts:
        err = None
        
        for res in socket.getaddrinfo(host, port, family, socket.SOCK_STREAM):
            af, sock_type, proto, canon_name, sa = res
            sock = None
            try:
                sock = socket.socket(af, sock_type, proto)
                
                # If provided, set socket level options before connecting.
                _set_socket_options(sock, socket_options)

                if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
                    sock.settimeout(timeout)
                if source_address:
                    sock.bind(source_address)
                sock.connect(sa)
                return sock

            except socket.error as e:
                err = e
                if sock is not None:
                    sock.close()
                    sock = None

    if err is not None:
        raise err

    raise socket.error("getaddrinfo returns an empty list")

class test_requests(unittest.TestCase):
    def test_with_ipv6(self):
        requests.packages.urllib3.disable_warnings()
        urllib3_cn.create_connection = create_connection
        
        print('requests version: {0}'.format(requests.__version__))
        print('OS: {0}'.format(os.name))
        print('Sys Version: {0}'.format(sys.version))
        
        url = 'https://[fe80::2ac1:3cff:fe89:a728]/#login'
        res = requests.get(url, verify=False) 
        
        self.assertTrue(res.ok, 'Res is not OK')
        print('Status Code: {0}'.format(res.status_code))
        
if __name__ == '__main__':
    unittest.main()
```

And it can work both on windows & linux, stdout are
```
[root@localhost ~]#  /usr/local/bin/python3.9 test_requests.py
requests version: 2.27.1
OS: posix
Sys Version: 3.9.0 (default, Aug 20 2021, 21:07:34) 
[GCC 4.8.5 20150623 (Red Hat 4.8.5-4)]
Status Code: 200
.
----------------------------------------------------------------------
Ran 1 test in 0.197s

OK

C:\Users\fiona\Desktop>python test_requests.py
requests version: 2.25.1
OS: nt
Sys Version: 3.5.2 (v3.5.2:4def2a2901a5, Jun 25 2016, 22:18:55) [MSC v.1900 64 bit (AMD64)]
Status Code: 200
.
----------------------------------------------------------------------
Ran 1 test in 0.611s

OK
```

Don't know does it work
FYR

Thanks and best regard.