-
Notifications
You must be signed in to change notification settings - Fork 5
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
5 changed files
with
185 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1 @@ | ||
CONFIG_PACKAGE_ns-binding=y |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,51 @@ | ||
# | ||
# Copyright (C) 2024 Nethesis | ||
# | ||
# This is free software, licensed under the GNU General Public License v3. | ||
# | ||
|
||
include $(TOPDIR)/rules.mk | ||
|
||
PKG_NAME:=ns-binding | ||
PKG_VERSION:=0.0.1 | ||
PKG_RELEASE:=1 | ||
|
||
PKG_BUILD_DIR:=$(BUILD_DIR)/ns-binding-$(PKG_VERSION) | ||
|
||
PKG_MAINTAINER:=Tommaso Bailetti <tommaso.bailetti@nethesis.it> | ||
PKG_LICENSE:=GPL-3.0-only | ||
|
||
include $(INCLUDE_DIR)/package.mk | ||
|
||
define Package/ns-binding | ||
SECTION:=base | ||
CATEGORY:=NethSecurity | ||
TITLE:=MAC/IP binding | ||
URL:=https://github.com/NethServer/nethsecurity | ||
DEPENDS:=+python3-nethsec +dnsmasq-full +ns-api | ||
PKGARCH:=all | ||
endef | ||
|
||
define Package/ns-binding/description | ||
Tool to force bind MAC addresses to IP addresses | ||
endef | ||
|
||
define Build/Compile | ||
endef | ||
|
||
define Package/ns-binding/postinst | ||
#!/bin/sh | ||
if [ -z "$${IPKG_INSTROOT}" ]; then | ||
/etc/init.d/ns-binding restart | ||
fi | ||
exit 0 | ||
endef | ||
|
||
define Package/ns-binding/install | ||
$(INSTALL_DIR) $(1)/usr/sbin | ||
$(INSTALL_BIN) ./files/ns-binding.py $(1)/usr/sbin/ns-binding | ||
$(INSTALL_DIR) $(1)/etc/init.d | ||
$(INSTALL_BIN) ./files/ns-binding.init $(1)/etc/init.d/ns-binding | ||
endef | ||
|
||
$(eval $(call BuildPackage,ns-binding)) |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,30 @@ | ||
# ns-binding | ||
|
||
This package provides a way to create IP/MAC bindings in DHCP-managed networks. | ||
|
||
## Usage | ||
|
||
Once configured a DHCP server through the UI, you can create bindings for the interface setting a `ns_binding` option | ||
in the DHCP server configuration. The IP/MAC bindings will be created off the static leases defined in the | ||
configuration. | ||
|
||
For instance, if the DHCP server is named `GREEN_1`, to add the necessary rules for the interface you must: | ||
|
||
```bash | ||
uci set dhcp.GREEN_1.ns_binding='1' | ||
uci commit dhcp | ||
reload_config | ||
``` | ||
|
||
This will create the necessary rules to bind the IP/MAC addresses in the network based off the static leases. | ||
|
||
From now on, the IP/MAC bindings will be automatically generated and updated whenever the `dhcp` configuration is | ||
changed. | ||
|
||
To disable the binding you can either remove the `ns_binding` option or set it to `0`. | ||
|
||
```bash | ||
uci set dhcp.GREEN_1.ns_binding='0' | ||
uci commit dhcp | ||
reload_config | ||
``` |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,27 @@ | ||
#!/bin/sh /etc/rc.common | ||
|
||
# | ||
# Copyright (C) 2024 Nethesis S.r.l. | ||
# SPDX-License-Identifier: GPL-2.0-only | ||
# | ||
|
||
USE_PROCD=1 | ||
|
||
start_service() { | ||
# Main service | ||
procd_open_instance | ||
procd_set_param command /usr/sbin/ns-binding | ||
procd_set_param stdout 1 | ||
procd_set_param stderr 1 | ||
procd_close_instance | ||
} | ||
|
||
reload_service() | ||
{ | ||
restart | ||
} | ||
|
||
service_triggers() | ||
{ | ||
procd_add_reload_trigger dhcp | ||
} |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,76 @@ | ||
#!/usr/bin/python3 | ||
|
||
# | ||
# Copyright (C) 2024 Nethesis S.r.l. | ||
# SPDX-License-Identifier: GPL-2.0-only | ||
# | ||
|
||
from euci import EUci | ||
from nethsec import utils | ||
import subprocess | ||
|
||
e_uci = EUci() | ||
|
||
# Filter out DHCP servers that are not ns-binding enabled | ||
network_interfaces = { | ||
name: iface.get('device') | ||
for name, iface in utils.get_all_by_type(e_uci, 'network', 'interface').items() | ||
} | ||
dhcp_servers = [ | ||
server for server in utils.get_all_by_type(e_uci, 'dhcp', 'dhcp').values() | ||
if server.get('ns_binding', '0') == '1' and server.get('interface') in network_interfaces | ||
] | ||
# generate list of interfaces used by DHCP servers | ||
dhcp_interfaces = [ | ||
network_interfaces[server.get('interface')] | ||
for server in dhcp_servers | ||
] | ||
|
||
if len(dhcp_interfaces) > 0: | ||
# reservation entry | ||
reservations = { | ||
reservation['mac']: reservation['ip'] | ||
for reservation in utils.get_all_by_type(e_uci, 'dhcp', 'host').values() | ||
} | ||
# file generation | ||
binding_items = [f'{mac} . {ip}' for mac, ip in reservations.items()] | ||
other_interfaces = [iface for iface in network_interfaces.values() if iface not in dhcp_interfaces] | ||
file = f""" | ||
table inet ns-binding | ||
delete table inet ns-binding | ||
table inet ns-binding {{ | ||
set bindingListV4 {{ | ||
type ether_addr . ipv4_addr | ||
policy memory | ||
flags interval | ||
auto-merge | ||
{'elements = {' if len(binding_items) > 0 else ''} | ||
{', '.join(binding_items)} | ||
{'}' if len(binding_items) > 0 else ''} | ||
}} | ||
# if interface is not in other_interfaces, allow dhcp queries and check with bindingListV4 for all rest | ||
chain input {{ | ||
type filter hook input priority -110; policy drop; | ||
ct state established,related counter accept | ||
iifname {{ {' , '.join(other_interfaces)} }} counter accept | ||
udp dport 67 counter accept | ||
udp dport 68 counter accept | ||
ether saddr . ip saddr @bindingListV4 counter accept | ||
}} | ||
chain lan-forward {{ | ||
type filter hook forward priority -110; policy drop; | ||
ct state established,related counter accept | ||
iifname {{ {' , '.join(other_interfaces)} }} counter accept | ||
ether saddr . ip saddr @bindingListV4 counter accept | ||
}} | ||
}} | ||
""" | ||
subprocess.run(['/usr/sbin/nft', '-f', '-'], input=file.encode(), check=True) | ||
print('ns-binding table created') | ||
else: | ||
subprocess.run(['/usr/sbin/nft', 'delete', 'table', 'inet', 'ns-binding'], capture_output=True) | ||
print('ns-binding table deleted') |