[utils] Skip remote IP addresses non matching to source address' IP version (closes #13422)
This commit is contained in:
		@@ -882,7 +882,40 @@ def _create_http_connection(ydl_handler, http_class, is_https, *args, **kwargs):
 | 
			
		||||
        kwargs['strict'] = True
 | 
			
		||||
    hc = http_class(*args, **compat_kwargs(kwargs))
 | 
			
		||||
    source_address = ydl_handler._params.get('source_address')
 | 
			
		||||
 | 
			
		||||
    if source_address is not None:
 | 
			
		||||
        filter_for = socket.AF_INET if '.' in source_address else socket.AF_INET6
 | 
			
		||||
        # This is to workaround _create_connection() from socket where it will try all
 | 
			
		||||
        # address data from getaddrinfo() including IPv6. This filters the result from
 | 
			
		||||
        # getaddrinfo() based on the source_address value.
 | 
			
		||||
        # This is based on the cpython socket.create_connection() function.
 | 
			
		||||
        # https://github.com/python/cpython/blob/master/Lib/socket.py#L691
 | 
			
		||||
        def _create_connection(address, timeout=socket._GLOBAL_DEFAULT_TIMEOUT, source_address=None):
 | 
			
		||||
            host, port = address
 | 
			
		||||
            err = None
 | 
			
		||||
            addrs = socket.getaddrinfo(host, port, 0, socket.SOCK_STREAM)
 | 
			
		||||
            ip_addrs = [addr for addr in addrs if addr[0] == filter_for]
 | 
			
		||||
            for res in ip_addrs:
 | 
			
		||||
                af, socktype, proto, canonname, sa = res
 | 
			
		||||
                sock = None
 | 
			
		||||
                try:
 | 
			
		||||
                    sock = socket.socket(af, socktype, proto)
 | 
			
		||||
                    if timeout is not socket._GLOBAL_DEFAULT_TIMEOUT:
 | 
			
		||||
                        sock.settimeout(timeout)
 | 
			
		||||
                    sock.bind(source_address)
 | 
			
		||||
                    sock.connect(sa)
 | 
			
		||||
                    err = None  # Explicitly break reference cycle
 | 
			
		||||
                    return sock
 | 
			
		||||
                except socket.error as _:
 | 
			
		||||
                    err = _
 | 
			
		||||
                    if sock is not None:
 | 
			
		||||
                        sock.close()
 | 
			
		||||
            if err is not None:
 | 
			
		||||
                raise err
 | 
			
		||||
            else:
 | 
			
		||||
                raise socket.error('Unknown error occurred')
 | 
			
		||||
        hc._create_connection = _create_connection
 | 
			
		||||
 | 
			
		||||
        sa = (source_address, 0)
 | 
			
		||||
        if hasattr(hc, 'source_address'):  # Python 2.7+
 | 
			
		||||
            hc.source_address = sa
 | 
			
		||||
 
 | 
			
		||||
		Reference in New Issue
	
	Block a user