From 088c28cbda796d58c6328cf82af73af8ede46be9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Gr=C3=A4f?= Date: Sun, 26 Aug 2018 19:43:52 +0200 Subject: [PATCH 1/4] #1.7.0 (#160) # 1.7.0 - First official Release of XMRigCC-amd #33 #3 - Full integration of xmrigCC-amd into XMRigCCServer/Dashboard with GPUInfo / remote logging - Config property to enable/disable config upload on startup (--cc-upload-config-on-startup) #80 - Refactoring of remote logging feature: #143 - Only deltas will be send to the XMRigCCServer - Fetching miner log on dashboard upon need - Maximum lines of log history kept per miner can be configured on XMRigCCServer - Fix correct hugepages status on Dashboard - Fix cpu affinity for single thread usage - Add all needed security infos to XMRigCCServer logging to harden the server (f.e. fail2ban) - Fix commandline params overwrite config.json #157 - Fix building miner with API support #145 --- CHANGELOG.md | 3 +++ src/cc/Httpd.cpp | 58 +++++++++++++++++++++++----------------------- src/cc/Httpd.h | 8 +++---- src/cc/Service.cpp | 56 +++++++++++++++++++++++++++++++------------- src/cc/Service.h | 2 +- src/config_cc.json | 2 +- src/version.h | 2 +- 7 files changed, 79 insertions(+), 52 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b2eb88..fca275b0 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -8,6 +8,9 @@ - Maximum lines of log history kept per miner can be configured on XMRigCCServer - Fix correct hugepages status on Dashboard - Fix cpu affinity for single thread usage +- Add all needed security infos to XMRigCCServer logging to harden the server (f.e. fail2ban) +- Fix commandline params overwrite config.json #157 +- Fix bulding of miner with API support Cannot #145 # 1.6.5 - Hashrate improve -> add autodetection mode for cpu-affinity - Hashrate improve, more stable hashrates -> refactor memory allocation diff --git a/src/cc/Httpd.cpp b/src/cc/Httpd.cpp index f222b10a..79cb7054 100644 --- a/src/cc/Httpd.cpp +++ b/src/cc/Httpd.cpp @@ -93,28 +93,29 @@ std::string Httpd::readFile(const std::string &fileName) return data.str(); } -unsigned Httpd::tokenAuth(struct MHD_Connection* connection) +unsigned Httpd::tokenAuth(struct MHD_Connection* connection, const std::string& clientIp) { if (!m_options->ccToken()) { - LOG_WARN("AccessToken not set. Access Granted!"); + LOG_WARN("[%s] 200 OK - WARNING AccessToken not set!", clientIp.c_str()); return MHD_HTTP_OK; } const char* header = MHD_lookup_connection_value(connection, MHD_HEADER_KIND, MHD_HTTP_HEADER_AUTHORIZATION); if (m_options->ccToken() && !header) { + LOG_WARN("[%s] 401 UNAUTHORIZED", clientIp.c_str()); return MHD_HTTP_UNAUTHORIZED; } const size_t size = strlen(header); if (size < 8 || strlen(m_options->ccToken()) != size - 7 || memcmp("Bearer ", header, 7) != 0) { - LOG_WARN("AccessToken wrong. Access Forbidden!"); + LOG_ERR("[%s] 403 FORBIDDEN - AccessToken wrong!", clientIp.c_str()); return MHD_HTTP_FORBIDDEN; } return strncmp(m_options->ccToken(), header + 7, strlen(m_options->ccToken())) == 0 ? MHD_HTTP_OK : MHD_HTTP_FORBIDDEN; } -unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp) +unsigned Httpd::basicAuth(struct MHD_Connection* connection, const std::string& clientIp, std::string& resp) { unsigned result = MHD_HTTP_OK; @@ -123,7 +124,7 @@ unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp) "Please configure admin user and pass to view this Page." ""); - LOG_WARN("Admin user/password not set. Access Forbidden!"); + LOG_ERR("[%s] 403 FORBIDDEN - Admin user/password not set!", clientIp.c_str()); result = MHD_HTTP_FORBIDDEN; } else { @@ -136,7 +137,7 @@ unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp) if (user == nullptr || strcmp(user, m_options->ccAdminUser()) != 0 || pass == nullptr || strcmp(pass, m_options->ccAdminPass()) != 0) { - LOG_WARN("Admin user/password wrong. Access Unauthorized!"); + LOG_ERR("[%s] 403 FORBIDDEN - Admin user/password wrong!", clientIp.c_str()); result = MHD_HTTP_UNAUTHORIZED; } @@ -148,6 +149,7 @@ unsigned Httpd::basicAuth(struct MHD_Connection* connection, std::string& resp) free(pass); } } else { + LOG_WARN("[%s] 401 UNAUTHORIZED", clientIp.c_str()); result = MHD_HTTP_UNAUTHORIZED; } } @@ -179,24 +181,36 @@ int Httpd::sendResponse(MHD_Connection* connection, unsigned status, MHD_Respons int Httpd::handler(void* httpd, MHD_Connection* connection, const char* url, const char* method, const char* version, const char* upload_data, size_t* upload_data_size, void** con_cls) { + std::string clientIp; + const MHD_ConnectionInfo *info = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); + if (info) { + char clientHost[NI_MAXHOST]; + int ec = getnameinfo(info->client_addr, sizeof(*info->client_addr), clientHost, sizeof(clientHost), + 0, 0, NI_NUMERICHOST|NI_NUMERICSERV); + + if (ec == 0) { + clientIp = std::string(clientHost); + } + } + if (strcmp(method, MHD_HTTP_METHOD_OPTIONS) == 0) { - LOG_INFO("OPTIONS Requested"); + LOG_INFO("[%s] OPTIONS Requested", clientIp.c_str()); return sendResponse(connection, MHD_HTTP_OK, nullptr, CONTENT_TYPE_HTML); } if (strcmp(method, MHD_HTTP_METHOD_GET) != 0 && strcmp(method, MHD_HTTP_METHOD_POST) != 0) { - LOG_ERR("HTTP_METHOD_NOT_ALLOWED"); + LOG_ERR("[%s] 405 METHOD NOT ALLOWED (%s)", clientIp.c_str(), method); return sendResponse(connection, MHD_HTTP_METHOD_NOT_ALLOWED, nullptr, CONTENT_TYPE_HTML); } if (strstr(url, "/client/")) { - unsigned status = static_cast(httpd)->tokenAuth(connection); + unsigned status = static_cast(httpd)->tokenAuth(connection, clientIp); if (status != MHD_HTTP_OK) { return sendResponse(connection, status, nullptr, CONTENT_TYPE_JSON); } } else { std::string resp; - unsigned status = static_cast(httpd)->basicAuth(connection, resp); + unsigned status = static_cast(httpd)->basicAuth(connection, clientIp, resp); if (status != MHD_HTTP_OK) { MHD_Response* rsp = nullptr; if (!resp.empty()) { @@ -207,15 +221,13 @@ int Httpd::handler(void* httpd, MHD_Connection* connection, const char* url, con } if (strcmp(method, MHD_HTTP_METHOD_GET) == 0) { - return handleGET(static_cast(httpd), connection, url); + return handleGET(static_cast(httpd), connection, clientIp, url); } else { - return handlePOST(static_cast(httpd), connection, url, upload_data, upload_data_size, con_cls); + return handlePOST(static_cast(httpd), connection, clientIp, url, upload_data, upload_data_size, con_cls); } - - return MHD_NO; } -int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, const char* urlPtr) +int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, const std::string& clientIp, const char* urlPtr) { std::string resp; std::string url(urlPtr); @@ -227,7 +239,7 @@ int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, cons clientId = std::string(clientIdPtr); } - unsigned status = Service::handleGET(httpd->m_options, url, clientId, resp); + unsigned status = Service::handleGET(httpd->m_options, url, clientIp, clientId, resp); MHD_Response* rsp = nullptr; if (!resp.empty()) { @@ -244,7 +256,7 @@ int Httpd::handleGET(const Httpd* httpd, struct MHD_Connection* connection, cons return sendResponse(connection, status, rsp, contentType); } -int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, const char* urlPtr, const char* upload_data, +int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, const std::string& clientIp, const char* urlPtr, const char* upload_data, size_t* upload_data_size, void** con_cls) { auto* cc = (ConnectionContext*)* con_cls; @@ -259,20 +271,8 @@ int Httpd::handlePOST(const Httpd* httpd, struct MHD_Connection* connection, con } else { std::string resp; std::string url(urlPtr); - std::string clientIp; std::string clientId; - const MHD_ConnectionInfo *info = MHD_get_connection_info(connection, MHD_CONNECTION_INFO_CLIENT_ADDRESS); - if (info) { - char clientHost[NI_MAXHOST]; - int ec = getnameinfo(info->client_addr, sizeof(*info->client_addr), clientHost, sizeof(clientHost), - 0, 0, NI_NUMERICHOST|NI_NUMERICSERV); - - if (ec == 0) { - clientIp = std::string(clientHost); - } - } - const char* clientIdPtr = MHD_lookup_connection_value(connection, MHD_GET_ARGUMENT_KIND, "clientId"); if (clientIdPtr) { clientId = std::string(clientIdPtr); diff --git a/src/cc/Httpd.h b/src/cc/Httpd.h index 8d3ee6fe..fcec7d83 100644 --- a/src/cc/Httpd.h +++ b/src/cc/Httpd.h @@ -51,12 +51,12 @@ private: static int sendResponse(MHD_Connection* connection, unsigned status, MHD_Response* rsp, const char* contentType); - unsigned basicAuth(MHD_Connection* connection, std::string &resp); - unsigned tokenAuth(MHD_Connection* connection); + unsigned basicAuth(MHD_Connection* connection, const std::string& clientIp, std::string &resp); + unsigned tokenAuth(MHD_Connection* connection, const std::string& clientIp); static int handler(void* httpd, MHD_Connection* connection, const char* url, const char* method, const char* version, const char* upload_data, size_t* upload_data_size, void**con_cls); - static int handleGET(const Httpd* httpd, MHD_Connection* connection, const char* url); - static int handlePOST(const Httpd* httpd, MHD_Connection* connection, const char* url, const char* upload_data, size_t* upload_data_size, void** con_cls); + static int handleGET(const Httpd* httpd, MHD_Connection* connection, const std::string& clientIp, const char* url); + static int handlePOST(const Httpd* httpd, MHD_Connection* connection, const std::string& clientIp, const char* url, const char* upload_data, size_t* upload_data_size, void** con_cls); static std::string readFile(const std::string &fileName); diff --git a/src/cc/Service.cpp b/src/cc/Service.cpp index a12d44be..9131ee31 100644 --- a/src/cc/Service.cpp +++ b/src/cc/Service.cpp @@ -62,13 +62,20 @@ void Service::release() uv_mutex_unlock(&m_mutex); } -unsigned Service::handleGET(const Options* options, const std::string& url, const std::string& clientId, std::string& resp) +unsigned Service::handleGET(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, std::string& resp) { uv_mutex_lock(&m_mutex); unsigned resultCode = MHD_HTTP_NOT_FOUND; - LOG_INFO("GET(url='%s', clientId='%s')", url.c_str(), clientId.c_str()); + std::string params; + if (!clientId.empty()) + { + params += "?clientId="; + params += clientId; + } + + LOG_INFO("[%s] GET '%s%s'", clientIp.c_str(), url.c_str(), params.c_str()); if (url == "/") { resultCode = getAdminPage(options, resp); @@ -82,10 +89,13 @@ unsigned Service::handleGET(const Options* options, const std::string& url, cons resultCode = getClientCommand(clientId, resp); } else if (url.rfind("/admin/getClientLog", 0) == 0) { resultCode = getClientLog(clientId, resp); + } else { + LOG_WARN("[%s] 404 NOT FOUND (%s)", clientIp.c_str(), url.c_str()); } } else { - LOG_ERR("Request does not contain clientId: %s", url.c_str()); + resultCode = MHD_HTTP_BAD_REQUEST; + LOG_ERR("[%s] 400 BAD REQUEST - Request does not contain clientId (%s)", clientIp.c_str(), url.c_str()); } } @@ -101,17 +111,32 @@ unsigned Service::handlePOST(const Options* options, const std::string& url, con unsigned resultCode = MHD_HTTP_NOT_FOUND; - LOG_INFO("POST(url='%s', clientIp='%s', clientId='%s', dataLen='%d')", - url.c_str(), clientIp.c_str(), clientId.c_str(), data.length()); + std::string params; + if (!clientId.empty()) + { + params += "?clientId="; + params += clientId; + } - if (url.rfind("/client/setClientStatus", 0) == 0) { - resultCode = setClientStatus(options, clientIp, clientId, data, resp); - } else if (url.rfind("/admin/setClientConfig", 0) == 0 || url.rfind("/client/setClientConfig", 0) == 0) { - resultCode = setClientConfig(options, clientId, data, resp); - } else if (url.rfind("/admin/setClientCommand", 0) == 0) { - resultCode = setClientCommand(clientId, data, resp); - } else if (url.rfind("/admin/resetClientStatusList", 0) == 0) { - resultCode = resetClientStatusList(data, resp); + LOG_INFO("[%s] POST '%s%s', dataLen='%d'", + clientIp.c_str(), url.c_str(), params.c_str(), data.length()); + + if (!clientId.empty()) { + if (url.rfind("/client/setClientStatus", 0) == 0) { + resultCode = setClientStatus(options, clientIp, clientId, data, resp); + } else if (url.rfind("/admin/setClientConfig", 0) == 0 || url.rfind("/client/setClientConfig", 0) == 0) { + resultCode = setClientConfig(options, clientId, data, resp); + } else if (url.rfind("/admin/setClientCommand", 0) == 0) { + resultCode = setClientCommand(clientId, data, resp); + } else { + LOG_WARN("[%s] 400 BAD REQUEST - Request does not contain clientId (%s)", clientIp.c_str(), url.c_str()); + } + } else { + if (url.rfind("/admin/resetClientStatusList", 0) == 0) { + resultCode = resetClientStatusList(data, resp); + } else { + LOG_WARN("[%s] 404 NOT FOUND (%s)", clientIp.c_str(), url.c_str()); + } } uv_mutex_unlock(&m_mutex); @@ -227,8 +252,6 @@ unsigned Service::setClientStatus(const Options* options, const std::string& cli rapidjson::Document document; if (!document.Parse(data.c_str()).HasParseError()) { - LOG_INFO("Status from client: %s", clientId.c_str()); - ClientStatus clientStatus; clientStatus.parseFromJson(document); clientStatus.setExternalIp(clientIp); @@ -245,7 +268,8 @@ unsigned Service::setClientStatus(const Options* options, const std::string& cli m_clientCommand.erase(clientId); } } else { - LOG_ERR("Parse Error Occured: %d", document.GetParseError()); + LOG_ERR("[%s] ClientStatus for client '%s' - Parse Error Occured: %d", + clientIp.c_str(), clientId.c_str(), document.GetParseError()); } return resultCode; diff --git a/src/cc/Service.h b/src/cc/Service.h index e909debd..b4e7d610 100644 --- a/src/cc/Service.h +++ b/src/cc/Service.h @@ -42,7 +42,7 @@ public: static bool start(); static void release(); - static unsigned handleGET(const Options* options, const std::string& url, const std::string& clientId, std::string& resp); + static unsigned handleGET(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, std::string& resp); static unsigned handlePOST(const Options* options, const std::string& url, const std::string& clientIp, const std::string& clientId, const std::string& data, std::string& resp); private: diff --git a/src/config_cc.json b/src/config_cc.json index ea4e492a..c753c2c9 100644 --- a/src/config_cc.json +++ b/src/config_cc.json @@ -1,7 +1,7 @@ { "background": false, // true to run the cc-server in the background (no console) "colors": true, // false to disable colored output - "log-file": null, // log all output to a file + "log-file": "server.log", // log all output to a file "syslog": false, // use system log for output messages "cc-server": { "port": 3344, // port the CC Server will listens on diff --git a/src/version.h b/src/version.h index df1b4407..f8ce56e2 100644 --- a/src/version.h +++ b/src/version.h @@ -36,7 +36,7 @@ #define APP_DESC "XMRigCC CPU miner" #define APP_COPYRIGHT "Copyright (C) 2017- BenDr0id" #endif -#define APP_VERSION "1.7.0_beta1 (based on XMRig)" +#define APP_VERSION "1.7.0 (based on XMRig)" #define APP_DOMAIN "" #define APP_SITE "https://github.com/Bendr0id/xmrigCC" #define APP_KIND "cpu" From f295d2eb95fc4050bc4d1d0301d3512e9a9269d7 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Gr=C3=A4f?= Date: Thu, 30 Aug 2018 21:39:22 +0200 Subject: [PATCH 2/4] Fix for segfault in file logger --- src/log/FileLog.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/log/FileLog.cpp b/src/log/FileLog.cpp index 77f2e713..7d04e574 100644 --- a/src/log/FileLog.cpp +++ b/src/log/FileLog.cpp @@ -98,5 +98,5 @@ void FileLog::write(char *data, size_t size) uv_fs_t *req = new uv_fs_t; req->data = buf.base; - uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, 0, FileLog::onWrite); + uv_fs_write(uv_default_loop(), req, m_file, &buf, 1, -1, FileLog::onWrite); } From e1aac6d4508a80e4125923570c8b9debdd476cfd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ben=20Gr=C3=A4f?= Date: Mon, 10 Sep 2018 15:35:49 +0200 Subject: [PATCH 3/4] Update config_cc.json --- src/config_cc.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/config_cc.json b/src/config_cc.json index c753c2c9..ea4e492a 100644 --- a/src/config_cc.json +++ b/src/config_cc.json @@ -1,7 +1,7 @@ { "background": false, // true to run the cc-server in the background (no console) "colors": true, // false to disable colored output - "log-file": "server.log", // log all output to a file + "log-file": null, // log all output to a file "syslog": false, // use system log for output messages "cc-server": { "port": 3344, // port the CC Server will listens on From b3a8783498a66f9f3777e8b5db99e16b554f78f8 Mon Sep 17 00:00:00 2001 From: djfinch Date: Tue, 11 Sep 2018 11:33:29 +0200 Subject: [PATCH 4/4] OSX compile fix. (#166) * OSX compile fix. --- src/cc/GPUInfo.cpp | 14 +++++++------- 1 file changed, 7 insertions(+), 7 deletions(-) diff --git a/src/cc/GPUInfo.cpp b/src/cc/GPUInfo.cpp index 72ba83f9..324d7408 100644 --- a/src/cc/GPUInfo.cpp +++ b/src/cc/GPUInfo.cpp @@ -40,13 +40,13 @@ rapidjson::Value GPUInfo::toJson(rapidjson::MemoryPoolAllocator (m_deviceIdx), allocator); + gpuInfo.AddMember("raw_intensity", static_cast(m_rawIntensity), allocator); + gpuInfo.AddMember("work_size", static_cast(m_workSize), allocator); + gpuInfo.AddMember("max_work_size", static_cast(m_maxWorkSize), allocator); + gpuInfo.AddMember("free_mem", static_cast(m_freeMem), allocator); + gpuInfo.AddMember("mem_chunk", m_memChunk, allocator); + gpuInfo.AddMember("comp_mode", m_memChunk, allocator); gpuInfo.AddMember("compute_units", m_memChunk, allocator); return gpuInfo;