mirror of
https://github.com/home-assistant/core.git
synced 2025-07-21 04:07:08 +00:00
Only use the X-Forwarded-For header if connection is from a trusted network (#15182)
See https://github.com/home-assistant/home-assistant/issues/14345#issuecomment-400854569
This commit is contained in:
parent
dbb786c548
commit
19f2bbf52f
@ -180,7 +180,7 @@ class HomeAssistantHTTP(object):
|
|||||||
middlewares=[staticresource_middleware])
|
middlewares=[staticresource_middleware])
|
||||||
|
|
||||||
# This order matters
|
# This order matters
|
||||||
setup_real_ip(app, use_x_forwarded_for)
|
setup_real_ip(app, use_x_forwarded_for, trusted_networks)
|
||||||
|
|
||||||
if is_ban_enabled:
|
if is_ban_enabled:
|
||||||
setup_bans(hass, app, login_threshold)
|
setup_bans(hass, app, login_threshold)
|
||||||
|
@ -11,18 +11,22 @@ from .const import KEY_REAL_IP
|
|||||||
|
|
||||||
|
|
||||||
@callback
|
@callback
|
||||||
def setup_real_ip(app, use_x_forwarded_for):
|
def setup_real_ip(app, use_x_forwarded_for, trusted_networks):
|
||||||
"""Create IP Ban middleware for the app."""
|
"""Create IP Ban middleware for the app."""
|
||||||
@middleware
|
@middleware
|
||||||
async def real_ip_middleware(request, handler):
|
async def real_ip_middleware(request, handler):
|
||||||
"""Real IP middleware."""
|
"""Real IP middleware."""
|
||||||
|
connected_ip = ip_address(
|
||||||
|
request.transport.get_extra_info('peername')[0])
|
||||||
|
request[KEY_REAL_IP] = connected_ip
|
||||||
|
|
||||||
|
# Only use the XFF header if enabled, present, and from a trusted proxy
|
||||||
if (use_x_forwarded_for and
|
if (use_x_forwarded_for and
|
||||||
X_FORWARDED_FOR in request.headers):
|
X_FORWARDED_FOR in request.headers and
|
||||||
|
any(connected_ip in trusted_network
|
||||||
|
for trusted_network in trusted_networks)):
|
||||||
request[KEY_REAL_IP] = ip_address(
|
request[KEY_REAL_IP] = ip_address(
|
||||||
request.headers.get(X_FORWARDED_FOR).split(',')[0])
|
request.headers.get(X_FORWARDED_FOR).split(',')[0])
|
||||||
else:
|
|
||||||
request[KEY_REAL_IP] = \
|
|
||||||
ip_address(request.transport.get_extra_info('peername')[0])
|
|
||||||
|
|
||||||
return await handler(request)
|
return await handler(request)
|
||||||
|
|
||||||
|
@ -41,7 +41,7 @@ def app():
|
|||||||
"""Fixture to setup a web.Application."""
|
"""Fixture to setup a web.Application."""
|
||||||
app = web.Application()
|
app = web.Application()
|
||||||
app.router.add_get('/', mock_handler)
|
app.router.add_get('/', mock_handler)
|
||||||
setup_real_ip(app, False)
|
setup_real_ip(app, False, [])
|
||||||
return app
|
return app
|
||||||
|
|
||||||
|
|
||||||
|
@ -1,6 +1,7 @@
|
|||||||
"""Test real IP middleware."""
|
"""Test real IP middleware."""
|
||||||
from aiohttp import web
|
from aiohttp import web
|
||||||
from aiohttp.hdrs import X_FORWARDED_FOR
|
from aiohttp.hdrs import X_FORWARDED_FOR
|
||||||
|
from ipaddress import ip_network
|
||||||
|
|
||||||
from homeassistant.components.http.real_ip import setup_real_ip
|
from homeassistant.components.http.real_ip import setup_real_ip
|
||||||
from homeassistant.components.http.const import KEY_REAL_IP
|
from homeassistant.components.http.const import KEY_REAL_IP
|
||||||
@ -15,7 +16,7 @@ async def test_ignore_x_forwarded_for(aiohttp_client):
|
|||||||
"""Test that we get the IP from the transport."""
|
"""Test that we get the IP from the transport."""
|
||||||
app = web.Application()
|
app = web.Application()
|
||||||
app.router.add_get('/', mock_handler)
|
app.router.add_get('/', mock_handler)
|
||||||
setup_real_ip(app, False)
|
setup_real_ip(app, False, [])
|
||||||
|
|
||||||
mock_api_client = await aiohttp_client(app)
|
mock_api_client = await aiohttp_client(app)
|
||||||
|
|
||||||
@ -27,11 +28,27 @@ async def test_ignore_x_forwarded_for(aiohttp_client):
|
|||||||
assert text != '255.255.255.255'
|
assert text != '255.255.255.255'
|
||||||
|
|
||||||
|
|
||||||
async def test_use_x_forwarded_for(aiohttp_client):
|
async def test_use_x_forwarded_for_without_trusted_proxy(aiohttp_client):
|
||||||
"""Test that we get the IP from the transport."""
|
"""Test that we get the IP from the transport."""
|
||||||
app = web.Application()
|
app = web.Application()
|
||||||
app.router.add_get('/', mock_handler)
|
app.router.add_get('/', mock_handler)
|
||||||
setup_real_ip(app, True)
|
setup_real_ip(app, True, [])
|
||||||
|
|
||||||
|
mock_api_client = await aiohttp_client(app)
|
||||||
|
|
||||||
|
resp = await mock_api_client.get('/', headers={
|
||||||
|
X_FORWARDED_FOR: '255.255.255.255'
|
||||||
|
})
|
||||||
|
assert resp.status == 200
|
||||||
|
text = await resp.text()
|
||||||
|
assert text != '255.255.255.255'
|
||||||
|
|
||||||
|
|
||||||
|
async def test_use_x_forwarded_for_with_trusted_proxy(aiohttp_client):
|
||||||
|
"""Test that we get the IP from the transport."""
|
||||||
|
app = web.Application()
|
||||||
|
app.router.add_get('/', mock_handler)
|
||||||
|
setup_real_ip(app, True, [ip_network('127.0.0.1')])
|
||||||
|
|
||||||
mock_api_client = await aiohttp_client(app)
|
mock_api_client = await aiohttp_client(app)
|
||||||
|
|
||||||
|
Loading…
x
Reference in New Issue
Block a user