therandomsecurityguy/flan-go-scan

GitHub: therandomsecurityguy/flan-go-scan

Flan 是一个用 Go 编写的模块化网络扫描器,集成了端口扫描、服务指纹识别、云端资产发现及 AI 分析功能。

Stars: 16 | Forks: 1

![Go-Gopher-Flan-small](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/bebdb15f99021139.png) # flan [![Go 1.23+](https://img.shields.io/badge/Go-1.23%2B-00ADD8?logo=go&logoColor=white)](https://go.dev/dl/) [![License: BSD 3-Clause](https://img.shields.io/badge/License-BSD%203--Clause-blue.svg)](LICENSE) [![CI](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/a0e5bcf645021140.svg)](https://github.com/therandomsecurityguy/flan-go-scan/actions/workflows/ci.yml) Flan 是一个用 Go 编写的瑞士军刀式网络扫描器。它是 [Flan Scan](https://github.com/cloudflare/flan) 的继任者。 ## 功能 - 具有并发限制的 TCP 端口扫描 - 通过 [fingerprintx](https://github.com/praetorian-inc/fingerprintx) 进行 51 种协议的服务指纹识别(SSH、HTTP、MySQL、Redis、RDP、PostgreSQL 等) - 技术检测(Wappalyzer)和 CPE 生成 - TLS 证书检查(版本、密码套件、主题、颁发者、SAN、过期时间、自签名) - 通过 `--tls-verify` 进行可选的严格 TLS 证书验证 - 通过 NVD API 按 CPE 查询 CVE - 主机发现(TCP 探测以跳过死主机) - 通过 10 个无需密钥的来源进行被动子域枚举(crt.sh、Common Crawl、Wayback Machine、RapidDNS、Anubis、Digitorus、HudsonRock、SiteDossier、THC、ThreatCrowd) - CDN 检测(Cloudflare)—— 默认情况下在 CDN 主机上仅扫描端口 80/443 - DNS 枚举,支持通配符检测和自定义字典/解析器 - 通过 `CLOUDFLARE_API_TOKEN` 进行基于 Cloudflare Zone 的目标发现 - 通过标准 AWS SDK 凭证链或 `--aws-profile` 进行 AWS 资产发现 - NS、MX、TXT、CNAME 记录查询 - 支持 CIDR 和标准输入 - nmap top 100/1000 端口列表,以及扩展的 2000/5000 预设 - 扫描检查点和恢复 - 针对大规模运行的扫描防护(`max_targets`、`max_ports_per_target`、`max_duration`) - 进度报告 - 通过 `--udp` 进行 UDP 服务检测(DNS、NTP、SNMP、IPSEC) - 通过 `--crawl` 进行带有应用指纹识别的 Web 爬虫(基于路径、Header 和 Cookie 检测 60 多种 CMS、框架和管理工具) - 针对云/管理/数据层面的默认深度产品指纹识别,例如 Kubernetes、Grafana、Vault、Elasticsearch、PostgreSQL、Redis、LDAP、SMB、GraphQL、OpenVPN 和 IPsec - 上下文感知的速率限制和 TLS 检查 —— 在 Ctrl+C 时干净关闭 - 在 SIGINT/SIGTERM 时优雅关闭 - 通过 [Together API](https://together.ai) 进行 AI 驱动的安全分析(`Qwen/Qwen3.5-9B`)—— 每次扫描提供简要摘要,使用 `--analyze` 提供详细报告 - 带有 TTY 检测的精美流式 CLI 输出(管道传输时为 JSONL) - 每次运行的扫描元数据报告(`scan-metadata-*.json`),用于审计 - JSON、JSONL(流式)、CSV 和文本输出 - 域模式输出保留子域和 IP 上下文(`hostname (ip):port`) - 安全 Header 检查在 `2xx/3xx` HTTP 响应上进行评估;`4xx/5xx` 响应报告为已跳过 - 可通过 YAML 配置 ## 架构 ![Flan Scan Runtime](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/615666de94021141.png) ## 安装 从 GitHub 安装: ``` go install github.com/therandomsecurityguy/flan-go-scan/cmd/flan@latest ``` 从源码安装(go 版本 > 1.21): ``` git clone git@github.com:therandomsecurityguy/flan-go-scan.git cd flan-go-scan go build -o flan ./cmd/flan ./flan --help ``` Docker: ``` git clone git@github.com:therandomsecurityguy/flan-go-scan.git cd flan-go-scan docker build -t flan . docker run --rm flan --help docker run --rm flan -t scanme.nmap.org --json ``` ## 用法 ``` flan --help ``` 扫描单个目标: ``` flan -t scanme.nmap.org ``` 扫描一个域(DNS 枚举 + 端口扫描): ``` flan -d example.com ``` 从文件扫描 top 1000 端口: ``` flan -l targets.txt --top-ports 1000 ``` 直接对已开放的端点进行指纹识别: ``` flan -t scanme.nmap.org:22 --fingerprint-only ``` 直接对已知的数据库或服务端点进行指纹识别: ``` flan -t 10.0.0.15:5432 --fingerprint-only ``` 针对常见控制平面和管理层面的高信噪比平台指纹会自动显示,包括 `Kubernetes`、`Grafana`、`Vault`、`Artifactory`、`Elasticsearch`、`Consul`、`Prometheus`、`TeamCity` 和 `etcd`。 从标准输入扫描 CIDR 范围: ``` echo "10.0.0.0/24" | flan -l - ``` 使用自定义字典和解析器扫描: ``` flan -d example.com -w wordlist.txt -r 8.8.8.8:53 ``` 仅被动枚举(跳过暴力破解): ``` flan -d example.com --passive-only ``` 仅输出子域(subfinder 风格,每行一个): ``` flan -d example.com --subdomains-only ``` 域扫描端口配置: ``` flan -d example.com --subdomain-ports web ``` 调整被动枚举来源/设置: ``` flan -d example.com --subfinder-all --subfinder-max-time 10 --subfinder-threads 20 ``` 扫描 CDN 主机上的所有端口(默认仅 80/443): ``` flan -d example.com --scan-cdn ``` 从 Cloudflare Zone 发现扫描目标: ``` flan --cloudflare --cloudflare-zones example.net --cloudflare-include api.example.net ``` 将 Cloudflare 发现限制为匹配的主机名: ``` flan --cloudflare --cloudflare-zones example.net --cloudflare-include "api.example.net" --cloudflare-exclude "internal.example.net" ``` 仅打印 Cloudflare 发现的主机名: ``` flan --cloudflare --cloudflare-zones example.net --cloudflare-include "api.example.net" --subdomains-only ``` 从 AWS 发现扫描目标: ``` AWS_PROFILE= flan --aws --aws-regions us-west-2 ``` 仅打印 AWS 发现的目标: ``` AWS_PROFILE= flan --aws --aws-regions us-west-2 --subdomains-only ``` 写入标准化的 AWS 清单快照以便后续比对: ``` AWS_PROFILE= flan --aws --aws-regions us-west-2 --aws-inventory-out reports/aws-inventory.json ``` 当存在之前的快照时,仅扫描新增或更改的 AWS 目标: ``` AWS_PROFILE= flan --aws --aws-regions us-west-2 --aws-inventory-out reports/aws-inventory.json --aws-delta-only ``` 从 kubeconfig 验证 Kubernetes 访问: ``` flan --kubeconfig ~/.kube/config --kube-context prod-cluster ``` 从已验证的集群枚举外部可访问的 Kubernetes 资源并扫描它们: ``` flan --kubeconfig ~/.kube/config --kube-context prod-cluster --kube-inventory ``` 写入标准化的 Kubernetes 清单快照以便后续比对: ``` flan --kubeconfig ~/.kube/config --kube-context prod-cluster --kube-inventory --kube-inventory-out reports/kubernetes-inventory.json ``` 当存在之前的快照时,仅扫描新增或更改的 Kubernetes 资源: ``` flan --kubeconfig ~/.kube/config --kube-context prod-cluster --kube-inventory --kube-inventory-out reports/kubernetes-inventory.json --kube-delta-only ``` 写入标准化的 Cloudflare 清单快照以便后续比对: ``` flan --cloudflare --cloudflare-zones example.net --cloudflare-include "api.example.net" --cloudflare-inventory-out reports/cloudflare-example-net.json ``` 将当前的 Cloudflare 清单与之前的快照进行比对: ``` flan --cloudflare --cloudflare-zones example.net --cloudflare-include "api.example.net" --cloudflare-inventory-out reports/cloudflare-example-net.json --cloudflare-diff-against reports/cloudflare-example-net-prev.json ``` 当存在之前的快照时,仅扫描新增/更改的 Cloudflare 主机: ``` flan --cloudflare --cloudflare-zones example.net --cloudflare-include "api.example.net" --cloudflare-inventory-out reports/cloudflare-example-net.json --cloudflare-delta-only ``` 启用 UDP 扫描: ``` flan -t scanme.nmap.org --udp ``` 爬取 HTTP/HTTPS 服务以查找端点、敏感路径和应用指纹: ``` flan -t example.com --crawl ``` 运行正常扫描并让 Flan 自动显示更深层的产品指纹: ``` flan -t api.example.com ``` 使用自定义深度进行爬取: ``` flan -t example.com --crawl --crawl-depth 3 ``` 使用详细的 AI 驱动分析进行扫描(需要 `TOGETHER_API_KEY`): ``` flan -t scanme.nmap.org --analyze ``` 使用自定义资产上下文文件进行策略感知的 AI 分析: ``` flan -t api.example.com --context /path/to/context.yaml ``` ## 运行时行为 Flan 使用确定性的解析器链:如果提供了自定义解析器则使用它,否则使用系统解析器,然后是配置的后备解析器。解析器和缓存统计信息会记录在扫描元数据中。 ``` scan: rate_limit: 200 workers: 100 max_host_conns: 0 max_targets: 5000 max_ports_per_target: 5000 max_duration: 30m dns: resolver: "" fallback_resolvers: ["1.1.1.1:53", "8.8.8.8:53"] lookup_timeout: 3s ``` 使用 `--workers`、`--rate-limit` 和 `--max-host-conns` 来调整扫描并发性,使大规模清单支持的运行对共享目标和负载均衡服务更加温和。 ### 控制平面与发现 ![Flan Control Plane And Discovery](https://static.pigsec.cn/wp-content/uploads/repos/2026/04/52b1ccad48021143.png) ### Cloudflare 发现 Cloudflare 发现是基于 Zone 的。它保留 `A`、`AAAA` 和 `CNAME` 扫描候选,默认跳过验证、通配符和非公网 IP 记录。它可以持久化标准化的清单快照,在运行之间进行比对,并可选择将扫描范围缩小到新增或更改的主机。如果省略了 `--cloudflare-diff-against` 但设置了 `--cloudflare-inventory-out`,Flan 将重用清单输出路径作为比对基准。 ``` cloudflare: enabled: false zones: [] include: [] exclude: [] token_env: CLOUDFLARE_API_TOKEN timeout: 15s inventory_out: "" diff_against: "" delta_only: false ``` ``` GitHub Actions: set CLOUDFLARE_API_TOKEN as a repository secret. Optional scope inputs: CLOUDFLARE_ZONES, CLOUDFLARE_INCLUDE, CLOUDFLARE_EXCLUDE, CLOUDFLARE_TOP_PORTS. ``` ### AWS 发现 AWS 发现是以清单为先的。它从 `Route53`、`EC2`、`ELB/ELBv2`、`CloudFront`、`API Gateway`、`Lightsail`、`EKS`、`Lambda` 函数 URL 和 S3 网站端点收集公共扫描目标。它可以持久化标准化的清单快照,在运行之间进行比对,并可选择将扫描范围缩小到新增或更改的目标。如果省略了 `--aws-diff-against` 但设置了 `--aws-inventory-out`,Flan 将重用清单输出路径作为比对基准。 ``` aws: enabled: false profile: "" regions: [] include: [] exclude: [] timeout: 15s inventory_out: "" diff_against: "" delta_only: false ``` ``` Authentication uses the standard AWS SDK credential chain. Common options: AWS_PROFILE=, aws sso login, or environment credentials. ``` ### Kubernetes 访问 Kubernetes kubeconfig 支持是显式的。Flan 可以通过 API 服务器 `/version` 端点验证集群访问,或者在启用 `--kube-inventory` 时从已验证的集群访问中枚举外部相关资源。当前的清单阶段专注于 API 服务器元数据、`Ingress` 资源、`LoadBalancer` 服务和外部可访问的 `NodePort` 服务。Kubernetes 衍生的扫描结果会将集群、命名空间、资源种类和暴露元数据带入输出和 AI 摘要中。 ``` kubernetes: enabled: false inventory: false kubeconfig: "" context: "" timeout: 10s inventory_out: "" diff_against: "" delta_only: false ``` ``` Path resolution order when Kubernetes mode is enabled: --kubeconfig, config file, KUBECONFIG, then ~/.kube/config. Use --kube-context when the kubeconfig contains multiple contexts. Use --kube-inventory to turn authenticated cluster access into scan targets. If --kube-diff-against is omitted but --kube-inventory-out is set, Flan reuses the inventory output path as the diff base. ``` ## 标志 | 标志 | 描述 | |------|-------------| | `-t` | 目标主机/IP | | `-l` | 目标文件(默认 `ips.txt`,`-` 表示标准输入) | | `-d` | 通过 DNS 枚举的域 | | `-p` | 要扫描的端口 | | `--top-ports` | 使用常用端口配置:`100`、`1000`、`2000` 或 `5000` | | `--subdomain-ports` | 域模式端口配置:`web`、`standard` 或 `full` | | `-c` | 配置文件(默认 `config/config.yaml`) | | `--workers` | 并发扫描工作线程数 | | `--rate-limit` | 全局每秒扫描请求数 | | `--max-host-conns` | 每个主机 IP 的最大并发扫描连接数(`0` 表示禁用) | | `--fingerprint-only` | 将手动输入视为 `host:port` 目标并跳过主机发现 | | `-w` | 自定义 DNS 子域字典 | | `-r` | 自定义 DNS 解析器(ip:port) | | `--cloudflare` | 从 Cloudflare Zone DNS 记录中发现扫描目标 | | `--cloudflare-zones` | 逗号分隔的 Cloudflare Zone 过滤器 | | `--cloudflare-include` | 逗号分隔的主机名包含过滤器 | | `--cloudflare-exclude` | 逗号分隔的主机名排除过滤器 | | `--cloudflare-inventory-out` | 将标准化的 Cloudflare 清单快照写入此路径 | | `--cloudflare-diff-against` | 将当前的 Cloudflare 清单与之前的快照进行比较;省略时默认为 `--cloudflare-inventory-out` | | `--cloudflare-delta-only` | 当存在之前的快照时,仅扫描新增/更改的 Cloudflare 主机 | | `--aws` | 从 AWS 资产中发现扫描目标 | | `--aws-profile` | 要使用的 AWS 共享配置配置文件 | | `--aws-regions` | 逗号分隔的 AWS 区域过滤器 | | `--aws-include` | 逗号分隔的 AWS 目标包含过滤器 | | `--aws-exclude` | 逗号分隔的 AWS 目标排除过滤器 | | `--aws-inventory-out` | 将标准化的 AWS 清单快照写入此路径 | | `--aws-diff-against` | 将当前的 AWS 清单与之前的快照进行比较;省略时默认为 `--aws-inventory-out` | | `--aws-delta-only` | 当存在之前的快照时,仅扫描新增/更改的 AWS 目标 | | `--kubeconfig` | 用于 Kubernetes 验证的 kubeconfig 路径 | | `--kube-context` | 可选的 kubeconfig 上下文 | | `--kube-inventory` | 从选定集群枚举外部可访问的 Kubernetes 资源 | | `--kube-inventory-out` | 将标准化的 Kubernetes 清单快照写入此路径 | | `--kube-diff-against` | 将当前的 Kubernetes 清单与之前的快照进行比较;省略时默认为 `--kube-inventory-out` | | `--kube-delta-only` | 当存在之前的快照时,仅扫描新增/更改的 Kubernetes 资源 | | `--passive-only` | 跳过暴力破解,仅使用被动来源 | | `--subdomains-only` | 打印发现的子域并退出(不进行端口扫描) | | `--subfinder-sources` | 逗号分隔的被动来源覆盖 | | `--subfinder-exclude-sources` | 逗号分隔的要排除的被动来源 | | `--subfinder-all` | 使用所有 subfinder 被动来源 | | `--subfinder-recursive` | 仅使用支持递归的被动来源 | | `--subfinder-max-time` | 最大枚举时间(分钟) | | `--subfinder-rate-limit` | 被动枚举 HTTP 请求/秒 | | `--subfinder-threads` | 被动枚举线程数 | | `--subfinder-provider-config` | subfinder 提供者配置路径 | | `--scan-cdn` | 扫描 CDN 主机上的所有端口(默认:仅 80/443) | | `--udp` | 启用 UDP 扫描(默认端口 53、123、161、500) | | `--crawl` | 爬取 HTTP/HTTPS 服务以查找端点、敏感路径和应用指纹 | | `--crawl-depth` | 最大爬取深度(默认:2) | | `--tls-enum` | 枚举支持的 TLS 版本和密码套件(每个 TLS 端口约 60 个连接,默认关闭) | | `--tls-verify` | 验证 TLS 证书以进行 TLS 检查、爬取、Header 探测和 TLS 枚举 | | `--context` | 资产上下文 YAML 文件(如果存在则自动加载 `config/context.yaml`) | | `--analyze` | 通过 Together API 进行详细的 AI 安全分析(需要 `TOGETHER_API_KEY`) | | `--json` | JSON 输出 | | `--jsonl` | JSONL 流式输出 | | `--csv` | CSV 输出 | ## 测试 ``` go test ./... -v ``` ## 许可证 BSD 3-Clause License
标签:AWS资产, C2日志可视化, CDN检测, Cloudflare, CPE生成, CVE查询, DNS枚举, Go语言, GraphQL安全矩阵, MITRE ATT&CK, TLS证书, Web爬虫, 二进制发布, 域名枚举, 多线程扫描, 子域名枚举, 子域名突变, 安全扫描器, 开源工具, 技术栈识别, 指纹识别, 数据统计, 日志审计, 服务发现, 程序破解, 端口扫描, 系统安全, 网络安全, 网络安全工具, 网络工具, 请求拦截, 隐私保护