1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-07-08 00:34:57 +03:00

OpenVPN: Add packet scrambling/obfuscation feature

This allows an OpenVPN client to bypass a firewall which is aware of the protocol and is able to block it.
The XOR mask set on the server has to be the same on the client, otherwise it will not be able to connect with certain obfuscation modes.
A special OpenVPN client built with the "XOR patch" is required in order to use this function, because it has never been merged in the official OpenVPN repository.

Two parameters are added to the server configuration: "OpenVPNObfuscationMethod" and "OpenVPNObfuscationMask".
Their value can be retrieved with "OpenVpnObfuscationGet" and set with "OpenVpnObfuscationEnable" in the VPN Command Line Management Utility.
This commit is contained in:
Davide Beatrici
2018-11-12 22:32:37 +01:00
parent 25c99a7e04
commit 6a45921f41
14 changed files with 566 additions and 123 deletions

View File

@ -8919,6 +8919,8 @@ void InOpenVpnSstpConfig(OPENVPN_SSTP_CONFIG *t, PACK *p)
t->EnableOpenVPN = PackGetBool(p, "EnableOpenVPN");
t->EnableSSTP = PackGetBool(p, "EnableSSTP");
PackGetStr(p, "OpenVPNPortList", t->OpenVPNPortList, sizeof(t->OpenVPNPortList));
t->OpenVPNObfuscation= PackGetBool(p, "OpenVPNObfuscation");
PackGetStr(p, "OpenVPNObfuscationMask", t->OpenVPNObfuscationMask, sizeof(t->OpenVPNObfuscationMask));
}
void OutOpenVpnSstpConfig(PACK *p, OPENVPN_SSTP_CONFIG *t)
{
@ -8931,6 +8933,8 @@ void OutOpenVpnSstpConfig(PACK *p, OPENVPN_SSTP_CONFIG *t)
PackAddBool(p, "EnableOpenVPN", t->EnableOpenVPN);
PackAddBool(p, "EnableSSTP", t->EnableSSTP);
PackAddStr(p, "OpenVPNPortList", t->OpenVPNPortList);
PackAddBool(p, "OpenVPNObfuscation", t->OpenVPNObfuscation);
PackAddStr(p, "OpenVPNObfuscationMask", t->OpenVPNObfuscationMask);
}
// DDNS_CLIENT_STATUS

View File

@ -1076,7 +1076,9 @@ typedef struct CEDAR
UINT FifoBudget; // Fifo budget
SSL_ACCEPT_SETTINGS SslAcceptSettings; // SSL Accept Settings
UINT DhParamBits; // Bits of Diffie-Hellman parameters
char OpenVPNDefaultClientOption[MAX_SIZE]; // OpenVPN Default Client Option String
char OpenVPNDefaultClientOption[MAX_SIZE]; // OpenVPN: Default Client Option String
bool OpenVPNObfuscation; // OpenVPN: Obfuscation mode
char OpenVPNObfuscationMask[MAX_SIZE]; // OpenVPN: String (mask) for XOR obfuscation
} CEDAR;
// Type of CEDAR

View File

@ -7573,6 +7573,8 @@ void PsMain(PS *ps)
{"OpenVpnEnable", PsOpenVpnEnable},
{"OpenVpnGet", PsOpenVpnGet},
{"OpenVpnMakeConfig", PsOpenVpnMakeConfig},
{"OpenVpnObfuscationEnable", PsOpenVpnObfuscationEnable},
{"OpenVpnObfuscationGet", PsOpenVpnObfuscationGet},
{"SstpEnable", PsSstpEnable},
{"SstpGet", PsSstpGet},
{"ServerCertRegenerate", PsServerCertRegenerate},
@ -21411,6 +21413,103 @@ UINT PsOpenVpnMakeConfig(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
return ret;
}
// Enable / disable the OpenVPN compatible server function's obfuscation mode
UINT PsOpenVpnObfuscationEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
LIST *o;
PS *ps = (PS *)param;
UINT ret = 0;
OPENVPN_SSTP_CONFIG t;
// Parameter list that can be specified
PARAM args[] =
{
// "name", prompt_proc, prompt_param, eval_proc, eval_param
{"[yes|no]", CmdPrompt, _UU("CMD_OpenVpnObfuscationEnable_Prompt_[yes|no]"), CmdEvalNotEmpty, NULL},
{"MASK", CmdPrompt, _UU("CMD_OpenVpnObfuscationEnable_Prompt_MASK"), NULL, NULL},
};
o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
// RPC call
ret = ScGetOpenVpnSstpConfig(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
// An error has occured
CmdPrintError(c, ret);
FreeParamValueList(o);
return ret;
}
t.OpenVPNObfuscation = GetParamYes(o, "[yes|no]");
StrCpy(t.OpenVPNObfuscationMask, sizeof(t.OpenVPNObfuscationMask), GetParamStr(o, "MASK"));
// RPC call
ret = ScSetOpenVpnSstpConfig(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
// An error has occured
CmdPrintError(c, ret);
FreeParamValueList(o);
return ret;
}
FreeParamValueList(o);
return 0;
}
// Get the current settings for the OpenVPN compatible server function's obfuscation mode
UINT PsOpenVpnObfuscationGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
LIST *o;
PS *ps = (PS *)param;
UINT ret = 0;
OPENVPN_SSTP_CONFIG t;
o = ParseCommandList(c, cmd_name, str, NULL, 0);
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
// RPC call
ret = ScGetOpenVpnSstpConfig(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
// An error has occured
CmdPrintError(c, ret);
FreeParamValueList(o);
return ret;
}
else
{
wchar_t tmp[MAX_PATH];
CT *ct = CtNewStandard();
CtInsert(ct, _UU("CMD_OpenVpnObfuscationGet_PRINT_Enabled"), _UU(t.OpenVPNObfuscation ? "SEC_YES" : "SEC_NO"));
StrToUni(tmp, sizeof(tmp), t.OpenVPNObfuscationMask);
CtInsert(ct, _UU("CMD_OpenVpnObfuscationGet_PRINT_Mask"), tmp);
CtFree(ct, c);
}
FreeParamValueList(o);
return 0;
}
// Enable / disable the Microsoft SSTP VPN compatible server function
UINT PsSstpEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{

View File

@ -687,6 +687,8 @@ UINT PsEtherIpClientList(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsOpenVpnEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsOpenVpnGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsOpenVpnMakeConfig(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsOpenVpnObfuscationEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsOpenVpnObfuscationGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsSstpEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsSstpGet(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsServerCertRegenerate(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);

View File

@ -306,9 +306,150 @@ UINT OvsDecrypt(CIPHER *cipher, MD *md, UCHAR *iv, UCHAR *dest, UCHAR *src, UINT
return 0;
}
// XOR the bytes with the specified string
void OvsDataXorMask(void *data, const UINT data_size, const char *mask, const UINT mask_size)
{
UINT i;
UCHAR *buf;
// Validate arguments
if (data == NULL || data_size == 0 || mask == NULL || mask_size == 0)
{
return;
}
for (i = 0, buf = data; i < data_size; i++, buf++)
{
*buf = *buf ^ mask[i % mask_size];
}
}
// XOR each byte with its position within the buffer
void OvsDataXorPtrPos(void *data, const UINT size)
{
UINT i;
UCHAR *buf;
// Validate arguments
if (data == NULL || size == 0)
{
return;
}
for (i = 0, buf = data; i < size; i++, buf++)
{
*buf = *buf ^ i + 1;
}
}
// Reverse bytes order if they're more than 2, keeping the first byte unchanged
void OvsDataReverse(void *data, const UINT size)
{
UINT i;
UCHAR tmp;
UCHAR *buf_start, *buf_end;
// Validate arguments
if (data == NULL || size < 3)
{
return;
}
for (i = 0, buf_start = (UCHAR *)data + 1, buf_end = (UCHAR *)data + (size - 1); i < (size - 1 ) / 2; i++, buf_start++, buf_end--)
{
tmp = *buf_start;
*buf_start = *buf_end;
*buf_end = tmp;
}
}
// Detects the method used to obfuscate the packet
UINT OvsDetectObfuscation(void *data, UINT size, char *xormask)
{
UINT ret;
void *tmp;
OPENVPN_PACKET *parsed_packet;
// Validate arguments
if (data == NULL || size == 0)
{
return INFINITE;
}
ret = INFINITE;
tmp = NULL;
// OPENVPN_SCRAMBLE_MODE_DISABLED
parsed_packet = OvsParsePacket(data, size);
if (parsed_packet != NULL)
{
ret = OPENVPN_SCRAMBLE_MODE_DISABLED;
goto final;
}
// OPENVPN_SCRAMBLE_MODE_XORMASK
tmp = Clone(data, size);
OvsDataXorMask(tmp, size, xormask, StrLen(xormask));
parsed_packet = OvsParsePacket(tmp, size);
if (parsed_packet != NULL)
{
ret = OPENVPN_SCRAMBLE_MODE_XORMASK;
goto final;
}
Free(tmp);
// OPENVPN_SCRAMBLE_MODE_XORPTRPOS
tmp = Clone(data, size);
OvsDataXorPtrPos(tmp, size);
parsed_packet = OvsParsePacket(tmp, size);
if (parsed_packet != NULL)
{
ret = OPENVPN_SCRAMBLE_MODE_XORPTRPOS;
goto final;
}
Free(tmp);
// OPENVPN_SCRAMBLE_MODE_REVERSE
tmp = Clone(data, size);
OvsDataReverse(tmp, size);
parsed_packet = OvsParsePacket(tmp, size);
if (parsed_packet != NULL)
{
ret = OPENVPN_SCRAMBLE_MODE_REVERSE;
goto final;
}
Free(tmp);
// OPENVPN_SCRAMBLE_MODE_OBFUSCATE
tmp = Clone(data, size);
OvsDataXorMask(tmp, size, xormask, StrLen(xormask));
OvsDataXorPtrPos(tmp, size);
OvsDataReverse(tmp, size);
OvsDataXorPtrPos(tmp, size);
parsed_packet = OvsParsePacket(tmp, size);
if (parsed_packet != NULL)
{
ret = OPENVPN_SCRAMBLE_MODE_OBFUSCATE;
goto final;
}
final:
OvsFreePacket(parsed_packet);
Free(tmp);
return ret;
}
// Process the received packet
void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
{
OPENVPN_CHANNEL *c;
OPENVPN_SESSION *se;
OPENVPN_PACKET *recv_packet;
// Validate arguments
@ -317,7 +458,6 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
return;
}
// Search for the session
se = OvsFindOrCreateSession(s, &p->DstIP, p->DestPort, &p->SrcIP, p->SrcPort, protocol);
if (se == NULL)
@ -325,142 +465,179 @@ void OvsProceccRecvPacket(OPENVPN_SERVER *s, UDPPACKET *p, UINT protocol)
return;
}
// Parse the packet
recv_packet = OvsParsePacket(p->Data, p->Size);
if (recv_packet != NULL)
// Detect obfuscation mode and save it for the next packets in the same session
if (se->ObfuscationMode == INFINITE)
{
OPENVPN_CHANNEL *c = NULL;
if (recv_packet->OpCode != OPENVPN_P_DATA_V1 && recv_packet->MySessionId != 0)
se->ObfuscationMode = OvsDetectObfuscation(p->Data, p->Size, s->Cedar->OpenVPNObfuscationMask);
if (se->ObfuscationMode != INFINITE)
{
Debug("RECV PACKET: %u %I64u\n", recv_packet->KeyId, recv_packet->MySessionId);
}
if (recv_packet->OpCode != OPENVPN_P_DATA_V1)
{
Debug(" PKT %u %u\n", recv_packet->OpCode, recv_packet->KeyId);
}
if (recv_packet->OpCode != OPENVPN_P_DATA_V1)
{
// Control packet
if (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2 ||
recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
{
// Connection request packet
if (se->Channels[recv_packet->KeyId] != NULL)
{
// Release when there is a channel data already
OvsFreeChannel(se->Channels[recv_packet->KeyId]);
se->Channels[recv_packet->KeyId] = NULL;
}
// Create a new channel
c = OvsNewChannel(se, recv_packet->KeyId);
if (se->ClientSessionId == 0)
{
se->ClientSessionId = recv_packet->MySessionId;
}
se->Channels[recv_packet->KeyId] = c;
Debug("OpenVPN New Channel :%u\n", recv_packet->KeyId);
OvsLog(s, se, c, "LO_NEW_CHANNEL");
}
/* else if (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
{
// Response to soft reset request packet
OPENVPN_PACKET *p;
p = OvsNewControlPacket(OPENVPN_P_CONTROL_SOFT_RESET_V1, recv_packet->KeyId, se->ServerSessionId,
0, NULL, 0, 0, 0, NULL);
OvsSendPacketNow(s, se, p);
OvsFreePacket(p);
}*/
else
{
// Packet other than the connection request
if (se->Channels[recv_packet->KeyId] != NULL)
{
c = se->Channels[recv_packet->KeyId];
}
}
if (c != NULL)
{
// Delete the send packet list by looking the packet ID in the ACK list of arrived packet
OvsDeleteFromSendingControlPacketList(c, recv_packet->NumAck, recv_packet->AckPacketId);
if (recv_packet->OpCode != OPENVPN_P_ACK_V1)
{
// Add the Packet ID of arrived packet to the list
InsertIntDistinct(c->AckReplyList, recv_packet->PacketId);
Debug("Recv Packet ID (c=%u): %u\n", c->KeyId, recv_packet->PacketId);
if ((recv_packet->PacketId > c->MaxRecvPacketId)
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2)
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1))
{
c->MaxRecvPacketId = recv_packet->PacketId;
// Process the received control packet
OvsProcessRecvControlPacket(s, se, c, recv_packet);
}
}
}
Debug("OvsProceccRecvPacket(): detected packet obfuscation/scrambling mode: %u\n", se->ObfuscationMode);
}
else
{
// Data packet
Debug("OvsProceccRecvPacket(): failed to detect packet obfuscation/scrambling mode!\n");
return;
}
}
// Handle scrambled packet
switch (se->ObfuscationMode)
{
case OPENVPN_SCRAMBLE_MODE_DISABLED:
break;
case OPENVPN_SCRAMBLE_MODE_XORMASK:
OvsDataXorMask(p->Data, p->Size, s->Cedar->OpenVPNObfuscationMask, StrLen(s->Cedar->OpenVPNObfuscationMask));
break;
case OPENVPN_SCRAMBLE_MODE_XORPTRPOS:
OvsDataXorPtrPos(p->Data, p->Size);
break;
case OPENVPN_SCRAMBLE_MODE_REVERSE:
OvsDataReverse(p->Data, p->Size);
break;
case OPENVPN_SCRAMBLE_MODE_OBFUSCATE:
OvsDataXorMask(p->Data, p->Size, s->Cedar->OpenVPNObfuscationMask, StrLen(s->Cedar->OpenVPNObfuscationMask));
OvsDataXorPtrPos(p->Data, p->Size);
OvsDataReverse(p->Data, p->Size);
OvsDataXorPtrPos(p->Data, p->Size);
}
// Parse the packet
recv_packet = OvsParsePacket(p->Data, p->Size);
if (recv_packet == NULL)
{
Debug("OvsProceccRecvPacket(): OvsParsePacket() returned NULL!\n");
return;
}
if (recv_packet->OpCode != OPENVPN_P_DATA_V1 && recv_packet->MySessionId != 0)
{
Debug("RECV PACKET: %u %I64u\n", recv_packet->KeyId, recv_packet->MySessionId);
}
if (recv_packet->OpCode != OPENVPN_P_DATA_V1)
{
Debug(" PKT %u %u\n", recv_packet->OpCode, recv_packet->KeyId);
}
if (recv_packet->OpCode != OPENVPN_P_DATA_V1)
{
// Control packet
if (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2 ||
recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
{
// Connection request packet
if (se->Channels[recv_packet->KeyId] != NULL)
{
OPENVPN_CHANNEL *c = se->Channels[recv_packet->KeyId];
if (c->Status == OPENVPN_CHANNEL_STATUS_ESTABLISHED)
// Release when there is a channel data already
OvsFreeChannel(se->Channels[recv_packet->KeyId]);
se->Channels[recv_packet->KeyId] = NULL;
}
// Create a new channel
c = OvsNewChannel(se, recv_packet->KeyId);
if (se->ClientSessionId == 0)
{
se->ClientSessionId = recv_packet->MySessionId;
}
se->Channels[recv_packet->KeyId] = c;
Debug("OpenVPN New Channel :%u\n", recv_packet->KeyId);
OvsLog(s, se, c, "LO_NEW_CHANNEL");
}
/* else if (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1)
{
// Response to soft reset request packet
OPENVPN_PACKET *p;
p = OvsNewControlPacket(OPENVPN_P_CONTROL_SOFT_RESET_V1, recv_packet->KeyId, se->ServerSessionId,
0, NULL, 0, 0, 0, NULL);
OvsSendPacketNow(s, se, p);
OvsFreePacket(p);
}*/
else
{
// Packet other than the connection request
if (se->Channels[recv_packet->KeyId] != NULL)
{
c = se->Channels[recv_packet->KeyId];
}
}
if (c != NULL)
{
// Delete the send packet list by looking the packet ID in the ACK list of arrived packet
OvsDeleteFromSendingControlPacketList(c, recv_packet->NumAck, recv_packet->AckPacketId);
if (recv_packet->OpCode != OPENVPN_P_ACK_V1)
{
// Add the Packet ID of arrived packet to the list
InsertIntDistinct(c->AckReplyList, recv_packet->PacketId);
Debug("Recv Packet ID (c=%u): %u\n", c->KeyId, recv_packet->PacketId);
if ((recv_packet->PacketId > c->MaxRecvPacketId)
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_HARD_RESET_CLIENT_V2)
|| (recv_packet->OpCode == OPENVPN_P_CONTROL_SOFT_RESET_V1))
{
UINT size;
UCHAR *data = s->TmpBuf;
if (c->CipherDecrypt->IsAeadCipher)
c->MaxRecvPacketId = recv_packet->PacketId;
// Process the received control packet
OvsProcessRecvControlPacket(s, se, c, recv_packet);
}
}
}
}
else
{
// Data packet
if (se->Channels[recv_packet->KeyId] != NULL)
{
OPENVPN_CHANNEL *c = se->Channels[recv_packet->KeyId];
if (c->Status == OPENVPN_CHANNEL_STATUS_ESTABLISHED)
{
UINT size;
UCHAR *data = s->TmpBuf;
if (c->CipherDecrypt->IsAeadCipher)
{
// Update variable part (packet ID) of IV
Copy(c->IvRecv, recv_packet->Data, sizeof(recv_packet->PacketId));
// Decrypt
size = OvsDecrypt(c->CipherDecrypt, NULL, c->IvRecv, data, recv_packet->Data + sizeof(UINT), recv_packet->DataSize - sizeof(UINT));
}
else
{
// Decrypt
size = OvsDecrypt(c->CipherDecrypt, c->MdRecv, c->IvRecv, data, recv_packet->Data, recv_packet->DataSize);
// Seek buffer after the packet ID
data += sizeof(UINT);
size -= sizeof(UINT);
}
// Update of last communication time
se->LastCommTick = s->Now;
if (size < sizeof(ping_signature) || Cmp(data, ping_signature, sizeof(ping_signature)) != 0)
{
// Receive a packet!
if (se->Ipc != NULL)
{
// Update variable part (packet ID) of IV
Copy(c->IvRecv, recv_packet->Data, sizeof(recv_packet->PacketId));
// Decrypt
size = OvsDecrypt(c->CipherDecrypt, NULL, c->IvRecv, data, recv_packet->Data + sizeof(UINT), recv_packet->DataSize - sizeof(UINT));
}
else
{
// Decrypt
size = OvsDecrypt(c->CipherDecrypt, c->MdRecv, c->IvRecv, data, recv_packet->Data, recv_packet->DataSize);
// Seek buffer after the packet ID
data += sizeof(UINT);
size -= sizeof(UINT);
}
// Update of last communication time
se->LastCommTick = s->Now;
if (size < sizeof(ping_signature) || Cmp(data, ping_signature, sizeof(ping_signature)) != 0)
{
// Receive a packet!
if (se->Ipc != NULL)
switch (se->Mode)
{
switch (se->Mode)
{
case OPENVPN_MODE_L2: // Send an Ethernet packet to a session
IPCSendL2(se->Ipc, data, size);
break;
case OPENVPN_MODE_L3: // Send an IPv4 packet to a session
IPCSendIPv4(se->Ipc, data, size);
break;
}
case OPENVPN_MODE_L2: // Send an Ethernet packet to a session
IPCSendL2(se->Ipc, data, size);
break;
case OPENVPN_MODE_L3: // Send an IPv4 packet to a session
IPCSendIPv4(se->Ipc, data, size);
break;
}
}
}
}
}
OvsFreePacket(recv_packet);
}
OvsFreePacket(recv_packet);
}
// Remove a packet which the opponent has received from the transmission list
@ -1725,7 +1902,6 @@ OPENVPN_PACKET *OvsParsePacket(UCHAR *data, UINT size)
return ret;
LABEL_ERROR:
Debug("OvsParsePacket Error.\n");
OvsFreePacket(ret);
return NULL;
}
@ -1830,6 +2006,8 @@ OPENVPN_SESSION *OvsNewSession(OPENVPN_SERVER *s, IP *server_ip, UINT server_por
Copy(&se->ServerIp, server_ip, sizeof(IP));
se->ServerPort = server_port;
se->ObfuscationMode = s->Cedar->OpenVPNObfuscation ? INFINITE : OPENVPN_SCRAMBLE_MODE_DISABLED;
se->LastCommTick = s->Now;
se->Protocol = protocol;
@ -2508,6 +2686,27 @@ void OvsSendPacketRawNow(OPENVPN_SERVER *s, OPENVPN_SESSION *se, void *data, UIN
return;
}
// Scramble the packet
switch (se->ObfuscationMode)
{
case OPENVPN_SCRAMBLE_MODE_DISABLED:
break;
case OPENVPN_SCRAMBLE_MODE_XORMASK:
OvsDataXorMask(data, size, s->Cedar->OpenVPNObfuscationMask, StrLen(s->Cedar->OpenVPNObfuscationMask));
break;
case OPENVPN_SCRAMBLE_MODE_XORPTRPOS:
OvsDataXorPtrPos(data, size);
break;
case OPENVPN_SCRAMBLE_MODE_REVERSE:
OvsDataReverse(data, size);
break;
case OPENVPN_SCRAMBLE_MODE_OBFUSCATE:
OvsDataXorPtrPos(data, size);
OvsDataReverse(data, size);
OvsDataXorPtrPos(data, size);
OvsDataXorMask(data, size, s->Cedar->OpenVPNObfuscationMask, StrLen(s->Cedar->OpenVPNObfuscationMask));
}
u = NewUdpPacket(&se->ServerIp, se->ServerPort, &se->ClientIp, se->ClientPort,
data, size);

View File

@ -185,6 +185,12 @@
#define OPENVPN_MODE_L2 1 // TAP (Ethernet)
#define OPENVPN_MODE_L3 2 // TUN (IP)
// Scramble mode
#define OPENVPN_SCRAMBLE_MODE_DISABLED 0 // No scramble
#define OPENVPN_SCRAMBLE_MODE_XORMASK 1 // XOR the bytes with the specified string
#define OPENVPN_SCRAMBLE_MODE_XORPTRPOS 2 // XOR each byte with its position in the buffer
#define OPENVPN_SCRAMBLE_MODE_REVERSE 3 // Reverses bytes order, keeping the first byte unchanged
#define OPENVPN_SCRAMBLE_MODE_OBFUSCATE 4 // Performs the above steps using the specified string for xormask
//// Type
@ -271,6 +277,7 @@ struct OPENVPN_SESSION
OPENVPN_CHANNEL *Channels[OPENVPN_NUM_CHANNELS]; // Channels (up to 8)
UINT LastCreatedChannelIndex; // Channel number that is created in the last
UINT Mode; // Mode (L3 or L2)
UINT ObfuscationMode; // Packet obfuscation/scrambling mode
UINT LinkMtu; // link-mtu
UINT TunMtu; // tun-mtu
IPC_ASYNC *IpcAsync; // Asynchronous IPC connection

View File

@ -154,6 +154,9 @@ void SiSetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c)
NormalizeIntListStr(s->OpenVpnServerUdpPorts, sizeof(s->OpenVpnServerUdpPorts),
c->OpenVPNPortList, true, ", ");
s->Cedar->OpenVPNObfuscation = c->OpenVPNObfuscation;
StrCpy(s->Cedar->OpenVPNObfuscationMask, sizeof(s->Cedar->OpenVPNObfuscationMask), c->OpenVPNObfuscationMask);
// Apply the OpenVPN configuration
if (s->OpenVpnServerUdp != NULL)
{
@ -194,6 +197,9 @@ void SiGetOpenVPNAndSSTPConfig(SERVER *s, OPENVPN_SSTP_CONFIG *c)
}
StrCpy(c->OpenVPNPortList, sizeof(c->OpenVPNPortList), s->OpenVpnServerUdpPorts);
c->OpenVPNObfuscation = s->Cedar->OpenVPNObfuscation;
StrCpy(c->OpenVPNObfuscationMask, sizeof(c->OpenVPNObfuscationMask), s->Cedar->OpenVPNObfuscationMask);
}
Unlock(s->OpenVpnSstpConfigLock);
}
@ -2569,6 +2575,8 @@ void SiLoadInitialConfiguration(SERVER *s)
ToStr(c.OpenVPNPortList, OPENVPN_UDP_PORT);
}
c.OpenVPNObfuscation = false;
SiSetOpenVPNAndSSTPConfig(s, &c);
{
@ -6000,6 +6008,16 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
config.EnableSSTP = !s->DisableSSTPServer;
StrCpy(config.OpenVPNPortList, sizeof(config.OpenVPNPortList), tmp);
config.OpenVPNObfuscation = CfgGetBool(f, "OpenVPNObfuscation");
if (CfgGetStr(f, "OpenVPNObfuscationMask", tmp, sizeof(tmp)))
{
if (IsEmptyStr(tmp) == false)
{
StrCpy(config.OpenVPNObfuscationMask, sizeof(config.OpenVPNObfuscationMask), tmp);
}
}
SiSetOpenVPNAndSSTPConfig(s, &config);
if (s->ServerType == SERVER_TYPE_FARM_MEMBER)
@ -6271,6 +6289,9 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
SiGetOpenVPNAndSSTPConfig(s, &config);
CfgAddStr(f, "OpenVPN_UdpPortList", config.OpenVPNPortList);
CfgAddBool(f, "OpenVPNObfuscation", config.OpenVPNObfuscation);
CfgAddStr(f, "OpenVPNObfuscationMask", config.OpenVPNObfuscationMask);
}
// WebTimePage

View File

@ -253,6 +253,8 @@ struct OPENVPN_SSTP_CONFIG
{
bool EnableOpenVPN; // OpenVPN is enabled
char OpenVPNPortList[MAX_SIZE]; // OpenVPN UDP port number list
bool OpenVPNObfuscation; // OpenVPN: Obfuscation mode
char OpenVPNObfuscationMask[MAX_SIZE]; // OpenVPN: String (mask) for XOR obfuscation
bool EnableSSTP; // SSTP is enabled
};