1
0
mirror of https://github.com/SoftEtherVPN/SoftEtherVPN.git synced 2025-04-03 18:00:08 +03:00

Support custom VPN Azure service

This commit is contained in:
Yihong Wu 2023-01-04 14:07:15 +00:00
parent b8110237ef
commit 03ce6d47ba
11 changed files with 740 additions and 93 deletions

View File

@ -1644,6 +1644,8 @@ PACK *AdminDispatch(RPC *rpc, char *name, PACK *p)
DECLARE_RPC("GetSpecialListener", RPC_SPECIAL_LISTENER, StGetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener)
DECLARE_RPC("GetAzureStatus", RPC_AZURE_STATUS, StGetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
DECLARE_RPC("SetAzureStatus", RPC_AZURE_STATUS, StSetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
DECLARE_RPC_EX("SetAzureCustom", RPC_AZURE_CUSTOM, StSetAzureCustom, InRpcAzureCustom, OutRpcAzureCustom, FreeRpcAzureCustom)
DECLARE_RPC_EX("GetAzureCustom", RPC_AZURE_CUSTOM, StGetAzureCustom, InRpcAzureCustom, OutRpcAzureCustom, FreeRpcAzureCustom)
DECLARE_RPC("GetDDnsInternetSettng", INTERNET_SETTING, StGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
DECLARE_RPC("SetDDnsInternetSettng", INTERNET_SETTING, StSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
// RPC function declaration: till here
@ -1831,6 +1833,8 @@ DECLARE_SC("SetSpecialListener", RPC_SPECIAL_LISTENER, ScSetSpecialListener, InR
DECLARE_SC("GetSpecialListener", RPC_SPECIAL_LISTENER, ScGetSpecialListener, InRpcSpecialListener, OutRpcSpecialListener)
DECLARE_SC("GetAzureStatus", RPC_AZURE_STATUS, ScGetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
DECLARE_SC("SetAzureStatus", RPC_AZURE_STATUS, ScSetAzureStatus, InRpcAzureStatus, OutRpcAzureStatus)
DECLARE_SC_EX("GetAzureCustom", RPC_AZURE_CUSTOM, ScGetAzureCustom, InRpcAzureCustom, OutRpcAzureCustom, FreeRpcAzureCustom)
DECLARE_SC_EX("SetAzureCustom", RPC_AZURE_CUSTOM, ScSetAzureCustom, InRpcAzureCustom, OutRpcAzureCustom, FreeRpcAzureCustom)
DECLARE_SC("GetDDnsInternetSettng", INTERNET_SETTING, ScGetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
DECLARE_SC("SetDDnsInternetSettng", INTERNET_SETTING, ScSetDDnsInternetSetting, InRpcInternetSetting, OutRpcInternetSetting)
// RPC call function declaration: till here
@ -1919,6 +1923,12 @@ UINT StGetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t)
{
t->IsConnected = ac->IsConnected;
t->IsEnabled = ac->IsEnabled;
t->UseCustom = ac->UseCustom;
if (ac->UseCustom && ac->CustomConfig != NULL)
{
StrCpy(t->CurrentHostname, sizeof(t->CurrentHostname), ac->CustomConfig->Hostname);
}
}
Unlock(ac->Lock);
@ -1940,7 +1950,90 @@ UINT StSetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t)
return ERR_NOT_SUPPORTED;
}
SiSetAzureEnable(s, t->IsEnabled);
SiSetAzureEnable(s, t->IsEnabled, t->UseCustom);
IncrementServerConfigRevision(s);
return ERR_NO_ERROR;
}
// Get Azure custom config
UINT StGetAzureCustom(ADMIN *a, RPC_AZURE_CUSTOM *t)
{
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
UINT ret = ERR_NO_ERROR;
AZURE_CLIENT *ac;
SERVER_ADMIN_ONLY;
NO_SUPPORT_FOR_BRIDGE;
if (SiIsAzureSupported(s) == false)
{
return ERR_NOT_SUPPORTED;
}
ac = s->AzureClient;
if (ac == NULL)
{
return ERR_NOT_SUPPORTED;
}
Zero(t, sizeof(RPC_AZURE_CUSTOM));
Lock(ac->Lock);
{
if (ac->CustomConfig != NULL)
{
StrCpy(t->ServerName, sizeof(t->ServerName), ac->CustomConfig->ServerName);
t->ServerPort = ac->CustomConfig->ServerPort;
StrCpy(t->Hostname, sizeof(t->Hostname), ac->CustomConfig->Hostname);
Copy(t->HashedPassword, ac->CustomConfig->HashedPassword, SHA1_SIZE);
t->ClientX = CloneX(ac->CustomConfig->ClientX);
t->ClientK = CloneK(ac->CustomConfig->ClientK);
t->ServerCert = CloneX(ac->CustomConfig->ServerCert);
t->VerifyServer = ac->CustomConfig->VerifyServer;
t->AddDefaultCA = ac->CustomConfig->AddDefaultCA;
}
}
Unlock(ac->Lock);
return ERR_NO_ERROR;
}
// Set Azure custom config
UINT StSetAzureCustom(ADMIN *a, RPC_AZURE_CUSTOM *t)
{
SERVER *s = a->Server;
CEDAR *c = s->Cedar;
UINT ret = ERR_NO_ERROR;
SERVER_ADMIN_ONLY;
NO_SUPPORT_FOR_BRIDGE;
if (SiIsAzureSupported(s) == false)
{
return ERR_NOT_SUPPORTED;
}
AZURE_CUSTOM_CONFIG *config = ZeroMalloc(sizeof(AZURE_CUSTOM_CONFIG));
if (t->ClientX != NULL && t->ClientK != NULL && CheckXandK(t->ClientX, t->ClientK) == false)
{
return ERR_PROTOCOL_ERROR;
}
StrCpy(config->ServerName, sizeof(config->ServerName), t->ServerName);
config->ServerPort = t->ServerPort;
StrCpy(config->Hostname, sizeof(config->Hostname), t->Hostname);
Copy(config->HashedPassword, t->HashedPassword, SHA1_SIZE);
config->ClientX = CloneX(t->ClientX);
config->ClientK = CloneK(t->ClientK);
config->ServerCert = CloneX(t->ServerCert);
config->VerifyServer = t->VerifyServer;
config->AddDefaultCA = t->AddDefaultCA;
SiApplyAzureConfig(s, NULL, config);
IncrementServerConfigRevision(s);
@ -10545,6 +10638,8 @@ void InRpcAzureStatus(RPC_AZURE_STATUS *t, PACK *p)
t->IsConnected = PackGetBool(p, "IsConnected");
t->IsEnabled = PackGetBool(p, "IsEnabled");
t->UseCustom = PackGetBool(p, "UseCustom");
PackGetStr(p, "CurrentHostname", t->CurrentHostname, sizeof(t->CurrentHostname));
}
void OutRpcAzureStatus(PACK *p, RPC_AZURE_STATUS *t)
{
@ -10556,6 +10651,60 @@ void OutRpcAzureStatus(PACK *p, RPC_AZURE_STATUS *t)
PackAddBool(p, "IsConnected", t->IsConnected);
PackAddBool(p, "IsEnabled", t->IsEnabled);
PackAddBool(p, "UseCustom", t->UseCustom);
PackAddStr(p, "CurrentHostname", t->CurrentHostname);
}
// RPC_AZURE_CUSTOM
void InRpcAzureCustom(RPC_AZURE_CUSTOM *t, PACK *p)
{
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
Zero(t, sizeof(RPC_AZURE_CUSTOM));
PackGetStr(p, "ServerName", t->ServerName, sizeof(t->ServerName));
t->ServerPort = PackGetInt(p, "ServerPort");
PackGetStr(p, "Hostname", t->Hostname, sizeof(t->Hostname));
PackGetData2(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
t->ClientX = PackGetX(p, "ClientCert");
t->ClientK = PackGetK(p, "ClientKey");
t->ServerCert = PackGetX(p, "ServerCert");
t->VerifyServer = PackGetBool(p, "VerifyServer");
t->AddDefaultCA = PackGetBool(p, "AddDefaultCA");
}
void OutRpcAzureCustom(PACK *p, RPC_AZURE_CUSTOM *t)
{
// Validate arguments
if (t == NULL || p == NULL)
{
return;
}
PackAddStr(p, "ServerName", t->ServerName);
PackAddInt(p, "ServerPort", t->ServerPort);
PackAddStr(p, "Hostname", t->Hostname);
PackAddData(p, "HashedPassword", t->HashedPassword, sizeof(t->HashedPassword));
PackAddX(p, "ClientCert", t->ClientX);
PackAddK(p, "ClientKey", t->ClientK);
PackAddX(p, "ServerCert", t->ServerCert);
PackAddBool(p, "VerifyServer", t->VerifyServer);
PackAddBool(p, "AddDefaultCA", t->AddDefaultCA);
}
void FreeRpcAzureCustom(RPC_AZURE_CUSTOM *t)
{
// Validate arguments
if (t == NULL)
{
return;
}
FreeX(t->ServerCert);
FreeX(t->ClientX);
FreeK(t->ClientK);
}
// RPC_SPECIAL_LISTENER

View File

@ -933,6 +933,22 @@ struct RPC_AZURE_STATUS
{
bool IsEnabled; // Whether enabled
bool IsConnected; // Whether it's connected
bool UseCustom; // Whether using custom service
char CurrentHostname[MAX_HOST_NAME_LEN + 1];
};
// Get / Set the custom Azure config
struct RPC_AZURE_CUSTOM
{
char ServerName[MAX_HOST_NAME_LEN + 1]; // VPN Azure server name
UINT ServerPort; // VPN Azure port number
char Hostname[MAX_HOST_NAME_LEN + 1]; // VPN Azure client hostname
UCHAR HashedPassword[SHA1_SIZE]; // Hashed passwords
X *ClientX; // VPN Azure client certificate
K *ClientK; // VPN Azure client private key
X *ServerCert; // VPN Azure server certificate
bool VerifyServer; // Verify server certificate
bool AddDefaultCA; // Use default trust store to verify server
};
// Constants
@ -1130,6 +1146,8 @@ UINT StSetSpecialListener(ADMIN *a, RPC_SPECIAL_LISTENER *t);
UINT StGetSpecialListener(ADMIN *a, RPC_SPECIAL_LISTENER *t);
UINT StGetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t);
UINT StSetAzureStatus(ADMIN *a, RPC_AZURE_STATUS *t);
UINT StGetAzureCustom(ADMIN *a, RPC_AZURE_CUSTOM *t);
UINT StSetAzureCustom(ADMIN *a, RPC_AZURE_CUSTOM *t);
UINT StGetDDnsInternetSetting(ADMIN *a, INTERNET_SETTING *t);
UINT StSetDDnsInternetSetting(ADMIN *a, INTERNET_SETTING *t);
UINT StSetVgsConfig(ADMIN *a, VGS_CONFIG *t);
@ -1281,6 +1299,8 @@ UINT ScSetSpecialListener(RPC *r, RPC_SPECIAL_LISTENER *t);
UINT ScGetSpecialListener(RPC *r, RPC_SPECIAL_LISTENER *t);
UINT ScGetAzureStatus(RPC *r, RPC_AZURE_STATUS *t);
UINT ScSetAzureStatus(RPC *r, RPC_AZURE_STATUS *t);
UINT ScGetAzureCustom(RPC *r, RPC_AZURE_CUSTOM *t);
UINT ScSetAzureCustom(RPC *r, RPC_AZURE_CUSTOM *t);
UINT ScGetDDnsInternetSetting(RPC *r, INTERNET_SETTING *t);
UINT ScSetDDnsInternetSetting(RPC *r, INTERNET_SETTING *t);
UINT ScSetVgsConfig(RPC *r, VGS_CONFIG *t);
@ -1512,6 +1532,9 @@ void InRpcSpecialListener(RPC_SPECIAL_LISTENER *t, PACK *p);
void OutRpcSpecialListener(PACK *p, RPC_SPECIAL_LISTENER *t);
void InRpcAzureStatus(RPC_AZURE_STATUS *t, PACK *p);
void OutRpcAzureStatus(PACK *p, RPC_AZURE_STATUS *t);
void InRpcAzureCustom(RPC_AZURE_CUSTOM *t, PACK *p);
void OutRpcAzureCustom(PACK *p, RPC_AZURE_CUSTOM *t);
void FreeRpcAzureCustom(RPC_AZURE_CUSTOM *t);
void InRpcInternetSetting(INTERNET_SETTING *t, PACK *p);
void OutRpcInternetSetting(PACK *p, INTERNET_SETTING *t);

View File

@ -39,7 +39,7 @@ void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param)
UCHAR uc;
// Receive 1 byte
if (RecvAll(s, &uc, 1, false) == 0)
if (RecvAll(s, &uc, 1, param->UseEncryption) == 0)
{
break;
}
@ -70,6 +70,7 @@ void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param)
UINT client_port;
UINT server_port;
UCHAR session_id[SHA1_SIZE];
UCHAR relay_cert_hash[SHA1_SIZE];
if (PackGetIp(p, "client_ip", &client_ip) &&
PackGetIp(p, "server_ip", &server_ip) &&
@ -87,15 +88,58 @@ void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param)
SLog(ac->Cedar, "LS_AZURE_START", ipstr, client_port);
// Create new socket and connect VPN Azure Server
if (ac->DDnsStatusCopy.InternetSetting.ProxyType == PROXY_DIRECT)
if (param->UseCustom)
{
ns = ConnectEx2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT,
0, (bool *)&ac->Halt);
// Get relay server info from pack
char relay_addr[MAX_HOST_NAME_LEN + 1];
UINT relay_port;
relay_port = PackGetInt(p, "relay_port");
if (PackGetStr(p, "relay_address", relay_addr, sizeof(relay_addr)) &&
PackGetData2(p, "cert_hash", relay_cert_hash, sizeof(relay_cert_hash)) &&
relay_port != 0)
{
ns = ConnectEx2(relay_addr, relay_port, 0, (bool *)&ac->Halt);
if (ns != NULL)
{
UINT ssl_err = 0;
Copy(&ns->SslAcceptSettings, &ac->Cedar->SslAcceptSettings, sizeof(SSL_ACCEPT_SETTINGS));
if (StartSSLEx3(ns, NULL, NULL, NULL, 0, relay_addr, NULL, &ssl_err) == false)
{
if (ssl_err != 0)
{
SLog(ac->Cedar, "LS_AZURE_SSL_ERROR", GetUniErrorStr(ssl_err), ssl_err);
}
Disconnect(ns);
ReleaseSock(ns);
ns = NULL;
}
}
}
}
else
{
ns = WpcSockConnect2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT,
&ac->DDnsStatusCopy.InternetSetting, NULL, AZURE_VIA_PROXY_TIMEOUT);
BUF *b = StrToBin(ac->DDnsStatus.AzureCertHash);
if (b->Size == SHA1_SIZE)
{
Copy(relay_cert_hash, b->Buf, SHA1_SIZE);
}
FreeBuf(b);
if (ac->DDnsStatusCopy.InternetSetting.ProxyType == PROXY_DIRECT)
{
ns = ConnectEx2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT,
0, (bool *)&ac->Halt);
}
else
{
ns = WpcSockConnect2(ac->DDnsStatusCopy.CurrentAzureIp, AZURE_SERVER_PORT,
&ac->DDnsStatusCopy.InternetSetting, NULL, AZURE_VIA_PROXY_TIMEOUT);
}
}
if (ns == NULL)
@ -114,17 +158,12 @@ void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param)
if (StartSSLEx3(ns, NULL, NULL, NULL, 0, NULL, NULL, &ssl_err))
{
// Check certification
char server_cert_hash_str[MAX_SIZE];
UCHAR server_cert_hash[SHA1_SIZE];
Zero(server_cert_hash, sizeof(server_cert_hash));
GetXDigest(ns->RemoteX, server_cert_hash, true);
BinToStr(server_cert_hash_str, sizeof(server_cert_hash_str),
server_cert_hash, SHA1_SIZE);
if (IsEmptyStr(ac->DDnsStatusCopy.AzureCertHash) || StrCmpi(server_cert_hash_str, ac->DDnsStatusCopy.AzureCertHash) == 0
|| StrCmpi(server_cert_hash_str, ac->DDnsStatus.AzureCertHash) == 0)
if (Cmp(relay_cert_hash, server_cert_hash, SHA1_SIZE) == 0)
{
if (SendAll(ns, AZURE_PROTOCOL_DATA_SIANGTURE, 24, true))
{
@ -185,7 +224,7 @@ void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param)
// Send 1 byte
uc = 0;
if (SendAll(s, &uc, 1, false) == 0)
if (SendAll(s, &uc, 1, param->UseEncryption) == 0)
{
break;
}
@ -219,29 +258,59 @@ void AcMainThread(THREAD *thread, void *param)
DDNS_CLIENT_STATUS st;
bool connect_now = false;
bool azure_ip_changed = false;
bool use_custom_azure = false;
bool use_encryption = false;
char hostname[MAX_HOST_NAME_LEN + 1];
UCHAR hashed_password[SHA1_SIZE];
char server_address[MAX_HOST_NAME_LEN + 1];
UINT server_port = AZURE_SERVER_PORT;
bool add_default_ca = false;
bool verify_server = false;
X *server_cert = NULL;
X *client_cert = NULL;
K *client_key = NULL;
Lock(ac->Lock);
{
Copy(&st, &ac->DDnsStatus, sizeof(DDNS_CLIENT_STATUS));
if (StrCmpi(st.CurrentAzureIp, ac->DDnsStatusCopy.CurrentAzureIp) != 0)
if (ac->UseCustom && ac->CustomConfig != NULL)
{
if (IsEmptyStr(st.CurrentAzureIp) == false)
use_custom_azure = true;
use_encryption = true;
StrCpy(hostname, sizeof(hostname), ac->CustomConfig->Hostname);
Copy(hashed_password, ac->CustomConfig->HashedPassword, SHA1_SIZE);
StrCpy(server_address, sizeof(server_address), ac->CustomConfig->ServerName);
server_port = ac->CustomConfig->ServerPort;
verify_server = ac->CustomConfig->VerifyServer;
add_default_ca = ac->CustomConfig->AddDefaultCA;
server_cert = CloneX(ac->CustomConfig->ServerCert);
client_cert = CloneX(ac->CustomConfig->ClientX);
client_key = CloneK(ac->CustomConfig->ClientK);
}
else
{
Copy(&st, &ac->DDnsStatus, sizeof(DDNS_CLIENT_STATUS));
StrCpy(server_address, sizeof(server_address), st.CurrentAzureIp);
StrCpy(hostname, sizeof(hostname), st.CurrentHostName);
if (StrCmpi(st.CurrentAzureIp, ac->DDnsStatusCopy.CurrentAzureIp) != 0)
{
// Destination IP address is changed
if (IsEmptyStr(st.CurrentAzureIp) == false)
{
// Destination IP address is changed
connect_now = true;
num_reconnect_retry = 0;
}
}
if (StrCmpi(st.CurrentHostName, ac->DDnsStatusCopy.CurrentHostName) != 0)
{
// DDNS host name is changed
connect_now = true;
num_reconnect_retry = 0;
}
}
if (StrCmpi(st.CurrentHostName, ac->DDnsStatusCopy.CurrentHostName) != 0)
{
// DDNS host name is changed
connect_now = true;
num_reconnect_retry = 0;
Copy(&ac->DDnsStatusCopy, &st, sizeof(DDNS_CLIENT_STATUS));
}
Copy(&ac->DDnsStatusCopy, &st, sizeof(DDNS_CLIENT_STATUS));
}
Unlock(ac->Lock);
@ -272,19 +341,49 @@ void AcMainThread(THREAD *thread, void *param)
connect_now = true;
}
if (IsEmptyStr(st.CurrentAzureIp) == false && IsEmptyStr(st.CurrentHostName) == false)
if (IsEmptyStr(server_address) == false && IsEmptyStr(hostname) == false)
{
if (connect_now)
{
SOCK *s;
char *host = NULL;
UINT port = AZURE_SERVER_PORT;
UINT port;
Debug("VPN Azure: Connecting to %s...\n", st.CurrentAzureIp);
Debug("VPN Azure: Connecting to %s...\n", server_address);
if (ParseHostPort(st.CurrentAzureIp, &host, &port, AZURE_SERVER_PORT))
if (ParseHostPort(server_address, &host, &port, server_port))
{
if (st.InternetSetting.ProxyType == PROXY_DIRECT)
if (use_custom_azure)
{
s = ConnectEx2(host, port, 0, (bool *)&ac->Halt);
if (s != NULL && use_encryption)
{
// Enable SSL peer verification if we have a server cert or trust system CA
SSL_VERIFY_OPTION ssl_option;
Zero(&ssl_option, sizeof(ssl_option));
ssl_option.VerifyPeer = verify_server;
ssl_option.AddDefaultCA = add_default_ca;
ssl_option.VerifyHostname = verify_server;
ssl_option.SavedCert = server_cert;
UINT ssl_err = 0;
Copy(&s->SslAcceptSettings, &ac->Cedar->SslAcceptSettings, sizeof(SSL_ACCEPT_SETTINGS));
if (StartSSLEx3(s, client_cert, client_key, NULL, 0, server_address, &ssl_option, &ssl_err) == false)
{
if (ssl_err != 0)
{
SLog(ac->Cedar, "LS_AZURE_SSL_ERROR", GetUniErrorStr(ssl_err), ssl_err);
}
Disconnect(s);
ReleaseSock(s);
s = NULL;
}
}
}
else if (st.InternetSetting.ProxyType == PROXY_DIRECT)
{
s = ConnectEx2(host, port, 0, (bool *)&ac->Halt);
}
@ -306,11 +405,11 @@ void AcMainThread(THREAD *thread, void *param)
{
ac->CurrentSock = s;
ac->IsConnected = true;
StrCpy(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp), st.CurrentAzureIp);
StrCpy(ac->ConnectingAzureIp, sizeof(ac->ConnectingAzureIp), server_address);
}
Unlock(ac->Lock);
SendAll(s, AZURE_PROTOCOL_CONTROL_SIGNATURE, StrLen(AZURE_PROTOCOL_CONTROL_SIGNATURE), false);
SendAll(s, AZURE_PROTOCOL_CONTROL_SIGNATURE, StrLen(AZURE_PROTOCOL_CONTROL_SIGNATURE), use_encryption);
// Receive parameter
p = RecvPackWithHash(s);
@ -326,6 +425,11 @@ void AcMainThread(THREAD *thread, void *param)
param.ControlTimeout = PackGetInt(p, "ControlTimeout");
param.DataTimeout = PackGetInt(p, "DataTimeout");
param.SslTimeout = PackGetInt(p, "SslTimeout");
param.UseCustom = use_custom_azure;
param.UseEncryption = use_encryption;
UCHAR random[SHA1_SIZE];
PackGetData2(p, "Random", random, sizeof(random));
FreePack(p);
@ -344,14 +448,29 @@ void AcMainThread(THREAD *thread, void *param)
// Send parameter
p = NewPack();
PackAddStr(p, "CurrentHostName", st.CurrentHostName);
PackAddStr(p, "CurrentAzureIp", st.CurrentAzureIp);
PackAddInt64(p, "CurrentAzureTimestamp", st.CurrentAzureTimestamp);
PackAddStr(p, "CurrentAzureSignature", st.CurrentAzureSignature);
PackAddStr(p, "CurrentHostName", hostname);
PackAddStr(p, "CurrentAzureIp", server_address);
if (use_custom_azure == false)
{
PackAddInt64(p, "CurrentAzureTimestamp", st.CurrentAzureTimestamp);
PackAddStr(p, "CurrentAzureSignature", st.CurrentAzureSignature);
}
else
{
BUF *b = NewBuf();
UCHAR hash[SHA1_SIZE];
WriteBuf(b, hashed_password, SHA1_SIZE);
WriteBuf(b, random, SHA1_SIZE);
Sha1(hash, b->Buf, b->Size);
PackAddData(p, "PasswordHash", hash, SHA1_SIZE);
FreeBuf(b);
}
Lock(ac->Lock);
{
if (StrCmpi(st.CurrentHostName, ac->DDnsStatus.CurrentHostName) != 0)
if (use_custom_azure == false && StrCmpi(hostname, ac->DDnsStatus.CurrentHostName) != 0)
{
hostname_changed = true;
}
@ -363,7 +482,7 @@ void AcMainThread(THREAD *thread, void *param)
if (SendPackWithHash(s, p))
{
// Receive result
if (RecvAll(s, &c, 1, false))
if (RecvAll(s, &c, 1, use_encryption))
{
if (c && ac->Halt == false)
{
@ -417,6 +536,10 @@ void AcMainThread(THREAD *thread, void *param)
}
}
}
FreeX(server_cert);
FreeX(client_cert);
FreeK(client_key);
}
else
{
@ -448,31 +571,45 @@ void AcMainThread(THREAD *thread, void *param)
}
// Enable or disable VPN Azure client
void AcSetEnable(AZURE_CLIENT *ac, bool enabled)
void AcSetEnable(AZURE_CLIENT *ac, bool enabled, bool use_custom)
{
bool old_status;
bool changed = false;
// Validate arguments
if (ac == NULL)
{
return;
}
old_status = ac->IsEnabled;
if (ac->IsEnabled != enabled)
{
ac->IsEnabled = enabled;
changed = true;
}
ac->IsEnabled = enabled;
if (ac->UseCustom != use_custom)
{
ac->UseCustom = use_custom;
changed = true;
}
if (ac->IsEnabled && (ac->IsEnabled != old_status))
if (ac->IsEnabled && ac->UseCustom == false && changed)
{
ac->DDnsTriggerInt++;
}
AcApplyCurrentConfig(ac, NULL);
if (ac->IsEnabled == false)
{
// If VPN Azure client is disabled, disconnect current data connection
changed = true;
}
AcApplyCurrentConfig(ac, NULL, NULL, changed);
}
// Set current configuration to VPN Azure client
void AcApplyCurrentConfig(AZURE_CLIENT *ac, DDNS_CLIENT_STATUS *ddns_status)
void AcApplyCurrentConfig(AZURE_CLIENT *ac, DDNS_CLIENT_STATUS *ddns_status, AZURE_CUSTOM_CONFIG *config, bool disconnect)
{
bool disconnect_now = false;
bool disconnect_now = disconnect;
SOCK *disconnect_sock = NULL;
// Validate arguments
if (ac == NULL)
@ -483,29 +620,48 @@ void AcApplyCurrentConfig(AZURE_CLIENT *ac, DDNS_CLIENT_STATUS *ddns_status)
// Get current DDNS configuration
Lock(ac->Lock);
{
if (ddns_status != NULL)
if (config != NULL)
{
if (StrCmpi(ac->DDnsStatus.CurrentHostName, ddns_status->CurrentHostName) != 0)
if (ac->UseCustom)
{
// If host name is changed, disconnect current data connection
disconnect_now = true;
}
if (Cmp(&ac->DDnsStatus.InternetSetting, &ddns_status->InternetSetting, sizeof(INTERNET_SETTING)) != 0)
if (ac->CustomConfig == NULL)
{
// If proxy setting is changed, disconnect current data connection
disconnect_now = true;
ac->CustomConfig = config;
}
else
{
FreeX(ac->CustomConfig->ServerCert);
FreeX(ac->CustomConfig->ClientX);
FreeK(ac->CustomConfig->ClientK);
Free(ac->CustomConfig);
ac->CustomConfig = config;
}
}
if (ddns_status != NULL)
{
if (ac->UseCustom == false)
{
if (StrCmpi(ac->DDnsStatus.CurrentHostName, ddns_status->CurrentHostName) != 0)
{
// If host name is changed, disconnect current data connection
disconnect_now = true;
}
if (Cmp(&ac->DDnsStatus.InternetSetting, &ddns_status->InternetSetting, sizeof(INTERNET_SETTING)) != 0)
{
// If proxy setting is changed, disconnect current data connection
disconnect_now = true;
}
}
Copy(&ac->DDnsStatus, ddns_status, sizeof(DDNS_CLIENT_STATUS));
}
if (ac->IsEnabled == false)
{
// If VPN Azure client is disabled, disconnect current data connection
disconnect_now = true;
}
if (disconnect_now)
{
if (ac->CurrentSock != NULL)
@ -555,6 +711,14 @@ void FreeAzureClient(AZURE_CLIENT *ac)
ReleaseSock(disconnect_sock);
}
if (ac->CustomConfig != NULL)
{
FreeX(ac->CustomConfig->ServerCert);
FreeX(ac->CustomConfig->ClientX);
FreeK(ac->CustomConfig->ClientK);
Free(ac->CustomConfig);
}
Set(ac->Event);
// Stop main thread
@ -569,7 +733,7 @@ void FreeAzureClient(AZURE_CLIENT *ac)
}
// Create new VPN Azure client
AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server)
AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server, AZURE_CUSTOM_CONFIG *config)
{
AZURE_CLIENT *ac;
// Validate arguments
@ -584,10 +748,14 @@ AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server)
ac->Server = server;
ac->CustomConfig = config;
ac->Lock = NewLock();
ac->IsEnabled = false;
ac->UseCustom = false;
ac->Event = NewEvent();
// Start main thread

View File

@ -29,6 +29,20 @@
#define AZURE_VIA_PROXY_TIMEOUT 5000
// Azure custom configuration
struct AZURE_CUSTOM_CONFIG
{
char ServerName[MAX_HOST_NAME_LEN + 1]; // VPN Azure server name
UINT ServerPort; // VPN Azure port number
char Hostname[MAX_HOST_NAME_LEN + 1]; // VPN Azure client hostname
UCHAR HashedPassword[SHA1_SIZE]; // Hashed passwords
X *ClientX; // VPN Azure client certificate
K *ClientK; // VPN Azure client private key
X *ServerCert; // VPN Azure server certificate
bool VerifyServer; // Verify server certificate
bool AddDefaultCA; // Use default trust store to verify server
};
// Communications parameter
struct AZURE_PARAM
{
@ -36,6 +50,8 @@ struct AZURE_PARAM
UINT ControlTimeout;
UINT DataTimeout;
UINT SslTimeout;
bool UseCustom;
bool UseEncryption;
};
// VPN Azure Client
@ -46,6 +62,7 @@ struct AZURE_CLIENT
LOCK *Lock;
DDNS_CLIENT_STATUS DDnsStatus;
volatile bool IsEnabled;
volatile bool UseCustom;
EVENT *Event;
volatile bool Halt;
THREAD *MainThread;
@ -56,15 +73,16 @@ struct AZURE_CLIENT
AZURE_PARAM AzureParam;
volatile UINT DDnsTriggerInt;
volatile bool IsConnected;
AZURE_CUSTOM_CONFIG *CustomConfig;
};
// Function prototype
AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server);
AZURE_CLIENT *NewAzureClient(CEDAR *cedar, SERVER *server, AZURE_CUSTOM_CONFIG *config);
void FreeAzureClient(AZURE_CLIENT *ac);
void AcApplyCurrentConfig(AZURE_CLIENT *ac, DDNS_CLIENT_STATUS *ddns_status);
void AcApplyCurrentConfig(AZURE_CLIENT *ac, DDNS_CLIENT_STATUS *ddns_status, AZURE_CUSTOM_CONFIG *config, bool disconnect);
void AcMainThread(THREAD *thread, void *param);
void AcSetEnable(AZURE_CLIENT *ac, bool enabled);
void AcSetEnable(AZURE_CLIENT *ac, bool enabled, bool use_custom);
void AcWaitForRequest(AZURE_CLIENT *ac, SOCK *s, AZURE_PARAM *param);

View File

@ -380,6 +380,7 @@ typedef struct RPC_WINVER RPC_WINVER;
typedef struct RPC_ENUM_ETHERIP_ID RPC_ENUM_ETHERIP_ID;
typedef struct RPC_SPECIAL_LISTENER RPC_SPECIAL_LISTENER;
typedef struct RPC_AZURE_STATUS RPC_AZURE_STATUS;
typedef struct RPC_AZURE_CUSTOM RPC_AZURE_CUSTOM;
// ==============================================================
@ -643,6 +644,7 @@ typedef struct DDNS_CLIENT_STATUS DDNS_CLIENT_STATUS;
// ==============================================================
typedef struct AZURE_CLIENT AZURE_CLIENT;
typedef struct AZURE_PARAM AZURE_PARAM;
typedef struct AZURE_CUSTOM_CONFIG AZURE_CUSTOM_CONFIG;
// ==============================================================

View File

@ -7749,6 +7749,8 @@ void PsMain(PS *ps)
{"DynamicDnsSetHostname", PsDynamicDnsSetHostname},
{"VpnAzureGetStatus", PsVpnAzureGetStatus},
{"VpnAzureSetEnable", PsVpnAzureSetEnable},
{"VpnAzureGetCustom", PsVpnAzureGetCustom},
{"VpnAzureSetCustom", PsVpnAzureSetCustom},
};
// Generate a prompt
@ -22239,7 +22241,8 @@ UINT PsVpnAzureSetEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
PARAM args[] =
{
// "name", prompt_proc, prompt_param, eval_proc, eval_param
{"[yes|no]", CmdPrompt, _UU("VpnAzureSetEnable_PROMPT"), CmdEvalNotEmpty, NULL},
{"[yes|no]", CmdPrompt, _UU("CMD_VpnAzureSetEnable_PROMPT"), CmdEvalNotEmpty, NULL},
{"CUSTOM", CmdPrompt, _UU("CMD_VpnAzureSetEnableCustom_PROMPT"), CmdEvalNotEmpty, NULL},
};
o = ParseCommandList(c, cmd_name, str, args, sizeof(args) / sizeof(args[0]));
@ -22250,6 +22253,7 @@ UINT PsVpnAzureSetEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
Zero(&t, sizeof(t));
t.IsEnabled = GetParamYes(o, "[yes|no]");
t.UseCustom = GetParamYes(o, "CUSTOM");
// RPC call
ret = ScSetAzureStatus(ps->Rpc, &t);
@ -22288,11 +22292,6 @@ UINT PsVpnAzureGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
// RPC call
ret = ScGetAzureStatus(ps->Rpc, &t);
if (ret == ERR_NO_ERROR)
{
ret = ScGetDDnsClientStatus(ps->Rpc, &t2);
}
if (ret != ERR_NO_ERROR)
{
// An error has occured
@ -22309,9 +22308,23 @@ UINT PsVpnAzureGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
if (t.IsEnabled)
{
wchar_t tmp[MAX_SIZE];
Zero(tmp, sizeof(tmp));
UniFormat(tmp, sizeof(tmp), L"%S%S", t2.CurrentHostName, AZURE_DOMAIN_SUFFIX);
if (t.UseCustom)
{
StrToUni(tmp, sizeof(tmp), t.CurrentHostname);
}
else
{
ret = ScGetDDnsClientStatus(ps->Rpc, &t2);
if (ret == ERR_NO_ERROR && IsEmptyStr(t2.CurrentHostName) == false)
{
UniFormat(tmp, sizeof(tmp), L"%S%S", t2.CurrentHostName, AZURE_DOMAIN_SUFFIX);
}
}
CtInsert(ct, _UU("CMD_VpnAzureGetStatus_PRINT_CUSTOM"), _UU(t.UseCustom ? "SEC_YES" : "SEC_NO"));
CtInsert(ct, _UU("CMD_VpnAzureGetStatus_PRINT_CONNECTED"), _UU(t.IsConnected ? "SEC_YES" : "SEC_NO"));
CtInsert(ct, _UU("CMD_VpnAzureGetStatus_PRINT_HOSTNAME"), tmp);
}
@ -22324,6 +22337,147 @@ UINT PsVpnAzureGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
return 0;
}
// Set the custom VPN Azure service
UINT PsVpnAzureSetCustom(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
LIST *o;
PS *ps = (PS *)param;
UINT ret = 0;
RPC_AZURE_CUSTOM t;
char *server;
UINT port;
X *x;
K *k;
// Parameter list that can be specified
PARAM args[] =
{
{"SERVER", CmdPrompt, _UU("CMD_VpnAzureSetCustom_Prompt_Server"), CmdEvalHostAndPort, NULL},
{"HOSTNAME", CmdPrompt, _UU("CMD_VpnAzureSetCustom_Prompt_Hostname"), CmdEvalNotEmpty, NULL},
{"PASSWORD", CmdPromptChoosePassword, NULL, NULL, NULL},
{"LOADCERT", CmdPrompt, _UU("CMD_VpnAzureSetCustom_Prompt_ClientX"), NULL, NULL},
{"LOADKEY", CmdPrompt, _UU("CMD_VpnAzureSetCustom_Prompt_ClientK"), NULL, NULL},
{"VERIFY", CmdPrompt, _UU("CMD_VpnAzureSetCustom_Prompt_Verify"), CmdEvalNotEmpty, NULL},
{"TRUSTCA", CmdPrompt, _UU("CMD_VpnAzureSetCustom_Prompt_TrustCA"), CmdEvalNotEmpty, NULL},
{"SERVCERT", CmdPrompt, _UU("CMD_VpnAzureSetCustom_Prompt_ServerX"), 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));
ParseHostPort(GetParamStr(o, "SERVER"), &server, &port, 443);
StrCpy(t.ServerName, sizeof(t.ServerName), server);
t.ServerPort = port;
Free(server);
StrCpy(t.Hostname, sizeof(t.Hostname), GetParamStr(o, "HOSTNAME"));
HashPassword(t.HashedPassword, t.Hostname, GetParamStr(o, "PASSWORD"), true);
if (UniIsEmptyStr(GetParamUniStr(o, "LOADCERT")) == false && UniIsEmptyStr(GetParamUniStr(o, "LOADKEY")) == false &&
CmdLoadCertAndKey(c, &x, &k, GetParamUniStr(o, "LOADCERT"), GetParamUniStr(o, "LOADKEY")))
{
c->Write(c, _UU("CMD_VpnAzureSetCustom_MSG_ClientCertLoaded"));
t.ClientX = x;
t.ClientK = k;
}
x = FileToXW(GetParamUniStr(o, "SERVCERT"));
if (x != NULL)
{
c->Write(c, _UU("CMD_VpnAzureSetCustom_MSG_ServerCertLoaded"));
t.ServerCert = x;
}
t.VerifyServer = GetParamYes(o, "VERIFY");
t.AddDefaultCA = GetParamYes(o, "TRUSTCA");
// RPC call
ret = ScSetAzureCustom(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
// An error has occured
CmdPrintError(c, ret);
FreeParamValueList(o);
return ret;
}
FreeRpcAzureCustom(&t);
FreeParamValueList(o);
return 0;
}
// Get the current config of the custom VPN Azure function
UINT PsVpnAzureGetCustom(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{
LIST *o;
PS *ps = (PS *)param;
UINT ret = 0;
RPC_AZURE_CUSTOM t;
o = ParseCommandList(c, cmd_name, str, NULL, 0);
if (o == NULL)
{
return ERR_INVALID_PARAMETER;
}
Zero(&t, sizeof(t));
// RPC call
ret = ScGetAzureCustom(ps->Rpc, &t);
if (ret != ERR_NO_ERROR)
{
// An error has occured
CmdPrintError(c, ret);
FreeParamValueList(o);
return ret;
}
else
{
CT *ct = CtNewStandard();
wchar_t tmp[MAX_SIZE];
StrToUni(tmp, sizeof(tmp), t.ServerName);
CtInsert(ct, _UU("CMD_VpnAzureGetCustom_PRINT_SERVERNAME"), tmp);
UniFormat(tmp, sizeof(tmp), _UU("CM_ST_PORT_TCP"), t.ServerPort);
CtInsert(ct, _UU("CMD_VpnAzureGetCustom_PRINT_SERVERPORT"), tmp);
StrToUni(tmp, sizeof(tmp), t.Hostname);
CtInsert(ct, _UU("CMD_VpnAzureGetCustom_PRINT_HOSTNAME"), tmp);
if (t.ClientX != NULL)
{
GetAllNameFromX(tmp, sizeof(tmp), t.ClientX);
CtInsert(ct, _UU("CMD_VpnAzureGetCustom_PRINT_CLIENTCERT"), tmp);
}
CtInsert(ct, _UU("CMD_VpnAzureGetCustom_PRINT_VERIFYSERVER"), _UU(t.VerifyServer ? "SEC_YES" : "SEC_NO"));
CtInsert(ct, _UU("CMD_VpnAzureGetCustom_PRINT_DEFAULTCA"), _UU(t.AddDefaultCA ? "SEC_YES" : "SEC_NO"));
if (t.ServerCert != NULL)
{
GetAllNameFromX(tmp, sizeof(tmp), t.ServerCert);
CtInsert(ct, _UU("CMD_VpnAzureGetCustom_PRINT_SERVERCERT"), tmp);
}
CtFree(ct, c);
FreeRpcAzureCustom(&t);
}
FreeParamValueList(o);
return 0;
}
// Get the current state of the dynamic DNS function
UINT PsDynamicDnsGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param)
{

View File

@ -610,6 +610,8 @@ UINT PsDynamicDnsGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param
UINT PsDynamicDnsSetHostname(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsVpnAzureSetEnable(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsVpnAzureGetStatus(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsVpnAzureSetCustom(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
UINT PsVpnAzureGetCustom(CONSOLE *c, char *cmd_name, wchar_t *str, void *param);
#endif // COMMAND_H

View File

@ -128,7 +128,7 @@ UINT DCChangeHostName(DDNS_CLIENT *c, char *hostname)
DCGetStatus(c, &st);
SiApplyAzureConfig(c->Cedar->Server, &st);
SiApplyAzureConfig(c->Cedar->Server, &st, NULL);
}
return ret;
@ -174,7 +174,7 @@ void DCThread(THREAD *thread, void *param)
bool vgs_server_triggered = false;
if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL && c->Cedar->Server->UseCustomVpnAzure == false)
{
if (c->Cedar->Server->AzureClient->DDnsTriggerInt != last_azure_ddns_trigger_int)
{
@ -327,7 +327,7 @@ void DCThread(THREAD *thread, void *param)
DCGetStatus(c, &st);
SiApplyAzureConfig(c->Cedar->Server, &st);
SiApplyAzureConfig(c->Cedar->Server, &st, NULL);
}
AddInterrupt(interrupt, c->NextRegisterTick_IPv4);
@ -362,7 +362,7 @@ void DCThread(THREAD *thread, void *param)
DCGetStatus(c, &st);
SiApplyAzureConfig(c->Cedar->Server, &st);
SiApplyAzureConfig(c->Cedar->Server, &st, NULL);
}
AddInterrupt(interrupt, c->NextRegisterTick_IPv6);
@ -391,7 +391,7 @@ void DCThread(THREAD *thread, void *param)
if (last_time_ip_changed)
{
if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL)
if (c->Cedar->Server != NULL && c->Cedar->Server->AzureClient != NULL && c->Cedar->Server->UseCustomVpnAzure == false)
{
c->Cedar->Server->AzureClient->IpStatusRevision++;
}
@ -476,7 +476,7 @@ UINT DCRegister(DDNS_CLIENT *c, bool ipv6, DDNS_REGISTER_PARAM *p, char *replace
if (ipv6 == false)
{
// Get the current status of the VPN Azure Client
if (c->Cedar->Server != NULL)
if (c->Cedar->Server != NULL && c->Cedar->Server->UseCustomVpnAzure == false)
{
AZURE_CLIENT *ac = c->Cedar->Server->AzureClient;

View File

@ -2450,6 +2450,14 @@ void SiLoadInitialConfiguration(SERVER *s)
{
// Create a DDNS client
s->DDnsClient = NewDDNSClient(s->Cedar, NULL, NULL);
// Create a default VPN Azure client
if (s->ServerType == SERVER_TYPE_STANDALONE)
{
s->AzureClient = NewAzureClient(s->Cedar, s, NULL);
AcSetEnable(s->AzureClient, s->EnableVpnAzure, s->UseCustomVpnAzure);
}
}
@ -2626,14 +2634,6 @@ void SiInitConfiguration(SERVER *s)
s->AutoSaveConfigSpanSaved = s->AutoSaveConfigSpan;
// Create a VPN Azure client
if (s->DDnsClient != NULL && s->Cedar->Bridge == false && s->ServerType == SERVER_TYPE_STANDALONE)
{
s->AzureClient = NewAzureClient(s->Cedar, s);
AcSetEnable(s->AzureClient, s->EnableVpnAzure);
}
// Reduce the storage interval in the case of user mode
#ifdef OS_WIN32
if (MsIsUserMode())
@ -2649,7 +2649,7 @@ void SiInitConfiguration(SERVER *s)
}
// Set the state of Enabled / Disabled of Azure Client
void SiSetAzureEnable(SERVER *s, bool enabled)
void SiSetAzureEnable(SERVER *s, bool enabled, bool use_custom)
{
// Validate arguments
if (s == NULL)
@ -2659,14 +2659,16 @@ void SiSetAzureEnable(SERVER *s, bool enabled)
if (s->AzureClient != NULL)
{
AcSetEnable(s->AzureClient, enabled);
AcSetEnable(s->AzureClient, enabled, use_custom);
}
s->EnableVpnAzure = enabled;
s->UseCustomVpnAzure = use_custom;
}
// Apply the Config to the Azure Client
void SiApplyAzureConfig(SERVER *s, DDNS_CLIENT_STATUS *ddns_status)
void SiApplyAzureConfig(SERVER *s, DDNS_CLIENT_STATUS *ddns_status, AZURE_CUSTOM_CONFIG *config)
{
// Validate arguments
if (s == NULL)
@ -2674,7 +2676,7 @@ void SiApplyAzureConfig(SERVER *s, DDNS_CLIENT_STATUS *ddns_status)
return;
}
AcApplyCurrentConfig(s->AzureClient, ddns_status);
AcApplyCurrentConfig(s->AzureClient, ddns_status, config, false);
}
// Get whether the Azure Client is enabled
@ -2714,7 +2716,7 @@ bool SiIsAzureSupported(SERVER *s)
// Read the server settings from the CFG
bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
{
FOLDER *f1, *f2, *f3, *f4, *f5, *f6, *f7, *f8, *f9;
FOLDER *f1, *f2, *f3, *f4, *f5, *f6, *f7, *f8, *f9, *f10;
// Validate arguments
if (s == NULL || root == NULL)
{
@ -2730,6 +2732,7 @@ bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
f7 = CfgGetFolder(root, "IPsec");
f8 = CfgGetFolder(root, "DDnsClient");
f9 = CfgGetFolder(root, "WireGuardKeyList");
f10 = CfgGetFolder(root, "VPNAzureClient");
if (f1 == NULL)
{
@ -2871,6 +2874,63 @@ bool SiLoadConfigurationCfg(SERVER *s, FOLDER *root)
}
}
}
if (f10 == NULL)
{
// Create a default VPN Azure client
if (s->ServerType == SERVER_TYPE_STANDALONE)
{
s->AzureClient = NewAzureClient(s->Cedar, s, NULL);
AcSetEnable(s->AzureClient, s->EnableVpnAzure, s->UseCustomVpnAzure);
}
}
else
{
if (s->ServerType == SERVER_TYPE_STANDALONE)
{
// Custom VPN Azure client
AZURE_CUSTOM_CONFIG *config = ZeroMalloc(sizeof(AZURE_CUSTOM_CONFIG));
CfgGetStr(f10, "ServerName", config->ServerName, sizeof(config->ServerName));
config->ServerPort = CfgGetInt(f10, "ServerPort");
CfgGetStr(f10, "Hostname", config->Hostname, sizeof(config->Hostname));
CfgGetByte(f10, "HashedPassword", config->HashedPassword, SHA1_SIZE);
config->VerifyServer = CfgGetBool(f10, "VerifyServer");
config->AddDefaultCA = CfgGetBool(f10, "AddDefaultCA");
BUF *b;
// VPN Azure server certificate
b = CfgGetBuf(f10, "ServerCert");
if (b != NULL)
{
config->ServerCert = BufToX(b, false);
FreeBuf(b);
}
// VPN Azure client certificate
b = CfgGetBuf(f10, "ClientCert");
if (b != NULL)
{
config->ClientX = BufToX(b, false);
FreeBuf(b);
}
// VPN Azure client private key
b = CfgGetBuf(f10, "ClientKey");
if (b != NULL)
{
config->ClientK = BufToK(b, true, false, NULL);
FreeBuf(b);
}
// Create a VPN Azure client
s->AzureClient = NewAzureClient(s->Cedar, s, config);
AcSetEnable(s->AzureClient, s->EnableVpnAzure, s->UseCustomVpnAzure);
}
}
}
s->IPsecMessageDisplayed = CfgGetBool(root, "IPsecMessageDisplayed");
@ -3226,6 +3286,35 @@ FOLDER *SiWriteConfigurationToCfg(SERVER *s)
CfgAddStr(ddns_folder, "CustomHttpHeader", t->CustomHttpHeader);
}
FOLDER *azure_folder = CfgCreateFolder(root, "VPNAzureClient");
if (s->AzureClient != NULL && s->AzureClient->CustomConfig != NULL)
{
CfgAddStr(azure_folder, "ServerName", s->AzureClient->CustomConfig->ServerName);
CfgAddInt(azure_folder, "ServerPort", s->AzureClient->CustomConfig->ServerPort);
CfgAddStr(azure_folder, "Hostname", s->AzureClient->CustomConfig->Hostname);
CfgAddByte(azure_folder, "HashedPassword", s->AzureClient->CustomConfig->HashedPassword, sizeof(s->AzureClient->CustomConfig->HashedPassword));
CfgAddBool(azure_folder, "VerifyServer", s->AzureClient->CustomConfig->VerifyServer);
CfgAddBool(azure_folder, "AddDefaultCA", s->AzureClient->CustomConfig->AddDefaultCA);
BUF *b;
// VPN Azure server certificate
b = XToBuf(s->AzureClient->CustomConfig->ServerCert, false);
CfgAddBuf(azure_folder, "ServerCert", b);
FreeBuf(b);
// VPN Azure client certificate
b = XToBuf(s->AzureClient->CustomConfig->ClientX, false);
CfgAddBuf(azure_folder, "ClientCert", b);
FreeBuf(b);
// VPN Azure client private key
b = KToBuf(s->AzureClient->CustomConfig->ClientK, false, NULL);
CfgAddBuf(azure_folder, "ClientKey", b);
FreeBuf(b);
}
}
CfgAddBool(root, "IPsecMessageDisplayed", s->IPsecMessageDisplayed);
@ -5994,6 +6083,7 @@ void SiLoadServerCfg(SERVER *s, FOLDER *f)
// Configuration of VPN Azure Client
s->EnableVpnAzure = CfgGetBool(f, "EnableVpnAzure");
s->UseCustomVpnAzure = CfgGetBool(f, "UseCustomVpnAzure");
// Disable GetHostName when accepting TCP
s->DisableGetHostNameWhenAcceptTcp = CfgGetBool(f, "DisableGetHostNameWhenAcceptTcp");
@ -6334,6 +6424,7 @@ void SiWriteServerCfg(FOLDER *f, SERVER *s)
if (s->AzureClient != NULL)
{
CfgAddBool(f, "EnableVpnAzure", s->EnableVpnAzure);
CfgAddBool(f, "UseCustomVpnAzure", s->UseCustomVpnAzure);
}
CfgAddBool(f, "DisableGetHostNameWhenAcceptTcp", s->DisableGetHostNameWhenAcceptTcp);

View File

@ -256,6 +256,7 @@ struct SERVER
AZURE_CLIENT *AzureClient; // VPN Azure client
bool EnableVpnAzure; // Flag whether VPN Azure client is enabled
bool UseCustomVpnAzure; // Use custom VPN Azure service
bool DisableGetHostNameWhenAcceptTcp; // Disable GetHostName when accepting TCP
bool DisableCoreDumpOnUnix; // Disable core dump on UNIX
@ -635,8 +636,8 @@ void SiApplySpecialListenerStatus(SERVER *s);
bool SiIsAzureEnabled(SERVER *s);
bool SiIsAzureSupported(SERVER *s);
void SiApplyAzureConfig(SERVER *s, DDNS_CLIENT_STATUS *ddns_status);
void SiSetAzureEnable(SERVER *s, bool enabled);
void SiApplyAzureConfig(SERVER *s, DDNS_CLIENT_STATUS *ddns_status, AZURE_CUSTOM_CONFIG *config);
void SiSetAzureEnable(SERVER *s, bool enabled, bool use_custom);
void SiUpdateCurrentRegion(CEDAR *c, char *region, bool force_update);
void SiGetCurrentRegion(CEDAR *c, char *region, UINT region_size);

View File

@ -6457,6 +6457,7 @@ CMD_VpnAzureGetStatus Show the current status of VPN Azure function
CMD_VpnAzureGetStatus_Help Get and show the current status of the VPN Azure function.\n\nVPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company.\nYou don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC.\nVPN Azure is a cloud VPN service operated by SoftEther VPN Project. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions.\n\nThe VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to "vpnazure.net". To change the hostname use the DynamicDnsSetHostname command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
CMD_VpnAzureGetStatus_Args VpnAzureGetStatus
CMD_VpnAzureGetStatus_PRINT_ENABLED VPN Azure Function is Enabled
CMD_VpnAzureGetStatus_PRINT_CUSTOM Use Custom VPN Azure Service
CMD_VpnAzureGetStatus_PRINT_CONNECTED Connection to VPN Azure Cloud Server is Established
CMD_VpnAzureGetStatus_PRINT_HOSTNAME Hostname of this VPN Server on VPN Azure Service
@ -6464,9 +6465,47 @@ CMD_VpnAzureGetStatus_PRINT_HOSTNAME Hostname of this VPN Server on VPN Azure Se
# VpnAzureSetStatus command
CMD_VpnAzureSetEnable Enable / Disable VPN Azure Function
CMD_VpnAzureSetEnable_Help Enable or disable the VPN Azure function.\n\nVPN Azure makes it easier to establish a VPN Session from your home PC to your office PC. While a VPN connection is established, you can access to any other servers on the private network of your company.\nYou don't need a global IP address on the office PC (VPN Server). It can work behind firewalls or NATs. No network administrator's configuration required. You can use the built-in SSTP-VPN Client of Windows in your home PC.\nVPN Azure is a cloud VPN service operated by SoftEther VPN Project. VPN Azure is free of charge and available to anyone. Visit http://www.vpnazure.net/ to see details and how-to-use instructions.\n\nThe VPN Azure hostname is same to the hostname of the Dynamic DNS setting, but altering the domain suffix to "vpnazure.net". To change the hostname use the DynamicDnsSetHostname command.\n\nTo execute this command, you must have VPN Server administrator privileges. \nThis command cannot be run on VPN Bridge.\nYou cannot execute this command for Virtual Hubs of VPN Servers operating as a cluster.
CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no]
CMD_VpnAzureSetEnable_Args VpnAzureSetEnable [yes|no] [/CUSTOM:yes|no]
CMD_VpnAzureSetEnable_[yes|no] Specify 'yes' to enable VPN Azure. 'no' to disable it.
CMD_VpnAzureSetEnable_CUSTOM Specify 'yes' to use custom VPN Azure service. 'no' to use the default service.
CMD_VpnAzureSetEnable_PROMPT Enable VPN Azure (yes / no):
CMD_VpnAzureSetEnableCustom_PROMPT Use custom VPN Azure service (yes / no):
# VpnAzureGetCustom command
CMD_VpnAzureGetCustom Show the current configuration of custom VPN Azure service
CMD_VpnAzureGetCustom_Help Get and show the current configuration of the custom VPN Azure service.\n\nCustom VPN Azure does not rely on Dynamic DNS service and lets you use VPN Azure function with a privately hosted relay server.
CMD_VpnAzureGetCustom_Args VpnAzureGetCustom
CMD_VpnAzureGetCustom_PRINT_SERVERNAME Server Address
CMD_VpnAzureGetCustom_PRINT_SERVERPORT Port Number
CMD_VpnAzureGetCustom_PRINT_HOSTNAME VPN Azure Hostname
CMD_VpnAzureGetCustom_PRINT_CLIENTCERT Registered Client Individual Certificate
CMD_VpnAzureGetCustom_PRINT_SERVERCERT Registered Server Individual Certificate
CMD_VpnAzureGetCustom_PRINT_VERIFYSERVER Verify Server Certificate
CMD_VpnAzureGetCustom_PRINT_DEFAULTCA Trust System Certificate Store
# VpnAzureSetCustom command
CMD_VpnAzureSetCustom Set the current configuration of custom VPN Azure service
CMD_VpnAzureSetCustom_Help Set the current configuration of the custom VPN Azure service.\n\nCustom VPN Azure does not rely on Dynamic DNS service and lets you use VPN Azure function with a privately hosted relay server.
CMD_VpnAzureSetCustom_Args VpnAzureSetCustom [/SERVER:server:port] [/HOSTNAME:hostname] [/PASSWORD:password] [/LOADCERT:path] [/LOADKEY:path] [/VERIFY:yes|no] [/TRUSTCA:yes|no] [/SERVCERT:path]
CMD_VpnAzureSetCustom_SERVER Specify the hostname or IP address, and port number of the VPN Azure server.
CMD_VpnAzureSetCustom_HOSTNAME Specify the VPN Azure client hostname in FQDN.
CMD_VpnAzureSetCustom_PASSWORD Specify the password for VPN Azure client. Leave blank if password is not needed.
CMD_VpnAzureSetCustom_LOADCERT Specify the X.509 format certificate file for client certificate authentication. Leave blank if not needed.
CMD_VpnAzureSetCustom_LOADKEY Specify the Base-64-encoded private key file name for the certificate. Leave blank if not needed.
CMD_VpnAzureSetCustom_VERIFY Specify whether to verify the VPN Azure Server's certificate.
CMD_VpnAzureSetCustom_TRUSTCA Specify whether to use the system trust store when verifying the VPN Azure Server.
CMD_VpnAzureSetCustom_SERVCERT Specify the X.509 format certificate file for server certificate verification. Leave blank if not needed.
CMD_VpnAzureSetCustom_Prompt_Server VPN Azure Server Address and Port Number:
CMD_VpnAzureSetCustom_Prompt_Hostname VPN Azure Client Hostname (e.g. vpn1234.myazure.net):
CMD_VpnAzureSetCustom_Prompt_ClientX Read X.509 certificate from file name for client authentication:\nLeave blank if the client does not use certificate authentication.\n
CMD_VpnAzureSetCustom_Prompt_ClientK Read private key from file name for client authentication:\nLeave blank if the client does not use certificate authentication.\n
CMD_VpnAzureSetCustom_Prompt_Verify Verify the VPN Azure Server's certificate (yes / no):
CMD_VpnAzureSetCustom_Prompt_TrustCA Use the system trust store when verifying the VPN Azure Server (yes / no):
CMD_VpnAzureSetCustom_Prompt_ServerX Read X.509 certificate from file name for server verification:\n\nLeave blank if not needed.\n
CMD_VpnAzureSetCustom_MSG_ClientCertLoaded A pair of certificate and private key were saved successfully for client authentication.
CMD_VpnAzureSetCustom_MSG_ServerCertLoaded A server certificate was saved successfully for server verification.