mirror of
https://github.com/netbirdio/netbird.git
synced 2026-04-16 07:16:38 +00:00
[client,signal,management] Add browser client support (#4415)
This commit is contained in:
@@ -8,14 +8,16 @@ import (
|
||||
"fmt"
|
||||
"net"
|
||||
"net/http"
|
||||
|
||||
// nolint:gosec
|
||||
_ "net/http/pprof"
|
||||
"strings"
|
||||
"net/netip"
|
||||
"time"
|
||||
|
||||
"go.opentelemetry.io/contrib/instrumentation/google.golang.org/grpc/otelgrpc"
|
||||
"go.opentelemetry.io/otel/metric"
|
||||
"golang.org/x/crypto/acme/autocert"
|
||||
"golang.org/x/net/http2"
|
||||
"golang.org/x/net/http2/h2c"
|
||||
|
||||
"github.com/netbirdio/netbird/signal/metrics"
|
||||
|
||||
@@ -23,6 +25,8 @@ import (
|
||||
"github.com/netbirdio/netbird/shared/signal/proto"
|
||||
"github.com/netbirdio/netbird/signal/server"
|
||||
"github.com/netbirdio/netbird/util"
|
||||
"github.com/netbirdio/netbird/util/wsproxy"
|
||||
wsproxyserver "github.com/netbirdio/netbird/util/wsproxy/server"
|
||||
"github.com/netbirdio/netbird/version"
|
||||
|
||||
log "github.com/sirupsen/logrus"
|
||||
@@ -32,6 +36,8 @@ import (
|
||||
"google.golang.org/grpc/keepalive"
|
||||
)
|
||||
|
||||
const legacyGRPCPort = 10000
|
||||
|
||||
var (
|
||||
signalPort int
|
||||
metricsPort int
|
||||
@@ -113,7 +119,7 @@ var (
|
||||
}
|
||||
proto.RegisterSignalExchangeServer(grpcServer, srv)
|
||||
|
||||
grpcRootHandler := grpcHandlerFunc(grpcServer)
|
||||
grpcRootHandler := grpcHandlerFunc(grpcServer, metricsServer.Meter)
|
||||
|
||||
if certManager != nil {
|
||||
startServerWithCertManager(certManager, grpcRootHandler)
|
||||
@@ -123,19 +129,30 @@ var (
|
||||
var grpcListener net.Listener
|
||||
var httpListener net.Listener
|
||||
|
||||
// If certManager is configured and signalPort == 443, then the gRPC server has already been started
|
||||
if certManager == nil || signalPort != 443 {
|
||||
grpcListener, err = serveGRPC(grpcServer, signalPort)
|
||||
// Start the main server - always serve HTTP with WebSocket proxy support
|
||||
// If certManager is configured and signalPort == 443, it's already handled by startServerWithCertManager
|
||||
if certManager == nil {
|
||||
// Without TLS, serve plain HTTP
|
||||
httpListener, err = net.Listen("tcp", fmt.Sprintf(":%d", signalPort))
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("running gRPC server: %s", grpcListener.Addr().String())
|
||||
log.Infof("running HTTP server with WebSocket proxy (no TLS): %s", httpListener.Addr().String())
|
||||
serveHTTP(httpListener, grpcRootHandler)
|
||||
} else if signalPort != 443 {
|
||||
// With TLS but not on port 443, serve HTTPS
|
||||
httpListener, err = tls.Listen("tcp", fmt.Sprintf(":%d", signalPort), certManager.TLSConfig())
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
log.Infof("running HTTPS server with WebSocket proxy: %s", httpListener.Addr().String())
|
||||
serveHTTP(httpListener, grpcRootHandler)
|
||||
}
|
||||
|
||||
if signalPort != 10000 {
|
||||
if signalPort != legacyGRPCPort {
|
||||
// The Signal gRPC server was running on port 10000 previously. Old agents that are already connected to Signal
|
||||
// are using port 10000. For compatibility purposes we keep running a 2nd gRPC server on port 10000.
|
||||
compatListener, err = serveGRPC(grpcServer, 10000)
|
||||
compatListener, err = serveGRPC(grpcServer, legacyGRPCPort)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
@@ -236,11 +253,14 @@ func startServerWithCertManager(certManager *autocert.Manager, grpcRootHandler h
|
||||
}
|
||||
}
|
||||
|
||||
func grpcHandlerFunc(grpcServer *grpc.Server) http.Handler {
|
||||
func grpcHandlerFunc(grpcServer *grpc.Server, meter metric.Meter) http.Handler {
|
||||
wsProxy := wsproxyserver.New(netip.AddrPortFrom(netip.AddrFrom4([4]byte{127, 0, 0, 1}), legacyGRPCPort), wsproxyserver.WithOTelMeter(meter))
|
||||
|
||||
return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
|
||||
grpcHeader := strings.HasPrefix(r.Header.Get("Content-Type"), "application/grpc") ||
|
||||
strings.HasPrefix(r.Header.Get("Content-Type"), "application/grpc+proto")
|
||||
if r.ProtoMajor == 2 && grpcHeader {
|
||||
switch {
|
||||
case r.URL.Path == wsproxy.ProxyPath:
|
||||
wsProxy.Handler().ServeHTTP(w, r)
|
||||
default:
|
||||
grpcServer.ServeHTTP(w, r)
|
||||
}
|
||||
})
|
||||
@@ -257,7 +277,11 @@ func notifyStop(msg string) {
|
||||
|
||||
func serveHTTP(httpListener net.Listener, handler http.Handler) {
|
||||
go func() {
|
||||
err := http.Serve(httpListener, handler)
|
||||
// Use h2c to support HTTP/2 without TLS (needed for gRPC)
|
||||
h1s := &http.Server{
|
||||
Handler: h2c.NewHandler(handler, &http2.Server{}),
|
||||
}
|
||||
err := h1s.Serve(httpListener)
|
||||
if err != nil {
|
||||
notifyStop(fmt.Sprintf("failed running HTTP server %v", err))
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user