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.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 | 58 ++++++++++++++++++++++++++++++++-------------- src/cc/Service.h | 2 +- src/config_cc.json | 2 +- src/version.h | 2 +- 7 files changed, 80 insertions(+), 53 deletions(-) diff --git a/CHANGELOG.md b/CHANGELOG.md index 16b2eb885e..fca275b047 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 f222b10a22..79cb7054ba 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 8d3ee6fe0a..fcec7d8303 100644 --- a/src/cc/Httpd.h +++ b/src/cc/Httpd.h @@ -51,12 +51,12 @@ class Httpd 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 a12d44bea4..9131ee3173 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()); - - 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); + std::string params; + if (!clientId.empty()) + { + params += "?clientId="; + params += clientId; + } + + 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 e909debd6d..b4e7d61047 100644 --- a/src/cc/Service.h +++ b/src/cc/Service.h @@ -42,7 +42,7 @@ class Service 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 ea4e492abb..c753c2c9fe 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 df1b4407a5..f8ce56e256 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"