feat: add clientid key

This commit is contained in:
zarazaex69
2026-05-06 18:23:39 +03:00
parent d1454d2fa6
commit 8be56493f0
5 changed files with 48 additions and 16 deletions

View File

@@ -28,6 +28,7 @@ type config struct {
transport string transport string
carrier string carrier string
roomID string roomID string
clientID string
provider string provider string
socksPort int socksPort int
socksHost string socksHost string
@@ -110,6 +111,7 @@ func parseFlags() config {
flag.StringVar(&cfg.transport, "transport", "", "Transport: datachannel, videochannel, seichannel") flag.StringVar(&cfg.transport, "transport", "", "Transport: datachannel, videochannel, seichannel")
flag.StringVar(&cfg.carrier, "carrier", "", "Carrier: telemost, jazz, wbstream") flag.StringVar(&cfg.carrier, "carrier", "", "Carrier: telemost, jazz, wbstream")
flag.StringVar(&cfg.roomID, "id", "", "Room ID") 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.StringVar(&cfg.provider, "provider", "", "Deprecated alias for -carrier")
flag.IntVar(&cfg.socksPort, "socks-port", 0, "SOCKS5 port (client only)") flag.IntVar(&cfg.socksPort, "socks-port", 0, "SOCKS5 port (client only)")
flag.StringVar(&cfg.socksHost, "socks-host", "", "SOCKS5 listen host (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, Transport: cfg.transport,
Carrier: firstNonEmpty(cfg.carrier, cfg.provider), Carrier: firstNonEmpty(cfg.carrier, cfg.provider),
RoomID: cfg.roomID, RoomID: cfg.roomID,
ClientID: cfg.clientID,
KeyHex: cfg.keyHex, KeyHex: cfg.keyHex,
SOCKSHost: cfg.socksHost, SOCKSHost: cfg.socksHost,
SOCKSPort: cfg.socksPort, SOCKSPort: cfg.socksPort,

View File

@@ -77,6 +77,8 @@ var (
ErrSOCKSHostRequired = errors.New("socks host required for cnc mode (use -socks-host)") ErrSOCKSHostRequired = errors.New("socks host required for cnc mode (use -socks-host)")
// ErrSOCKSPortRequired indicates that socks port is required for cnc mode. // ErrSOCKSPortRequired indicates that socks port is required for cnc mode.
ErrSOCKSPortRequired = errors.New("socks port required for cnc mode (use -socks-port)") 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 <id>)")
) )
// Config holds runtime session settings. // Config holds runtime session settings.
@@ -86,6 +88,7 @@ type Config struct {
Transport string Transport string
Carrier string Carrier string
RoomID string RoomID string
ClientID string
KeyHex string KeyHex string
SOCKSHost string SOCKSHost string
SOCKSPort int SOCKSPort int
@@ -186,6 +189,9 @@ func validateCommon(cfg Config) error {
if cfg.RoomID == "" && cfg.Carrier != "jazz" { if cfg.RoomID == "" && cfg.Carrier != "jazz" {
return ErrRoomIDRequired return ErrRoomIDRequired
} }
if cfg.ClientID == "" {
return ErrClientIDRequired
}
if cfg.KeyHex == "" { if cfg.KeyHex == "" {
return ErrKeyRequired return ErrKeyRequired
} }
@@ -271,6 +277,7 @@ func Run(ctx context.Context, cfg Config) error {
cfg.Carrier, cfg.Carrier,
roomURL, roomURL,
cfg.KeyHex, cfg.KeyHex,
cfg.ClientID,
cfg.DNSServer, cfg.DNSServer,
cfg.SOCKSProxyAddr, cfg.SOCKSProxyAddr,
cfg.SOCKSProxyPort, cfg.SOCKSProxyPort,
@@ -298,6 +305,7 @@ func Run(ctx context.Context, cfg Config) error {
cfg.Carrier, cfg.Carrier,
roomURL, roomURL,
cfg.KeyHex, cfg.KeyHex,
cfg.ClientID,
fmt.Sprintf("%s:%d", cfg.SOCKSHost, cfg.SOCKSPort), fmt.Sprintf("%s:%d", cfg.SOCKSHost, cfg.SOCKSPort),
cfg.DNSServer, cfg.DNSServer,
"", "",

View File

@@ -45,6 +45,7 @@ type Client struct {
conn *muxconn.Conn conn *muxconn.Conn
session *smux.Session session *smux.Session
sessMu sync.RWMutex sessMu sync.RWMutex
clientID string
dnsServer string dnsServer string
} }
@@ -55,7 +56,8 @@ func Run(
transportName, transportName,
carrierName, carrierName,
roomURL, roomURL,
keyHex string, keyHex,
clientID string,
localAddr string, localAddr string,
dnsServer, dnsServer,
socksUser string, socksUser string,
@@ -74,7 +76,7 @@ func Run(
vp8BatchSize int, vp8BatchSize int,
) error { ) error {
return RunWithReady( return RunWithReady(
ctx, linkName, transportName, carrierName, roomURL, keyHex, localAddr, ctx, linkName, transportName, carrierName, roomURL, keyHex, clientID, localAddr,
dnsServer, socksUser, socksPass, nil, dnsServer, socksUser, socksPass, nil,
videoWidth, videoHeight, videoFPS, videoBitrate, videoHW, videoWidth, videoHeight, videoFPS, videoBitrate, videoHW,
videoQRSize, videoQRRecovery, videoCodec, videoTileModule, videoTileRS, videoQRSize, videoQRRecovery, videoCodec, videoTileModule, videoTileRS,
@@ -89,7 +91,8 @@ func RunWithReady(
transportName, transportName,
carrierName, carrierName,
roomURL, roomURL,
keyHex string, keyHex,
clientID string,
localAddr string, localAddr string,
dnsServer, dnsServer,
_ string, _ string,
@@ -116,7 +119,7 @@ func RunWithReady(
return fmt.Errorf("setupCipher failed: %w", err) 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( if err := c.bringUpLink(
runCtx, linkName, transportName, carrierName, roomURL, cancel, 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 { func (c *Client) sendConnectRequest(stream *smux.Stream, targetAddr string, targetPort int) error {
connectReq, err := json.Marshal(map[string]any{ connectReq, err := json.Marshal(map[string]any{
"cmd": "connect", "cmd": "connect",
"addr": targetAddr, "client_id": c.clientID,
"port": targetPort, "addr": targetAddr,
"port": targetPort,
}) })
if err != nil { if err != nil {
return fmt.Errorf("sid=%d marshal connect req: %w", stream.ID(), err) return fmt.Errorf("sid=%d marshal connect req: %w", stream.ID(), err)

View File

@@ -41,6 +41,7 @@ type Server struct {
sessMu sync.RWMutex sessMu sync.RWMutex
reinstallMu sync.Mutex reinstallMu sync.Mutex
wg sync.WaitGroup wg sync.WaitGroup
clientID string
dnsServer string dnsServer string
resolver *net.Resolver resolver *net.Resolver
socksProxyAddr string socksProxyAddr string
@@ -49,9 +50,10 @@ type Server struct {
// ConnectRequest is a message from the client to establish a new connection. // ConnectRequest is a message from the client to establish a new connection.
type ConnectRequest struct { type ConnectRequest struct {
Cmd string `json:"cmd"` Cmd string `json:"cmd"`
Addr string `json:"addr"` ClientID string `json:"client_id"`
Port int `json:"port"` Addr string `json:"addr"`
Port int `json:"port"`
} }
// Run starts the server with the specified parameters. // Run starts the server with the specified parameters.
@@ -61,7 +63,8 @@ func Run(
transportName, transportName,
carrierName, carrierName,
roomURL, roomURL,
keyHex string, keyHex,
clientID string,
dnsServer, dnsServer,
socksProxyAddr string, socksProxyAddr string,
socksProxyPort int, socksProxyPort int,
@@ -88,6 +91,7 @@ func Run(
s := &Server{ s := &Server{
cipher: cipher, cipher: cipher,
clientID: clientID,
dnsServer: dnsServer, dnsServer: dnsServer,
socksProxyAddr: socksProxyAddr, socksProxyAddr: socksProxyAddr,
socksProxyPort: socksProxyPort, socksProxyPort: socksProxyPort,
@@ -339,6 +343,10 @@ func (s *Server) handleStream(_ context.Context, stream *smux.Stream) {
header = append(header, tmp[:n]...) header = append(header, tmp[:n]...)
if req, ok := parseConnectRequest(header); ok { if req, ok := parseConnectRequest(header); ok {
_ = stream.SetReadDeadline(time.Time{}) _ = stream.SetReadDeadline(time.Time{})
if !s.authorizeRequest(req) {
logger.Warnf("sid=%d rejected: client_id mismatch", stream.ID())
return
}
s.dispatch(stream, req) s.dispatch(stream, req)
return return
} }
@@ -363,6 +371,10 @@ func parseConnectRequest(buf []byte) (ConnectRequest, bool) {
return req, true return req, true
} }
func (s *Server) authorizeRequest(req ConnectRequest) bool {
return req.ClientID == s.clientID
}
func (s *Server) dispatch(stream *smux.Stream, req ConnectRequest) { func (s *Server) dispatch(stream *smux.Stream, req ConnectRequest) {
addr := net.JoinHostPort(req.Addr, strconv.Itoa(req.Port)) addr := net.JoinHostPort(req.Addr, strconv.Itoa(req.Port))
logger.Infof("sid=%d connect %s", stream.ID(), addr) logger.Infof("sid=%d connect %s", stream.ID(), addr)

View File

@@ -34,6 +34,7 @@ var (
errAlreadyRunning = errors.New("olcRTC already running") errAlreadyRunning = errors.New("olcRTC already running")
errCarrierRequired = errors.New("carrier is required") errCarrierRequired = errors.New("carrier is required")
errRoomIDRequired = errors.New("roomID is required") errRoomIDRequired = errors.New("roomID is required")
errClientIDRequired = errors.New("clientID is required")
errKeyHexRequired = errors.New("keyHex is required") errKeyHexRequired = errors.New("keyHex is required")
errNotRunning = errors.New("olcRTC is not running") errNotRunning = errors.New("olcRTC is not running")
errStoppedBeforeReady = errors.New("olcRTC stopped before becoming ready") errStoppedBeforeReady = errors.New("olcRTC stopped before becoming ready")
@@ -140,21 +141,22 @@ func SetDebug(enabled bool) {
// Start launches the olcRTC client in background. // Start launches the olcRTC client in background.
// carrierName: carrier/provider name ("telemost", "jazz", "wbstream", "wbstream") // carrierName: carrier/provider name ("telemost", "jazz", "wbstream", "wbstream")
// roomID: carrier-specific room ID // roomID: carrier-specific room ID
// clientID: client identifier that must match the server's -client-id
// keyHex: 64-char hex encryption key // keyHex: 64-char hex encryption key
// socksPort: local SOCKS5 proxy port (e.g. 10808) // socksPort: local SOCKS5 proxy port (e.g. 10808)
// socksUser/socksPass: SOCKS5 credentials (empty = no auth). // 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() mu.Lock()
ensureDefaultConfigLocked() ensureDefaultConfigLocked()
cfg := defaults cfg := defaults
mu.Unlock() 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. // StartWithTransport launches the client with an explicit transport for this start.
func StartWithTransport( func StartWithTransport(
carrierName, transportName, roomID, keyHex string, carrierName, transportName, roomID, clientID, keyHex string,
socksPort int, socksPort int,
socksUser, socksPass string, socksUser, socksPass string,
) error { ) error {
@@ -164,11 +166,11 @@ func StartWithTransport(
cfg.transport = transportName cfg.transport = transportName
mu.Unlock() 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( func startWithConfig(
carrierName, transportName, roomID, keyHex string, carrierName, transportName, roomID, clientID, keyHex string,
socksPort int, socksPort int,
socksUser, socksPass string, socksUser, socksPass string,
cfg mobileConfig, cfg mobileConfig,
@@ -189,6 +191,8 @@ func startWithConfig(
return errCarrierRequired return errCarrierRequired
case roomID == "" && carrierName != "jazz": case roomID == "" && carrierName != "jazz":
return errRoomIDRequired return errRoomIDRequired
case clientID == "":
return errClientIDRequired
case keyHex == "": case keyHex == "":
return errKeyHexRequired return errKeyHexRequired
} }
@@ -213,6 +217,7 @@ func startWithConfig(
carrierName, carrierName,
roomURL, roomURL,
keyHex, keyHex,
clientID,
fmt.Sprintf("127.0.0.1:%d", socksPort), fmt.Sprintf("127.0.0.1:%d", socksPort),
cfg.dnsServer, cfg.dnsServer,
socksUser, socksUser,