parent
f1a1276143
commit
380f55737d
|
@ -1,5 +1,6 @@
|
|||
PORTNAME= zerotier
|
||||
DISTVERSION= 1.12.2
|
||||
PORTREVISION= 1
|
||||
CATEGORIES= net
|
||||
|
||||
MAINTAINER= dch@FreeBSD.org
|
||||
|
|
|
@ -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/<app-path>
|
||||
+
|
||||
+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 '<html><meta charset=utf-8><title>appA</title><body><h1>hello world A' | sudo tee app/appA/index.html
|
||||
+echo '<html><meta charset=utf-8><title>app2</title><body><h1>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).
|
|
@ -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);
|
|
@ -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;
|
||||
}
|
|
@ -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<std::string> 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());
|
Loading…
Reference in New Issue