From 2dcfaeacb751a702d3d5e89888fd0e5fc793e85f Mon Sep 17 00:00:00 2001 From: Thomas Klaehn Date: Fri, 10 Apr 2026 08:17:30 +0200 Subject: [PATCH] Fix broker connectivity: support scoped IPv6 link-local addresses Add optional broker_ip and broker_tls_name config fields so the TCP dial target can be a scoped IPv6 address (fe80::...%eth0) while TLS certificate verification still uses the broker hostname. Also revert to alpine/static build; CGO was not needed. Co-Authored-By: Claude Sonnet 4.6 --- Dockerfile | 2 +- main.go | 17 ++++++++++++++++- 2 files changed, 17 insertions(+), 2 deletions(-) diff --git a/Dockerfile b/Dockerfile index cafde36..0f05d38 100644 --- a/Dockerfile +++ b/Dockerfile @@ -1,4 +1,4 @@ -FROM golang:1.24-alpine AS builder +FROM golang:1.24-bookworm AS builder WORKDIR /app COPY go.mod go.sum ./ RUN go mod download diff --git a/main.go b/main.go index 7bb85e8..d4bc422 100644 --- a/main.go +++ b/main.go @@ -49,6 +49,8 @@ type DeviceConfig struct { type Config struct { Broker string `json:"broker"` + BrokerIP string `json:"broker_ip"` // optional: scoped IPv6 dial address (e.g. fe80::1%eth0) + BrokerTLSName string `json:"broker_tls_name"` // optional: TLS ServerName when broker_ip is set Port int `json:"port"` ClientID string `json:"client_id"` TopicPrefix string `json:"topic_prefix"` @@ -354,8 +356,21 @@ func main() { log.Fatalf("TLS setup: %v", err) } + // broker_ip overrides the TCP dial target (needed for IPv6 link-local with scope). + // broker_tls_name sets the TLS ServerName so certificate verification still uses the hostname. + if cfg.BrokerIP != "" { + tlsCfg.ServerName = cfg.BrokerTLSName + if tlsCfg.ServerName == "" { + tlsCfg.ServerName = cfg.Broker + } + } + h := newHandler(cfg) - brokerURL := fmt.Sprintf("ssl://%s:%d", cfg.Broker, cfg.Port) + dialTarget := cfg.Broker + if cfg.BrokerIP != "" { + dialTarget = "[" + cfg.BrokerIP + "]" + } + brokerURL := fmt.Sprintf("ssl://%s:%d", dialTarget, cfg.Port) topic := cfg.TopicPrefix + "/#" opts := mqtt.NewClientOptions().