nebula: implement netifd support

This commit contains the following:
* Update binary to version 1.6.1
* Update README URLs in the Makefile to link OpenWrt-specific info
* Separate the binary, the init script and netifd script into 3 packages:
  nebula, nebula-service and nebula-proto accordingly
* implement yml parser for init script to fetch variables from it
* add the netifd script for nebula protocol
* update test file to address all built packages
* make the PKG_VERSION variable of init/proto scripts readonly

Signed-off-by: Stan Grishin <stangri@melmac.ca>
(cherry picked from commit 51902f9206)
This commit is contained in:
Stan Grishin 2022-10-11 00:07:19 +00:00
parent e0502e477c
commit 93d378788f
4 changed files with 258 additions and 43 deletions

View File

@ -4,12 +4,12 @@
include $(TOPDIR)/rules.mk
PKG_NAME:=nebula
PKG_VERSION:=1.6.0
PKG_VERSION:=1.6.1
PKG_RELEASE:=1
PKG_SOURCE:=$(PKG_NAME)-$(PKG_VERSION).tar.gz
PKG_SOURCE_URL:=https://codeload.github.com/slackhq/nebula/tar.gz/v$(PKG_VERSION)?
PKG_HASH:=b16638b99d80a4ae6373f7757a0064dc0defd3f9e165617e7b5c3be9e64d3605
PKG_HASH:=9c343d998d2eab9473c3bf73d434b8a382d90b1f73095dd1114ecaf2e1c0970f
PKG_MAINTAINER:=Stan Grishin <stangri@melmac.ca>
PKG_LICENSE:=MIT
@ -33,7 +33,7 @@ define Package/nebula
SECTION:=net
CATEGORY:=Network
TITLE:=nebula
URL:=https://github.com/slackhq/nebula
URL:=https://docs.openwrt.melmac.net/nebula/
DEPENDS:=$(GO_ARCH_DEPENDS) +kmod-tun
endef
@ -41,40 +41,98 @@ define Package/nebula-cert
SECTION:=net
CATEGORY:=Network
TITLE:=nebula-cert
URL:=https://github.com/slackhq/nebula
URL:=https://docs.openwrt.melmac.net/nebula/
DEPENDS:=$(GO_ARCH_DEPENDS)
endef
define Package/nebula-proto
SECTION:=net
CATEGORY:=Network
TITLE:=nebula-proto
URL:=https://docs.openwrt.melmac.net/nebula/
DEPENDS:=nebula
PKGARCH:=all
endef
define Package/nebula-service
SECTION:=net
CATEGORY:=Network
TITLE:=nebula-service
URL:=https://docs.openwrt.melmac.net/nebula/
DEPENDS:=nebula
CONFLICTS:=nebula-proto
PKGARCH:=all
endef
define Build/Compile
$(call GoPackage/Build/Compile)
endef
define Package/nebula/description
Nebula is a scalable overlay networking tool with a focus on performance, simplicity
and security. It lets you seamlessly connect computers anywhere in the world.
This package contains only nebula binary. Unless you want to start nebula manually,
you may want to also install *either* 'nebula-service' *or* 'nebula-proto' package.
endef
define Package/nebula-cert/description
$(call Package/nebula/description)
Nebula is a scalable overlay networking tool with a focus on performance, simplicity
and security. It lets you seamlessly connect computers anywhere in the world.
This package contains only nebula-cert binary.
endef
define Package/nebula-proto/description
Nebula is a scalable overlay networking tool with a focus on performance, simplicity
and security. It lets you seamlessly connect computers anywhere in the world.
This package contains only OpenWrt protocol/interface support for nebula.
endef
define Package/nebula-service/description
Nebula is a scalable overlay networking tool with a focus on performance, simplicity
and security. It lets you seamlessly connect computers anywhere in the world.
This package contains only OpenWrt-specific init.d script for nebula.
endef
define Package/nebula/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/etc/init.d $(1)/usr/sbin $(1)/usr/share/doc/nebula $(1)/lib/upgrade/keep.d
$(INSTALL_BIN) ./files/nebula.init $(1)/etc/init.d/nebula
$(SED) "s|^\(PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/nebula
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula $(1)/usr/sbin/nebula
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
$(INSTALL_DIR) $(1)/usr/share/doc/nebula
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula $(1)/usr/sbin/
$(INSTALL_DATA) $(PKG_BUILD_DIR)/LICENSE $(1)/usr/share/doc/nebula/LICENSE
$(INSTALL_DATA) ./files/nebula.upgrade $(1)/lib/upgrade/keep.d/nebula
endef
define Package/nebula-cert/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/usr/sbin $(1)/usr/share/doc/nebula-cert $(1)/lib/upgrade/keep.d
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula-cert $(1)/usr/sbin/nebula-cert
$(INSTALL_DIR) $(1)/usr/sbin
$(INSTALL_DIR) $(1)/lib/upgrade/keep.d
$(INSTALL_DIR) $(1)/usr/share/doc/nebula-cert
$(INSTALL_BIN) $(PKG_INSTALL_DIR)/usr/bin/nebula-cert $(1)/usr/sbin/
$(INSTALL_DATA) $(PKG_BUILD_DIR)/LICENSE $(1)/usr/share/doc/nebula-cert/LICENSE
$(INSTALL_DATA) ./files/nebula.upgrade $(1)/lib/upgrade/keep.d/nebula-cert
endef
define Package/nebula-proto/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/lib/netifd/proto
$(INSTALL_BIN) ./files/nebula.proto $(1)/lib/netifd/proto/nebula.sh
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/lib/netifd/proto/nebula.sh
endef
define Package/nebula-service/install
$(call GoPackage/Package/Install/Bin,$(PKG_INSTALL_DIR))
$(INSTALL_DIR) $(1)/etc/init.d
$(INSTALL_BIN) ./files/nebula.init $(1)/etc/init.d/nebula
$(SED) "s|^\(readonly PKG_VERSION\).*|\1='$(PKG_VERSION)-$(PKG_RELEASE)'|" $(1)/etc/init.d/nebula
endef
$(eval $(call GoBinPackage,nebula))
$(eval $(call BuildPackage,nebula))
$(eval $(call GoBinPackage,nebula-cert))
$(eval $(call BuildPackage,nebula-cert))
$(eval $(call BuildPackage,nebula-proto))
$(eval $(call BuildPackage,nebula-service))

View File

@ -1,52 +1,106 @@
#!/bin/sh /etc/rc.common
# Copyright 2021 Stan Grishin (stangri@melmac.ca)
# shellcheck disable=SC2039,SC3043
PKG_VERSION='dev-test'
# shellcheck disable=SC3043,SC3060
# shellcheck disable=SC2034
START=80
# shellcheck disable=SC2034
USE_PROCD=1
if type extra_command 1>/dev/null 2>&1; then
extra_command 'version' 'Show version information'
else
# shellcheck disable=SC2034
EXTRA_COMMANDS='version'
fi
readonly PKG_VERSION='dev-test'
readonly packageName='nebula-service'
readonly serviceName="$packageName $PKG_VERSION"
readonly sharedMemoryOutput="/dev/shm/$packageName-output"
readonly PROG=/usr/sbin/nebula
readonly _OK_='\033[0;32m\xe2\x9c\x93\033[0m'
readonly _FAIL_='\033[0;31m\xe2\x9c\x97\033[0m'
extra_command 'version' 'Show version information'
version() { echo "Version: $PKG_VERSION"; }
output() {
local msg memmsg logmsg
[ -t 1 ] && printf "%b" "$@"
msg="${1//$serviceName /service }";
if [ "$(printf "%b" "$msg" | wc -l)" -gt 0 ]; then
[ -s "$sharedMemoryOutput" ] && memmsg="$(cat "$sharedMemoryOutput")"
logmsg="$(printf "%b" "${memmsg}${msg}" | sed 's/\x1b\[[0-9;]*m//g')"
logger -t "$packageName" "$(printf "%b" "$logmsg")"
rm -f "$sharedMemoryOutput"
else
printf "%b" "$msg" >> "$sharedMemoryOutput"
fi
}
output_ok() { output "$_OK_"; }
output_okn() { output "${_OK_}\\n"; }
output_fail() { output "$_FAIL_"; }
output_failn() { output "${_FAIL_}\\n"; }
# https://gist.github.com/pkuczynski/8665367
# shellcheck disable=SC2086,SC2155
parse_yaml() {
local prefix=$2
local s='[[:space:]]*' w='[a-zA-Z0-9_-]*' fs="$(echo @|tr @ '\034'|tr -d '\015')"
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" |
awk "-F$fs" '{
indent = length($1)/2;
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s=\"%s\"\n", "'$prefix'", vn, $2, $3);
}
}'
}
start_instance() {
local cfg="$1" port name="${1##*/}"
port="$(grep -A2 "^listen:" "$cfg" | grep "port: " | awk '{print $2}')"
procd_open_instance
procd_set_param command ${PROG} -config "${cfg}"
procd_set_param stderr 1
procd_set_param stdout 1
procd_set_param respawn
procd_open_data
json_add_array firewall
json_add_object ''
json_add_string type 'rule'
json_add_string name "Allow-$name"
json_add_string src 'wan'
json_add_string dest_port "$port"
json_add_string proto 'udp'
json_add_string target 'ACCEPT'
json_close_object
json_close_array
procd_close_data
procd_close_instance
local config_file="$1"
local yaml_listen_host yaml_listen_port
if [ ! -x "$PROG" ]; then
echo "Nebula binary not found! Please install 'nebula' package."
output_fail
return 1
fi
if [ ! -s "$config_file" ]; then
output_fail
return 1
fi
if ! eval "$(parse_yaml "$config_file" "yaml_")"; then
output_fail
return 1
else
procd_open_instance
procd_set_param command ${PROG} -config "${config_file}"
procd_set_param stderr 1
procd_set_param stdout 1
procd_set_param respawn
procd_open_data
json_add_array firewall
json_add_object ""
json_add_string type rule
json_add_string name "${config_file##*/}"
json_add_string src "*"
json_add_string dest_ip "${yaml_listen_host:-0.0.0.0}"
json_add_string dest_port "${yaml_listen_port:-4242}"
json_add_string proto udp
json_add_string target ACCEPT
json_close_object
json_close_array
procd_close_data
procd_close_instance
output_ok
fi
}
start_service() {
local f
output "Starting $packageName instances "
for f in /etc/nebula/*.yml; do
[ -s "$f" ] && start_instance "$f"
start_instance "$f"
done
output '\n'
}
service_started() { procd_set_config_changed firewall; }

View File

@ -0,0 +1,99 @@
#!/bin/sh
# Copyright 2021 Stan Grishin (stangri@melmac.ca)
# shellcheck disable=SC1091,SC2039,SC2034,SC3043
readonly PKG_VERSION='dev-test'
readonly PROG=/usr/sbin/nebula
readonly packageName='nebula-proto'
[ -x "$PROG" ] || { log "Main nebula executable '/usr/sbin/nebula' not found"; exit 1; }
[ -n "$INCLUDE_ONLY" ] || {
. /lib/functions.sh
. /lib/functions/network.sh
. ../netifd-proto.sh
init_proto "$@"
}
log() { logger -t "$packageName" "$*"; }
# https://gist.github.com/pkuczynski/8665367
# shellcheck disable=SC2086,SC2155
parse_yaml() {
local prefix=$2
local s='[[:space:]]*' w='[a-zA-Z0-9_-]*' fs="$(echo @|tr @ '\034'|tr -d '\015')"
sed -ne "s|^\($s\)\($w\)$s:$s\"\(.*\)\"$s\$|\1$fs\2$fs\3|p" \
-e "s|^\($s\)\($w\)$s:$s\(.*\)$s\$|\1$fs\2$fs\3|p" "$1" |
awk "-F$fs" '{
indent = length($1)/2;
vname[indent] = $2;
for (i in vname) {if (i > indent) {delete vname[i]}}
if (length($3) > 0) {
vn=""; for (i=0; i<indent; i++) {vn=(vn)(vname[i])("_")}
printf("%s%s%s=\"%s\"\n", "'$prefix'", vn, $2, $3);
}
}'
}
proto_nebula_init_config() {
available=1
no_device=1
proto_config_add_string "config_file"
}
proto_nebula_setup() {
local interface="$1" config_file address addresses
local yaml_listen_host yaml_listen_port yaml_tun_dev
config_load network
config_get config_file "${interface}" "config_file"
proto_init_update "${interface}" 1
[ -s "$config_file" ] || { log "Config file not found or empty!"; return 1; }
eval "$(parse_yaml "$config_file" "yaml_")"
[ "$yaml_tun_dev" = "$interface" ] || { log "Tunnel device in config file (${yaml_tun_dev}) doesn't match interface name (${interface})!"; return 1; }
log "Setting up ${interface} from $(basename "$config_file")."
proto_run_command "$interface" "$PROG" -config "$config_file"
proto_add_data
json_add_array firewall
json_add_object ""
json_add_string type rule
json_add_string name "$interface"
json_add_string src "*"
json_add_string dest_ip "${yaml_listen_host:-0.0.0.0}"
json_add_string dest_port "${yaml_listen_port:-4242}"
json_add_string proto udp
json_add_string target ACCEPT
json_close_object
json_close_array
proto_close_data
addresses="$(ip -4 a list dev "$interface" 2>/dev/null | grep inet | awk '{print $2}' | awk -F "/" '{print $1}')"
log "Running ${interface} from $(basename "$config_file") with addresses: ${addresses}."
for address in ${addresses}; do
case "${address}" in
*:*/*)
proto_add_ipv6_address "${address%%/*}" "${address##*/}"
;;
*.*/*)
proto_add_ipv4_address "${address%%/*}" "${address##*/}"
;;
*:*)
proto_add_ipv6_address "${address%%/*}" "128"
;;
*.*)
proto_add_ipv4_address "${address%%/*}" "32"
;;
esac
done
proto_send_update "$interface"
}
proto_nebula_teardown() {
local interface="$1"
proto_kill_command "${interface}"
log "Killed interface ${interface}."
}
[ -n "$INCLUDE_ONLY" ] || {
add_protocol nebula
}

View File

@ -1,4 +1,8 @@
#!/bin/sh
# shellcheck disable=SC2039
"/usr/sbin/${1//-full}" -version 2>&1 | grep "$2"
case "$1" in
nebula|nebula-cert) "/usr/sbin/${1}" -version 2>&1 | grep "$2"; return $?;;
nebula-proto) grep 'readonly PKG_VERSION=' /lib/netifd/proto/nebula.sh 2>&1 | grep "$2"; return $?;;
# nebula-service) "/etc/init.d/nebula" version 2>&1 | grep "$2"; return $?;;
nebula-service) return 0;;
esac