大家好,欢迎来到IT知识分享网。
只需要在命令行加 –tls即可:
C:\Users\bonel\Desktop\xmrig-6.18.0-msvc-win64\xmrig-6.18.0>xmrig.exe -o pool.hashvault.pro:3333 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD -p x --tls
* ABOUT XMRig/6.18.0 MSVC/2019
* LIBS libuv/1.44.1 OpenSSL/1.1.1o hwloc/2.7.1
* HUGE PAGES unavailable
* 1GB PAGES unavailable
* CPU 11th Gen Intel(R) Core(TM) i5-11400 @ 2.60GHz (1) 64-bit AES VM
L2:1.5 MB L3:36.0 MB 3C/3T NUMA:1
* MEMORY 1.2/3.0 GB (38%)
* MOTHERBOARD innotek GmbH - VirtualBox
* DONATE 1%
* ASSEMBLY auto:intel
* POOL #1 pool.hashvault.pro:3333 algo auto
* COMMANDS hashrate, pause, resume, results, connection
* OPENCL disabled
* CUDA disabled
[2022-07-12 10:28:55.214] net use pool pool.hashvault.pro:3333 TLSv1.3 125.253.92.50
[2022-07-12 10:28:55.220] net fingerprint (SHA-256): "420c7850e09b7c0bdcf748a7da9eb3647daf8515718f36d9ccfdd6b9ff834b14"
[2022-07-12 10:28:55.221] net new job from pool.hashvault.pro:3333 diff 72000 algo rx/0 height 2665379 (6 tx)
[2022-07-12 10:28:55.222] cpu use argon2 implementation AVX2
[2022-07-12 10:28:55.222] msr to access MSR registers Administrator privileges required.
[2022-07-12 10:28:55.222] msr FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW
[2022-07-12 10:28:55.223] randomx init dataset algo rx/0 (3 threads) seed 6b9d4c7053de0009...
[2022-07-12 10:28:55.223] randomx allocated 2336 MB (2080+256) huge pages 0% 0/1168 +JIT (0 ms)
[2022-07-12 10:29:01.257] net new job from pool.hashvault.pro:3333 diff 116758 algo rx/0 height 2665379 (6 tx)
[2022-07-12 10:29:01.785] signal Ctrl+C received, exiting
[2022-07-12 10:29:07.345] randomx dataset ready (12119 ms)
C:\Users\bonel\Desktop\xmrig-6.18.0-msvc-win64\xmrig-6.18.0>
看下矿池的IP:
C:\Users\bonelee>ping pool.hashvault.pro
正在 Ping pool.hashvault.pro [131.153.76.130] 具有 32 字节的数据:
来自 131.153.76.130 的回复: 字节=32 时间=235ms TTL=43
来自 131.153.76.130 的回复: 字节=32 时间=233ms TTL=43
131.153.76.130 的 Ping 统计信息:
数据包: 已发送 = 2,已接收 = 2,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 233ms,最长 = 235ms,平均 = 234ms
Control-C
然后在挖矿过程中抓包,可以看到,在通信过程中完全使用了tls1.3的通信流量:
这下通过流量检测有些麻烦了!
补充,我又在挖矿过程中进行了一次抓包,
D:\share\xmrig-6.18.0-msvc-win64\xmrig-6.18.0>xmrig.exe -o pool.hashvault.pro:3333 -u 48edfHu7V9Z84YzzMa6fUueoELZ9ZRXq9VetWzYGzKt52XU5xvqgzYnDK9URnRoJMk1j8nLwEVsaSWJ4fhdUyZijBGUicoD -p x --tls
* ABOUT XMRig/6.18.0 MSVC/2019
* LIBS libuv/1.44.1 OpenSSL/1.1.1o hwloc/2.7.1
* HUGE PAGES permission granted
* 1GB PAGES unavailable
* CPU 11th Gen Intel(R) Core(TM) i5-11400 @ 2.60GHz (1) 64-bit AES
L2:3.0 MB L3:12.0 MB 6C/12T NUMA:1
* MEMORY 9.5/15.7 GB (60%)
Controller0-ChannelA-DIMM0: 16 GB DDR4 @ 2933 MHz M378A2G43AB3-CWE
Controller0-ChannelB-DIMM0: <empty>
* MOTHERBOARD LENOVO - 3730
* DONATE 1%
* ASSEMBLY auto:intel
* POOL #1 pool.hashvault.pro:3333 algo auto
* COMMANDS hashrate, pause, resume, results, connection
* OPENCL disabled
* CUDA disabled
[2022-07-12 14:14:22.717] net use pool pool.hashvault.pro:3333 TLSv1.3 125.253.92.50
[2022-07-12 14:14:22.718] net fingerprint (SHA-256): "420c7850e09b7c0bdcf748a7da9eb3647daf8515718f36d9ccfdd6b9ff834b14"
[2022-07-12 14:14:22.719] net new job from pool.hashvault.pro:3333 diff 72000 algo rx/0 height 2665490 (4 tx)
[2022-07-12 14:14:22.719] cpu use argon2 implementation AVX-512F
[2022-07-12 14:14:22.720] msr to access MSR registers Administrator privileges required.
[2022-07-12 14:14:22.720] msr FAILED TO APPLY MSR MOD, HASHRATE WILL BE LOW
[2022-07-12 14:14:22.721] randomx init dataset algo rx/0 (12 threads) seed 6b9d4c7053de0009...
[2022-07-12 14:14:22.726] randomx allocated 2336 MB (2080+256) huge pages 0% 0/1168 +JIT (5 ms)
[2022-07-12 14:14:26.652] randomx dataset ready (3926 ms)
[2022-07-12 14:14:26.652] cpu use profile rx (6 threads) scratchpad 2048 KB
[2022-07-12 14:14:26.677] cpu READY threads 6/6 (6) huge pages 0% 0/6 memory 12288 KB (24 ms)
[2022-07-12 14:14:58.596] net new job from pool.hashvault.pro:3333 diff 72000 algo rx/0 height 2665491 (9 tx)
[2022-07-12 14:15:07.586] cpu accepted (1/0) diff 72000 (274 ms)
[2022-07-12 14:15:24.414] cpu accepted (2/0) diff 72000 (1621 ms)
[2022-07-12 14:15:26.716] miner speed 10s/60s/15m 1020.2 n/a n/a H/s max 1092.4 H/s
[2022-07-12 14:15:56.798] cpu accepted (3/0) diff 72000 (297 ms)
[2022-07-12 14:16:01.720] net new job from pool.hashvault.pro:3333 diff 66120 algo rx/0 height 2665491 (9 tx)
[2022-07-12 14:16:21.318] signal Ctrl+C received, exiting
[2022-07-12 14:16:21.325] cpu stopped (7 ms)
D:\share\xmrig-6.18.0-msvc-win64\xmrig-6.18.0>PING pool.hashvault.pro
正在 Ping pool.hashvault.pro [125.253.92.50] 具有 32 字节的数据:
来自 125.253.92.50 的回复: 字节=32 时间=148ms TTL=47
来自 125.253.92.50 的回复: 字节=32 时间=144ms TTL=47
125.253.92.50 的 Ping 统计信息:
数据包: 已发送 = 2,已接收 = 2,丢失 = 0 (0% 丢失),
往返行程的估计时间(以毫秒为单位):
最短 = 144ms,最长 = 148ms,平均 = 146ms
Control-C
^C
D:\share\xmrig-6.18.0-msvc-win64\xmrig-6.18.0>
虽然cmd里提示tls1.3,但是我看到却是tls1.2,咋回事?
我又试了几次,因为有动态dns,这次IP是131.153.76.130,不过还是tls1.3
又试了几次,还是tls1.3
源码分析,用的是网络通信client IClient:
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_ICLIENT_H
#define XMRIG_ICLIENT_H
#include "3rdparty/rapidjson/fwd.h"
#include "base/tools/Object.h"
#include <functional>
namespace xmrig {
class Algorithm;
class Job;
class JobResult;
class Pool;
class ProxyUrl;
class String;
class IClient
{
public:
XMRIG_DISABLE_COPY_MOVE(IClient)
enum Extension {
EXT_ALGO,
EXT_NICEHASH,
EXT_CONNECT,
EXT_TLS,
EXT_KEEPALIVE,
EXT_MAX
};
using Callback = std::function<void(const rapidjson::Value &result, bool success, uint64_t elapsed)>;
IClient() = default;
virtual ~IClient() = default;
virtual bool disconnect() = 0;
virtual bool hasExtension(Extension extension) const noexcept = 0;
virtual bool isEnabled() const = 0;
virtual bool isTLS() const = 0;
virtual const char *mode() const = 0;
virtual const char *tag() const = 0;
virtual const char *tlsFingerprint() const = 0;
virtual const char *tlsVersion() const = 0;
virtual const Job &job() const = 0;
virtual const Pool &pool() const = 0;
virtual const String &ip() const = 0;
virtual int id() const = 0;
virtual int64_t send(const rapidjson::Value &obj, Callback callback) = 0;
virtual int64_t send(const rapidjson::Value &obj) = 0;
virtual int64_t sequence() const = 0;
virtual int64_t submit(const JobResult &result) = 0;
virtual void connect() = 0;
virtual void connect(const Pool &pool) = 0;
virtual void deleteLater() = 0;
virtual void setAlgo(const Algorithm &algo) = 0;
virtual void setEnabled(bool enabled) = 0;
virtual void setPool(const Pool &pool) = 0;
virtual void setProxy(const ProxyUrl &proxy) = 0;
virtual void setQuiet(bool quiet) = 0;
virtual void setRetries(int retries) = 0;
virtual void setRetryPause(uint64_t ms) = 0;
virtual void tick(uint64_t now) = 0;
};
} /* namespace xmrig */
#endif // XMRIG_ICLIENT_H
然后看到baseclient继承自它,
/* XMRig
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_BASECLIENT_H
#define XMRIG_BASECLIENT_H
#include <map>
#include "base/kernel/interfaces/IClient.h"
#include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h"
#include "base/tools/Chrono.h"
namespace xmrig {
class IClientListener;
class SubmitResult;
class BaseClient : public IClient
{
public:
BaseClient(int id, IClientListener *listener);
protected:
inline bool isEnabled() const override { return m_enabled; }
inline const char *tag() const override { return m_tag.c_str(); }
inline const Job &job() const override { return m_job; }
inline const Pool &pool() const override { return m_pool; }
inline const String &ip() const override { return m_ip; }
inline int id() const override { return m_id; }
inline int64_t sequence() const override { return m_sequence; }
inline void setAlgo(const Algorithm &algo) override { m_pool.setAlgo(algo); }
inline void setEnabled(bool enabled) override { m_enabled = enabled; }
inline void setProxy(const ProxyUrl &proxy) override { m_pool.setProxy(proxy); }
inline void setQuiet(bool quiet) override { m_quiet = quiet; }
inline void setRetries(int retries) override { m_retries = retries; }
inline void setRetryPause(uint64_t ms) override { m_retryPause = ms; }
void setPool(const Pool &pool) override;
protected:
enum SocketState {
UnconnectedState,
HostLookupState,
ConnectingState,
ConnectedState,
ClosingState,
ReconnectingState
};
struct SendResult
{
inline SendResult(Callback &&callback) : callback(callback), ts(Chrono::steadyMSecs()) {}
Callback callback;
const uint64_t ts;
};
inline bool isQuiet() const { return m_quiet || m_failures >= m_retries; }
virtual bool handleResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
bool handleSubmitResponse(int64_t id, const char *error = nullptr);
bool m_quiet = false;
IClientListener *m_listener;
int m_id;
int m_retries = 5;
int64_t m_failures = 0;
Job m_job;
Pool m_pool;
SocketState m_state = UnconnectedState;
std::map<int64_t, SendResult> m_callbacks;
std::map<int64_t, SubmitResult> m_results;
std::string m_tag;
String m_ip;
String m_password;
String m_rigId;
String m_user;
uint64_t m_retryPause = 5000;
static int64_t m_sequence;
private:
bool m_enabled = true;
};
} /* namespace xmrig */
#endif /* XMRIG_BASECLIENT_H */
真正有意义的client来了,setpool,login啥的都在里面
/* XMRig
* Copyright (c) 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CLIENT_H
#define XMRIG_CLIENT_H
#include <bitset>
#include <map>
#include <uv.h>
#include <vector>
#include "base/kernel/interfaces/IDnsListener.h"
#include "base/kernel/interfaces/ILineListener.h"
#include "base/net/stratum/BaseClient.h"
#include "base/net/stratum/Job.h"
#include "base/net/stratum/Pool.h"
#include "base/net/stratum/SubmitResult.h"
#include "base/net/tools/LineReader.h"
#include "base/net/tools/Storage.h"
#include "base/tools/Object.h"
using BIO = struct bio_st;
namespace xmrig {
class DnsRequest;
class IClientListener;
class JobResult;
class Client : public BaseClient, public IDnsListener, public ILineListener
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Client)
constexpr static uint64_t kConnectTimeout = 20 * 1000;
constexpr static uint64_t kResponseTimeout = 20 * 1000;
constexpr static size_t kMaxSendBufferSize = 1024 * 16;
Client(int id, const char *agent, IClientListener *listener);
~Client() override;
protected:
bool disconnect() override;
bool isTLS() const override;
const char *tlsFingerprint() const override;
const char *tlsVersion() const override;
int64_t send(const rapidjson::Value &obj, Callback callback) override;
int64_t send(const rapidjson::Value &obj) override;
int64_t submit(const JobResult &result) override;
void connect() override;
void connect(const Pool &pool) override;
void deleteLater() override;
void tick(uint64_t now) override;
void onResolved(const DnsRecords &records, int status, const char *error) override;
inline bool hasExtension(Extension extension) const noexcept override { return m_extensions.test(extension); }
inline const char *mode() const override { return "pool"; }
inline void onLine(char *line, size_t size) override { parse(line, size); }
inline const char *agent() const { return m_agent; }
inline const char *url() const { return m_pool.url(); }
inline const String &rpcId() const { return m_rpcId; }
inline void setRpcId(const char *id) { m_rpcId = id; }
inline void setPoolUrl(const char *url) { m_pool.setUrl(url); }
virtual bool parseLogin(const rapidjson::Value &result, int *code);
virtual void login();
virtual void parseNotification(const char* method, const rapidjson::Value& params, const rapidjson::Value& error);
bool close();
virtual void onClose();
private:
class Socks5;
class Tls;
bool parseJob(const rapidjson::Value ¶ms, int *code);
bool send(BIO *bio);
bool verifyAlgorithm(const Algorithm &algorithm, const char *algo) const;
bool write(const uv_buf_t &buf);
int resolve(const String &host);
int64_t send(size_t size);
void connect(const sockaddr *addr);
void handshake();
void parse(char *line, size_t len);
void parseExtensions(const rapidjson::Value &result);
void parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error);
void ping();
void read(ssize_t nread, const uv_buf_t *buf);
void reconnect();
void setState(SocketState state);
void startTimeout();
inline SocketState state() const { return m_state; }
inline uv_stream_t *stream() const { return reinterpret_cast<uv_stream_t *>(m_socket); }
inline void setExtension(Extension ext, bool enable) noexcept { m_extensions.set(ext, enable); }
template<Extension ext> inline bool has() const noexcept { return m_extensions.test(ext); }
static bool isCriticalError(const char *message);
static void onClose(uv_handle_t *handle);
static void onConnect(uv_connect_t *req, int status);
static void onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf);
static inline Client *getClient(void *data) { return m_storage.get(data); }
const char *m_agent;
LineReader m_reader;
Socks5 *m_socks5 = nullptr;
std::bitset<EXT_MAX> m_extensions;
std::shared_ptr<DnsRequest> m_dns;
std::vector<char> m_sendBuf;
std::vector<char> m_tempBuf;
String m_rpcId;
Tls *m_tls = nullptr;
uint64_t m_expire = 0;
uint64_t m_jobs = 0;
uint64_t m_keepAlive = 0;
uintptr_t m_key = 0;
uv_tcp_t *m_socket = nullptr;
static Storage<Client> m_storage;
};
template<> inline bool Client::has<Client::EXT_NICEHASH>() const noexcept { return m_extensions.test(EXT_NICEHASH) || m_pool.isNicehash(); }
template<> inline bool Client::has<Client::EXT_KEEPALIVE>() const noexcept { return m_extensions.test(EXT_KEEPALIVE) || m_pool.keepAlive() > 0; }
} /* namespace xmrig */
#endif /* XMRIG_CLIENT_H */
其中,m_tls就是负责加密传输:
/* XMRig
* Copyright (c) 2019 jtgrassie <https://github.com/jtgrassie>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include <cassert>
#include <cinttypes>
#include <iterator>
#include <cstdio>
#include <cstring>
#include <utility>
#include <sstream>
#ifdef XMRIG_FEATURE_TLS
# include <openssl/ssl.h>
# include <openssl/err.h>
# include "base/net/stratum/Tls.h"
#endif
#include "base/net/stratum/Client.h"
#include "3rdparty/rapidjson/document.h"
#include "3rdparty/rapidjson/error/en.h"
#include "3rdparty/rapidjson/stringbuffer.h"
#include "3rdparty/rapidjson/writer.h"
#include "base/io/json/Json.h"
#include "base/io/json/JsonRequest.h"
#include "base/io/log/Log.h"
#include "base/kernel/interfaces/IClientListener.h"
#include "base/net/dns/Dns.h"
#include "base/net/dns/DnsRecords.h"
#include "base/net/stratum/Socks5.h"
#include "base/net/tools/NetBuffer.h"
#include "base/tools/Chrono.h"
#include "base/tools/Cvt.h"
#include "base/tools/cryptonote/BlobReader.h"
#include "net/JobResult.h"
#ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
namespace xmrig {
Storage<Client> Client::m_storage;
} /* namespace xmrig */
#ifdef APP_DEBUG
static const char *states[] = {
"unconnected",
"host-lookup",
"connecting",
"connected",
"closing",
"reconnecting"
};
#endif
xmrig::Client::Client(int id, const char *agent, IClientListener *listener) :
BaseClient(id, listener),
m_agent(agent),
m_sendBuf(1024),
m_tempBuf(256)
{
m_reader.setListener(this);
m_key = m_storage.add(this);
}
xmrig::Client::~Client()
{
delete m_socket;
}
bool xmrig::Client::disconnect()
{
m_keepAlive = 0;
m_expire = 0;
m_failures = -1;
return close();
}
bool xmrig::Client::isTLS() const
{
# ifdef XMRIG_FEATURE_TLS
return m_pool.isTLS() && m_tls;
# else
return false;
# endif
}
const char *xmrig::Client::tlsFingerprint() const
{
# ifdef XMRIG_FEATURE_TLS
if (isTLS() && m_pool.fingerprint() == nullptr) {
return m_tls->fingerprint();
}
# endif
return nullptr;
}
const char *xmrig::Client::tlsVersion() const
{
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
return m_tls->version();
}
# endif
return nullptr;
}
int64_t xmrig::Client::send(const rapidjson::Value &obj, Callback callback)
{
assert(obj["id"] == sequence());
m_callbacks.insert({ sequence(), std::move(callback) });
return send(obj);
}
int64_t xmrig::Client::send(const rapidjson::Value &obj)
{
using namespace rapidjson;
StringBuffer buffer(nullptr, 512);
Writer<StringBuffer> writer(buffer);
obj.Accept(writer);
const size_t size = buffer.GetSize();
if (size > kMaxSendBufferSize) {
LOG_ERR("%s " RED("send failed: ") RED_BOLD("\"max send buffer size exceeded: %zu\""), tag(), size);
close();
return -1;
}
if (size > (m_sendBuf.size() - 2)) {
m_sendBuf.resize(((size + 1) / 1024 + 1) * 1024);
}
memcpy(m_sendBuf.data(), buffer.GetString(), size);
m_sendBuf[size] = '\n';
m_sendBuf[size + 1] = '\0';
return send(size + 1);
}
int64_t xmrig::Client::submit(const JobResult &result)
{
# ifndef XMRIG_PROXY_PROJECT
if (result.clientId != m_rpcId || m_rpcId.isNull() || m_state != ConnectedState) {
return -1;
}
# endif
if (result.diff == 0) {
close();
return -1;
}
using namespace rapidjson;
# ifdef XMRIG_PROXY_PROJECT
const char *nonce = result.nonce;
const char *data = result.result;
# else
char *nonce = m_tempBuf.data();
char *data = m_tempBuf.data() + 16;
char *signature = m_tempBuf.data() + 88;
Cvt::toHex(nonce, sizeof(uint32_t) * 2 + 1, reinterpret_cast<const uint8_t *>(&result.nonce), sizeof(uint32_t));
Cvt::toHex(data, 65, result.result(), 32);
if (result.minerSignature()) {
Cvt::toHex(signature, 129, result.minerSignature(), 64);
}
# endif
Document doc(kObjectType);
auto &allocator = doc.GetAllocator();
Value params(kObjectType);
params.AddMember("id", StringRef(m_rpcId.data()), allocator);
params.AddMember("job_id", StringRef(result.jobId.data()), allocator);
params.AddMember("nonce", StringRef(nonce), allocator);
params.AddMember("result", StringRef(data), allocator);
# ifndef XMRIG_PROXY_PROJECT
if (result.minerSignature()) {
params.AddMember("sig", StringRef(signature), allocator);
}
# else
if (result.sig) {
params.AddMember("sig", StringRef(result.sig), allocator);
}
# endif
if (has<EXT_ALGO>() && result.algorithm.isValid()) {
params.AddMember("algo", StringRef(result.algorithm.name()), allocator);
}
JsonRequest::create(doc, m_sequence, "submit", params);
# ifdef XMRIG_PROXY_PROJECT
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), result.id, 0);
# else
m_results[m_sequence] = SubmitResult(m_sequence, result.diff, result.actualDiff(), 0, result.backend);
# endif
return send(doc);
}
void xmrig::Client::connect()
{
if (m_pool.proxy().isValid()) {
m_socks5 = new Socks5(this);
resolve(m_pool.proxy().host());
return;
}
# ifdef XMRIG_FEATURE_TLS
if (m_pool.isTLS()) {
m_tls = new Tls(this);
}
# endif
resolve(m_pool.host());
}
void xmrig::Client::connect(const Pool &pool)
{
setPool(pool);
connect();
}
void xmrig::Client::deleteLater()
{
if (!m_listener) {
return;
}
m_listener = nullptr;
if (!disconnect()) {
m_storage.remove(m_key);
}
}
void xmrig::Client::tick(uint64_t now)
{
if (m_state == ConnectedState) {
if (m_expire && now > m_expire) {
LOG_DEBUG_ERR("[%s] timeout", url());
close();
}
else if (m_keepAlive && now > m_keepAlive) {
ping();
}
return;
}
if (m_state == ReconnectingState && m_expire && now > m_expire) {
return connect();
}
if (m_state == ConnectingState && m_expire && now > m_expire) {
close();
}
}
void xmrig::Client::onResolved(const DnsRecords &records, int status, const char *error)
{
m_dns.reset();
assert(m_listener != nullptr);
if (!m_listener) {
return reconnect();
}
if (status < 0 && records.isEmpty()) {
if (!isQuiet()) {
LOG_ERR("%s " RED("DNS error: ") RED_BOLD("\"%s\""), tag(), error);
}
return reconnect();
}
const auto &record = records.get();
m_ip = record.ip();
connect(record.addr(m_socks5 ? m_pool.proxy().port() : m_pool.port()));
}
bool xmrig::Client::close()
{
if (m_state == ClosingState) {
return m_socket != nullptr;
}
if (m_state == UnconnectedState || m_socket == nullptr) {
return false;
}
setState(ClosingState);
if (uv_is_closing(reinterpret_cast<uv_handle_t*>(m_socket)) == 0) {
uv_close(reinterpret_cast<uv_handle_t*>(m_socket), Client::onClose);
}
return true;
}
bool xmrig::Client::parseJob(const rapidjson::Value ¶ms, int *code)
{
if (!params.IsObject()) {
*code = 2;
return false;
}
Job job(has<EXT_NICEHASH>(), m_pool.algorithm(), m_rpcId);
if (!job.setId(params["job_id"].GetString())) {
*code = 3;
return false;
}
const char *algo = Json::getString(params, "algo");
const char *blobData = Json::getString(params, "blob");
if (algo) {
job.setAlgorithm(algo);
}
else if (m_pool.coin().isValid()) {
uint8_t blobVersion = 0;
if (blobData) {
Cvt::fromHex(&blobVersion, 1, blobData, 2);
}
job.setAlgorithm(m_pool.coin().algorithm(blobVersion));
}
# ifdef XMRIG_FEATURE_HTTP
if (m_pool.mode() == Pool::MODE_SELF_SELECT) {
job.setExtraNonce(Json::getString(params, "extra_nonce"));
job.setPoolWallet(Json::getString(params, "pool_wallet"));
if (job.extraNonce().isNull() || job.poolWallet().isNull()) {
*code = 4;
return false;
}
}
else
# endif
{
if (!job.setBlob(blobData)) {
*code = 4;
return false;
}
}
if (!job.setTarget(params["target"].GetString())) {
*code = 5;
return false;
}
job.setHeight(Json::getUint64(params, "height"));
if (!verifyAlgorithm(job.algorithm(), algo)) {
*code = 6;
return false;
}
if (m_pool.mode() != Pool::MODE_SELF_SELECT && job.algorithm().family() == Algorithm::RANDOM_X && !job.setSeedHash(Json::getString(params, "seed_hash"))) {
*code = 7;
return false;
}
job.setSigKey(Json::getString(params, "sig_key"));
m_job.setClientId(m_rpcId);
if (m_job != job) {
m_jobs++;
m_job = std::move(job);
return true;
}
if (m_jobs == 0) { // https://github.com/xmrig/xmrig/issues/459
return false;
}
if (!isQuiet()) {
LOG_WARN("%s " YELLOW("duplicate job received, reconnect"), tag());
}
close();
return false;
}
bool xmrig::Client::send(BIO *bio)
{
# ifdef XMRIG_FEATURE_TLS
uv_buf_t buf;
buf.len = BIO_get_mem_data(bio, &buf.base); // NOLINT(cppcoreguidelines-pro-type-cstyle-cast)
if (buf.len == 0) {
return true;
}
LOG_DEBUG("[%s] TLS send (%d bytes)", url(), static_cast<int>(buf.len));
bool result = false;
if (state() == ConnectedState && uv_is_writable(stream())) {
result = write(buf);
}
else {
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", url(), m_state);
}
(void) BIO_reset(bio);
return result;
# else
return false;
# endif
}
bool xmrig::Client::verifyAlgorithm(const Algorithm &algorithm, const char *algo) const
{
if (!algorithm.isValid()) {
if (!isQuiet()) {
if (algo == nullptr) {
LOG_ERR("%s " RED("unknown algorithm, make sure you set \"algo\" or \"coin\" option"), tag(), algo);
}
else {
LOG_ERR("%s " RED("unsupported algorithm ") RED_BOLD("\"%s\" ") RED("detected, reconnect"), tag(), algo);
}
}
return false;
}
bool ok = true;
m_listener->onVerifyAlgorithm(this, algorithm, &ok);
if (!ok && !isQuiet()) {
LOG_ERR("%s " RED("incompatible/disabled algorithm ") RED_BOLD("\"%s\" ") RED("detected, reconnect"), tag(), algorithm.name());
}
return ok;
}
bool xmrig::Client::write(const uv_buf_t &buf)
{
const int rc = uv_try_write(stream(), &buf, 1);
if (static_cast<size_t>(rc) == buf.len) {
return true;
}
if (!isQuiet()) {
LOG_ERR("%s " RED("write error: ") RED_BOLD("\"%s\""), tag(), uv_strerror(rc));
}
close();
return false;
}
int xmrig::Client::resolve(const String &host)
{
setState(HostLookupState);
m_reader.reset();
if (m_failures == -1) {
m_failures = 0;
}
m_dns = Dns::resolve(host, this);
return 0;
}
int64_t xmrig::Client::send(size_t size)
{
LOG_DEBUG("[%s] send (%d bytes): \"%.*s\"", url(), size, static_cast<int>(size) - 1, m_sendBuf.data());
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
if (!m_tls->send(m_sendBuf.data(), size)) {
return -1;
}
}
else
# endif
{
if (state() != ConnectedState || !uv_is_writable(stream())) {
LOG_DEBUG_ERR("[%s] send failed, invalid state: %d", url(), m_state);
return -1;
}
uv_buf_t buf = uv_buf_init(m_sendBuf.data(), (unsigned int) size);
if (!write(buf)) {
return -1;
}
}
m_expire = Chrono::steadyMSecs() + kResponseTimeout;
return m_sequence++;
}
void xmrig::Client::connect(const sockaddr *addr)
{
setState(ConnectingState);
auto req = new uv_connect_t;
req->data = m_storage.ptr(m_key);
m_socket = new uv_tcp_t;
m_socket->data = m_storage.ptr(m_key);
uv_tcp_init(uv_default_loop(), m_socket);
uv_tcp_nodelay(m_socket, 1);
# ifndef WIN32
uv_tcp_keepalive(m_socket, 1, 60);
# endif
uv_tcp_connect(req, m_socket, addr, onConnect);
}
void xmrig::Client::handshake()
{
if (m_socks5) {
return m_socks5->handshake();
}
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
m_expire = Chrono::steadyMSecs() + kResponseTimeout;
m_tls->handshake();
}
else
# endif
{
login();
}
}
bool xmrig::Client::parseLogin(const rapidjson::Value &result, int *code)
{
setRpcId(Json::getString(result, "id"));
if (rpcId().isNull()) {
*code = 1;
return false;
}
parseExtensions(result);
const bool rc = parseJob(result["job"], code);
m_jobs = 0;
return rc;
}
void xmrig::Client::login()
{
using namespace rapidjson;
m_results.clear();
Document doc(kObjectType);
auto &allocator = doc.GetAllocator();
Value params(kObjectType);
params.AddMember("login", m_user.toJSON(), allocator);
params.AddMember("pass", m_password.toJSON(), allocator);
params.AddMember("agent", StringRef(m_agent), allocator);
if (!m_rigId.isNull()) {
params.AddMember("rigid", m_rigId.toJSON(), allocator);
}
m_listener->onLogin(this, doc, params);
JsonRequest::create(doc, 1, "login", params);
send(doc);
}
void xmrig::Client::onClose()
{
delete m_socket;
m_socket = nullptr;
setState(UnconnectedState);
# ifdef XMRIG_FEATURE_TLS
if (m_tls) {
delete m_tls;
m_tls = nullptr;
}
# endif
reconnect();
}
void xmrig::Client::parse(char *line, size_t len)
{
startTimeout();
LOG_DEBUG("[%s] received (%d bytes): \"%.*s\"", url(), len, static_cast<int>(len), line);
if (len < 22 || line[0] != '{') {
if (!isQuiet()) {
LOG_ERR("%s " RED("JSON decode failed"), tag());
}
return;
}
rapidjson::Document doc;
if (doc.ParseInsitu(line).HasParseError()) {
if (!isQuiet()) {
LOG_ERR("%s " RED("JSON decode failed: ") RED_BOLD("\"%s\""), tag(), rapidjson::GetParseError_En(doc.GetParseError()));
}
return;
}
if (!doc.IsObject()) {
return;
}
const auto &id = Json::getValue(doc, "id");
const auto &error = Json::getValue(doc, "error");
const char *method = Json::getString(doc, "method");
if (method && strcmp(method, "client.reconnect") == 0) {
const auto ¶ms = Json::getValue(doc, "params");
if (!params.IsArray()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: params is not an array"), tag());
return;
}
auto arr = params.GetArray();
if (arr.Empty()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: params array is empty"), tag());
return;
}
if (arr.Size() != 2) {
LOG_ERR("%s " RED("invalid client.reconnect notification: params array has wrong size"), tag());
return;
}
if (!arr[0].IsString()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: host is not a string"), tag());
return;
}
if (!arr[1].IsString()) {
LOG_ERR("%s " RED("invalid client.reconnect notification: port is not a string"), tag());
return;
}
std::stringstream s;
s << arr[0].GetString() << ":" << arr[1].GetString();
LOG_WARN("%s " YELLOW("client.reconnect to %s"), tag(), s.str().c_str());
setPoolUrl(s.str().c_str());
return reconnect();
}
if (id.IsInt64()) {
return parseResponse(id.GetInt64(), Json::getValue(doc, "result"), error);
}
if (!method) {
return;
}
if (error.IsObject()) {
if (!isQuiet()) {
LOG_ERR("%s " RED("error: ") RED_BOLD("\"%s\"") RED(", code: ") RED_BOLD("%d"),
tag(), Json::getString(error, "message"), Json::getInt(error, "code"));
}
return;
}
parseNotification(method, Json::getValue(doc, "params"), error);
}
void xmrig::Client::parseExtensions(const rapidjson::Value &result)
{
m_extensions.reset();
if (!result.HasMember("extensions")) {
return;
}
const rapidjson::Value &extensions = result["extensions"];
if (!extensions.IsArray()) {
return;
}
for (const rapidjson::Value &ext : extensions.GetArray()) {
if (!ext.IsString()) {
continue;
}
const char *name = ext.GetString();
if (strcmp(name, "algo") == 0) {
setExtension(EXT_ALGO, true);
}
else if (strcmp(name, "nicehash") == 0) {
setExtension(EXT_NICEHASH, true);
}
else if (strcmp(name, "connect") == 0) {
setExtension(EXT_CONNECT, true);
}
else if (strcmp(name, "keepalive") == 0) {
setExtension(EXT_KEEPALIVE, true);
startTimeout();
}
# ifdef XMRIG_FEATURE_TLS
else if (strcmp(name, "tls") == 0) {
setExtension(EXT_TLS, true);
}
# endif
}
}
void xmrig::Client::parseNotification(const char *method, const rapidjson::Value ¶ms, const rapidjson::Value &)
{
if (strcmp(method, "job") == 0) {
int code = -1;
if (parseJob(params, &code)) {
m_listener->onJobReceived(this, m_job, params);
}
else {
close();
}
return;
}
}
void xmrig::Client::parseResponse(int64_t id, const rapidjson::Value &result, const rapidjson::Value &error)
{
if (handleResponse(id, result, error)) {
return;
}
if (error.IsObject()) {
const char *message = error["message"].GetString();
if (!handleSubmitResponse(id, message) && !isQuiet()) {
LOG_ERR("%s " RED("error: ") RED_BOLD("\"%s\"") RED(", code: ") RED_BOLD("%d"), tag(), message, Json::getInt(error, "code"));
}
if (m_id == 1 || isCriticalError(message)) {
close();
}
return;
}
if (!result.IsObject()) {
return;
}
if (id == 1) {
int code = -1;
if (!parseLogin(result, &code)) {
if (!isQuiet()) {
LOG_ERR("%s " RED("login error code: ") RED_BOLD("%d"), tag(), code);
}
close();
return;
}
m_failures = 0;
m_listener->onLoginSuccess(this);
if (m_job.isValid()) {
m_listener->onJobReceived(this, m_job, result["job"]);
}
return;
}
handleSubmitResponse(id);
}
void xmrig::Client::ping()
{
send(snprintf(m_sendBuf.data(), m_sendBuf.size(), "{\"id\":%" PRId64 ",\"jsonrpc\":\"2.0\",\"method\":\"keepalived\",\"params\":{\"id\":\"%s\"}}\n", m_sequence, m_rpcId.data()));
m_keepAlive = 0;
}
void xmrig::Client::read(ssize_t nread, const uv_buf_t *buf)
{
const auto size = static_cast<size_t>(nread);
if (nread < 0) {
if (!isQuiet()) {
LOG_ERR("%s " RED("read error: ") RED_BOLD("\"%s\""), tag(), uv_strerror(static_cast<int>(nread)));
}
close();
return;
}
assert(m_listener != nullptr);
if (!m_listener) {
return reconnect();
}
if (m_socks5) {
m_socks5->read(buf->base, size);
if (m_socks5->isReady()) {
delete m_socks5;
m_socks5 = nullptr;
# ifdef XMRIG_FEATURE_TLS
if (m_pool.isTLS() && !m_tls) {
m_tls = new Tls(this);
}
# endif
handshake();
}
return;
}
# ifdef XMRIG_FEATURE_TLS
if (isTLS()) {
LOG_DEBUG("[%s] TLS received (%d bytes)", url(), static_cast<int>(nread));
m_tls->read(buf->base, size);
}
else
# endif
{
m_reader.parse(buf->base, size);
}
}
void xmrig::Client::reconnect()
{
if (!m_listener) {
m_storage.remove(m_key);
return;
}
m_keepAlive = 0;
if (m_failures == -1) {
return m_listener->onClose(this, -1);
}
setState(ReconnectingState);
m_failures++;
m_listener->onClose(this, static_cast<int>(m_failures));
}
void xmrig::Client::setState(SocketState state)
{
LOG_DEBUG("[%s] state: \"%s\" -> \"%s\"", url(), states[m_state], states[state]);
if (m_state == state) {
return;
}
switch (state) {
case HostLookupState:
m_expire = 0;
break;
case ConnectingState:
m_expire = Chrono::steadyMSecs() + kConnectTimeout;
break;
case ReconnectingState:
m_expire = Chrono::steadyMSecs() + m_retryPause;
break;
default:
break;
}
m_state = state;
}
void xmrig::Client::startTimeout()
{
m_expire = 0;
if (has<EXT_KEEPALIVE>()) {
const uint64_t ms = static_cast<uint64_t>(m_pool.keepAlive() > 0 ? m_pool.keepAlive() : Pool::kKeepAliveTimeout) * 1000;
m_keepAlive = Chrono::steadyMSecs() + ms;
}
}
bool xmrig::Client::isCriticalError(const char *message)
{
if (!message) {
return false;
}
if (strncasecmp(message, "Unauthenticated", 15) == 0) {
return true;
}
if (strncasecmp(message, "your IP is banned", 17) == 0) {
return true;
}
if (strncasecmp(message, "IP Address currently banned", 27) == 0) {
return true;
}
if (strncasecmp(message, "Invalid job id", 14) == 0) {
return true;
}
return false;
}
void xmrig::Client::onClose(uv_handle_t *handle)
{
auto client = getClient(handle->data);
if (!client) {
return;
}
client->onClose();
}
void xmrig::Client::onConnect(uv_connect_t *req, int status)
{
auto client = getClient(req->data);
delete req;
if (!client) {
return;
}
if (status < 0) {
if (!client->isQuiet()) {
LOG_ERR("%s " RED("connect error: ") RED_BOLD("\"%s\""), client->tag(), uv_strerror(status));
}
if (client->state() == ReconnectingState || client->state() == ClosingState) {
return;
}
if (client->state() != ConnectingState) {
return;
}
client->close();
return;
}
if (client->state() == ConnectedState) {
return;
}
client->setState(ConnectedState);
uv_read_start(client->stream(), NetBuffer::onAlloc, onRead);
client->handshake();
}
void xmrig::Client::onRead(uv_stream_t *stream, ssize_t nread, const uv_buf_t *buf)
{
auto client = getClient(stream->data);
if (client) {
client->read(nread, buf);
}
NetBuffer::release(buf);
}
关键代码:
void xmrig::Client::connect()
{
if (m_pool.proxy().isValid()) {
m_socks5 = new Socks5(this);
resolve(m_pool.proxy().host());
return;
}
# ifdef XMRIG_FEATURE_TLS
if (m_pool.isTLS()) {
m_tls = new Tls(this);
}
# endif
resolve(m_pool.host());
}
我们看看m_tls的类定义,
/* XMRig
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#ifndef XMRIG_CLIENT_TLS_H
#define XMRIG_CLIENT_TLS_H
using BIO = struct bio_st;
using SSL = struct ssl_st;
using SSL_CTX = struct ssl_ctx_st;
using X509 = struct x509_st;
#include "base/net/stratum/Client.h"
#include "base/tools/Object.h"
namespace xmrig {
class Client::Tls
{
public:
XMRIG_DISABLE_COPY_MOVE_DEFAULT(Tls)
Tls(Client *client);
~Tls();
bool handshake();
bool send(const char *data, size_t size);
const char *fingerprint() const;
const char *version() const;
void read(const char *data, size_t size);
private:
bool send();
bool verify(X509 *cert);
bool verifyFingerprint(X509 *cert);
BIO *m_read = nullptr;
BIO *m_write = nullptr;
bool m_ready = false;
char m_fingerprint[32 * 2 + 8]{};
Client *m_client;
SSL *m_ssl = nullptr;
SSL_CTX *m_ctx;
};
} /* namespace xmrig */
#endif /* XMRIG_CLIENT_TLS_H */
看看关键的函数实现,
/* XMRig
* Copyright (c) 2018 Lee Clagett <https://github.com/vtnerd>
* Copyright (c) 2018-2021 SChernykh <https://github.com/SChernykh>
* Copyright (c) 2016-2021 XMRig <https://github.com/xmrig>, <support@xmrig.com>
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
#include "base/net/stratum/Tls.h"
#include "base/io/log/Log.h"
#include "base/net/stratum/Client.h"
#include "base/tools/Cvt.h"
#ifdef _MSC_VER
# define strncasecmp(x,y,z) _strnicmp(x,y,z)
#endif
#include <cassert>
#include <openssl/ssl.h>
xmrig::Client::Tls::Tls(Client *client) :
m_client(client)
{
m_ctx = SSL_CTX_new(SSLv23_method());
assert(m_ctx != nullptr);
if (!m_ctx) {
return;
}
m_write = BIO_new(BIO_s_mem());
m_read = BIO_new(BIO_s_mem());
SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
}
xmrig::Client::Tls::~Tls()
{
if (m_ctx) {
SSL_CTX_free(m_ctx);
}
if (m_ssl) {
SSL_free(m_ssl);
}
}
bool xmrig::Client::Tls::handshake()
{
m_ssl = SSL_new(m_ctx);
assert(m_ssl != nullptr);
if (!m_ssl) {
return false;
}
SSL_set_connect_state(m_ssl);
SSL_set_bio(m_ssl, m_read, m_write);
SSL_do_handshake(m_ssl);
return send();
}
bool xmrig::Client::Tls::send(const char *data, size_t size)
{
SSL_write(m_ssl, data, size);
return send();
}
const char *xmrig::Client::Tls::fingerprint() const
{
return m_ready ? m_fingerprint : nullptr;
}
const char *xmrig::Client::Tls::version() const
{
return m_ready ? SSL_get_version(m_ssl) : nullptr;
}
void xmrig::Client::Tls::read(const char *data, size_t size)
{
BIO_write(m_read, data, size);
if (!SSL_is_init_finished(m_ssl)) {
const int rc = SSL_connect(m_ssl);
if (rc < 0 && SSL_get_error(m_ssl, rc) == SSL_ERROR_WANT_READ) {
send();
} else if (rc == 1) {
X509 *cert = SSL_get_peer_certificate(m_ssl);
if (!verify(cert)) {
X509_free(cert);
m_client->close();
return;
}
X509_free(cert);
m_ready = true;
m_client->login();
}
return;
}
static char buf[16384]{};
int bytes_read = 0;
while ((bytes_read = SSL_read(m_ssl, buf, sizeof(buf))) > 0) {
m_client->m_reader.parse(buf, static_cast<size_t>(bytes_read));
}
}
bool xmrig::Client::Tls::send()
{
return m_client->send(m_write);
}
bool xmrig::Client::Tls::verify(X509 *cert)
{
if (cert == nullptr) {
LOG_ERR("[%s] Failed to get server certificate", m_client->url());
return false;
}
if (!verifyFingerprint(cert)) {
LOG_ERR("[%s] Failed to verify server certificate fingerprint", m_client->url());
const char *fingerprint = m_client->m_pool.fingerprint();
if (strlen(m_fingerprint) == 64 && fingerprint != nullptr) {
LOG_ERR("\"%s\" was given", m_fingerprint);
LOG_ERR("\"%s\" was configured", fingerprint);
}
return false;
}
return true;
}
bool xmrig::Client::Tls::verifyFingerprint(X509 *cert)
{
const EVP_MD *digest = EVP_get_digestbyname("sha256");
if (digest == nullptr) {
return false;
}
unsigned char md[EVP_MAX_MD_SIZE];
unsigned int dlen = 0;
if (X509_digest(cert, digest, md, &dlen) != 1) {
return false;
}
Cvt::toHex(m_fingerprint, sizeof(m_fingerprint), md, 32);
const char *fingerprint = m_client->m_pool.fingerprint();
return fingerprint == nullptr || strncasecmp(m_fingerprint, fingerprint, 64) == 0;
}
从这里可以看出,支持tls1.2,和tls1.3
xmrig::Client::Tls::Tls(Client *client) :
m_client(client)
{
m_ctx = SSL_CTX_new(SSLv23_method());
assert(m_ctx != nullptr);
if (!m_ctx) {
return;
}
m_write = BIO_new(BIO_s_mem());
m_read = BIO_new(BIO_s_mem());
SSL_CTX_set_options(m_ctx, SSL_OP_NO_SSLv2 | SSL_OP_NO_SSLv3);
}
openssl的使用可以参考: https://www.cnblogs.com/sxmcACM/p/6082907.html
/* ---------------------------------------------------------- * 51 * 发送SSL2 SSL3 TLS 1.0 TLS 2.0 TLS 3.0 与服务器建链 * 52 * ---------------------------------------------------------- */ 53 method = SSLv23_client_method(); 54 55 /* ---------------------------------------------------------- * 56 * 创建一个新的SSL上下文 * 57 * ---------------------------------------------------------- */ 58 if ((ctx = SSL_CTX_new(method)) == NULL) 59 BIO_printf(outbio, "Unable to create a new SSL context structure.\n"); 60
总结起来就是说,xmrig使用openssl的tls客户端进行加密通信。
xmrig介绍:
XMRig一款高性能开源、跨平台,支持RandomX,CryptoNight和Argon2 算法 CPU / GPU的挖矿软件。
官方下载地址:https://github.com/xmrig/xmrig/releases
备用下载地址:xmrig
网络:
-o,–url =矿池的URL
-a,–algo = ALGO挖掘算法https://xmrig.com/docs/algorithms
–coin = COIN指定硬币而不是算法
-u,–user = USERNAME采矿服务器的用户名
-p,–pass =采矿服务器的密码
-O,–userpass = U:P用户名:采矿服务器的密码对
-k,–keepalive发送keepalived数据包以防止超时(需要池支持)
–nicehash启用nicehash.com支持
–rig-id =池端统计信息的ID绑定标识符(需要池支持)
–tls启用SSL / TLS支持(需要池支持)
–tls-fingerprint =用于严格证书固定的HEX池TLS证书指纹
–daemon使用守护程序RPC而不是池进行单独挖掘
–daemon-poll-interval = N守护程序轮询间隔,以毫秒为单位(默认值:1000)
-r,–retries = N切换到备份服务器之前重试的次数(默认值:5)
-R,–retry-pause = N重试之间暂停的时间(默认值:5)
–user-agent设置池的自定义用户代理字符串
–donate-level = N捐赠级别,默认5 %%(100分钟内5分钟)
–donate-over-proxy = N控制通过xmrig-proxy功能捐赠
CPU后端:
–no-cpu禁用CPU挖掘后端
-t,–threads = N个CPU线程数
-v,–av = N算法变化,0自动选择
–cpu-affinity设置与CPU内核的进程亲和力,对于内核0和1使用掩码0x3
–cpu-priority设置进程优先级(0空闲,2正常到5最高)
–cpu-max-threads-hint = N自动配置的最大CPU线程数(百分比)提示
–cpu-memory-pool = N永久内存池的2 MB页面数,-1(自动),0(禁用)
–no-huge-pages禁用大页面支持
–asm = ASM ASM优化,可能的值:auto,none,intel,ryzen,推土机
–randomx-init = N个线程计数以初始化RandomX数据集
–randomx-no-numa禁用对RandomX的NUMA支持
API:
–api-worker-id = ID API的ID自定义工人ID
–api-id = ID API的自定义实例ID
–http-host = HOST绑定HTTP API的主机(默认值:127.0.0.1)
–http-port = N绑定HTTP API的端口
–http-access-token = HTTP API的T访问令牌
–http-no-restricted启用对HTTP API的完全远程访问(仅在设置了访问令牌的情况下)
OpenCL后端:
–opencl启用OpenCL挖掘后端
–opencl-devices = N用逗号分隔的OpenCL设备列表
–opencl-platform = N OpenCL平台索引或名称
–opencl-loader = OpenCL-ICD-Loader的路径(OpenCL.dll或libOpenCL.so)
–opencl-no-cache禁用OpenCL缓存
–print-platforms打印可用的OpenCL平台并退出
CUDA后端:
–cuda启用CUDA挖掘后端
–cuda-loader = CUDA插件的路径(xmrig-cuda.dll或libxmrig-cuda.so)
–cuda-devices =以逗号分隔的要使用的CUDA设备列表
–cuda-bfactor-hint =自动配置的N bfactor提示(0-12)
–cuda-bsleep-hint = N自动配置的睡眠提示
–no-nvml禁用NVML(NVIDIA Management Library)支持
正在记录:
-S,-syslog将系统日志用于输出消息
-l,–log-file = FILE将所有输出记录到文件
–print-time = N每N秒打印一次哈希率报告
–health-print-time =每N秒N次打印健康报告
–no-color禁用彩色输出
其他:
-c,–config = FILE加载JSON格式的配置文件
-B,–background在后台运行矿工
-V,–version输出版本信息并退出
-h,–help显示此帮助并退出
-空运行测试配置并退出
–export-topology将hwloc拓扑导出到XML文件并退出
免责声明:本站所有文章内容,图片,视频等均是来源于用户投稿和互联网及文摘转载整编而成,不代表本站观点,不承担相关法律责任。其著作权各归其原作者或其出版社所有。如发现本站有涉嫌抄袭侵权/违法违规的内容,侵犯到您的权益,请在线联系站长,一经查实,本站将立刻删除。 本文来自网络,若有侵权,请联系删除,如若转载,请注明出处:https://haidsoft.com/29167.html




