示例#1
0
        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();
            }
        }
示例#2
0
        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();
            }
        }
示例#3
0
        public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config)
        {
            _config      = config;
            _endpoint    = endpoint;
            _credentials = credentials;

            _connectAction.Run();
        }
示例#4
0
 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);
     }
 }
示例#7
0
        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);
        }
示例#8
0
        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>());
        }
示例#9
0
        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));
        }
示例#10
0
 public OpenVpnProcessParams(
     VpnEndpoint endpoint,
     int managementPort,
     string password,
     IReadOnlyCollection <string> customDns)
 {
     Endpoint       = endpoint;
     ManagementPort = managementPort;
     Password       = password;
     CustomDns      = customDns;
 }
示例#11
0
 private void HandleBestEndpoint(VpnEndpoint endpoint, CancellationToken cancellationToken)
 {
     if (endpoint.Port != 0)
     {
         _vpnEndpoint = endpoint;
         _origin.Connect(endpoint, _vpnCredentials, _config);
     }
     else
     {
         DelayedDisconnect(cancellationToken);
     }
 }
示例#12
0
        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>();
        }
示例#13
0
        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}");
        }
示例#14
0
        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}");
        }
示例#15
0
        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;
 }
示例#17
0
        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);
        }
示例#18
0
        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());
        }
示例#19
0
        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);
        }
示例#20
0
        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);
        }
示例#21
0
        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();
        }
示例#22
0
 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;
 }
示例#23
0
        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);
        }
示例#24
0
        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);
        }
示例#25
0
 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;
 }
示例#26
0
        /// <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);
            }
        }
示例#27
0
        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);
        }
示例#28
0
        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);
        }
示例#29
0
        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);
        }
示例#30
0
 public void Connect(VpnEndpoint endpoint, VpnCredentials credentials, VpnConfig config)
 {
     _origin.Connect(endpoint, credentials, config);
 }