added readme; added special case camouflaging

This commit is contained in:
eerieaerial 2025-05-12 14:04:06 +04:00
parent 5fb3f5c228
commit 235addc585
9 changed files with 290 additions and 59 deletions

158
README.camo.md Normal file
View file

@ -0,0 +1,158 @@
# Камуфлирование пакетов ZeroTier
## Введение
Этот патч добавляет функцию сокрытия открытых полей и данных протокола ZeroTier, условно называемую "камуфлированием". Цель операции - не криптографическая защита, а создание видимости полностью случайного содержимого пакетов.
## Принцип работы
### Узоры камуфлирования
Основу механизма камуфлирования составляют 16 случайных 32-битных узоров, которые:
- Генерируются при инициализации стандартизованным ГСЧ (вихрь Мерсенна MT19937, определённый в стандарте C++11) с фиксированным порождающим словом
- Одинаковы для всех узлов с одинаковым порождающим словом
- Используются для XOR-преобразования содержимого пакета
- Служат признаком распознавания камуфлированных пакетов
Размер списка в 16 узоров выбран из соображений баланса между разнообразием узоров и вероятностью коллизии между признаком камуфлирования и случайно сгенерированным ID некамуфлированного пакета. Размер списка можно изменить путём задания нового значения макроса `PATTERN_COUNT` в файле `CamoPattern.hpp`. Рекомендуется использовать значения, равные степеням 2.
### Алгоритм камуфлирования
1. 64-битный ID в заголовке пакета разделяется на два 32-битных сегмента
2. Младший сегмент перемещается в конец пакета
3. Старший сегмент дублируется на место младшего
4. Данные от дубликата до конца пакета обрабатываются XOR со случайно выбранным узором
5. Раскамуфлирование выполняется в обратном порядке после распознавания узора
### Распознавание камуфлированных пакетов
Для распознавания того, камуфлирован пакет или нет, используется XOR между старшим и младшим сегментами ID. Если результат обнаружен в списке узоров, то это означает, что пакет закамуфлирован этим узором.
### Правила обработки пакетов
Пакеты обрабатываются на основе сравнения уровня камуфлирования адресата и отправителя. Уровень адресата определяется либо автоматически, либо заданием в настройках. Уровень отправителя определяется настройкой и относится только непосредственно к тому узлу, на котором производится обработка пакета в данный момент.
- _Входящие_: всегда автоматически раскамуфлируются для обеспечения работы внутренних механизмов
- сходящие_: камуфлируются, если уровень адресата равен уровню отправителя или меньше
- ересылаемые_: обрабатываются согласно выбранному правилу пересылки
### Уровни камуфлирования
Уровни камуфлирования имеют следующие названия от низшего к высшему:
- `NONE`
- `NODE`
- `CONTROLLER`
- `MOON`
- `PLANET`
- `INAPPLICABLE`
Особое значение имеют два уровня:
- `NONE` - не назначается автоматически в качестве уровня адресата. Выбор этого уровня в качестве уровня отправителя выключает камуфлирование пакетов при автоматическом выборе уровня адресата.
- `INAPPLICABLE` - в качестве уровня адресата назначается автоматически глобальным корневым серверам. Для выбора в качестве уровня отправителя недоступен.
Прочие уровни назначаются автоматически согласно роли адресата.
### Список известных адресатов
При определении уровня камуфлирования для адресата проводится поиск в списке известных адресатов. Если адресат там обнаружен, то используется уровень, который присвоен в списке. Если нет - то производится автоматическое определение уровня адресата и результат заносится в список. Настройки позволяют задать изначальное содержимое списка для принудительного назначения адресатам требуемого уровня.
### Правила пересылки
- `LEAVE` - сохраняет исходное состояние камуфлирования пересылаемого пакета
- `KNOWNHOSTS` - применяет те же правила, что и для исходящих пакетов
- `STRIP` - принудительно снимает камуфлирование со всех пересылаемых пакетов
- `APPLY` - принудительно камуфлирует все пересылаемые пакеты
## Настройки
Настройки задаются в файле `local.conf` в объекте `"camo"` внутри `"settings"`:
```json
{
"settings": {
"camo": {
"level": "none", // Уровень отправителя
"word": "DLGE", // Порождающее слово для узоров
"relayRule": "leave", // Правило пересылки
"knownHosts": { // Предустановленные уровни адресата для узлов
"none" : []
}
}
}
}
```
### Параметры
- `"level"`: регистронезависимая строка с названием уровня отправителя. По умолчанию: `"none"`. Любые значения, не соответствующие названию существующих уровней, интерпретируются как `"none"`. Значение `"inapplicable"` также интерпретируется как `"none"`, т.к. этот уровень недоступен для выбора.
- `"word"`: строка, содержащая порождающее слово для списка узоров. Если в строке меньше 4 символов, она дополняется до 4 символов последовательностью `"DLGE"`. Строка длиннее 4 символов обрезается. Если строка начинается с `"0x"`, она интерпретируется как 32-битное шестнадцатеричное число. По умолчанию: `"DLGE"`.
- `"relayRule"`: регистронезависимая строка, содержащая название правила пересылки. По умолчанию: `"leave"`. Любые значения, не соответствующие названию существующих правил, интерпретируются как `"leave"`.
- `"knownHosts"`: объект для предустановки уровней для конкретных узлов. Названия полей объекта соответствуют уровням камуфлирования. Названия полей, не соответствующие существующим уровням, интерпретируются как `"inapplicable"`. Значение каждого поля - массив строк с адресами.
## Примеры конфигураций
### "Белый список"
```json
{
"settings": {
"camo": {
"level": "none",
"knownHosts": {
"none": ["aaaaaaaaaa"]
}
}
}
}
```
Эта настройка выбирает уровень отправителя `NONE`, который автоматически не назначается адресатам. Это отключает камуфлирование для всех автоматически определяемых адресатов. Адресату `aaaaaaaaaa` принудительно назначается уровень `NONE`, и т.к. этот уровень равен выбранному, пакеты для него будут камуфлироваться.
### "Чёрный список"
```json
{
"settings": {
"camo": {
"level": "node",
"knownHosts": {
"inapplicable": ["aaaaaaaaaa"]
}
}
}
}
```
Здесь выбран уровень отправителя `NODE`, что включает камуфлирование для адресатов этого уровня и ниже. Адресату `aaaaaaaaaa` назначен уровень `INAPPLICABLE`, поэтому вне зависимости от выбранного уровня, пакеты для него камуфлироваться не будут.
### Принудительное включение для специфических узлов
```json
{
"settings": {
"camo": {
"level": "node",
"knownHosts": {
"node": ["aaaaaaaaaa"]
}
}
}
}
```
В этом примере корневому серверу `aaaaaaaaaa`, поддерживающему работу с камуфлированными пакетами, принудительно присваивается уровень `NODE`, чтобы пакеты для него камуфлировались наряду с обычными узлами.
### Комментарий
По большому счёту, в `"knownHosts"` имеет смысл использовать только уровни `NONE` и `INAPPLICABLE`. Первый - принудительно включает камуфлирование для указанных адресатов, второй - выключает.
## Перевод сети на камуфлирование
Для перевода всей сети на камуфлирование сначала необходимо установить службу ZeroTier с данным патчем без дополнительных настроек. При этом, служба будет работать так же, как штатная. После этого, на каждом узле производится включение камуфлирования с помощью настроек. Такой процесс позволяет перевести сеть на камуфлирование пакетов без потери работоспособности всей сети.
## Особенности сборки
Задание макроса `CAMO_TRACE` включает выдачу отладочных сообщений на стандартный вывод службы. Для этого нужно при сборке передать команде make параметр `DEFS="-DCAMO_TRACE"`

View file

@ -1,6 +1,8 @@
ZeroTier - Global Area Networking ZeroTier - Global Area Networking
====== ======
**NOTE: This project is a fork that implements packet camouflaging functionality. For usage instructions, see [README.camo.md](README.camo.md)**
*This document is written for a software developer audience. For information on using ZeroTier, see the: [Website](https://www.zerotier.com), [Documentation Site](https://docs.zerotier.com), and [Discussion Forum](https://discuss.zerotier.com).* *This document is written for a software developer audience. For information on using ZeroTier, see the: [Website](https://www.zerotier.com), [Documentation Site](https://docs.zerotier.com), and [Discussion Forum](https://discuss.zerotier.com).*
ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region. ZeroTier is a smart programmable Ethernet switch for planet Earth. It allows all networked devices, VMs, containers, and applications to communicate as if they all reside in the same physical data center or cloud region.

View file

@ -22,10 +22,10 @@ bool CamoPattern::isInitialized = false;
CamoLevel CamoPattern::camoLevel; CamoLevel CamoPattern::camoLevel;
uint32_t CamoPattern::camoWord; uint32_t CamoPattern::camoWord;
CamoRelayRule CamoPattern::relayRule; CamoRelayRule CamoPattern::relayRule;
std::array<std::array<uint8_t, BYTES_IN_WORD>, PATTERN_COUNT> CamoPattern::camoValues; CamoPatternArray CamoPattern::camoValues;
std::unordered_map<std::array<uint8_t, BYTES_IN_WORD>, size_t> CamoPattern::camoIndices; CamoIndexMap CamoPattern::camoIndices;
std::mutex CamoPattern::camoMutex; std::mutex CamoPattern::camoMutex;
std::unordered_map<Address, CamoLevel> CamoPattern::knownHosts; KnownHostsMap CamoPattern::knownHosts;
// Implementation of getCamoLevel // Implementation of getCamoLevel
@ -138,7 +138,7 @@ bool CamoPattern::isCamoRequired(const Address host, const RuntimeEnvironment *
// Implementation of init // Implementation of init
void CamoPattern::init(CamoLevel level, uint32_t word, std::unordered_map<Address, CamoLevel> hosts, CamoRelayRule rule) void CamoPattern::init(CamoLevel level, uint32_t word, KnownHostsMap hosts, CamoRelayRule rule)
{ {
std::lock_guard<std::mutex> lock(camoMutex); std::lock_guard<std::mutex> lock(camoMutex);
if (!isInitialized) if (!isInitialized)

View file

@ -14,8 +14,6 @@
#ifndef ZT_N_CAMOPATTERN_HPP #ifndef ZT_N_CAMOPATTERN_HPP
#define ZT_N_CAMOPATTERN_HPP #define ZT_N_CAMOPATTERN_HPP
#define CAMO_TRACE
#include <stdint.h> #include <stdint.h>
#include <array> #include <array>
#include <unordered_map> #include <unordered_map>
@ -26,33 +24,12 @@
#include "Buffer.hpp" #include "Buffer.hpp"
#include "RuntimeEnvironment.hpp" #include "RuntimeEnvironment.hpp"
#define BYTES_IN_WORD 4 #define BYTES_IN_WORD (sizeof(uint32_t) / sizeof(uint8_t))
#define PATTERN_COUNT 16 #define PATTERN_COUNT 16
#define PATTERN_INDEX_MASK 0xf
#define NO_CAMO PATTERN_COUNT #define NO_CAMO PATTERN_COUNT
#define ZT_CAMO_DEFAULT_WORDSTR "DLGE" #define ZT_CAMO_DEFAULT_WORDSTR "DLGE"
namespace std {
template<typename T, size_t N>
struct hash<std::array<T, N>> {
size_t operator()(const std::array<T, N>& array) const {
size_t hash = 0;
for (const auto& element : array) {
hash = hash * 31 + std::hash<T>{}(element);
}
return hash;
}
};
template<>
struct hash<ZeroTier::Address> {
size_t operator()(const ZeroTier::Address& address) const {
return std::hash<uint64_t>{}(address.toInt());
}
};
}
/** /**
* Camo functions debug trace macro * Camo functions debug trace macro
*/ */
@ -66,6 +43,43 @@ namespace std {
#define CT(...) ((void)0) #define CT(...) ((void)0)
#endif #endif
/**
* Type shorthands
*/
namespace ZeroTier {
enum class CamoLevel;
typedef std::array<uint8_t, BYTES_IN_WORD> CamoPatternBytes;
typedef std::array<CamoPatternBytes, PATTERN_COUNT> CamoPatternArray;
typedef std::unordered_map<CamoPatternBytes, size_t> CamoIndexMap;
typedef std::unordered_map<Address, CamoLevel> KnownHostsMap;
}
/**
* Hash functions for the respective unordered_maps
*/
namespace std {
template<>
struct hash<ZeroTier::CamoPatternBytes> {
size_t operator()(const ZeroTier::CamoPatternBytes& bytes) const {
uint32_t word = 0;
for (const auto& byte : bytes) {
word <<= 8;
word |= byte;
}
return std::hash<uint32_t>{}(word);
}
};
template<>
struct hash<ZeroTier::Address> {
size_t operator()(const ZeroTier::Address& address) const {
return std::hash<uint64_t>{}(address.toInt());
}
};
}
namespace ZeroTier { namespace ZeroTier {
/** /**
@ -102,7 +116,7 @@ class CamoPattern
static size_t getCamoIndex(const Buffer<C> &buffer) static size_t getCamoIndex(const Buffer<C> &buffer)
{ {
size_t result = NO_CAMO; size_t result = NO_CAMO;
std::array<uint8_t, BYTES_IN_WORD> camo; CamoPatternBytes camo;
if (buffer.size() > BYTES_IN_WORD * 2) if (buffer.size() > BYTES_IN_WORD * 2)
{ {
for (size_t i = 0; i < BYTES_IN_WORD; i++) for (size_t i = 0; i < BYTES_IN_WORD; i++)
@ -144,6 +158,8 @@ public:
/** /**
* Apply camouflage to buffer * Apply camouflage to buffer
* *
* This increases buffer length by adding ID word to the end
*
* @param buffer Buffer to apply camouflage to * @param buffer Buffer to apply camouflage to
*/ */
template<unsigned int C> template<unsigned int C>
@ -153,8 +169,8 @@ public:
if (isInitialized && (camoIndex == NO_CAMO)) { // Only apply if not already applied if (isInitialized && (camoIndex == NO_CAMO)) { // Only apply if not already applied
CT("PACKET CONTENTS BEFORE APPLYING CAMO:"); CT("PACKET CONTENTS BEFORE APPLYING CAMO:");
buffer.dump(); buffer.dump();
camoIndex = std::minstd_rand(std::time(nullptr))() & PATTERN_INDEX_MASK; camoIndex = std::minstd_rand(std::time(nullptr))() % PATTERN_COUNT;
std::array<uint8_t, BYTES_IN_WORD> camo = camoValues[camoIndex]; CamoPatternBytes camo = camoValues[camoIndex];
// Increase buffer size first to avoid overflow // Increase buffer size first to avoid overflow
size_t originalSize = buffer.size(); size_t originalSize = buffer.size();
@ -166,15 +182,16 @@ public:
data[i + originalSize] = data[i + BYTES_IN_WORD]; data[i + originalSize] = data[i + BYTES_IN_WORD];
} }
// Copy the first word on the second word's place
for (size_t i = 0; i < BYTES_IN_WORD; i++) {
data[i + BYTES_IN_WORD] = data[i];
}
// Apply XOR to the rest of the buffer // Apply XOR to the rest of the buffer
for (size_t i = BYTES_IN_WORD * 2; i < buffer.size(); i++) { for (size_t i = BYTES_IN_WORD; i < buffer.size(); i++) {
data[i] ^= camo[i % BYTES_IN_WORD]; data[i] ^= camo[i % BYTES_IN_WORD];
} }
// Apply XOR to create the camouflage pattern in the second word
for (size_t i = 0; i < BYTES_IN_WORD; i++) {
data[i + BYTES_IN_WORD] = data[i] ^ camo[i];
}
CT("PACKET CONTENTS AFTER APPLYING CAMO:"); CT("PACKET CONTENTS AFTER APPLYING CAMO:");
buffer.dump(); buffer.dump();
} }
@ -183,7 +200,7 @@ public:
/** /**
* Remove camouflage from buffer * Remove camouflage from buffer
* *
* This decreases buffer length by removing 'CAMO' from the end * This decreases buffer length by removing stored ID word from the end
* *
* @param buffer Buffer to remove camouflage from * @param buffer Buffer to remove camouflage from
*/ */
@ -200,10 +217,10 @@ public:
CT("PACKET CONTENTS BEFORE STRIPPING CAMO:"); CT("PACKET CONTENTS BEFORE STRIPPING CAMO:");
buffer.dump(); buffer.dump();
uint8_t * const data = reinterpret_cast<uint8_t *>(buffer.unsafeData()); uint8_t * const data = reinterpret_cast<uint8_t *>(buffer.unsafeData());
std::array<uint8_t, BYTES_IN_WORD> camo = camoValues[camoIndex]; CamoPatternBytes camo = camoValues[camoIndex];
for (size_t i = BYTES_IN_WORD * 2; i < buffer.size(); i++) for (size_t i = BYTES_IN_WORD * 2; i < buffer.size(); i++)
{ {
data[i] ^= camo[i % BYTES_IN_WORD]; data[i] ^= camo[i % BYTES_IN_WORD];
} }
size_t storedWordIndex = buffer.size() - BYTES_IN_WORD; size_t storedWordIndex = buffer.size() - BYTES_IN_WORD;
for (size_t i = 0; i < BYTES_IN_WORD; i++) for (size_t i = 0; i < BYTES_IN_WORD; i++)
@ -218,7 +235,7 @@ public:
return result; return result;
} }
static void init(CamoLevel level, uint32_t word, std::unordered_map<Address, CamoLevel> hosts, CamoRelayRule rule); static void init(CamoLevel level, uint32_t word, KnownHostsMap hosts, CamoRelayRule rule);
private: private:
@ -226,10 +243,10 @@ private:
static CamoLevel camoLevel; static CamoLevel camoLevel;
static uint32_t camoWord; static uint32_t camoWord;
static CamoRelayRule relayRule; static CamoRelayRule relayRule;
static std::array<std::array<uint8_t, BYTES_IN_WORD>, PATTERN_COUNT> camoValues; static CamoPatternArray camoValues;
static std::unordered_map<std::array<uint8_t, BYTES_IN_WORD>, size_t> camoIndices; static CamoIndexMap camoIndices;
static std::mutex camoMutex; static std::mutex camoMutex;
static std::unordered_map<Address, CamoLevel> knownHosts; static KnownHostsMap knownHosts;
}; };
} // namespace ZeroTier } // namespace ZeroTier

View file

@ -435,7 +435,11 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
Metrics::pkt_error_out++; Metrics::pkt_error_out++;
Metrics::pkt_error_identity_collision_out++; Metrics::pkt_error_identity_collision_out++;
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} else { } else {
RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC"); RR->t->incomingPacketMessageAuthenticationFailure(tPtr,_path,pid,fromAddress,hops(),"invalid MAC");
@ -595,7 +599,11 @@ bool IncomingPacket::_doHELLO(const RuntimeEnvironment *RR,void *tPtr,const bool
peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now); peer->recordOutgoingPacket(_path,outp.packetId(),outp.payloadLength(),outp.verb(),ZT_QOS_NO_FLOW,now);
Metrics::pkt_ok_out++; Metrics::pkt_ok_out++;
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),now); _path->send(RR,tPtr,outp.data(),outp.size(),now);
peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); // important for this to go first so received() knows the version peer->setRemoteVersion(protoVersion,vMajor,vMinor,vRevision); // important for this to go first so received() knows the version
@ -1000,7 +1008,11 @@ bool IncomingPacket::_doEXT_FRAME(const RuntimeEnvironment *RR,void *tPtr,const
Metrics::pkt_ok_out++; Metrics::pkt_ok_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} }
@ -1032,7 +1044,11 @@ bool IncomingPacket::_doECHO(const RuntimeEnvironment *RR,void *tPtr,const Share
Metrics::pkt_ok_out++; Metrics::pkt_ok_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
peer->received(tPtr,_path,hops(),pid,payloadLength(),Packet::VERB_ECHO,0,Packet::VERB_NOP,false,0,ZT_QOS_NO_FLOW); peer->received(tPtr,_path,hops(),pid,payloadLength(),Packet::VERB_ECHO,0,Packet::VERB_NOP,false,0,ZT_QOS_NO_FLOW);
@ -1231,7 +1247,11 @@ bool IncomingPacket::_doNETWORK_CONFIG_REQUEST(const RuntimeEnvironment *RR,void
Metrics::pkt_error_unsupported_op_out++; Metrics::pkt_error_unsupported_op_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} }
@ -1258,7 +1278,11 @@ bool IncomingPacket::_doNETWORK_CONFIG(const RuntimeEnvironment *RR,void *tPtr,c
Metrics::pkt_ok_out++; Metrics::pkt_ok_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} }
} }
@ -1304,7 +1328,11 @@ bool IncomingPacket::_doMULTICAST_GATHER(const RuntimeEnvironment *RR,void *tPtr
Metrics::pkt_ok_out++; Metrics::pkt_ok_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),now); _path->send(RR,tPtr,outp.data(),outp.size(),now);
} }
} }
@ -1414,7 +1442,11 @@ bool IncomingPacket::_doMULTICAST_FRAME(const RuntimeEnvironment *RR,void *tPtr,
Metrics::pkt_ok_out++; Metrics::pkt_ok_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} }
} }
@ -1559,7 +1591,11 @@ void IncomingPacket::_sendErrorNeedCredentials(const RuntimeEnvironment *RR,void
Metrics::pkt_error_need_membership_cert_out++; Metrics::pkt_error_need_membership_cert_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now()); _path->send(RR,tPtr,outp.data(),outp.size(),RR->node->now());
} }

View file

@ -203,7 +203,11 @@ void Multicaster::send(
Metrics::pkt_multicast_frame_out++; Metrics::pkt_multicast_frame_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED MULTICAST, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED MULTICAST, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
bestMulticastReplicatorPath->send(RR,tPtr,outp.data(),outp.size(),now); bestMulticastReplicatorPath->send(RR,tPtr,outp.data(),outp.size(),now);
return; return;
} }

View file

@ -250,7 +250,12 @@ void Peer::received(
Metrics::pkt_push_direct_paths_out++; Metrics::pkt_push_direct_paths_out++;
char buf[64]; char buf[64];
outp->destination().toString(buf); outp->destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp->packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp->packetId(), buf);
if (CamoPattern::isCamoRequired(outp->destination(), RR))
{
CamoPattern::applyCamo(*outp);
}
path->send(RR,tPtr,outp->data(),outp->size(),now); path->send(RR,tPtr,outp->data(),outp->size(),now);
} }
delete outp; delete outp;
@ -399,7 +404,11 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
Metrics::pkt_rendezvous_out++; Metrics::pkt_rendezvous_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
_paths[mine].p->send(RR,tPtr,outp.data(),outp.size(),now); _paths[mine].p->send(RR,tPtr,outp.data(),outp.size(),now);
} else { } else {
Packet outp(other->_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS); Packet outp(other->_id.address(),RR->identity.address(),Packet::VERB_RENDEZVOUS);
@ -417,7 +426,11 @@ void Peer::introduce(void *const tPtr,const int64_t now,const SharedPtr<Peer> &o
Metrics::pkt_rendezvous_out++; Metrics::pkt_rendezvous_out++;
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
if (CamoPattern::isCamoRequired(outp.destination(), RR))
{
CamoPattern::applyCamo(outp);
}
other->_paths[theirs].p->send(RR,tPtr,outp.data(),outp.size(),now); other->_paths[theirs].p->send(RR,tPtr,outp.data(),outp.size(),now);
} }
++alt; ++alt;
@ -468,7 +481,7 @@ void Peer::sendHELLO(void *tPtr,const int64_t localSocket,const InetAddress &atA
RR->node->expectReplyTo(outp.packetId()); RR->node->expectReplyTo(outp.packetId());
char buf[64]; char buf[64];
outp.destination().toString(buf); outp.destination().toString(buf);
CT("UNPROCESSED, packetId: %lx, address: %s", outp.packetId(), buf); CT("SWITCH PROCESSED, packetId: %lx, address: %s", outp.packetId(), buf);
RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC RR->sw->send(tPtr,outp,false); // false == don't encrypt full payload, but add MAC
} }
} }

View file

@ -1461,11 +1461,11 @@ public:
uint32_t camoWord = 0; uint32_t camoWord = 0;
for (size_t i = 0; i < BYTES_IN_WORD; i++) for (size_t i = 0; i < BYTES_IN_WORD; i++)
{ {
camoWord |= camoWordStr[i];
camoWord <<= 8; camoWord <<= 8;
camoWord |= camoWordStr[i];
} }
CamoRelayRule relayRule = CamoRelayRule::LEAVE; CamoRelayRule relayRule = CamoRelayRule::LEAVE;
std::unordered_map<Address, CamoLevel> knownHosts; KnownHostsMap knownHosts;
json &settings = lc["settings"]; json &settings = lc["settings"];
if (settings.is_object()) { if (settings.is_object()) {

View file

@ -9,6 +9,7 @@ pkgs.mkShell {
cmake cmake
cmake-language-server cmake-language-server
clang-tools clang-tools
pandoc
] ]
++ zerotieroneCustom.buildInputs ++ zerotieroneCustom.buildInputs
++ zerotieroneCustom.nativeBuildInputs; ++ zerotieroneCustom.nativeBuildInputs;