Currently we want to access our Azure IoT-Hub using RabbitMQ. We know that there are other options and already tested a few, but this project is to test if it is possible and suitable for us.
using RabbitMQ.Client;
using RabbitMQ.Client.Events;
using System;
using System.Text;
Our Code looks somewhat like this:
var factory = new ConnectionFactory();
factory.HostName = $"{IOT_HUB_NAME}.azure-devices.net";
// This fails with the message: 'None of the specified endpoints were reachable.'
using (var connection = factory.CreateConnection())
{
// ...
}
The endpoint the factory wants to connect to is:
amqp://<IoT-Hub Name>.azure-devices.net:5672
Our IT-Department already checked our filewall: it is not blocking this connection.
A quick check using telnet results in a connection error:
telnet <IoT-Hub Name>.azure-devices.net 5672
However, the port 5671 (another port required by AMQP) is available.
I already tried setting the factory.Port = 5671 with no success. Another check using the Microsoft Azure IoT SDK reveiled that it is indeed possible to connect to the IoT-Hub.
This leads me to the assumption that I either miss an important configuration or it might not be possible to connect to Azure IoT-Hubs with RabbitMQ.
You certainly want to look into addressing specific endpoints such as the device to cloud messaging one and into the authentication mechanisms linked from this doc as well.
Here again as an answer:
After having a talk with a Cloud Solution Architect at Microsoft in Berlin (Germany), I am pretty sure it is not possible because of the version difference in the used AMQP protocol (0.9.1 to 1.0 seems not to be possible).
Related
Expected Outcome
I'm attempting to make an ASP.NET Core 5.0 application using Kestrel, and I would like to auto port forward the server's port.
Package
I'm currently using the OpenNat.Core package. I have also tried the regular OpenNat and the same issue arises.
Issue
When port forwarding, the program says it has mapped everything correctly and the map even shows when listing all mapped ports on my router. Yet, when I attempt to view its status via CanYouSeeMe.org it returns a timed out error, and I am unable to access the server outside the network.
What I've Tried
I thought that the port mapping might have been opening after the server started, so I manually opened the port and then restarted the Kestrel server.
I made sure that my router supported UPnP
I also have a Synology NAS that I port forward from, and it works just fine.
I had a friend use ZenMap to check the port.
The port shows that it's filtered but not open (and no service was specified).
Code
using Open.Nat;
using System;
using System.Threading;
using System.Threading.Tasks;
...
public static async Task OpenPort(int port, string description)
{
try
{
NatDiscoverer discoverer = new NatDiscoverer();
CancellationTokenSource cts = new CancellationTokenSource(10000);
NatDevice device = await discoverer.DiscoverDeviceAsync(PortMapper.Upnp, cts);
Mapping map = new(Protocol.Tcp, port, port, description);
await device.CreatePortMapAsync(map);
Console.WriteLine($"Created {map}");
}
catch (Exception e)
{
Console.WriteLine(e.Message);
Console.WriteLine(e.StackTrace);
}
}
Nevermind my firewall was blocking the application. I was able to dynamically add a firewall rule to fix the issue.
I have been connecting .Net Core code from within a Docker container to a Neo4j DB. I tried using Neo4jClient first but ran into issues with the http connection out of the docker container. I then tried the Neo4j.Driver directly with the bolt connection using host.docker.internal to alias localhost. This worked fine. I swapped back to Neo4jClient with bolt (again from within Docker) but its failing with.
Thanks for any help.
Neo4j.Driver.V1.ServiceUnavailableException
HResult=0x80131500
Message=Connection with the server breaks due to SecurityException: Failed to establish encrypted connection with server bolt://host.docker.internal:7687/.
Source=Neo4j.Driver
Update:
Following Chris Skardon's help below. I switched on ssl for bolt as per section Example 11.2. Enable Bolt SSL.
As per instructions here at Neo4j
The code below using Neo4j.Driver directly works and updates the DB with 12 organisations.
Its running from within a .Net Core Docker container and using host.docker.internal. I would have expected this not to work without the Encryption config. But it does.
IDriver driver = GraphDatabase.Driver("bolt://host.docker.internal:7687", AuthTokens.Basic("neo4j", "xxxxx"));
IAsyncSession session = driver.AsyncSession(o => o.WithDatabase("neo4j"));
This code using Neo4jClient doesn’t work. I was originally running it within a docker container as above and thought that might be it. But still have a problem with no container
IDriver driver = GraphDatabase.Driver("bolt://localhost:7687", AuthTokens.Basic("neo4j", "xxxxx"), Config.Builder.WithEncryptionLevel(EncryptionLevel.Encrypted).ToConfig());
var client = new BoltGraphClient(driver);
The exceptions are:
Connection with the server breaks due to SecurityException: Failed
to establish encrypted connection with server
bolt://localhost:7687/.'
IOException: Authentication failed because
the remote party has closed the transport stream.
Nothing appears in the Neo4j logs. I don't have any specific code in the .Net Core API code for supporting SSL and googling the 2nd exception comes back with a lots of incorrect TLS results. So am exploring that.
The 4.x versions of Neo4j require Encryption to be set, Neo4jClient doesn't actually provide an easy way to do this, so you'd need to pass in an IDriver instance, like so:
var driver = GraphDatabase.Driver("bolt://localhost:7687", AuthTokens.Basic("neo4j", "neo"), Config.Builder.WithEncryptionLevel(EncryptionLevel.None).ToConfig());
var client = new BoltGraphClient(driver);
EDIT
I've been testing this - and the problem is actually the opposite - you need to turn the encrpytion level to 'None' - unless you actually have an SSL cert setup
I am new to rabbitmq using c#. We are trying to create an API for epex spot it uses AMQP in Transport label protocol and uses Rabbitmq for this.
I am able to connect to the epex spot's server using the credential provided.
ConnectionFactory factory = new RabbitMQ.Client.ConnectionFactory();
able to create channel
using (IConnection conn = factory.CreateConnection())
{
using (IModel channel = conn.CreateModel())
{
But when ever I try to DeclareExchange or DeclareQueue, I get error stating:
The AMQP operation was interrupted: AMQP close-reason, initiated by Peer, code=403, text="ACCESS_REFUSED - access to exchange 'M7.broadcastQueue.username' in vhost 'app' refused for user 'username'", classId=60, methodId=40
If I try to contact epexspot and ask for permission they say we have all the permission necessary. Can you guys please help how I can fix this issue or if anyone has faces similar issue before?
Your permissions are not set correctly. This command must be run to do so:
rabbitmqctl set_permissions -p app username '.*' '.*' '.*'
Whomever "epexspot" is didn't set them correctly, or tried to limit the read / write / configure permission for that user.
I'm assuming this is your message as well. When this is resolved, please follow up in all the places you have asked this question with details about the resolution so that others can learn from it.
NOTE: the RabbitMQ team monitors the rabbitmq-users mailing list and only sometimes answers questions on StackOverflow.
While connecting to the server, few important information were missing. Information like exchange were not provided.
these information grated the authorization part due to which this error kept raising.
Thank you
I see a lot of examples of usage RabbitMq in .NET (in ASP.NET or console applications). Most of them look like this:
using (var connecttion = MyConnectionFactoryWrapper.CreateConnection())
using (var channel = connection.CreateChannel())
{
...
}
Is it efficient? In documentation I see:
AMQP connections are typically long-lived. AMQP is an application
level protocol that uses TCP for reliable delivery.
So I suppose it's better to have one connection for application. Another point about channels:
AMQP 0-9-1 connections are multiplexed with channels that can be
thought of as "lightweight connections that share a single TCP
connection".
Here I suppose I can use channel-per-request in case of ASP.NET application. My question: is it the best practice to have connection-per-application and channel-per-request?
Yes, connection-per-application is a suggested approach. Channel-per-request should do as well, but I'd test it for your required throughput. For our project we used EasyNetQ which takes care of creating connections/channels for you. We just kept a single MessageBus instance for the application.
I am writing this to find out why the code below is resulting in failed setup for supersocket server.
var appServer = new AppServer();
if (!appServer.Setup(8080)){
MessageBox.Show("Failed!");
}
I have added rule in firewall that allows port 8080 since my firewall is enabled by company IT. Don't know why the setup fails. Is there an explanation?
In testing this locally in a console application using the following (requires NuGet packages SuperSocket and SuperSocket.Engine;
namespace SupersocketTest
{
using System;
using SuperSocket.SocketBase;
class Program
{
static void Main(string[] args)
{
var server = new AppServer();
bool success = server.Setup(8080);
Console.WriteLine($"Server setup: {success}");
Console.ReadKey();
}
}
}
The operation completes successfully.
Looking at the code online, the underlying connection is still Socket based (as the name of the package implies). As such, it's subject to all the rules around how sockets work normally in .NET.
Things that can cause a Socket fail to be set up are (but not limited to)
The socket is in use
The socket has been closed
The OS has run out of available sockets (not likely but technically possible)
Without more detail on the exception you're getting I can only guess but I suspect that the socket is in use as 8080 is a common alternative to 80 that another application could be using.