Skip to content
Snippets Groups Projects
Verified Commit 2b7213b2 authored by Jan Pavlinec's avatar Jan Pavlinec
Browse files

Merge branch 'hotfix/foris-controller-lan-redirect-patch' into develop

parents 30b87e82 6bafba09
Branches
Tags
1 merge request!697Turris OS 5.2 merge
From 5a4e5e2809c3ceca27418d3f32c0371d80d2a168 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Martin=20Mat=C4=9Bjek?= <martin.matejek@nic.cz>
Date: Wed, 30 Sep 2020 01:05:49 +0200
Subject: [PATCH] lan: allow control of 192.168.1.1 redirect
Add option to enable or disable redirection to 192.168.1.1,
which is intended for mainly for Turris Shield.
Without specific config values in uci config it won't do a thing on
other Turris routers.
---
foris_controller_backends/lan/__init__.py | 35 +++++-
foris_controller_backends/uci/__init__.py | 11 +-
foris_controller_modules/lan/handlers/mock.py | 7 +-
foris_controller_modules/lan/schema/lan.json | 13 ++-
tests/blackbox/test_lan.py | 104 +++++++++++++++---
tests/blackbox/uci_configs/defaults/firewall | 2 +
6 files changed, 147 insertions(+), 25 deletions(-)
diff --git a/foris_controller_backends/lan/__init__.py b/foris_controller_backends/lan/__init__.py
index 1deac59..2d535c2 100644
--- a/foris_controller_backends/lan/__init__.py
+++ b/foris_controller_backends/lan/__init__.py
@@ -1,6 +1,6 @@
#
# foris-controller
-# Copyright (C) 2019 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
+# Copyright (C) 2019-2020 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -29,6 +29,7 @@ from foris_controller_backends.uci import (
parse_bool,
store_bool,
get_sections_by_type,
+ section_exists,
)
from foris_controller_backends.files import BaseFile, path_exists
@@ -136,6 +137,7 @@ class LanUci(object):
with UciBackend() as backend:
network_data = backend.read("network")
dhcp_data = backend.read("dhcp")
+ firewall_data = backend.read("firewall")
try:
wireless_data = backend.read("wireless")
except UciException:
@@ -202,7 +204,7 @@ class LanUci(object):
from foris_controller_backends.networks import NetworksUci
- return {
+ result = {
"mode": mode,
"mode_managed": mode_managed,
"mode_unmanaged": mode_unmanaged,
@@ -212,6 +214,16 @@ class LanUci(object):
),
}
+ # quick hack for shield redirect to 192.168.1.1
+ lan_redirect_exists = section_exists(firewall_data, "firewall", "redirect_192_168_1_1")
+
+ if lan_redirect_exists:
+ result["lan_redirect"] = parse_bool(
+ get_option_named(firewall_data, "firewall", "redirect_192_168_1_1", "enabled", "1")
+ )
+
+ return result
+
def filter_dhcp_client_records(
self,
backend: UciBackend,
@@ -236,7 +248,20 @@ class LanUci(object):
) and not self.in_network(record["data"]["ip"], new_router_ip, new_netmask):
backend.del_section("dhcp", record["name"])
- def update_settings(self, mode, mode_managed=None, mode_unmanaged=None):
+ @staticmethod
+ def _store_lan_redirect(backend, enabled):
+ """ quick hack for shield redirect to 192.168.1.1
+ store only if there is section redirect_192_168_1_1
+ """
+
+ firewall_data = backend.read("firewall")
+ lan_redirect_exists = section_exists(firewall_data, "firewall", "redirect_192_168_1_1")
+
+ # store redirect only if section exists, otherwise skip and don't create section
+ if lan_redirect_exists:
+ backend.set_option("firewall", "redirect_192_168_1_1", "enabled", store_bool(enabled))
+
+ def update_settings(self, mode, mode_managed=None, mode_unmanaged=None, lan_redirect=None):
""" Updates the lan settings in uci
:param mode: lan setting mode managed/unmanaged
@@ -252,6 +277,9 @@ class LanUci(object):
backend.add_section("network", "interface", "lan")
backend.set_option("network", "lan", "_turris_mode", mode)
+ if lan_redirect is not None:
+ LanUci._store_lan_redirect(backend, lan_redirect)
+
if mode == "managed":
network_data = backend.read("network")
dhcp_data = backend.read("dhcp")
@@ -300,6 +328,7 @@ class LanUci(object):
# disable dhcp you are not managing this network...
backend.add_section("dhcp", "dhcp", "lan")
backend.set_option("dhcp", "lan", "ignore", store_bool(True))
+
if mode_unmanaged["lan_type"] == "dhcp":
if "hostname" in mode_unmanaged["lan_dhcp"]:
backend.set_option(
diff --git a/foris_controller_backends/uci/__init__.py b/foris_controller_backends/uci/__init__.py
index 925cffa..3da2700 100644
--- a/foris_controller_backends/uci/__init__.py
+++ b/foris_controller_backends/uci/__init__.py
@@ -1,6 +1,6 @@
#
# foris-controller
-# Copyright (C) 2017 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
+# Copyright (C) 2017-2020 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -65,6 +65,15 @@ def get_section(data, config, section):
return res[0] # only one section can be present (uci backend feature)
+def section_exists(data, config, section) -> bool:
+ """ Return whether named section exists as boolean"""
+ try:
+ get_section(data, config, section)
+ return True
+ except UciRecordNotFound:
+ return False
+
+
def get_option_named(data, config, section, option, default=None):
try:
res = get_section(data, config, section)
diff --git a/foris_controller_modules/lan/handlers/mock.py b/foris_controller_modules/lan/handlers/mock.py
index 4cce53f..1c619d3 100644
--- a/foris_controller_modules/lan/handlers/mock.py
+++ b/foris_controller_modules/lan/handlers/mock.py
@@ -1,6 +1,6 @@
#
# foris-controller
-# Copyright (C) 2019 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
+# Copyright (C) 2019-2020 CZ.NIC, z.s.p.o. (http://www.nic.cz/)
#
# This program is free software; you can redistribute it and/or modify
# it under the terms of the GNU General Public License as published by
@@ -70,6 +70,7 @@ class MockLanHandler(Handler, BaseMockHandler):
"dns2": None,
},
}
+ lan_redirect = True
@logger_wrapper(logger)
def get_settings(self):
@@ -97,6 +98,7 @@ class MockLanHandler(Handler, BaseMockHandler):
"interface_up_count": len(
[e for e in MockNetworksHandler.networks["lan"] if e["state"] == "up"]
),
+ "lan_redirect": MockLanHandler.lan_redirect,
}
return result
@@ -107,6 +109,9 @@ class MockLanHandler(Handler, BaseMockHandler):
:rtype: bool
"""
+ if "lan_redirect" in new_settings:
+ MockLanHandler.lan_redirect = new_settings["lan_redirect"]
+
MockLanHandler.mode = new_settings["mode"]
if new_settings["mode"] == "managed":
mode = new_settings["mode_managed"]
diff --git a/foris_controller_modules/lan/schema/lan.json b/foris_controller_modules/lan/schema/lan.json
index f11d885..db182ca 100644
--- a/foris_controller_modules/lan/schema/lan.json
+++ b/foris_controller_modules/lan/schema/lan.json
@@ -7,6 +7,10 @@
{"$ref": "#/definitions/network_settings_4_type"}
]
},
+ "lan_redirect": {
+ "description": "enable/disable firewall redirect to 192.168.1.1",
+ "type": "boolean"
+ },
"lan_unmanaged_settings_get": {
"description": "this device doesn't manage lan network it acts as a client",
@@ -79,7 +83,8 @@
"mode_managed": {"$ref": "#/definitions/lan_managed_settings_get"},
"mode_unmanaged": {"$ref": "#/definitions/lan_unmanaged_settings_get"},
"interface_count": {"type": "integer", "minimum": 0},
- "interface_up_count": {"type": "integer", "minimum": 0}
+ "interface_up_count": {"type": "integer", "minimum": 0},
+ "lan_redirect": {"$ref": "#/definitions/lan_redirect"}
},
"additionalProperties": false,
"required": ["mode", "mode_managed", "mode_unmanaged", "interface_count"]
@@ -90,7 +95,8 @@
"type": "object",
"properties": {
"mode": {"allOf": [{"$ref": "#/definitions/lan_mode"}, {"enum": ["managed"]}]},
- "mode_managed": {"$ref": "#/definitions/lan_managed_settings_set"}
+ "mode_managed": {"$ref": "#/definitions/lan_managed_settings_set"},
+ "lan_redirect": {"$ref": "#/definitions/lan_redirect"}
},
"additionalProperties": false,
"required": ["mode", "mode_managed"]
@@ -99,7 +105,8 @@
"type": "object",
"properties": {
"mode": {"allOf": [{"$ref": "#/definitions/lan_mode"}, {"enum": ["unmanaged"]}]},
- "mode_unmanaged": {"$ref": "#/definitions/lan_unmanaged_settings_set"}
+ "mode_unmanaged": {"$ref": "#/definitions/lan_unmanaged_settings_set"},
+ "lan_redirect": {"$ref": "#/definitions/lan_redirect"}
},
"additionalProperties": false,
"required": ["mode", "mode_unmanaged"]
diff --git a/tests/blackbox/test_lan.py b/tests/blackbox/test_lan.py
index b95b701..c7f4e83 100644
--- a/tests/blackbox/test_lan.py
+++ b/tests/blackbox/test_lan.py
@@ -17,8 +17,8 @@
# Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301 USA
#
-import pytest
import os
+import pytest
from foris_controller_testtools.fixtures import (
only_backends,
@@ -85,13 +85,14 @@ def test_get_settings(uci_configs_init, infrastructure):
res = infrastructure.process_message(
{"module": "lan", "action": "get_settings", "kind": "request"}
)
- assert set(res.keys()) == {"action", "kind", "data", "module"}
- assert set(res["data"].keys()) == {
+ assert res.keys() == {"action", "kind", "data", "module"}
+ assert res["data"].keys() == {
"mode",
"mode_managed",
"mode_unmanaged",
"interface_count",
"interface_up_count",
+ "lan_redirect"
}
assert res["data"]["mode"] in ["managed", "unmanaged"]
@@ -141,26 +142,36 @@ def test_update_settings(
assert res["module"] == "lan"
assert res["action"] == "get_settings"
assert res["kind"] == "reply"
+
+ data_lan_redirect = data.pop("lan_redirect", None)
+ res_lan_redirect = res["data"].pop("lan_redirect")
+ if data_lan_redirect:
+ # we can get lan_redirect in reply data regardless of whether we updated it or not
+ # so compare it only in case of updated lan_redirect
+ assert data_lan_redirect == res_lan_redirect
+
assert match_subdict(data, res["data"])
update(
{
"mode": "managed",
"mode_managed": {
- u"router_ip": u"192.168.5.8",
- u"netmask": u"255.255.255.0",
- u"dhcp": {u"enabled": False},
+ "router_ip": "192.168.5.8",
+ "netmask": "255.255.255.0",
+ "dhcp": {"enabled": False},
},
+ "lan_redirect": False,
}
)
update(
{
"mode": "managed",
"mode_managed": {
- u"router_ip": u"10.0.0.3",
- u"netmask": u"255.255.0.0",
- u"dhcp": {u"enabled": False},
+ "router_ip": "10.0.0.3",
+ "netmask": "255.255.0.0",
+ "dhcp": {"enabled": False},
},
+ "lan_redirect": True,
}
)
update(
@@ -456,19 +467,21 @@ def test_update_settings_openwrt(
res = infrastructure.process_message(
{"module": "lan", "action": "update_settings", "kind": "request", "data": data}
)
+ assert "errors" not in res
assert res["data"]["result"]
- with uci.UciBackend(UCI_CONFIG_DIR_PATH) as backend:
- return backend.read()
+ with uci.UciBackend(UCI_CONFIG_DIR_PATH) as backend:
+ return backend.read()
data = update(
{
"mode": "managed",
"mode_managed": {
- u"router_ip": u"192.168.5.8",
- u"netmask": u"255.255.255.0",
- u"dhcp": {u"enabled": False},
+ "router_ip": "192.168.5.8",
+ "netmask": "255.255.255.0",
+ "dhcp": {"enabled": False},
},
+ "lan_redirect": False,
}
)
assert uci.get_option_named(data, "network", "lan", "_turris_mode") == "managed"
@@ -476,15 +489,17 @@ def test_update_settings_openwrt(
assert uci.get_option_named(data, "network", "lan", "ipaddr") == "192.168.5.8"
assert uci.get_option_named(data, "network", "lan", "netmask") == "255.255.255.0"
assert uci.parse_bool(uci.get_option_named(data, "dhcp", "lan", "ignore"))
+ assert not uci.parse_bool(uci.get_option_named(data, "firewall", "redirect_192_168_1_1", "enabled"))
data = update(
{
"mode": "managed",
"mode_managed": {
- u"router_ip": u"10.1.0.3",
- u"netmask": u"255.252.0.0",
- u"dhcp": {u"enabled": True, u"start": 10, u"limit": 50, u"lease_time": 0},
+ "router_ip": "10.1.0.3",
+ "netmask": "255.252.0.0",
+ "dhcp": {"enabled": True, "start": 10, "limit": 50, "lease_time": 0},
},
+ "lan_redirect": True,
}
)
assert uci.get_option_named(data, "network", "lan", "_turris_mode") == "managed"
@@ -495,6 +510,7 @@ def test_update_settings_openwrt(
assert uci.get_option_named(data, "dhcp", "lan", "start") == "10"
assert uci.get_option_named(data, "dhcp", "lan", "limit") == "50"
assert uci.get_option_named(data, "dhcp", "lan", "dhcp_option") == ["6,10.1.0.3"]
+ assert uci.parse_bool(uci.get_option_named(data, "firewall", "redirect_192_168_1_1", "enabled"))
data = update(
{
@@ -1448,3 +1464,57 @@ def test_ipv6_address_in_dns(uci_configs_init, infrastructure, device, turris_os
{"module": "lan", "action": "get_settings", "kind": "request"}
)
assert "errors" not in res
+
+
+def test_get_settings_lan_redirect(uci_configs_init, infrastructure):
+ res = infrastructure.process_message(
+ {"module": "lan", "action": "get_settings", "kind": "request"}
+ )
+ assert "errors" not in res.keys()
+ assert res["data"]["lan_redirect"]
+
+
+@pytest.mark.only_backends(["openwrt"])
+def test_get_settings_lan_redirect_openwrt(uci_configs_init, infrastructure):
+ uci = get_uci_module(infrastructure.name)
+
+ # with redirect_192_168_1_1.enabled set it should return its value
+ with uci.UciBackend(UCI_CONFIG_DIR_PATH) as backend:
+ backend.set_option("firewall", "redirect_192_168_1_1", "enabled", 0)
+
+ res = infrastructure.process_message(
+ {"module": "lan", "action": "get_settings", "kind": "request"}
+ )
+ assert "errors" not in res.keys()
+ assert res["data"]["lan_redirect"] is False
+
+ with uci.UciBackend(UCI_CONFIG_DIR_PATH) as backend:
+ backend.set_option("firewall", "redirect_192_168_1_1", "enabled", 1)
+
+ res = infrastructure.process_message(
+ {"module": "lan", "action": "get_settings", "kind": "request"}
+ )
+ assert "errors" not in res.keys()
+ assert res["data"]["lan_redirect"]
+
+ # with redirect_192_168_1_1.enabled unset it should return lan_redirect == True
+ with uci.UciBackend(UCI_CONFIG_DIR_PATH) as backend:
+ backend.del_option("firewall", "redirect_192_168_1_1", "enabled")
+
+ res = infrastructure.process_message(
+ {"module": "lan", "action": "get_settings", "kind": "request"}
+ )
+
+ assert "errors" not in res.keys()
+ assert res["data"]["lan_redirect"]
+
+ # with missing section redirect_192_168_1_1 it shouldn't return lan_redirect
+ with uci.UciBackend(UCI_CONFIG_DIR_PATH) as backend:
+ backend.del_section("firewall", "redirect_192_168_1_1")
+
+ res = infrastructure.process_message(
+ {"module": "lan", "action": "get_settings", "kind": "request"}
+ )
+
+ assert "errors" not in res.keys()
+ assert "lan_redirect" not in res["data"].keys()
diff --git a/tests/blackbox/uci_configs/defaults/firewall b/tests/blackbox/uci_configs/defaults/firewall
index a1bc50d..d8e7011 100644
--- a/tests/blackbox/uci_configs/defaults/firewall
+++ b/tests/blackbox/uci_configs/defaults/firewall
@@ -209,3 +209,5 @@ config rule
# option dest_ip 194.25.2.129
# option dest_port 120
# option proto tcp
+
+config redirect_192_168_1_1 'redirect_192_168_1_1'
--
GitLab
0% or .
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment