diff --git a/homeassistant/util/network.py b/homeassistant/util/network.py index 70d7dc80505ff..bbab77a420e01 100644 --- a/homeassistant/util/network.py +++ b/homeassistant/util/network.py @@ -7,42 +7,16 @@ import yarl -# RFC6890 - IP addresses of loopback interfaces -IPV6_IPV4_LOOPBACK = ip_network("::ffff:127.0.0.0/104") - -LOOPBACK_NETWORKS = ( - ip_network("127.0.0.0/8"), - ip_network("::1/128"), - IPV6_IPV4_LOOPBACK, -) - -# RFC6890 - Address allocation for Private Internets -PRIVATE_NETWORKS = ( - ip_network("10.0.0.0/8"), - ip_network("172.16.0.0/12"), - ip_network("192.168.0.0/16"), - ip_network("fd00::/8"), - ip_network("::ffff:10.0.0.0/104"), - ip_network("::ffff:172.16.0.0/108"), - ip_network("::ffff:192.168.0.0/112"), -) - -# RFC6890 - Link local ranges -LINK_LOCAL_NETWORKS = ( - ip_network("169.254.0.0/16"), - ip_network("fe80::/10"), - ip_network("::ffff:169.254.0.0/112"), -) - def is_loopback(address: IPv4Address | IPv6Address) -> bool: """Check if an address is a loopback address.""" - return address.is_loopback or address in IPV6_IPV4_LOOPBACK + # the ::ffff: check is a workaround for python/cpython#117566 + return address.is_loopback or address in ip_network("::ffff:127.0.0.0/104") def is_private(address: IPv4Address | IPv6Address) -> bool: """Check if an address is a unique local non-loopback address.""" - return any(address in network for network in PRIVATE_NETWORKS) + return address.is_private and not is_loopback(address) and not address.is_link_local def is_link_local(address: IPv4Address | IPv6Address) -> bool: diff --git a/tests/components/auth/test_indieauth.py b/tests/components/auth/test_indieauth.py index 2a8d6894dc63c..e300601512e4d 100644 --- a/tests/components/auth/test_indieauth.py +++ b/tests/components/auth/test_indieauth.py @@ -83,8 +83,6 @@ def test_client_id_hostname() -> None: assert indieauth._parse_client_id("http://192.168.0.0") assert indieauth._parse_client_id("http://192.168.255.255") - with pytest.raises(ValueError): - assert indieauth._parse_client_id("http://255.255.255.255/") with pytest.raises(ValueError): assert indieauth._parse_client_id("http://11.0.0.0/") with pytest.raises(ValueError): diff --git a/tests/components/auth/test_login_flow.py b/tests/components/auth/test_login_flow.py index af9a2cf62f1a8..ca9a2ea9c325e 100644 --- a/tests/components/auth/test_login_flow.py +++ b/tests/components/auth/test_login_flow.py @@ -30,8 +30,8 @@ [ ("192.168.1.10", True), ("::ffff:192.168.0.10", True), - ("1.2.3.4", False), - ("2001:db8::1", False), + ("192.175.48.1", False), + ("2620:4f:8000::1", False), ], ) @pytest.mark.parametrize( @@ -81,8 +81,8 @@ async def test_fetch_auth_providers( [{"name": "Trusted Networks", "type": "trusted_networks", "id": None}], ), ("::ffff:192.168.0.10", []), - ("1.2.3.4", []), - ("2001:db8::1", []), + ("192.175.48.1", []), + ("2620:4f:8000::1", []), ], ) async def test_fetch_auth_providers_trusted_network( diff --git a/tests/components/http/test_auth.py b/tests/components/http/test_auth.py index e31e630807e19..ad779e8d7e084 100644 --- a/tests/components/http/test_auth.py +++ b/tests/components/http/test_auth.py @@ -54,7 +54,7 @@ ip_network("FD01:DB8::1"), ] TRUSTED_ADDRESSES = ["100.64.0.1", "192.0.2.100", "FD01:DB8::1", "2001:DB8:ABCD::1"] -EXTERNAL_ADDRESSES = ["198.51.100.1", "2001:DB8:FA1::1"] +EXTERNAL_ADDRESSES = ["192.175.48.1", "2620:4f:8000::1"] LOCALHOST_ADDRESSES = ["127.0.0.1", "::1"] UNTRUSTED_ADDRESSES = [*EXTERNAL_ADDRESSES, *LOCALHOST_ADDRESSES] PRIVATE_ADDRESSES = [ diff --git a/tests/util/test_network.py b/tests/util/test_network.py index c234a51764031..6b87764723f11 100644 --- a/tests/util/test_network.py +++ b/tests/util/test_network.py @@ -43,14 +43,26 @@ def test_is_invalid() -> None: def test_is_local() -> None: """Test local addresses.""" + # RFC 1918 space assert network_util.is_local(ip_address("192.168.0.1")) + # loopback assert network_util.is_local(ip_address("127.0.0.1")) + assert network_util.is_local(ip_address("::ffff:127.0.0.1")) + assert network_util.is_local(ip_address("::1")) + # IPv6 ULA assert network_util.is_local(ip_address("fd12:3456:789a:1::1")) + # IPv6 link-local assert network_util.is_local(ip_address("fe80::1234:5678:abcd")) + # mapped ipv4-to-ipv6 assert network_util.is_local(ip_address("::ffff:192.168.0.1")) + # Documentation/TEST-NET2 IP space, marked as Globally Reachable: False by IANA + assert network_util.is_local(ip_address("198.51.100.1")) + assert network_util.is_local(ip_address("2001:DB8:FA1::1")) + # AS112 space, marked as Globally Reachable: True by IANA + assert not network_util.is_local(ip_address("192.175.48.1")) + assert not network_util.is_local(ip_address("2620:4f:8000::1")) + # random globally routable IP space assert not network_util.is_local(ip_address("208.5.4.2")) - assert not network_util.is_local(ip_address("198.51.100.1")) - assert not network_util.is_local(ip_address("2001:DB8:FA1::1")) assert not network_util.is_local(ip_address("::ffff:208.5.4.2"))