diff --git a/requirements_test.txt b/requirements_test.txt
index 22ffaa60a0f18e6be56204f16ad2b20c5a97e418..713c8820bc11304a8e09030967d240cf417c679f 100644
--- a/requirements_test.txt
+++ b/requirements_test.txt
@@ -18,6 +18,7 @@ pipdeptree==2.1.0
 pylint-strict-informational==0.1
 pytest-aiohttp==0.3.0
 pytest-cov==2.12.1
+pytest-socket==0.4.1
 pytest-test-groups==1.0.3
 pytest-sugar==0.9.4
 pytest-timeout==1.4.2
diff --git a/tests/components/auth/conftest.py b/tests/components/auth/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..867f44d9f15f74ce816548509cbddfed8535c126
--- /dev/null
+++ b/tests/components/auth/conftest.py
@@ -0,0 +1,8 @@
+"""Test configuration for auth."""
+import pytest
+
+
+@pytest.fixture
+def aiohttp_client(loop, aiohttp_client, socket_enabled):
+    """Return aiohttp_client and allow opening sockets."""
+    return aiohttp_client
diff --git a/tests/components/emulated_hue/test_upnp.py b/tests/components/emulated_hue/test_upnp.py
index 8ea65380359fb4b185242b5f5a15f9ef2b694118..d918b378614765d939a4d3340f18cd4e0eba4b4b 100644
--- a/tests/components/emulated_hue/test_upnp.py
+++ b/tests/components/emulated_hue/test_upnp.py
@@ -28,6 +28,12 @@ class MockTransport:
         self.sends.append((response, addr))
 
 
+@pytest.fixture
+def aiohttp_client(loop, aiohttp_client, socket_enabled):
+    """Return aiohttp_client and allow opening sockets."""
+    return aiohttp_client
+
+
 @pytest.fixture
 def hue_client(aiohttp_client):
     """Return a hue API client."""
diff --git a/tests/components/frontend/test_init.py b/tests/components/frontend/test_init.py
index 9746fc6d83887736f52eed30c3ab4a6aa871884d..c508175a8463ab04c560afd92692cbb96106a853 100644
--- a/tests/components/frontend/test_init.py
+++ b/tests/components/frontend/test_init.py
@@ -79,6 +79,12 @@ async def frontend_themes(hass):
     )
 
 
+@pytest.fixture
+def aiohttp_client(loop, aiohttp_client, socket_enabled):
+    """Return aiohttp_client and allow opening sockets."""
+    return aiohttp_client
+
+
 @pytest.fixture
 async def mock_http_client(hass, aiohttp_client, frontend):
     """Start the Home Assistant HTTP component."""
diff --git a/tests/components/http/conftest.py b/tests/components/http/conftest.py
new file mode 100644
index 0000000000000000000000000000000000000000..c796ec50b51f166c598d1a2bbe0465fbd28c76a1
--- /dev/null
+++ b/tests/components/http/conftest.py
@@ -0,0 +1,8 @@
+"""Test configuration for http."""
+import pytest
+
+
+@pytest.fixture
+def aiohttp_client(loop, aiohttp_client, socket_enabled):
+    """Return aiohttp_client and allow opening sockets."""
+    return aiohttp_client
diff --git a/tests/components/image_processing/test_init.py b/tests/components/image_processing/test_init.py
index c0c57b17a7c2a4a26d7590d1c9e52cfb709693e2..ed8d49e8ddbbbe401aaec80ba38f74c33ef174bc 100644
--- a/tests/components/image_processing/test_init.py
+++ b/tests/components/image_processing/test_init.py
@@ -1,6 +1,8 @@
 """The tests for the image_processing component."""
 from unittest.mock import PropertyMock, patch
 
+import pytest
+
 import homeassistant.components.http as http
 import homeassistant.components.image_processing as ip
 from homeassistant.const import ATTR_ENTITY_PICTURE
@@ -11,6 +13,12 @@ from tests.common import assert_setup_component, async_capture_events
 from tests.components.image_processing import common
 
 
+@pytest.fixture
+def aiohttp_unused_port(loop, aiohttp_unused_port, socket_enabled):
+    """Return aiohttp_unused_port and allow opening sockets."""
+    return aiohttp_unused_port
+
+
 def get_url(hass):
     """Return camera url."""
     state = hass.states.get("camera.demo_camera")
diff --git a/tests/components/motioneye/test_camera.py b/tests/components/motioneye/test_camera.py
index 70c2d44436ac956493579397072384570b0a3ce1..b2264e78556db02beb7c1983fa89258291cec638 100644
--- a/tests/components/motioneye/test_camera.py
+++ b/tests/components/motioneye/test_camera.py
@@ -1,6 +1,5 @@
 """Test the motionEye camera."""
 import copy
-import logging
 from typing import Any, cast
 from unittest.mock import AsyncMock, Mock
 
@@ -48,7 +47,11 @@ from . import (
 
 from tests.common import async_fire_time_changed
 
-_LOGGER = logging.getLogger(__name__)
+
+@pytest.fixture
+def aiohttp_server(loop, aiohttp_server, socket_enabled):
+    """Return aiohttp_server and allow opening sockets."""
+    return aiohttp_server
 
 
 async def test_setup_camera(hass: HomeAssistant) -> None:
diff --git a/tests/components/nest/conftest.py b/tests/components/nest/conftest.py
index 764f037d1814ff20fdcc6295f333855289aa5a73..988d9d761fee3d4b4f79272989c5620b7d5466b3 100644
--- a/tests/components/nest/conftest.py
+++ b/tests/components/nest/conftest.py
@@ -48,6 +48,12 @@ class FakeAuth(AbstractAuth):
         return aiohttp.web.json_response()
 
 
+@pytest.fixture
+def aiohttp_client(loop, aiohttp_client, socket_enabled):
+    """Return aiohttp_client and allow opening sockets."""
+    return aiohttp_client
+
+
 @pytest.fixture
 async def auth(aiohttp_client):
     """Fixture for an AbstractAuth."""
diff --git a/tests/conftest.py b/tests/conftest.py
index 9ee6bbc680be3a7abac1d48e9866f4721c1e252d..845145c2ec270881bb78872ad994f688c8d380c3 100644
--- a/tests/conftest.py
+++ b/tests/conftest.py
@@ -3,6 +3,7 @@ import asyncio
 import datetime
 import functools
 import logging
+import socket
 import ssl
 import threading
 from unittest.mock import MagicMock, patch
@@ -10,6 +11,7 @@ from unittest.mock import MagicMock, patch
 from aiohttp.test_utils import make_mocked_request
 import multidict
 import pytest
+import pytest_socket
 import requests_mock as _requests_mock
 
 from homeassistant import core as ha, loader, runner, util
@@ -61,6 +63,70 @@ def pytest_configure(config):
     )
 
 
+def pytest_runtest_setup():
+    """Throw if tests attempt to open sockets.
+
+    allow_unix_socket is set to True because it's needed by asyncio.
+    Important: socket_allow_hosts must be called before disable_socket, otherwise all
+    destinations will be allowed.
+    """
+    pytest_socket.socket_allow_hosts(["127.0.0.1"])
+    disable_socket(allow_unix_socket=True)
+
+
+@pytest.fixture
+def socket_disabled(pytestconfig):
+    """Disable socket.socket for duration of this test function.
+
+    This incorporates changes from https://github.com/miketheman/pytest-socket/pull/76
+    and hardcodes allow_unix_socket to True because it's not passed on the command line.
+    """
+    socket_was_enabled = socket.socket == pytest_socket._true_socket
+    disable_socket(allow_unix_socket=True)
+    yield
+    if socket_was_enabled:
+        pytest_socket.enable_socket()
+
+
+@pytest.fixture
+def socket_enabled(pytestconfig):
+    """Enable socket.socket for duration of this test function.
+
+    This incorporates changes from https://github.com/miketheman/pytest-socket/pull/76
+    and hardcodes allow_unix_socket to True because it's not passed on the command line.
+    """
+    socket_was_disabled = socket.socket != pytest_socket._true_socket
+    pytest_socket.enable_socket()
+    yield
+    if socket_was_disabled:
+        disable_socket(allow_unix_socket=True)
+
+
+def disable_socket(allow_unix_socket=False):
+    """Disable socket.socket to disable the Internet. useful in testing.
+
+    This incorporates changes from https://github.com/miketheman/pytest-socket/pull/75
+    """
+
+    class GuardedSocket(socket.socket):
+        """socket guard to disable socket creation (from pytest-socket)."""
+
+        def __new__(cls, *args, **kwargs):
+            try:
+                if len(args) > 0:
+                    is_unix_socket = args[0] == socket.AF_UNIX
+                else:
+                    is_unix_socket = kwargs.get("family") == socket.AF_UNIX
+            except AttributeError:
+                # AF_UNIX not supported on Windows https://bugs.python.org/issue33408
+                is_unix_socket = False
+            if is_unix_socket and allow_unix_socket:
+                return super().__new__(cls, *args, **kwargs)
+            raise pytest_socket.SocketBlockedError()
+
+    socket.socket = GuardedSocket
+
+
 def check_real(func):
     """Force a function to require a keyword _test_real to be passed in."""
 
@@ -319,7 +385,7 @@ def local_auth(hass):
 
 
 @pytest.fixture
-def hass_client(hass, aiohttp_client, hass_access_token):
+def hass_client(hass, aiohttp_client, hass_access_token, socket_enabled):
     """Return an authenticated HTTP client."""
 
     async def auth_client():
@@ -332,7 +398,7 @@ def hass_client(hass, aiohttp_client, hass_access_token):
 
 
 @pytest.fixture
-def hass_client_no_auth(hass, aiohttp_client):
+def hass_client_no_auth(hass, aiohttp_client, socket_enabled):
     """Return an unauthenticated HTTP client."""
 
     async def client():
@@ -367,7 +433,7 @@ def current_request_with_host(current_request):
 
 
 @pytest.fixture
-def hass_ws_client(aiohttp_client, hass_access_token, hass):
+def hass_ws_client(aiohttp_client, hass_access_token, hass, socket_enabled):
     """Websocket client fixture connected to websocket server."""
 
     async def create_client(hass=hass, access_token=hass_access_token):
diff --git a/tests/test_test_fixtures.py b/tests/test_test_fixtures.py
new file mode 100644
index 0000000000000000000000000000000000000000..90362e95819f1f736f7d98c75a15aeacf69e7986
--- /dev/null
+++ b/tests/test_test_fixtures.py
@@ -0,0 +1,18 @@
+"""Test test fixture configuration."""
+import socket
+
+import pytest
+import pytest_socket
+
+
+def test_sockets_disabled():
+    """Test we can't open sockets."""
+    with pytest.raises(pytest_socket.SocketBlockedError):
+        socket.socket()
+
+
+def test_sockets_enabled(socket_enabled):
+    """Test we can't connect to an address different from 127.0.0.1."""
+    mysocket = socket.socket()
+    with pytest.raises(pytest_socket.SocketConnectBlockedError):
+        mysocket.connect(("127.0.0.2", 1234))