public async Task<bool> Alive(VpnEndpoint vpnEndpoint, Task timeoutTask) { OpenVpnHandshake packet = new(_staticKey); IPEndPoint endpoint = new(IPAddress.Parse(vpnEndpoint.Server.Ip), vpnEndpoint.Port); using Socket socket = new(AddressFamily.InterNetwork, SocketType.Stream, ProtocolType.Tcp); try { await SafeSocketAction(socket.ConnectAsync(endpoint)).WithTimeout(timeoutTask); byte[] bytes = packet.Bytes(true); await SafeSocketAction(socket.SendAsync(new ArraySegment<byte>(bytes), SocketFlags.None)).WithTimeout(timeoutTask); byte[] answer = new byte[1024]; int received = await SafeSocketFunc(socket.ReceiveAsync(new ArraySegment<byte>(answer), SocketFlags.None)).WithTimeout(timeoutTask); return received > 0; } catch (Exception) { return false; } finally { socket.Close(); } }
public async Task <bool> Alive(VpnEndpoint vpnEndpoint, Task timeoutTask) { var packet = new OpenVpnHandshake(_staticKey); var endpoint = new IPEndPoint(IPAddress.Parse(vpnEndpoint.Server.Ip), vpnEndpoint.Port); using var socket = new Socket( AddressFamily.InterNetwork, MapSocketType(vpnEndpoint.Protocol), MapProtocolType(vpnEndpoint.Protocol)); try { await SafeSocketAction(socket.ConnectAsync(endpoint)).WithTimeout(timeoutTask); var bytes = packet.Bytes(vpnEndpoint.Protocol == VpnProtocol.OpenVpnTcp); await SafeSocketAction(socket.SendAsync(new ArraySegment <byte>(bytes), SocketFlags.None)).WithTimeout(timeoutTask); var answer = new byte[1024]; var received = await SafeSocketFunc(socket.ReceiveAsync(new ArraySegment <byte>(answer), SocketFlags.None)).WithTimeout(timeoutTask); return(received > 0); } catch (Exception) { return(false); } finally { socket.Close(); } }
public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config) { _config = config; _endpoint = endpoint; _credentials = credentials; _connectAction.Run(); }
private async Task <bool> IsUdpEndpointAlive(VpnEndpoint endpoint, CancellationToken cancellationToken) { return(await IsEndpointAlive(async timeoutTask => await _udpPingClient.Ping( endpoint.Server.Ip, endpoint.Port, endpoint.Server.X25519PublicKey.Base64, timeoutTask), cancellationToken)); }
public void Reset() { foreach (var skipped in _skippedIps.Values) { skipped.Clear(); } Current = VpnEndpoint.EmptyEndpoint; }
private void Reconnect() { if (_reconnectPending) { _reconnectPending = false; _reconnecting = true; _endpoint = _candidates.Next(_protocol); _origin.Connect(_endpoint, _credentials, _config); } }
public void TestInitialize() { _logger = Substitute.For <ILogger>(); _taskQueue = new TaskQueue(); _origin = Substitute.For <ISingleVpnConnection>(); _endpoint = new VpnEndpoint(new VpnHost("proton.vpn", "135.27.46.203", string.Empty), VpnProtocol.OpenVpnTcp, 777); _credentials = new VpnCredentials("username", "password"); _config = new VpnConfig(new Dictionary <VpnProtocol, IReadOnlyCollection <int> >(), SplitTunnelMode.Disabled, useTunAdapter: false); }
public void TestInitialize() { _logger = Substitute.For <ILogger>(); _taskQueue = new TaskQueue(); _origin = Substitute.For <ISingleVpnConnection>(); _endpoint = new VpnEndpoint(new VpnHost("proton.vpn", "135.27.46.203"), VpnProtocol.OpenVpnTcp, 777); _credentials = new VpnCredentials("username", "password"); _config = new VpnConfig(new Dictionary <VpnProtocol, IReadOnlyCollection <int> >(), new List <string>()); }
private async Task <VpnEndpoint> ScanPortsAsync(VpnEndpoint endpoint, IReadOnlyDictionary <VpnProtocol, IReadOnlyCollection <int> > ports, IList <VpnProtocol> preferredProtocols, CancellationToken cancellationToken) { IList <Task <VpnEndpoint> > candidates = EndpointCandidates(endpoint, ports, preferredProtocols, cancellationToken); VpnEndpoint bestEndpoint = await BestEndpoint(candidates, preferredProtocols, cancellationToken); return(HandleBestEndpoint(bestEndpoint, endpoint.Server)); }
public OpenVpnProcessParams( VpnEndpoint endpoint, int managementPort, string password, IReadOnlyCollection <string> customDns) { Endpoint = endpoint; ManagementPort = managementPort; Password = password; CustomDns = customDns; }
private void HandleBestEndpoint(VpnEndpoint endpoint, CancellationToken cancellationToken) { if (endpoint.Port != 0) { _vpnEndpoint = endpoint; _origin.Connect(endpoint, _vpnCredentials, _config); } else { DelayedDisconnect(cancellationToken); } }
public void Enumerable_ShouldThrow_WhenProtocolIsNotSupported(VpnProtocol protocol) { // Arrange var endpoint = new VpnEndpoint(new VpnHost("abc.com", "1.2.3.4", string.Empty), protocol, 54321); var subject = new EndpointArguments(endpoint); // Act Action action = () => subject.ToList(); // Assert action.Should().Throw <ArgumentException>(); }
public void Enumerable_ShouldMap_VpnProtocol(VpnProtocol protocol, string expected) { // Arrange var endpoint = new VpnEndpoint(new VpnHost("abc.com", "7.7.7.7", string.Empty), protocol, 44444); var subject = new EndpointArguments(endpoint); // Act var result = subject.ToList(); // Assert result.Should().Contain($"--remote {endpoint.Server.Ip} {endpoint.Port} {expected}"); }
public void Enumerable_ShouldContain_RemoteOption() { // Arrange var endpoint = new VpnEndpoint(new VpnHost("abc.com", "11.22.33.44", string.Empty), VpnProtocol.OpenVpnUdp, 61874); var subject = new EndpointArguments(endpoint); // Act var result = subject.ToList(); // Assert result.First().Should().StartWith($"--remote {endpoint.Server.Ip} {endpoint.Port}"); }
public void Enumerable_ShouldContain_ExpectedNumberOfOptions() { // Arrange var endpoint = new VpnEndpoint(new VpnHost("abc.com", "4.5.6.7", string.Empty), VpnProtocol.OpenVpnUdp, 48965); var subject = new EndpointArguments(endpoint); // Act var result = subject.ToList(); // Assert result.Should().HaveCount(1); }
public OpenVpnProcessParams( VpnEndpoint endpoint, int managementPort, string password, VpnConfig config) { Endpoint = endpoint; ManagementPort = managementPort; Password = password; CustomDns = config.CustomDns; SkipIpv6 = config.SkipIpv6; }
private VpnEndpoint HandleBestEndpoint(VpnEndpoint bestEndpoint, VpnHost server) { bool isResponding = bestEndpoint.Port != 0; if (isResponding) { _logger.Info($"The endpoint {bestEndpoint.Server.Ip}:{bestEndpoint.Port} was the fastest to respond."); return(bestEndpoint); } _logger.Info($"No VPN port has responded for {server.Ip}."); return(VpnEndpoint.Empty); }
public void TestInitialize() { _logger = Substitute.For <ILogger>(); _taskQueue = new TaskQueue(); _origin = Substitute.For <ISingleVpnConnection>(); _endpoint = new VpnEndpoint(new VpnHost("proton.vpn", "135.27.46.203", string.Empty, null), VpnProtocol.OpenVpnTcp, 777); _credentials = new VpnCredentials("username", "password", "cert", new AsymmetricKeyPair( new SecretKey("U2VjcmV0S2V5", KeyAlgorithm.Unknown), new PublicKey("UHVibGljS2V5", KeyAlgorithm.Unknown))); _config = new VpnConfig(new VpnConfigParameters()); }
public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config) { _vpnEndpoint = endpoint; _vpnCredentials = credentials; _config = config; _cancellationHandle.Cancel(); var cancellationToken = _cancellationHandle.Token; _disconnectDelay = Task.Delay(DisconnectDelay, cancellationToken); Queued(ScanPorts, cancellationToken); }
public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config) { _endpoint = endpoint; _credentials = credentials; _config = config; _connectRequested = true; _disconnectRequested = false; _disconnectError = VpnError.Unknown; _logger.Info("HandlingRequestsWrapper: Connect requested, queuing Connect"); Queued(Connect); }
public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config) { if (endpoint.Server.X25519PublicKey == null) { InvokeStateChange(VpnStatus.Disconnected, VpnError.MissingServerPublicKey); return; } _credentials = credentials; _endpoint = endpoint; _vpnConfig = config; _connectAction.Run(); }
public OpenVpnProcessParams( VpnEndpoint endpoint, int managementPort, string password, IReadOnlyCollection <string> customDns, SplitTunnelMode splitTunnelMode, IReadOnlyCollection <string> splitTunnelIPs) { Endpoint = endpoint; ManagementPort = managementPort; Password = password; CustomDns = customDns; SplitTunnelMode = splitTunnelMode; SplitTunnelIPs = splitTunnelIPs; }
public void Connect(IReadOnlyList <VpnHost> servers, VpnConfig config, VpnProtocol protocol, VpnCredentials credentials) { _reconnectPending = false; _reconnecting = false; _disconnecting = false; _protocol = protocol; _credentials = credentials; _config = config; _candidates.Set(servers); _candidates.Reset(); _endpoint = _candidates.Next(_protocol); _origin.Connect(_endpoint, credentials, config); }
public VpnEndpoint Next(VpnProtocol protocol) { if (!string.IsNullOrEmpty(Current.Server.Ip)) { _skippedIps[protocol].Add(Current.Server.Ip); } var server = _all.FirstOrDefault(i => !_skippedIps[protocol].Contains(i.Ip)); if (server.IsEmpty()) { _skippedIps[protocol].Clear(); server = _all.FirstOrDefault(); } Current = Endpoint(server, protocol); return(Current); }
public OpenVpnProcessParams( VpnEndpoint endpoint, int managementPort, string password, IReadOnlyCollection <string> customDns, SplitTunnelMode splitTunnelMode, IReadOnlyCollection <string> splitTunnelIPs, bool useTunAdapter, string interfaceGuid) { Endpoint = endpoint; ManagementPort = managementPort; Password = password; CustomDns = customDns; SplitTunnelMode = splitTunnelMode; SplitTunnelIPs = splitTunnelIPs; UseTunAdapter = useTunAdapter; InterfaceGuid = interfaceGuid; }
/// <summary> /// Primary VPN connect method, doesn't finish until disconnect. /// This method will raise <see cref="TransportStatsChanged"/>, <see cref="VpnStateChanged"/> /// </summary> /// <param name="credentials"><see cref="VpnCredentials"/> (username and password) for authenticating to VPN server</param> /// <param name="endpoint"></param> /// <param name="cancellationToken"></param> /// <returns></returns> public async Task StartVpnConnection(VpnCredentials credentials, VpnEndpoint endpoint, CancellationToken cancellationToken) { _lastError = VpnError.None; _credentials = credentials; _endpoint = endpoint; _sendingFailed = false; _disconnectRequested = false; _disconnectAccepted = false; while (!cancellationToken.IsCancellationRequested && !_sendingFailed) { ReceivedManagementMessage message = await Receive(); if (message.IsChannelDisconnected) { if (!_disconnectRequested && _lastError == VpnError.None) { _lastError = VpnError.Unknown; } OnVpnStateChanged(VpnStatus.Disconnecting); return; } if (!cancellationToken.IsCancellationRequested) { HandleMessage(message); } } if (!_sendingFailed) { await SendExit(); } if (!cancellationToken.IsCancellationRequested && _sendingFailed) { OnVpnStateChanged(VpnStatus.Disconnecting); } }
private async Task <VpnEndpoint> GetPortAlive(VpnEndpoint endpoint, CancellationToken cancellationToken) { _logger.Info($"Pinging VPN endpoint {endpoint.Server.Ip}:{endpoint.Port} for {endpoint.VpnProtocol} protocol."); bool isAlive = false; switch (endpoint.VpnProtocol) { case VpnProtocol.OpenVpnTcp: isAlive = await IsOpenVpnEndpointAlive(endpoint, cancellationToken); break; case VpnProtocol.OpenVpnUdp: case VpnProtocol.WireGuard: isAlive = await IsUdpEndpointAlive(endpoint, cancellationToken); break; } return(isAlive ? endpoint : VpnEndpoint.Empty); }
private IList <Task <VpnEndpoint> > EndpointCandidates( VpnEndpoint endpoint, IReadOnlyDictionary <VpnProtocol, IReadOnlyCollection <int> > ports, IList <VpnProtocol> preferredProtocols, CancellationToken cancellationToken) { List <Task <VpnEndpoint> > list = new List <Task <VpnEndpoint> >(); foreach (VpnProtocol preferredProtocol in preferredProtocols) { if (!ports.ContainsKey(preferredProtocol) || (endpoint.Server.X25519PublicKey == null && preferredProtocol is VpnProtocol.WireGuard or VpnProtocol.OpenVpnUdp)) { continue; } foreach (int port in ports[preferredProtocol]) { list.Add(GetPortAlive(new VpnEndpoint(endpoint.Server, preferredProtocol, port), cancellationToken)); } } return(list); }
private async Task <VpnEndpoint> BestEndpoint(IList <Task <VpnEndpoint> > candidates, IList <VpnProtocol> preferredProtocols, CancellationToken cancellationToken) { Dictionary <VpnProtocol, VpnEndpoint> endpointsByProtocol = GetEndpointsByProtocol(preferredProtocols); while (candidates.Any()) { Task <VpnEndpoint> firstCompletedTask = await Task.WhenAny(candidates); candidates.Remove(firstCompletedTask); VpnEndpoint candidate = await firstCompletedTask; if (cancellationToken.IsCancellationRequested || candidate == null) { break; } if (candidate.Port != 0) { endpointsByProtocol[candidate.VpnProtocol] = candidate; if (candidate.VpnProtocol == preferredProtocols.First()) { break; } } } foreach (VpnProtocol preferredProtocol in preferredProtocols) { if (endpointsByProtocol[preferredProtocol] != null) { return(endpointsByProtocol[preferredProtocol]); } } return(VpnEndpoint.Empty); }
public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config) { _origin.Connect(endpoint, credentials, config); }