Traefik as Loadbalancer for MQTT over tcp with TLS - load-balancing

I am trying to use Traefik as Loadbalancer for MQTT over tcp with TLS (1.2). I found some posts here for the topic how to setup traefik for mqtt, but nothing related or solving my special problem/case.
I have setup the following configuration for simulating locally the behaviour of Traefik as a Reverse Proxy & Loadbalancer for MQTT on my developer Windows 10 machine
Mosquitto_168_8883 on Windows locally on Port 8883 with TLS enabled/selfsigned certificates
Traefik 2.1.2 on Windows listening on Port 7883 for routing to mqqt (toml see below)
Node-Red 1.0.3 on Windows (NodeJs 12.14.1) client connecting (a) directly to Mosquitto (b) over Traefik to Mosquito
(a) Directly connecting and publishing is working for Node-Red Client (Port 8883)
(b) via Traefik: Node-Red can not connect or publish to MQTT (Port 7883)
My Traefik TOML Configuration is as follows:
[tracing]
serviceName = "mqtt"
[log]
level = "DEBUG" # --log.level
[entryPoints]
[entryPoints.mqtt]
address = ":7883"
[entryPoints.traefik]
address ="localhost:8091"
[api]
dashboard = true
insecure = true
[tcp] # YAY!
[tcp.routers]
[tcp.routers.mqtt]
entrypoints = ["mqtt"]
rule = "HostSNI(`*`)" # Catches every request
service = "mqtt"
[tcp.routers.mqtt.tls]
passthrough = true
[tcp.services]
[tcp.services.mqtt]
[tcp.services.mqtt.loadBalancer]
[[tcp.services.mqtt.loadBalancer.servers]]
address = "localhost:8883"
Currently, I see nothing of interest within the active tracing and logging output. The Traefik UI shows no connection attemps via port 7883/TCP/Entrypoint mqtt
Does anyone has this usecase implemented up & running?
What am I doing wrong / what am I missing?
Thank you in advance.

Related

HAProxy TCP (443) Loadbalancing with different backend ports

I'm implementing a Frontend Loadbalancer which passthrough the traffic coming to port 80 and 443 to different backend ports. SSL termination is happening in the backend and HAproxy should not engage with anything other than forwarding the traffic coming to the frontend port 80 and 443 to the respective backend ports.
Port 80 forwarding seems fine and 443 is not working as expected and giving SSL handshake failure. Even my backend service is not coming up on the web browser with a warning saying this is not trusted. I have no clue why this is happening and my HAProxy experience is not that high and below is the current configuration. Please correct me if I'm wrong.
HAProxy is installed on Ubuntu 18.04.5 LTS
Config after the defaults section
frontend k8s_lb
mode tcp
bind x.x.x.x:80
default_backend kube_minions
frontend k8s_lb_https
mode tcp
bind x.x.x.x:443
default_backend kube_minions_https
backend kube_minions
mode tcp
balance roundrobin
server k8s_worker-01 x.x.x.x:32080
server k8s_worker-02 x.x.x.x:32080
backend kube_minions_https
mode tcp
balance roundrobin
server k8s_worker-01 x.x.x.x:32443
server k8s_worker-02 x.x.x.x:32443
The backend story:
I have a k8s cluster and traefik ingress which is running as a DaemonSet on each and every node, and minions are my backend servers. CertManager is in place to do the cert automation with Let's encrypt ACME protocol in the ingress resources, hence SSL termination should be happening through the ingress resources.
I have completed the certificates and everything seems perfect as I have already implemented a similar setup on AWS with a TCP loadbalancer and everything is perfectly working and running prod workloads.
So, I need to mention that backend services are all good and up and running. In this I replaced the AWS loadbalancer with HAProxy and need to implement the same.
Please assist me to fix this as I'm struggling with this and still no luck with the issue.
Thank you.
Sorry, I was able to figure it out and there is nothing to do with traefik and HAProxy for this SSL issue. My Client's DNS is configured in CloudFlare and they have enabled the universal SSL and it caused the issue.
I checked with a new DNS record from route53 working as expected so my HAProxy config do what I need.

Unable to enable TLS on ambassador

Trying to enable TLS port on ambassador using helm chart's service.annotations option. However it is either turning into incorrect config (where tls context is attached to cleartext port) or trying to bind 80 and 443 ports.
I've ambassador as a sub chart to my main chart. And I've defined values for this subchart as follows -
ambassador:
replicaCount: 1
service:
annotations: {"getambassador.io/config": "---\napiVersion: ambassador/v1\nkind: Module\nname: tls\nconfig:\n server:\n enabled: true\n secret: ambassador-certs\n redirect_cleartext_from: 8080\n"}
This results in binding the listener to port 443 always ignoring the actual tls target port (8443).
requirements.yaml look like this
dependencies:
- name: ambassador
version: 2.0.*
repository: "#stable"
Checking the logs reveal that the listener is being created on port 443 and fails as it is not being run as root. If I keep both ambassador and tls modules, then the tls context is always attached to port 8080 and making it a tls port. /ambassador/envoy/envoy.json has always one listener (8080). The chart being is used is ambassador-2.0.2. Any idea why this behavior?
This issue addressed as part of the helm chart 2.5.x. Upgrading the dependencies to 2.5.* resolved this issue.

Traefik - Unable to expose redis docker containers with the same port for different domains

I'm trying to set up a Redis with docker-compose for different environments.
Therefore I need to expose two domains with traefik on the same port:
domain.com:6379
domain-dev.com:6379
I can't expose those ports on the container, because they are running on the same server.
My docker-compose file (for domain-dev) looks like this:
version: '2'
services:
redis:
container_name: redis-signalr-dev
image: redis
volumes:
- ./redis-signalr-data:/data
restart: always
labels:
- traefik.enable=true
- traefik.backend=redis-signalr-dev
- traefik.frontend.rule=Host:domain-dev.com
- traefik.port=6379
- traefik.docker.network=traefik_default
- traefik.frontend.entryPoints=redis
networks:
- traefik_default
volumes:
redis-signalr-data:
networks:
traefik_default:
external: true
I also tried to configure the treafik to use the following endpoint:
--entrypoints='Name:redis Address::6379'
When connecting to "domain-dev.com:6379" a connection cannot be astablished.
Does anyone know a solution to this problem?
Traefik is a reverse proxy for http, not a tcp load balancer. So traefik itself (usually) opens ports 80 and 443 for ingress and forwards incoming http requests to the given http-able backends. The port you specify in your compose service labels is the port of the container, the traffic should be passed to.
So if you run a nodejs (http) server on port 3000, you would connect to http://yourdomain:80 and traefik would forward the requests to your nodejs container on port 3000. This means that by specifying a port on a compose service, you will not open this port on your host.
In your example running redis with its custom protocol, traefik is not a solution as traefik only does http proxying. To expose redis on your host (if you really want to do that), just use regular docker port mappings and point your domains to your docker hosts. Doing this, there is no way to use the same port with different domains, just specify two different ports for your both instances. For http this works by traefik inspecting the http requests and doing routing based on the host header.
Traefik 2.0 will have TCP support: https://github.com/containous/traefik/pull/4587
Until then you'd have to use NGINX or similar.

Create SSL endpoint on port 443 for self-hosted OWIN listener

I am using a self-hosted OWIN listener for a Web API implementation that runs in a local process. However, I am unable to listen on port 443 successfully.
The following works:
var startOptions = new StartOptions();
startOptions.Urls.Add("http://127.0.0.1:9866");
startOptions.Urls.Add("https://127.0.0.1:9877");
webServer = WebApp.Start<PbiMockStartup>(startOptions);
However, when change the port numbers to 80 and 443, I consistently get 503 - Service Unavailable. I added the same SSL certificate for both 9877 and 443 ports using the netsh command with no luck.
I see from "netstat" that the "SYSTEM" process with PID (4) is listening on port 443 already, however I could not find a way to stop it other than disabling the HTTP.sys module, which will not work for me.
How does one go about listening on port 443 from a self-hosted OWIN listener?
I tried adding URLs with "localhost" and machine-name in the startup options, but the final solution that worked out was to have a '+' like following:
var startOptions = new StartOptions();
startOptions.Urls.Add("http://+:80");
startOptions.Urls.Add("https://+:443");
webServer = WebApp.Start<MyMockClass>(startOptions);

SSL/TLS with Eclipse Paho JavaScript Client

I've got a JavaScript-based WebApp that includes the Eclipse Paho client.
The WebApp is stored and executed on an NGINX webserver.
On the same Server where the webserver is installed, the MQTT broker mosquitto is running. I've defined port 8884 as listener port for secured connections.
Running mosquitto_sub (simple C client) with --cafile and -p 8884 works fine!
Now I want to secure the WebApp using SSL by passing mqttOptions = { useSSL: true } in my MQTT client implementation.
I can see that the app is trying to establish an connection to wss://ip instead of ws://ip. But the server responds with a connection refused which is totally clear because I did not configure anything on the webserver as I do not have a clue how to manage this. Will the wss connection be 'mapped' to a https or something? Do I need a websocket proxy in NGINX? Thanks in advance for any help.
You can not use the same port for raw MQTT and MQTT over websockets with mosquitto, you need to create 2 separate listeners.
The fact that you can connect with mosquitto_sub implies you have only set up a listener with the raw MQTT.
e.g.
listener 8883
listener 8884
protocol websockets
This will create a native MQTT listener on 8883 and a MQTT over websockets on port 8884
I did so. Here is the mosquitto conf entry:
listener 8884 127.0.0.1
protocol websockets
cafile /path/to/ca.crt
certfile /path/to/certfile.crt
keyfile /path/to/keyfile.key
require_certificate false
and so the app is trying to connect to myip:8884