From ac9dc102d221502da7f4ffa613987af2abf6f23f Mon Sep 17 00:00:00 2001 From: Clemens Vasters Date: Fri, 30 Aug 2024 10:59:01 +0200 Subject: [PATCH] NoAuthentication option added for "LocalForward" in config (only) #77 --- .../Configuration/LocalForward.cs | 26 ++++ .../Configuration/LocalForwardBinding.cs | 7 + .../LocalForwardHost.cs | 6 +- .../SocketLocalForwardBridge.cs | 12 +- .../TcpLocalForwardBridge.cs | 14 +- .../UdpLocalForwardBridge.cs | 12 +- .../BridgeTest.cs | 134 ++++++++++-------- 7 files changed, 135 insertions(+), 76 deletions(-) diff --git a/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForward.cs b/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForward.cs index 05bb5c6..283847c 100644 --- a/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForward.cs +++ b/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForward.cs @@ -219,5 +219,31 @@ public List Bindings } } } + + public bool NoAuthentication + { + get + { + if (bindings.Count == 1) + { + return bindings[0].NoAuthentication; + } + else + { + return false; + } + } + set + { + if (bindings.Count == 0) + { + bindings.Add(new LocalForwardBinding { NoAuthentication = value }); + } + else + { + bindings[0].NoAuthentication = value; + } + } + } } } \ No newline at end of file diff --git a/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForwardBinding.cs b/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForwardBinding.cs index f360ecf..6edc5ce 100644 --- a/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForwardBinding.cs +++ b/src/Microsoft.Azure.Relay.Bridge/Configuration/LocalForwardBinding.cs @@ -12,6 +12,7 @@ public class LocalForwardBinding private string bindAddress; private string hostName; private int bindPort; + private bool noAuthentication = false; private string bindLocalSocket = null; string portName; @@ -190,5 +191,11 @@ public string BindLocalSocket bindLocalSocket = val; } } + + public bool NoAuthentication + { + get => noAuthentication; + set => noAuthentication = value; + } } } \ No newline at end of file diff --git a/src/Microsoft.Azure.Relay.Bridge/LocalForwardHost.cs b/src/Microsoft.Azure.Relay.Bridge/LocalForwardHost.cs index aa6784b..7bb3b7e 100644 --- a/src/Microsoft.Azure.Relay.Bridge/LocalForwardHost.cs +++ b/src/Microsoft.Azure.Relay.Bridge/LocalForwardHost.cs @@ -72,7 +72,7 @@ void StartEndpoint(LocalForward localForward, LocalForwardBinding binding) try { { - socketListenerBridge = SocketLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName); + socketListenerBridge = SocketLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName, binding.NoAuthentication); socketListenerBridge.Run(binding.BindLocalSocket); this.socketListenerBridges.Add(socketListenerBridge); @@ -115,7 +115,7 @@ void StartEndpoint(LocalForward localForward, LocalForwardBinding binding) if (bindToAddress != null) { tcpListenerBridge = - TcpLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName); + TcpLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName, binding.NoAuthentication); tcpListenerBridge.Run(new IPEndPoint(bindToAddress, binding.BindPort)); this.listenerBridges.Add(tcpListenerBridge); @@ -156,7 +156,7 @@ void StartEndpoint(LocalForward localForward, LocalForwardBinding binding) if (bindToAddress != null) { udpListenerBridge = - UdpLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName); + UdpLocalForwardBridge.FromConnectionString(this.config, rcbs, binding.PortName, binding.NoAuthentication); udpListenerBridge.Run(new IPEndPoint(bindToAddress, -binding.BindPort)); this.udpBridges.Add(udpListenerBridge); diff --git a/src/Microsoft.Azure.Relay.Bridge/SocketLocalForwardBridge.cs b/src/Microsoft.Azure.Relay.Bridge/SocketLocalForwardBridge.cs index a141cd5..a27c5c6 100644 --- a/src/Microsoft.Azure.Relay.Bridge/SocketLocalForwardBridge.cs +++ b/src/Microsoft.Azure.Relay.Bridge/SocketLocalForwardBridge.cs @@ -27,11 +27,15 @@ sealed class SocketLocalForwardBridge : IDisposable Socket socketListener; string localEndpoint; - public SocketLocalForwardBridge(Config config, RelayConnectionStringBuilder connectionString, string portName) + public SocketLocalForwardBridge(Config config, RelayConnectionStringBuilder connectionString, string portName, bool noAuth) { PortName = portName; this.config = config; - if (connectionString.SharedAccessKeyName == null && connectionString.SharedAccessSignature == null) + if (noAuth) + { + this.hybridConnectionClient = new HybridConnectionClient(new Uri(connectionString.Endpoint, connectionString.EntityPath)); + } + else if (string.IsNullOrEmpty(connectionString.SharedAccessKeyName) || string.IsNullOrEmpty(connectionString.SharedAccessSignature)) { this.hybridConnectionClient = new HybridConnectionClient(new Uri(connectionString.Endpoint, connectionString.EntityPath), Host.DefaultAzureCredentialTokenProvider); } @@ -52,9 +56,9 @@ public SocketLocalForwardBridge(Config config, RelayConnectionStringBuilder conn public HybridConnectionClient HybridConnectionClient => hybridConnectionClient; public static SocketLocalForwardBridge FromConnectionString(Config config, - RelayConnectionStringBuilder connectionString, string bindingPortName) + RelayConnectionStringBuilder connectionString, string bindingPortName, bool noAuth) { - return new SocketLocalForwardBridge(config, connectionString, bindingPortName); + return new SocketLocalForwardBridge(config, connectionString, bindingPortName, noAuth); } public void Close() diff --git a/src/Microsoft.Azure.Relay.Bridge/TcpLocalForwardBridge.cs b/src/Microsoft.Azure.Relay.Bridge/TcpLocalForwardBridge.cs index 14571d0..1b7cd71 100644 --- a/src/Microsoft.Azure.Relay.Bridge/TcpLocalForwardBridge.cs +++ b/src/Microsoft.Azure.Relay.Bridge/TcpLocalForwardBridge.cs @@ -15,7 +15,7 @@ namespace Microsoft.Azure.Relay.Bridge sealed class TcpLocalForwardBridge : IDisposable { public string PortName { get; } - + private readonly Config config; readonly CancellationTokenSource cancellationTokenSource = new CancellationTokenSource(); @@ -26,11 +26,15 @@ sealed class TcpLocalForwardBridge : IDisposable TcpListener tcpListener; string localEndpoint; - public TcpLocalForwardBridge(Config config, RelayConnectionStringBuilder connectionString, string portName) + public TcpLocalForwardBridge(Config config, RelayConnectionStringBuilder connectionString, string portName, bool noAuth) { PortName = portName; this.config = config; - if (connectionString.SharedAccessKeyName == null && connectionString.SharedAccessSignature == null) + if (noAuth) + { + this.hybridConnectionClient = new HybridConnectionClient(new Uri(connectionString.Endpoint, connectionString.EntityPath)); + } + else if (string.IsNullOrEmpty(connectionString.SharedAccessKeyName) || string.IsNullOrEmpty(connectionString.SharedAccessSignature)) { this.hybridConnectionClient = new HybridConnectionClient(new Uri(connectionString.Endpoint, connectionString.EntityPath), Host.DefaultAzureCredentialTokenProvider); } @@ -51,9 +55,9 @@ public TcpLocalForwardBridge(Config config, RelayConnectionStringBuilder connect public HybridConnectionClient HybridConnectionClient => hybridConnectionClient; public static TcpLocalForwardBridge FromConnectionString(Config config, - RelayConnectionStringBuilder connectionString, string portName) + RelayConnectionStringBuilder connectionString, string portName, bool noAuth) { - return new TcpLocalForwardBridge(config, connectionString, portName); + return new TcpLocalForwardBridge(config, connectionString, portName, noAuth); } public void Close() diff --git a/src/Microsoft.Azure.Relay.Bridge/UdpLocalForwardBridge.cs b/src/Microsoft.Azure.Relay.Bridge/UdpLocalForwardBridge.cs index 61a3b02..44c4c6e 100644 --- a/src/Microsoft.Azure.Relay.Bridge/UdpLocalForwardBridge.cs +++ b/src/Microsoft.Azure.Relay.Bridge/UdpLocalForwardBridge.cs @@ -30,11 +30,15 @@ sealed class UdpLocalForwardBridge : IDisposable UdpClient udpClient; string localEndpoint; - public UdpLocalForwardBridge(Config config, RelayConnectionStringBuilder connectionString, string portName) + public UdpLocalForwardBridge(Config config, RelayConnectionStringBuilder connectionString, string portName, bool noAuth) { PortName = portName; this.config = config; - if (connectionString.SharedAccessKeyName == null && connectionString.SharedAccessSignature == null) + if (noAuth) + { + this.hybridConnectionClient = new HybridConnectionClient(new Uri(connectionString.Endpoint, connectionString.EntityPath)); + } + else if (string.IsNullOrEmpty(connectionString.SharedAccessKeyName) || string.IsNullOrEmpty(connectionString.SharedAccessSignature)) { this.hybridConnectionClient = new HybridConnectionClient(new Uri(connectionString.Endpoint, connectionString.EntityPath), Host.DefaultAzureCredentialTokenProvider); } @@ -55,9 +59,9 @@ public UdpLocalForwardBridge(Config config, RelayConnectionStringBuilder connect public HybridConnectionClient HybridConnectionClient => hybridConnectionClient; public static UdpLocalForwardBridge FromConnectionString(Config config, - RelayConnectionStringBuilder connectionString, string portName) + RelayConnectionStringBuilder connectionString, string portName, bool noAuth) { - return new UdpLocalForwardBridge(config, connectionString, portName); + return new UdpLocalForwardBridge(config, connectionString, portName, noAuth); } public void Close() diff --git a/test/unit/Microsoft.Azure.Relay.Bridge.Tests/BridgeTest.cs b/test/unit/Microsoft.Azure.Relay.Bridge.Tests/BridgeTest.cs index 654633a..4fc5457 100644 --- a/test/unit/Microsoft.Azure.Relay.Bridge.Tests/BridgeTest.cs +++ b/test/unit/Microsoft.Azure.Relay.Bridge.Tests/BridgeTest.cs @@ -20,14 +20,17 @@ public class BridgeTest : IClassFixture #if _WINDOWS private const string relayA1 = "a1.win"; private const string relayA2 = "a2.win"; + private const string relayA3 = "a3.win"; private const string relayHttp = "http.win"; #elif _LINUX private const string relayA1 = "a1.linux"; private const string relayA2 = "a2.linux"; + private const string relayA3 = "a3.linux"; private const string relayHttp = "http.linux"; #elif _OSX private const string relayA1 = "a1.osx"; private const string relayA2 = "a2.osx"; + private const string relayA3 = "a3.osx"; private const string relayHttp = "http.osx"; #endif @@ -106,6 +109,75 @@ public void TcpBridge() } } + [Fact] + public void TcpBridgeNoAuth() + { + // set up the bridge first + Config cfg = new Config + { + AzureRelayConnectionString = Utilities.GetConnectionString() + }; + cfg.LocalForward.Add(new LocalForward + { + BindAddress = "127.0.97.1", + BindPort = 29876, + PortName = "test", + RelayName = relayA3, + NoAuthentication = true + }); + cfg.RemoteForward.Add(new RemoteForward + { + Host = "127.0.97.2", + HostPort = 29877, + PortName = "test", + RelayName = relayA3 + }); + Host host = new Host(cfg); + host.Start(); + + try + { + // now try to use it + var l = new TcpListener(IPAddress.Parse("127.0.97.2"), 29877); + l.Start(); + l.AcceptTcpClientAsync().ContinueWith((t) => + { + var c = t.Result; + var stream = c.GetStream(); + using (var b = new StreamReader(stream)) + { + var text = b.ReadLine(); + using (var w = new StreamWriter(stream)) + { + w.WriteLine(text); + w.Flush(); + } + } + }); + + using (var s = new TcpClient()) + { + s.Connect("127.0.97.1", 29876); + var sstream = s.GetStream(); + using (var w = new StreamWriter(sstream)) + { + w.WriteLine("Hello!"); + w.Flush(); + using (var b = new StreamReader(sstream)) + { + Assert.Equal("Hello!", b.ReadLine()); + } + } + } + + l.Stop(); + } + finally + { + host.Stop(); + } + } + [Fact] public void UdpBridge() { @@ -189,7 +261,7 @@ public void UdpBridge() } } -#if _SYSTEMD +#if _LINUX [Fact(Skip="Unreliable")] public void SocketBridge() { @@ -270,65 +342,7 @@ public void SocketBridge() } #endif - [Fact(Skip = "Unreliable")] - public void TcpBridgeBadListener() - { - // set up the bridge first - Config cfg = new Config - { - AzureRelayConnectionString = Utilities.GetConnectionString() - }; - cfg.LocalForward.Add(new LocalForward - { - BindAddress = "127.0.97.1", - BindPort = 29876, - RelayName = relayA1 - }); - cfg.RemoteForward.Add(new RemoteForward - { - Host = "127.0.97.2", - HostPort = 29877, - RelayName = relayA1 - }); - Host host = new Host(cfg); - host.Start(); - - try - { - // now try to use it - var l = new TcpListener(IPAddress.Parse("127.0.97.2"), 29877); - l.Start(); - l.AcceptTcpClientAsync().ContinueWith((t) => - { - t.Result.Client.Close(0); - l.Stop(); - }); - - using (var s = new TcpClient()) - { - s.Connect("127.0.97.1", 29876); - s.NoDelay = true; - s.Client.Blocking = true; - using (var w = s.GetStream()) - { - byte[] bytes = new byte[1024 * 1024]; - Assert.Throws(() => - { - for (int i = 0; i < 5; i++) - { - w.Write(bytes, 0, bytes.Length); - } - }); - } - } - } - finally - { - host.Stop(); - } - } - - + [Fact] public async Task HttpBridge() {