158 lines
3.9 KiB
Go
158 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"context"
|
|
"errors"
|
|
"fmt"
|
|
"os"
|
|
"os/signal"
|
|
"runtime/debug"
|
|
"syscall"
|
|
"time"
|
|
|
|
"github.com/ettle/strcase"
|
|
"github.com/hamba/cmd/v3"
|
|
"github.com/urfave/cli/v3"
|
|
)
|
|
|
|
const (
|
|
flagTargets = "targets"
|
|
flagPorts = "ports"
|
|
flagCustomRoutes = "custom-routes"
|
|
flagCustomCredentials = "custom-credentials"
|
|
flagScanner = "scanner"
|
|
flagScanSpeed = "scan-speed"
|
|
flagAttackInterval = "attack-interval"
|
|
flagTimeout = "timeout"
|
|
flagSkipScan = "skip-scan"
|
|
flagDebug = "debug"
|
|
flagUI = "ui"
|
|
flagOutput = "output"
|
|
)
|
|
|
|
var (
|
|
version = "dev"
|
|
commit = "none"
|
|
date = "unknown"
|
|
)
|
|
|
|
var flags = cmd.Flags{
|
|
&cli.StringSliceFlag{
|
|
Name: flagTargets,
|
|
Usage: "The targets on which to scan for open RTSP streams in a network range format",
|
|
Aliases: []string{"t"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagTargets)),
|
|
},
|
|
&cli.StringSliceFlag{
|
|
Name: flagPorts,
|
|
Usage: "The ports on which to search for RTSP streams",
|
|
Aliases: []string{"p"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagPorts)),
|
|
Value: []string{"554", "5554", "8554", "http"},
|
|
},
|
|
&cli.StringFlag{
|
|
Name: flagCustomRoutes,
|
|
Usage: "The path on which to load a custom routes dictionary",
|
|
Aliases: []string{"r"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagCustomRoutes)),
|
|
},
|
|
&cli.StringFlag{
|
|
Name: flagCustomCredentials,
|
|
Usage: "The path on which to load a custom credentials JSON dictionary",
|
|
Aliases: []string{"c"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagCustomCredentials)),
|
|
},
|
|
&cli.StringFlag{
|
|
Name: flagScanner,
|
|
Usage: "Discovery scanner backend: nmap or masscan",
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagScanner)),
|
|
Value: "nmap",
|
|
},
|
|
&cli.Int16Flag{
|
|
Name: flagScanSpeed,
|
|
Usage: "The nmap speed preset to use for scanning (lower is stealthier)",
|
|
Aliases: []string{"s"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagScanSpeed)),
|
|
Value: 4,
|
|
},
|
|
&cli.DurationFlag{
|
|
Name: flagAttackInterval,
|
|
Usage: "The interval between each attack (i.e: 2000ms, higher is stealthier)",
|
|
Aliases: []string{"I"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagAttackInterval)),
|
|
Value: 0,
|
|
},
|
|
&cli.DurationFlag{
|
|
Name: flagTimeout,
|
|
Usage: "The timeout to use for attack attempts (i.e: 2000ms)",
|
|
Aliases: []string{"T"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagTimeout)),
|
|
Value: 2000 * time.Millisecond,
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: flagSkipScan,
|
|
Usage: "Skip discovery and treat every target and port as an RTSP stream",
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagSkipScan)),
|
|
Value: false,
|
|
},
|
|
&cli.BoolFlag{
|
|
Name: flagDebug,
|
|
Usage: "Enable debug logs",
|
|
Aliases: []string{"d"},
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagDebug)),
|
|
Value: false,
|
|
},
|
|
&cli.StringFlag{
|
|
Name: flagUI,
|
|
Usage: "UI mode: auto, tui, or plain",
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagUI)),
|
|
Value: "auto",
|
|
},
|
|
&cli.StringFlag{
|
|
Name: flagOutput,
|
|
Usage: "Write discovered streams to an M3U file at the given path",
|
|
Sources: cli.EnvVars(strcase.ToSNAKE(flagOutput)),
|
|
},
|
|
}
|
|
|
|
func main() {
|
|
os.Exit(realMain())
|
|
}
|
|
|
|
func realMain() (code int) {
|
|
defer func() {
|
|
if v := recover(); v != nil {
|
|
_, _ = fmt.Fprintf(os.Stderr, "Panic: %v\n%s\n", v, debug.Stack())
|
|
code = 1
|
|
}
|
|
}()
|
|
|
|
app := &cli.Command{
|
|
Name: "Cameradar",
|
|
Version: version,
|
|
Usage: "Scan targets for RTSP streams",
|
|
Flags: flags,
|
|
Action: runCameradar,
|
|
Commands: []*cli.Command{
|
|
{
|
|
Name: "version",
|
|
Usage: "Print version information",
|
|
Action: printVersion,
|
|
},
|
|
},
|
|
}
|
|
|
|
ctx, cancel := signal.NotifyContext(context.Background(), syscall.SIGINT, syscall.SIGTERM)
|
|
defer cancel()
|
|
|
|
err := app.Run(ctx, os.Args)
|
|
if err != nil {
|
|
if errors.Is(err, context.Canceled) {
|
|
return 1
|
|
}
|
|
_, _ = fmt.Fprintf(os.Stderr, "Error: %s\n", err.Error())
|
|
return 1
|
|
}
|
|
return 0
|
|
}
|