From 8be56493f037c7685c290246348c141ffe17b7ad Mon Sep 17 00:00:00 2001 From: zarazaex69 Date: Wed, 6 May 2026 18:23:39 +0300 Subject: [PATCH] feat: add clientid key --- cmd/olcrtc/main.go | 3 +++ internal/app/session/session.go | 8 ++++++++ internal/client/client.go | 18 +++++++++++------- internal/server/server.go | 20 ++++++++++++++++---- mobile/mobile.go | 15 ++++++++++----- 5 files changed, 48 insertions(+), 16 deletions(-) diff --git a/cmd/olcrtc/main.go b/cmd/olcrtc/main.go index 95d2988..7fa128c 100644 --- a/cmd/olcrtc/main.go +++ b/cmd/olcrtc/main.go @@ -28,6 +28,7 @@ type config struct { transport string carrier string roomID string + clientID string provider string socksPort int socksHost string @@ -110,6 +111,7 @@ func parseFlags() config { flag.StringVar(&cfg.transport, "transport", "", "Transport: datachannel, videochannel, seichannel") flag.StringVar(&cfg.carrier, "carrier", "", "Carrier: telemost, jazz, wbstream") flag.StringVar(&cfg.roomID, "id", "", "Room ID") + flag.StringVar(&cfg.clientID, "client-id", "", "Client ID: binds one srv to one cnc (required)") flag.StringVar(&cfg.provider, "provider", "", "Deprecated alias for -carrier") flag.IntVar(&cfg.socksPort, "socks-port", 0, "SOCKS5 port (client only)") flag.StringVar(&cfg.socksHost, "socks-host", "", "SOCKS5 listen host (client only)") @@ -178,6 +180,7 @@ func toSessionConfig(cfg config) session.Config { Transport: cfg.transport, Carrier: firstNonEmpty(cfg.carrier, cfg.provider), RoomID: cfg.roomID, + ClientID: cfg.clientID, KeyHex: cfg.keyHex, SOCKSHost: cfg.socksHost, SOCKSPort: cfg.socksPort, diff --git a/internal/app/session/session.go b/internal/app/session/session.go index 3ea732e..61edd02 100644 --- a/internal/app/session/session.go +++ b/internal/app/session/session.go @@ -77,6 +77,8 @@ var ( ErrSOCKSHostRequired = errors.New("socks host required for cnc mode (use -socks-host)") // ErrSOCKSPortRequired indicates that socks port is required for cnc mode. ErrSOCKSPortRequired = errors.New("socks port required for cnc mode (use -socks-port)") + // ErrClientIDRequired indicates that client ID is required. + ErrClientIDRequired = errors.New("client ID required (use -client-id )") ) // Config holds runtime session settings. @@ -86,6 +88,7 @@ type Config struct { Transport string Carrier string RoomID string + ClientID string KeyHex string SOCKSHost string SOCKSPort int @@ -186,6 +189,9 @@ func validateCommon(cfg Config) error { if cfg.RoomID == "" && cfg.Carrier != "jazz" { return ErrRoomIDRequired } + if cfg.ClientID == "" { + return ErrClientIDRequired + } if cfg.KeyHex == "" { return ErrKeyRequired } @@ -271,6 +277,7 @@ func Run(ctx context.Context, cfg Config) error { cfg.Carrier, roomURL, cfg.KeyHex, + cfg.ClientID, cfg.DNSServer, cfg.SOCKSProxyAddr, cfg.SOCKSProxyPort, @@ -298,6 +305,7 @@ func Run(ctx context.Context, cfg Config) error { cfg.Carrier, roomURL, cfg.KeyHex, + cfg.ClientID, fmt.Sprintf("%s:%d", cfg.SOCKSHost, cfg.SOCKSPort), cfg.DNSServer, "", diff --git a/internal/client/client.go b/internal/client/client.go index d776717..c338c31 100644 --- a/internal/client/client.go +++ b/internal/client/client.go @@ -45,6 +45,7 @@ type Client struct { conn *muxconn.Conn session *smux.Session sessMu sync.RWMutex + clientID string dnsServer string } @@ -55,7 +56,8 @@ func Run( transportName, carrierName, roomURL, - keyHex string, + keyHex, + clientID string, localAddr string, dnsServer, socksUser string, @@ -74,7 +76,7 @@ func Run( vp8BatchSize int, ) error { return RunWithReady( - ctx, linkName, transportName, carrierName, roomURL, keyHex, localAddr, + ctx, linkName, transportName, carrierName, roomURL, keyHex, clientID, localAddr, dnsServer, socksUser, socksPass, nil, videoWidth, videoHeight, videoFPS, videoBitrate, videoHW, videoQRSize, videoQRRecovery, videoCodec, videoTileModule, videoTileRS, @@ -89,7 +91,8 @@ func RunWithReady( transportName, carrierName, roomURL, - keyHex string, + keyHex, + clientID string, localAddr string, dnsServer, _ string, @@ -116,7 +119,7 @@ func RunWithReady( return fmt.Errorf("setupCipher failed: %w", err) } - c := &Client{cipher: cipher, dnsServer: dnsServer} + c := &Client{cipher: cipher, clientID: clientID, dnsServer: dnsServer} if err := c.bringUpLink( runCtx, linkName, transportName, carrierName, roomURL, cancel, @@ -355,9 +358,10 @@ func (c *Client) tunnel(conn net.Conn, sess *smux.Session, targetAddr string, ta func (c *Client) sendConnectRequest(stream *smux.Stream, targetAddr string, targetPort int) error { connectReq, err := json.Marshal(map[string]any{ - "cmd": "connect", - "addr": targetAddr, - "port": targetPort, + "cmd": "connect", + "client_id": c.clientID, + "addr": targetAddr, + "port": targetPort, }) if err != nil { return fmt.Errorf("sid=%d marshal connect req: %w", stream.ID(), err) diff --git a/internal/server/server.go b/internal/server/server.go index 99fb2ae..f3edf63 100644 --- a/internal/server/server.go +++ b/internal/server/server.go @@ -41,6 +41,7 @@ type Server struct { sessMu sync.RWMutex reinstallMu sync.Mutex wg sync.WaitGroup + clientID string dnsServer string resolver *net.Resolver socksProxyAddr string @@ -49,9 +50,10 @@ type Server struct { // ConnectRequest is a message from the client to establish a new connection. type ConnectRequest struct { - Cmd string `json:"cmd"` - Addr string `json:"addr"` - Port int `json:"port"` + Cmd string `json:"cmd"` + ClientID string `json:"client_id"` + Addr string `json:"addr"` + Port int `json:"port"` } // Run starts the server with the specified parameters. @@ -61,7 +63,8 @@ func Run( transportName, carrierName, roomURL, - keyHex string, + keyHex, + clientID string, dnsServer, socksProxyAddr string, socksProxyPort int, @@ -88,6 +91,7 @@ func Run( s := &Server{ cipher: cipher, + clientID: clientID, dnsServer: dnsServer, socksProxyAddr: socksProxyAddr, socksProxyPort: socksProxyPort, @@ -339,6 +343,10 @@ func (s *Server) handleStream(_ context.Context, stream *smux.Stream) { header = append(header, tmp[:n]...) if req, ok := parseConnectRequest(header); ok { _ = stream.SetReadDeadline(time.Time{}) + if !s.authorizeRequest(req) { + logger.Warnf("sid=%d rejected: client_id mismatch", stream.ID()) + return + } s.dispatch(stream, req) return } @@ -363,6 +371,10 @@ func parseConnectRequest(buf []byte) (ConnectRequest, bool) { return req, true } +func (s *Server) authorizeRequest(req ConnectRequest) bool { + return req.ClientID == s.clientID +} + func (s *Server) dispatch(stream *smux.Stream, req ConnectRequest) { addr := net.JoinHostPort(req.Addr, strconv.Itoa(req.Port)) logger.Infof("sid=%d connect %s", stream.ID(), addr) diff --git a/mobile/mobile.go b/mobile/mobile.go index 420bb6f..5a74367 100644 --- a/mobile/mobile.go +++ b/mobile/mobile.go @@ -34,6 +34,7 @@ var ( errAlreadyRunning = errors.New("olcRTC already running") errCarrierRequired = errors.New("carrier is required") errRoomIDRequired = errors.New("roomID is required") + errClientIDRequired = errors.New("clientID is required") errKeyHexRequired = errors.New("keyHex is required") errNotRunning = errors.New("olcRTC is not running") errStoppedBeforeReady = errors.New("olcRTC stopped before becoming ready") @@ -140,21 +141,22 @@ func SetDebug(enabled bool) { // Start launches the olcRTC client in background. // carrierName: carrier/provider name ("telemost", "jazz", "wbstream", "wbstream") // roomID: carrier-specific room ID +// clientID: client identifier that must match the server's -client-id // keyHex: 64-char hex encryption key // socksPort: local SOCKS5 proxy port (e.g. 10808) // socksUser/socksPass: SOCKS5 credentials (empty = no auth). -func Start(carrierName, roomID, keyHex string, socksPort int, socksUser, socksPass string) error { +func Start(carrierName, roomID, clientID, keyHex string, socksPort int, socksUser, socksPass string) error { mu.Lock() ensureDefaultConfigLocked() cfg := defaults mu.Unlock() - return startWithConfig(carrierName, cfg.transport, roomID, keyHex, socksPort, socksUser, socksPass, cfg) + return startWithConfig(carrierName, cfg.transport, roomID, clientID, keyHex, socksPort, socksUser, socksPass, cfg) } // StartWithTransport launches the client with an explicit transport for this start. func StartWithTransport( - carrierName, transportName, roomID, keyHex string, + carrierName, transportName, roomID, clientID, keyHex string, socksPort int, socksUser, socksPass string, ) error { @@ -164,11 +166,11 @@ func StartWithTransport( cfg.transport = transportName mu.Unlock() - return startWithConfig(carrierName, transportName, roomID, keyHex, socksPort, socksUser, socksPass, cfg) + return startWithConfig(carrierName, transportName, roomID, clientID, keyHex, socksPort, socksUser, socksPass, cfg) } func startWithConfig( - carrierName, transportName, roomID, keyHex string, + carrierName, transportName, roomID, clientID, keyHex string, socksPort int, socksUser, socksPass string, cfg mobileConfig, @@ -189,6 +191,8 @@ func startWithConfig( return errCarrierRequired case roomID == "" && carrierName != "jazz": return errRoomIDRequired + case clientID == "": + return errClientIDRequired case keyHex == "": return errKeyHexRequired } @@ -213,6 +217,7 @@ func startWithConfig( carrierName, roomURL, keyHex, + clientID, fmt.Sprintf("127.0.0.1:%d", socksPort), cfg.dnsServer, socksUser,