From nobody Sun Mar 24 15:29:34 2024 X-Original-To: dev-commits-ports-main@mlmmj.nyi.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2610:1c1:1:606c::19:1]) by mlmmj.nyi.freebsd.org (Postfix) with ESMTP id 4V2g3L5LZXz5Fv6Q; Sun, 24 Mar 2024 15:29:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from mxrelay.nyi.freebsd.org (mxrelay.nyi.freebsd.org [IPv6:2610:1c1:1:606c::19:3]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256 client-signature RSA-PSS (4096 bits) client-digest SHA256) (Client CN "mxrelay.nyi.freebsd.org", Issuer "R3" (verified OK)) by mx1.freebsd.org (Postfix) with ESMTPS id 4V2g3L4TkTz49SB; Sun, 24 Mar 2024 15:29:34 +0000 (UTC) (envelope-from git@FreeBSD.org) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1711294174; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=xDOFmPKkOW+sn+NMA4OQAa4fhO0ExRN8QhvBDOSOecM=; b=YNkpTrjWwOB1g9TXJnwHjNZQEKTgHYc18rh9kdQ/HReBM1TN1CEiw79YwbyVAhlJOelhXE JNb25yzMMIbkTeaa4chC2iY0SM1prkrrYOnAxZP/XAlZHgZIQTxGRpX3ansuRN/ZRP1vEt elBOmVcHSUEAKqHn5sHbY3B0G3uZwa2giaMsa4IN106UWCzYxewNXXwa+HdJIGXNIONaVI Gnj34qPyPcZhvYOiFBbCAFaNCqovGWB343F5Xb0rMw5+EGw09KUSNWGoGt6S4cv6SllUT3 508F9dGeILeDEZ5Cl124P470MglxQFp9H1D7bZPT5dVxIZMP5Sk2tCMBH6pmpw== ARC-Seal: i=1; s=dkim; d=freebsd.org; t=1711294174; a=rsa-sha256; cv=none; b=BTTzlPp+JNmkUmWct6SWBWO16ULgQJWl42hjm0XJZo8lnWz7Q78fmBa/PgZW1Y50oSEwfI KRNIlI5/WaCnSOkfiPwrbrsTvGCVAMy+2tTKFvVcKDXHjYdskqcw2XDR3O5R1pXInjN0pB eYMTEVuanwsJZ+gYcwHpfVTW9sxd228V3yA8nvCwxkFqE9tSRQjcrcVpzGPz7WkW6Bs67a B2m3I6LeeubinQFdGfYRMiCqTwS1Zkjm22C9PryrlTKqxM92vWVbQ8nvGv/YJL7Z8RzJlP +CmBVD14MTkfydG/cjecvwseGT/dBwr9tv6A2uGOFwwWzI1n7xSFC9zazEs+og== ARC-Authentication-Results: i=1; mx1.freebsd.org; none ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=freebsd.org; s=dkim; t=1711294174; h=from:from:reply-to:subject:subject:date:date:message-id:message-id: to:to:cc:mime-version:mime-version:content-type:content-type: content-transfer-encoding:content-transfer-encoding; bh=xDOFmPKkOW+sn+NMA4OQAa4fhO0ExRN8QhvBDOSOecM=; b=qE7LYzKFpZLYr5JirqV8yF5Dpy7JskYMmkiKZAXyxXGRh1SeRBGSnZxNoLb4TqNU4Kqdzx Gbr6VBPGA/LU4BG3Adm4D1VPBAOieyPGHNnfp1IlvMddZwoL2oBkJsB6KE2/i5uOMNsJHD od4qwCh8+OiL5YDHA3mGlZf94o9sqN63mx/oxkVv8jZQ5Oe+9IOvwI6c+iSoSzdKOVMSzT +Kvwc895u/jJNE3WZ+Lya5LdO4btSMwRHmYZDBBAkyJ9nBx8Q0NaEIinC0tYC1X2oEx4N7 JbXGknVCZp65xmgjoUt9afUFx8+73RWimWVsLqxehq2tmUujbB56Oc1yRhvVKQ== Received: from gitrepo.freebsd.org (gitrepo.freebsd.org [IPv6:2610:1c1:1:6068::e6a:5]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature RSA-PSS (4096 bits) server-digest SHA256) (Client did not present a certificate) by mxrelay.nyi.freebsd.org (Postfix) with ESMTPS id 4V2g3L41WqzdKP; Sun, 24 Mar 2024 15:29:34 +0000 (UTC) (envelope-from git@FreeBSD.org) Received: from gitrepo.freebsd.org ([127.0.1.44]) by gitrepo.freebsd.org (8.17.1/8.17.1) with ESMTP id 42OFTYV2094451; Sun, 24 Mar 2024 15:29:34 GMT (envelope-from git@gitrepo.freebsd.org) Received: (from git@localhost) by gitrepo.freebsd.org (8.17.1/8.17.1/Submit) id 42OFTYSr094448; Sun, 24 Mar 2024 15:29:34 GMT (envelope-from git) Date: Sun, 24 Mar 2024 15:29:34 GMT Message-Id: <202403241529.42OFTYSr094448@gitrepo.freebsd.org> To: ports-committers@FreeBSD.org, dev-commits-ports-all@FreeBSD.org, dev-commits-ports-main@FreeBSD.org From: Dave Cottlehuber Subject: git: e2adf7a4e801 - main - net/zerotier: fix local auth, add internal webserver List-Id: Commits to the main branch of the FreeBSD ports repository List-Archive: https://lists.freebsd.org/archives/dev-commits-ports-main List-Help: List-Post: List-Subscribe: List-Unsubscribe: Sender: owner-dev-commits-ports-main@freebsd.org X-BeenThere: dev-commits-ports-main@freebsd.org MIME-Version: 1.0 Content-Type: text/plain; charset=utf-8 Content-Transfer-Encoding: 8bit X-Git-Committer: dch X-Git-Repository: ports X-Git-Refname: refs/heads/main X-Git-Reftype: branch X-Git-Commit: e2adf7a4e8012a7eb5a4fc93c4cb945698f6afc1 Auto-Submitted: auto-generated The branch main has been updated by dch: URL: https://cgit.FreeBSD.org/ports/commit/?id=e2adf7a4e8012a7eb5a4fc93c4cb945698f6afc1 commit e2adf7a4e8012a7eb5a4fc93c4cb945698f6afc1 Author: Dave Cottlehuber AuthorDate: 2024-03-24 15:29:30 +0000 Commit: Dave Cottlehuber CommitDate: 2024-03-24 15:29:30 +0000 net/zerotier: fix local auth, add internal webserver PR: 277735 --- net/zerotier/Makefile | 1 + net/zerotier/files/patch-README.md | 26 ++++ .../patch-controller_EmbeddedNetworkController.cpp | 26 ++++ net/zerotier/files/patch-node_InetAddress.cpp | 23 ++++ net/zerotier/files/patch-service_OneService.cpp | 138 +++++++++++++++++++++ 5 files changed, 214 insertions(+) diff --git a/net/zerotier/Makefile b/net/zerotier/Makefile index 31625cd8b1c4..b66ebf553035 100644 --- a/net/zerotier/Makefile +++ b/net/zerotier/Makefile @@ -1,5 +1,6 @@ PORTNAME= zerotier DISTVERSION= 1.12.2 +PORTREVISION= 1 CATEGORIES= net MAINTAINER= dch@FreeBSD.org diff --git a/net/zerotier/files/patch-README.md b/net/zerotier/files/patch-README.md new file mode 100644 index 000000000000..2ef84861cac6 --- /dev/null +++ b/net/zerotier/files/patch-README.md @@ -0,0 +1,26 @@ +--- README.md.orig 2023-09-14 19:09:26 UTC ++++ README.md +@@ -169,3 +169,23 @@ If there are other metrics you'd like to see tracked, + | zt_peer_packet_errors | node_id | Counter | number of incoming packet errors from a peer | + + If there are other metrics you'd like to see tracked, ask us in an Issue or send us a Pull Request! ++ ++### HTTP / App server ++ ++There is a static http file server suitable for hosting Single Page Apps at http://localhost:9993/app/ ++ ++Use `zerotier-cli info -j` to find your zerotier-one service's homeDir ++ ++``` sh ++cd $ZT_HOME ++sudo mkdir -p app/app1 ++sudo mkdir -p app/appB ++echo 'appA

hello world A' | sudo tee app/appA/index.html ++echo 'app2

hello world 2' | sudo tee app/app2/index.html ++curl -sL http://localhost:9993/app/appA http://localhost:9993/app/app2 ++``` ++ ++Then visit [http://localhost:9993/app/app1/](http://localhost:9993/app/app1/) and [http://localhost:9993/app/appB/](http://localhost:9993/app/appB/) ++ ++Requests to paths don't exist return the app root index.html, as is customary for SPAs. ++If you want, you can write some javascript that talks to the service or controller [api](https://docs.zerotier.com/service/v1). diff --git a/net/zerotier/files/patch-controller_EmbeddedNetworkController.cpp b/net/zerotier/files/patch-controller_EmbeddedNetworkController.cpp new file mode 100644 index 000000000000..1f037774fcfb --- /dev/null +++ b/net/zerotier/files/patch-controller_EmbeddedNetworkController.cpp @@ -0,0 +1,26 @@ +--- controller/EmbeddedNetworkController.cpp.orig 2023-09-14 19:09:26 UTC ++++ controller/EmbeddedNetworkController.cpp +@@ -874,6 +874,7 @@ void EmbeddedNetworkController::configureHTTPControlPl + std::string memberListPath = "/controller/network/([0-9a-fA-F]{16})/member"; + std::string memberPath = "/controller/network/([0-9a-fA-F]{16})/member/([0-9a-fA-F]{10})"; + ++ + auto controllerGet = [&, setContent](const httplib::Request &req, httplib::Response &res) { + char tmp[4096]; + const bool dbOk = _db.isReady(); +@@ -885,11 +886,11 @@ void EmbeddedNetworkController::configureHTTPControlPl + (unsigned long long)OSUtils::now(), + dbOk ? "true" : "false"); + +- if (!dbOk) { +- res.status = 503; +- } ++ if (!dbOk) { ++ res.status = 503; ++ } + +- setContent(req, res, tmp); ++ setContent(req, res, tmp); + }; + s.Get(controllerPath, controllerGet); + sv6.Get(controllerPath, controllerGet); diff --git a/net/zerotier/files/patch-node_InetAddress.cpp b/net/zerotier/files/patch-node_InetAddress.cpp new file mode 100644 index 000000000000..2b1b7a6e4b4a --- /dev/null +++ b/net/zerotier/files/patch-node_InetAddress.cpp @@ -0,0 +1,23 @@ +--- node/InetAddress.cpp.orig 2023-09-14 19:09:26 UTC ++++ node/InetAddress.cpp +@@ -132,7 +132,20 @@ InetAddress::IpScope InetAddress::ipScope() const + return IP_SCOPE_PRIVATE; // fc00::/7 + } + } ++ ++ // :::ffff:127.0.0.1 ++ // 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0xff, 0xff, 0x7f, 0, 0, 1 + unsigned int k = 0; ++ while ((!ip[k])&&(k < 9)) { ++ ++k; ++ } ++ if (k == 9) { ++ if (ip[10] == 0xff && ip[11] == 0xff && ip[12] == 0x7f) { ++ return IP_SCOPE_LOOPBACK; ++ } ++ } ++ ++ k = 0; + while ((!ip[k])&&(k < 15)) { + ++k; + } diff --git a/net/zerotier/files/patch-service_OneService.cpp b/net/zerotier/files/patch-service_OneService.cpp new file mode 100644 index 000000000000..884b42e88a65 --- /dev/null +++ b/net/zerotier/files/patch-service_OneService.cpp @@ -0,0 +1,138 @@ +--- service/OneService.cpp.orig 2023-09-14 19:09:26 UTC ++++ service/OneService.cpp +@@ -795,6 +795,7 @@ class OneServiceImpl : public OneService (public) + bool _allowTcpFallbackRelay; + bool _forceTcpRelay; + bool _allowSecondaryPort; ++ bool _enableWebServer; + + unsigned int _primaryPort; + unsigned int _secondaryPort; +@@ -1557,6 +1558,7 @@ class OneServiceImpl : public OneService (public) + + std::vector noAuthEndpoints { "/sso", "/health" }; + ++ + auto setContent = [=] (const httplib::Request &req, httplib::Response &res, std::string content) { + if (req.has_param("jsonp")) { + if (content.length() > 0) { +@@ -1573,8 +1575,98 @@ class OneServiceImpl : public OneService (public) + } + }; + ++ // ++ // static file server for app ui' ++ // ++ if (_enableWebServer) { ++ static std::string appUiPath = "/app"; ++ static char appUiDir[16384]; ++ sprintf(appUiDir,"%s%s",_homePath.c_str(),appUiPath.c_str()); + +- auto authCheck = [=] (const httplib::Request &req, httplib::Response &res) { ++ auto ret = _controlPlane.set_mount_point(appUiPath, appUiDir); ++ _controlPlaneV6.set_mount_point(appUiPath, appUiDir); ++ if (!ret) { ++ fprintf(stderr, "Mounting app directory failed. Creating it. Path: %s - Dir: %s\n", appUiPath.c_str(), appUiDir); ++ if (!OSUtils::mkdir(appUiDir)) { ++ fprintf(stderr, "Could not create app directory either. Path: %s - Dir: %s\n", appUiPath.c_str(), appUiDir); ++ } else { ++ ret = _controlPlane.set_mount_point(appUiPath, appUiDir); ++ _controlPlaneV6.set_mount_point(appUiPath, appUiDir); ++ if (!ret) { ++ fprintf(stderr, "Really could not create and mount directory. Path: %s - Dir: %s\nWeb apps won't work.\n", appUiPath.c_str(), appUiDir); ++ } ++ } ++ } ++ ++ if (ret) { ++ // fallback to /index.html for paths that don't exist for SPAs ++ auto indexFallbackGet = [](const httplib::Request &req, httplib::Response &res) { ++ // fprintf(stderr, "fallback \n"); ++ ++ auto match = req.matches[1]; ++ if (match.matched) { ++ ++ // fallback ++ char indexHtmlPath[16384]; ++ sprintf(indexHtmlPath,"%s/%s/%s", appUiDir, match.str().c_str(), "index.html"); ++ // fprintf(stderr, "fallback path %s\n", indexHtmlPath); ++ ++ std::string indexHtml; ++ ++ if (!OSUtils::readFile(indexHtmlPath, indexHtml)) { ++ res.status = 500; ++ return; ++ } ++ ++ res.set_content(indexHtml.c_str(), "text/html"); ++ } else { ++ res.status = 500; ++ return; ++ } ++ }; ++ ++ auto slashRedirect = [](const httplib::Request &req, httplib::Response &res) { ++ // fprintf(stderr, "redirect \n"); ++ ++ // add .html ++ std::string htmlFile; ++ char htmlPath[16384]; ++ sprintf(htmlPath,"%s%s%s", appUiDir, (req.path).substr(appUiPath.length()).c_str(), ".html"); ++ // fprintf(stderr, "path: %s\n", htmlPath); ++ if (OSUtils::readFile(htmlPath, htmlFile)) { ++ res.set_content(htmlFile.c_str(), "text/html"); ++ return; ++ } else { ++ res.status = 301; ++ res.set_header("location", req.path + "/"); ++ } ++ }; ++ ++ // auto missingAssetGet = [&, setContent](const httplib::Request &req, httplib::Response &res) { ++ // fprintf(stderr, "missing \n"); ++ // res.status = 404; ++ // std::string html = "oops"; ++ // res.set_content(html, "text/plain"); ++ // res.set_header("Content-Type", "text/plain"); ++ // return; ++ // }; ++ ++ // auto fix no trailing slash by adding .html or redirecting to path/ ++ _controlPlane.Get(appUiPath + R"((/[\w|-]+)+$)", slashRedirect); ++ _controlPlaneV6.Get(appUiPath + R"((/[\w|-]+)+$)", slashRedirect); ++ ++ // // 404 missing assets for *.ext paths ++ // s.Get(appUiPath + R"(/\.\w+$)", missingAssetGet); ++ // sv6.Get(appUiPath + R"(/\.\w+$)", missingAssetGet); ++ ++ // fallback to index.html for unknown paths/files ++ _controlPlane.Get(appUiPath + R"((/[\w|-]+)(/[\w|-]+)*/$)", indexFallbackGet); ++ _controlPlaneV6.Get(appUiPath + R"((/[\w|-]+)(/[\w|-]+)*/$)", indexFallbackGet); ++ ++ } ++ } ++ ++ auto authCheck = [=] (const httplib::Request &req, httplib::Response &res) { + if (req.path == "/metrics") { + + if (req.has_header("x-zt1-auth")) { +@@ -1624,6 +1716,11 @@ class OneServiceImpl : public OneService (public) + isAuth = true; + } + ++ // Web Apps base path ++ if (req.path.rfind("/app", 0) == 0) { //starts with /app ++ isAuth = true; ++ } ++ + if (!isAuth) { + // check auth token + if (req.has_header("x-zt1-auth")) { +@@ -2429,6 +2526,7 @@ class OneServiceImpl : public OneService (public) + // bondingPolicy cannot be used with allowTcpFallbackRelay + _allowTcpFallbackRelay = OSUtils::jsonBool(settings["allowTcpFallbackRelay"],true); + _forceTcpRelay = OSUtils::jsonBool(settings["forceTcpRelay"],false); ++ _enableWebServer = (OSUtils::jsonBool(settings["enableWebServer"],false)); + + #ifdef ZT_TCP_FALLBACK_RELAY + _fallbackRelayAddress = InetAddress(OSUtils::jsonString(settings["tcpFallbackRelay"], ZT_TCP_FALLBACK_RELAY).c_str());