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:
@ -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
|
||||
|
@ -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
|
||||
|
@ -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)
|
||||
{
|
||||
|
@ -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);
|
||||
|
@ -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);
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
};
|
||||
|
||||
|
Reference in New Issue
Block a user