-
-
Notifications
You must be signed in to change notification settings - Fork 2.6k
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Support adding custom VPN Azure service #1739
Conversation
OK. Here is a brief explanation about what's inside the pull request. DesignA VPN Azure cloud server basically does two things, managing clients (i.e. VPN servers) and relaying VPN traffic. I will call the former control session and the latter data session. AuthenticationThe VPN server is able to authenticate itself to the Azure control server by password or certificate. EncryptionIn the official Azure service, the control session is not encrypted. It is now encrypted in TLS at all times. DNSWithout the help of DDNS, we need to manually setup the DNS environment. It can be done in various ways. The following is just an example. ScalabilityIf the number of Azure clients (i.e. VPN servers) is large, it may be inefficient to manage the passwords. Instead, one can issue client certificates in batches and add the issuer CA in the Azure server authentication. You can use my sample implementation to do that. Commands
|
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I successfully tested this PR (rebased onto current master) together with the latest master of vpnazure-go.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
I had some time playing around with this implementation in the meantime and started playing around with implementing some improvements to the vpnazure-go implementation that I would need, including a JSON API.
One suggestion/proposal/discussion starter:
I think it would make sense to change the initial connection handshake/signature for Azure VPN control and data channels to use a standard HTTP-compatible header.
Right now, the handshakes are ACTL
for the control channel and AZURE_CONNECT_SIGNATURE!
for the data channel before switching to Pack data.
Changing both to send an HTTP request like POST /vpnrelay/control HTTP/1.1
and POST /vpnrelay/data HTTP/1.1
instead would align the connection establishment with the other protocols used by SoftEther.
For example, a normal VPN client session is started with POST /vpnsvc/connect.cgi HTTP/1.1
, the built-in JSON-RPC is called by POST /api/* HTTP/1.1
and the Web Admin Console by POST /admin/* HTTP/1.1
. Even Microsoft's SSTP-VPN uses SSTP_DUPLEX_POST /sra_{BA195980-CD49-458b-9E23-C84EE0ADCD75}/ HTTP/1.1
for connection establishment.
Aligning the connection establishment to all use HTTP-style requests would facilitate distinguishing the protocols not only by TLS SNI, but also by using a standard HTTP parser like Go's net/http
package.
Right now, this PR is still in a stage where changes like this can be made and there is no urgent need to keep compatibility between the 'official' VPN Azure service and a custom relay server. In fact, it is already different in a few places, including using SHA1 for password hashes instead of SHA0.
} | ||
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); |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pseudo-code:
SendAll(s, AZURE_PROTOCOL_CONTROL_SIGNATURE, StrLen(AZURE_PROTOCOL_CONTROL_SIGNATURE), use_encryption); | |
if (use_custom_azure) | |
{ | |
HTTP_HEADER *h; | |
h = NewHttpHeader("POST", "/vpnrelay/control", "HTTP/1.1"); | |
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive")); | |
PostHttp(s, h, NULL, 0); | |
FreeHttpHeader(h); | |
} | |
else | |
{ | |
SendAll(s, AZURE_PROTOCOL_CONTROL_SIGNATURE, StrLen(AZURE_PROTOCOL_CONTROL_SIGNATURE), false); | |
} |
|
||
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)) |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Pseudo-code:
if (SendAll(ns, AZURE_PROTOCOL_DATA_SIANGTURE, 24, true)) | |
bool ok = false; | |
if (param->UseCustom) | |
{ | |
HTTP_HEADER *h; | |
h = NewHttpHeader("POST", "/vpnrelay/data", "HTTP/1.1"); | |
AddHttpValue(h, NewHttpValue("Connection", "Keep-Alive")); | |
ok = PostHttp(s, h, NULL, 0); | |
FreeHttpHeader(h); | |
} | |
else | |
{ | |
ok = SendAll(ns, AZURE_PROTOCOL_DATA_SIANGTURE, 24, true) | |
} | |
if (ok) |
I don't think the alignment is helpful. An azure server is not a SoftEther server. |
This would be helpful in the case you don't have full control over DNS and need to use a single DNS name for control, data and VPN connections. |
Well you are actually redesigning the azure system. |
Can you explain how this would be a breaking change? This would just change the connection signature from The idea is that this would make it easier to parse the type of an incoming connection on the VPN Azure server side. Right now, the decision on how to handle an incoming connection on the VPN Azure server relies on SNI. |
No, signatures and SNI are irrelevant. |
It's also important to note that VPN azure by nature must be able to handle an unspecified number of servers. There is no way to do that without manipulating DNS. |
So they are both not irrelevant, because they can be used to distinguish client and server connections.
The custom VPN Azure functionality is currently not in any existing client, so there is nothing that would need to be changed.
This is currently true, but does not need to be, because control and relay server can be different.
Multiple SoftEther servers can be handled without SNI and DNS when listening on more than one port. I really don't want to fight here, I just think that you don't understand why I am suggesting this. |
A sample implementation of VPN Azure in Go is here.
I will provide more description later.
String resources for other languages will also be added.
Changes proposed in this pull request: