diff --git a/Linguard/Cli.Test/AddInterfaceCommandShould.cs b/Linguard/Cli.Test/AddInterfaceCommandShould.cs index 90a8438..9b3109d 100644 --- a/Linguard/Cli.Test/AddInterfaceCommandShould.cs +++ b/Linguard/Cli.Test/AddInterfaceCommandShould.cs @@ -1,6 +1,4 @@ -using System.Linq; -using System.Net.NetworkInformation; -using System.Threading.Tasks; +using System.Threading.Tasks; using Castle.Core.Internal; using Core.Test.Mocks; using FluentAssertions; diff --git a/Linguard/Core.Test/ClientShould.cs b/Linguard/Core.Test/ClientShould.cs index 608976e..50c0305 100644 --- a/Linguard/Core.Test/ClientShould.cs +++ b/Linguard/Core.Test/ClientShould.cs @@ -13,7 +13,9 @@ namespace Core.Test; public class ClientShould { private static readonly Mock ConfigurationManagerMock = new DefaultConfigurationManager(); - private static IWireguardService WireguardService => new WireguardService(ConfigurationManagerMock.Object, new CommandRunner()); + private static IWireguardService WireguardService => + new WireguardService(ConfigurationManagerMock.Object, new CommandRunner(), + new InterfaceService(ConfigurationManagerMock.Object, new CommandRunner())); [Fact] public void CreateValidWireguardConfig() { diff --git a/Linguard/Core.Test/InterfaceShould.cs b/Linguard/Core.Test/InterfaceShould.cs index 1ab3d85..7e5fb63 100644 --- a/Linguard/Core.Test/InterfaceShould.cs +++ b/Linguard/Core.Test/InterfaceShould.cs @@ -15,7 +15,9 @@ namespace Core.Test; public class InterfaceShould { private static readonly Mock ConfigurationManagerMock = new DefaultConfigurationManager(); - private static IWireguardService WireguardService => new WireguardService(ConfigurationManagerMock.Object, new CommandRunner()); + private static IWireguardService WireguardService => + new WireguardService(ConfigurationManagerMock.Object, new CommandRunner(), + new InterfaceService(ConfigurationManagerMock.Object, new CommandRunner())); [Fact] public void CreateValidWireguardConfiguration() { diff --git a/Linguard/Core.Test/Mocks/NetworkInterfaceMock.cs b/Linguard/Core.Test/Mocks/NetworkInterfaceMock.cs index 8dfdb3c..06dcab7 100644 --- a/Linguard/Core.Test/Mocks/NetworkInterfaceMock.cs +++ b/Linguard/Core.Test/Mocks/NetworkInterfaceMock.cs @@ -1,10 +1,17 @@ using System.Net.NetworkInformation; +using Bogus; using Moq; namespace Core.Test.Mocks; public class NetworkInterfaceMock : Mock { - public NetworkInterfaceMock(string name) { + public NetworkInterfaceMock(string name, OperationalStatus status = OperationalStatus.Unknown) { SetupGet(i => i.Name).Returns(name); + SetupGet(i => i.OperationalStatus).Returns(status); + var properties = new Mock(); + properties.SetupGet(o => o.UnicastAddresses) + .Returns(new Mock().Object); + Setup(o => o.GetIPProperties()).Returns(properties.Object); + Setup(o => o.GetPhysicalAddress()).Returns(new PhysicalAddress(new Faker().Random.Bytes(6))); } } \ No newline at end of file diff --git a/Linguard/Core.Test/YamlConfigurationSerializerShould.cs b/Linguard/Core.Test/YamlConfigurationSerializerShould.cs index 090e1c2..9b1b55b 100644 --- a/Linguard/Core.Test/YamlConfigurationSerializerShould.cs +++ b/Linguard/Core.Test/YamlConfigurationSerializerShould.cs @@ -1,7 +1,5 @@ using System; using System.Collections.Generic; -using System.Linq; -using System.Net.NetworkInformation; using Core.Test.Mocks; using FluentAssertions; using Linguard.Core; @@ -10,7 +8,6 @@ using Linguard.Core.Models; using Linguard.Core.Models.Wireguard; using Linguard.Log; -using Moq; using Xunit; namespace Core.Test; diff --git a/Linguard/Core/Configuration/Serialization/DefaultYamlConfigurationSerializer.cs b/Linguard/Core/Configuration/Serialization/DefaultYamlConfigurationSerializer.cs index e93e8a2..43457cf 100644 --- a/Linguard/Core/Configuration/Serialization/DefaultYamlConfigurationSerializer.cs +++ b/Linguard/Core/Configuration/Serialization/DefaultYamlConfigurationSerializer.cs @@ -1,6 +1,4 @@ using Linguard.Core.Drivers.TrafficStorage; -using YamlDotNet.Core; -using YamlDotNet.Serialization; using YamlDotNet.Serialization.NamingConventions; namespace Linguard.Core.Configuration.Serialization; diff --git a/Linguard/Core/Services/DefaultClientGenerator.cs b/Linguard/Core/Services/DefaultClientGenerator.cs index 1cbb7a3..2feac8e 100644 --- a/Linguard/Core/Services/DefaultClientGenerator.cs +++ b/Linguard/Core/Services/DefaultClientGenerator.cs @@ -19,6 +19,14 @@ public DefaultClientGenerator(IWireguardService wireguard, IConfigurationManager public Client Generate(Interface iface) { return new Faker() + .RuleFor(c => c.Id, () => { + var clients = Configuration.Interfaces.SelectMany(i => i.Clients).ToList(); + Guid id = default; + while (id == default || clients.Any(c => c.Id == id)) { + id = Guid.NewGuid(); + } + return id; + }) .RuleFor(c => c.Nat, false) .RuleFor(c => c.Description, f => f.Lorem.Sentence()) .RuleFor(c => c.Name, f => f.Person.FullName) diff --git a/Linguard/Core/Services/DefaultInterfaceGenerator.cs b/Linguard/Core/Services/DefaultInterfaceGenerator.cs index b625dbb..8920c5b 100644 --- a/Linguard/Core/Services/DefaultInterfaceGenerator.cs +++ b/Linguard/Core/Services/DefaultInterfaceGenerator.cs @@ -20,6 +20,13 @@ public DefaultInterfaceGenerator(IConfigurationManager configurationManager, IWi public Interface Generate() { return new Faker() + .RuleFor(i => i.Id, () => { + Guid id = default; + while (id == default || Configuration.Interfaces.Any(iface => iface.Id == id)) { + id = Guid.NewGuid(); + } + return id; + }) .RuleFor(i => i.Auto, true) .RuleFor(i => i.Description, f => f.Lorem.Sentence()) .RuleFor(i => i.Gateway, f => { diff --git a/Linguard/Core/Services/IInterfaceService.cs b/Linguard/Core/Services/IInterfaceService.cs new file mode 100644 index 0000000..c15917c --- /dev/null +++ b/Linguard/Core/Services/IInterfaceService.cs @@ -0,0 +1,13 @@ +using System.Net.NetworkInformation; +using Linguard.Core.Models.Wireguard; + +namespace Linguard.Core.Services; + +public interface IInterfaceService { + IEnumerable NetworkInterfaces { get; } + Interface? GetInterface(Client client); + bool IsInterfaceUp(Interface iface); + bool IsInterfaceDown(Interface iface); + void StartInterface(Interface @interface); + void StopInterface(Interface @interface); +} \ No newline at end of file diff --git a/Linguard/Core/Services/IWireguardService.cs b/Linguard/Core/Services/IWireguardService.cs index f6b6481..8f137d9 100644 --- a/Linguard/Core/Services/IWireguardService.cs +++ b/Linguard/Core/Services/IWireguardService.cs @@ -5,11 +5,6 @@ namespace Linguard.Core.Services; public interface IWireguardService { - Interface? GetInterface(Client client); - bool IsInterfaceUp(Interface iface); - bool IsInterfaceDown(Interface iface); - void StartInterface(Interface @interface); - void StopInterface(Interface @interface); string? GenerateWireguardPrivateKey(); string? GenerateWireguardPublicKey(string privateKey); string[] GenerateOnUpRules(string interfaceName, NetworkInterface gateway); diff --git a/Linguard/Core/Services/InterfaceService.cs b/Linguard/Core/Services/InterfaceService.cs new file mode 100644 index 0000000..309ff58 --- /dev/null +++ b/Linguard/Core/Services/InterfaceService.cs @@ -0,0 +1,47 @@ +using System.Net.NetworkInformation; +using Linguard.Core.Configuration; +using Linguard.Core.Managers; +using Linguard.Core.Models.Wireguard; +using Linguard.Core.OS; +using Linguard.Core.Services.Exceptions; + +namespace Linguard.Core.Services; + +public class InterfaceService : IInterfaceService { + + private readonly IConfigurationManager _configurationManager; + private readonly ICommandRunner _commandRunner; + + public InterfaceService(IConfigurationManager configurationManager, ICommandRunner commandRunner) { + _configurationManager = configurationManager; + _commandRunner = commandRunner; + } + + private IWireguardConfiguration Configuration => _configurationManager.Configuration.Wireguard; + + public IEnumerable NetworkInterfaces => NetworkInterface.GetAllNetworkInterfaces(); + + public Interface? GetInterface(Client client) => Configuration.Interfaces + .SingleOrDefault(i => i.Clients.Contains(client)); + + public bool IsInterfaceUp(Interface iface) { + return NetworkInterfaces + .Any(i => i.Name.Equals(iface.Name) && i.OperationalStatus == OperationalStatus.Up); + } + + public bool IsInterfaceDown(Interface iface) { + return !IsInterfaceUp(iface); + } + + public void StartInterface(Interface @interface) { + var result = _commandRunner + .Run($"sudo {Configuration.WireguardQuickBin} up {@interface.Name}"); + if (!result.Success) throw new WireguardException(result.Stderr); + } + + public void StopInterface(Interface @interface) { + var result = _commandRunner + .Run($"sudo {Configuration.WireguardQuickBin} down {@interface.Name}"); + if (!result.Success) throw new WireguardException(result.Stderr); + } +} \ No newline at end of file diff --git a/Linguard/Core/Services/WireguardService.cs b/Linguard/Core/Services/WireguardService.cs index e3c3294..46f06d3 100644 --- a/Linguard/Core/Services/WireguardService.cs +++ b/Linguard/Core/Services/WireguardService.cs @@ -13,38 +13,17 @@ namespace Linguard.Core.Services; public class WireguardService : IWireguardService { private readonly IConfigurationManager _configurationManager; private readonly ICommandRunner _commandRunner; - - public WireguardService(IConfigurationManager configurationManager, ICommandRunner commandRunner) { + private readonly IInterfaceService _interfaceService; + + public WireguardService(IConfigurationManager configurationManager, ICommandRunner commandRunner, + IInterfaceService interfaceService) { _configurationManager = configurationManager; _commandRunner = commandRunner; + _interfaceService = interfaceService; } private IWireguardConfiguration Configuration => _configurationManager.Configuration.Wireguard; - public Interface? GetInterface(Client client) => Configuration.Interfaces - .SingleOrDefault(i => i.Clients.Contains(client)); - - public bool IsInterfaceUp(Interface iface) { - return NetworkInterface.GetAllNetworkInterfaces() - .Any(i => i.Name.Equals(iface.Name) && i.OperationalStatus == OperationalStatus.Up); - } - - public bool IsInterfaceDown(Interface iface) { - return !IsInterfaceUp(iface); - } - - public void StartInterface(Interface @interface) { - var result = _commandRunner - .Run($"sudo {Configuration.WireguardQuickBin} up {@interface.Name}"); - if (!result.Success) throw new WireguardException(result.Stderr); - } - - public void StopInterface(Interface @interface) { - var result = _commandRunner - .Run($"sudo {Configuration.WireguardQuickBin} down {@interface.Name}"); - if (!result.Success) throw new WireguardException(result.Stderr); - } - public string? GenerateWireguardPrivateKey() { var result = _commandRunner .Run($"sudo {Configuration.WireguardBin} genkey"); @@ -87,7 +66,7 @@ public string GenerateWireguardConfiguration(IWireguardPeer peer) { public DateTime GetLastHandshake(Client client) { var rawData = _commandRunner - .Run($"{Configuration.WireguardBin} show {GetInterface(client).Name} dump") + .Run($"{Configuration.WireguardBin} show {_interfaceService.GetInterface(client).Name} dump") .Stdout; try { return WireguardDumpParser.GetLastHandshake(rawData, client); @@ -106,7 +85,7 @@ public IEnumerable GetTrafficData() { } public TrafficData? GetTrafficData(Client client) { - var data = GetTrafficData(GetInterface(client)); + var data = GetTrafficData(_interfaceService.GetInterface(client)); return data.SingleOrDefault(e => e.Peer.Equals(client)); } diff --git a/Linguard/Web/Pages/EditInterface.razor b/Linguard/Web/Pages/EditInterface.razor index 6ab227c..7ae0a32 100644 --- a/Linguard/Web/Pages/EditInterface.razor +++ b/Linguard/Web/Pages/EditInterface.razor @@ -16,6 +16,7 @@ @inject NavigationManager _navigationManager @inject IJSRuntime _js @inject AbstractValidator _validator +@inject IInterfaceService _interfaceService @code { const string Title = "Interface"; @@ -37,7 +38,7 @@

@Title - @if (_wireguardService.IsInterfaceUp(Iface)) { + @if (_interfaceService.IsInterfaceUp(Iface)) { } else { diff --git a/Linguard/Web/Pages/Network.razor b/Linguard/Web/Pages/Network.razor index acacd22..21168e1 100644 --- a/Linguard/Web/Pages/Network.razor +++ b/Linguard/Web/Pages/Network.razor @@ -2,6 +2,7 @@ @using Linguard.Core.Utils @using System.Net.NetworkInformation @using System.Net.Sockets +@using Linguard.Core.Services @code { const string Title = "Network"; @@ -34,6 +35,7 @@ +@inject IInterfaceService _interfaceService @code { class NetworkInterfaceViewModel { @@ -49,11 +51,11 @@ protected override void OnInitialized() { _interfaces = new List(); - var interfaces = NetworkInterface.GetAllNetworkInterfaces() + var interfaces = _interfaceService.NetworkInterfaces .OrderBy(i => i.Name) .ToList(); foreach (var iface in interfaces) { - var addresses = iface.GetIPProperties().UnicastAddresses; + var addresses = iface.GetIPProperties().UnicastAddresses.ToList(); var ipv4 = addresses.FirstOrDefault( a => a.Address.AddressFamily == AddressFamily.InterNetwork); var ipv6 = addresses.FirstOrDefault( diff --git a/Linguard/Web/Pages/Wireguard.razor b/Linguard/Web/Pages/Wireguard.razor index 08f6a1f..ec82a59 100644 --- a/Linguard/Web/Pages/Wireguard.razor +++ b/Linguard/Web/Pages/Wireguard.razor @@ -8,7 +8,7 @@ @using Linguard.Web.Services @inject IConfigurationManager _configurationManager -@inject IWireguardService _wireguardService +@inject IInterfaceService _interfaceService @inject IWebService _webService @inject NotificationService _notificationService @inject DialogService _dialogService @@ -39,7 +39,7 @@