umutcamliyurt/PortTripper
GitHub: umutcamliyurt/PortTripper
PortTripper 是一个通过绑定大量随机虚假端口来干扰网络指纹识别扫描的蜜罐工具。
Stars: 2 | Forks: 0
# PortTripper
一个绑定大量虚假 TCP 和 UDP 端口的蜜罐,旨在干扰网络指纹识别。运行 `nmap` 或类似工具的攻击者会看到数千个开放端口,从而难以识别真实的服务。
## 工作原理
在启动时,PortTripper 会:
1. 扫描配置的端口范围,并构建已被真实服务占用的端口白名单(仅在首次运行时执行)。
2. 从该范围中排除白名单端口,提取最多 `-maxports` 个加密随机端口样本。使用 `crypto/rand` 进行选择意味着,即使攻击者知道配置的端口范围,开放端口集也是不可预测的。
3. 在每个选定的端口上绑定 TCP 和 UDP 监听器。
4. 在 TCP 上:接受连接,将其保持一段可配置的时间,然后断开,以此消耗扫描器的线程和文件描述符。
5. 在 UDP 上:读取并丢弃数据报而不作回复,因此对扫描器而言,这些端口显示为 `open|filtered` 而不是 `closed`。
所有真实的服务端口都不会受到干扰,因为它们在 PortTripper 启动之前就已经被绑定,并且自动生成的白名单会指示 PortTripper 跳过它们。
## 环境要求
- Go 1.21 或更高版本
- Linux(或任何 Unix 系统)。仅当 `-startport` 低于 1024 时,才需要以 root 身份或使用 `CAP_NET_BIND_SERVICE` 运行。
## 构建
```
go build -o PortTripper main.go
```
## 快速开始
```
# 首次运行:PortTripper 扫描已绑定端口,写入 whitelist.txt,然后启动。
sudo ./PortTripper
# 后续运行:whitelist.txt 已存在,跳过扫描。
sudo ./PortTripper
```
首次运行时你会看到:
```
[INFO] first run: scanning for already-bound ports range=1024-65000
[INFO] first run: whitelist written with currently-bound ports file=whitelist.txt
[INFO] whitelist loaded file=whitelist.txt ports=8
[INFO] port range exceeds max; binding a random subset range_size=63977 max_ports=1024 selected=1024
[INFO] all listeners started bound=2048 skipped=8 failed=0
```
## 参数标志
| 标志 | 默认值 | 描述 |
|------|---------|-------------|
| `-portfile` | `whitelist.txt` | 白名单文件路径 |
| `-startport` | `1024` | 要绑定的第一个(最小的)端口 |
| `-endport` | `65000` | 要绑定的最后一个(最大的)端口 |
| `-maxports` | `1024` | 最大绑定端口数;如果候选范围较大,则会选择一个加密随机子集。设置为 `0` 可绑定整个范围(不推荐,请参阅资源使用情况) |
| `-hold` | `2` | 关闭前保持 TCP 连接打开的秒数 |
| `-udp` | `true` | 除 TCP 外还绑定 UDP 端口;使用 `-udp=false` 禁用 |
| `-maxconns` | `10000` | 同时连接的全局上限 |
| `-maxconns-per-ip` | `64` | 来自单个源 IP 的同时 TCP 连接上限 |
| `-ratelimit` | `5` | 来自单个源 IP 的每秒新 TCP 连接最大数 |
| `-global-rate` | `5000` | 所有端口合并计算的每秒新连接的硬性上限 |
| `-drain-bytes` | `0` | 保持连接前每个 TCP 连接要读取并丢弃的字节数(0 = 无) |
| `-metrics` | _(关闭)_ | Prometheus `/metrics` 端点的地址,例如 `127.0.0.1:9100` |
| `-jsonlog` | `false` | 输出换行符分隔的 JSON 日志行,而不是纯文本 |
| `-verbose` | `false` | 打印调试级别的日志行(绑定失败、跳过的端口等) |
```
# 示例:覆盖端口 1024–65000,保持连接 5 秒,导出 metrics
sudo ./PortTripper -hold 5 -metrics 127.0.0.1:9100
# 绑定更多端口以扩大覆盖范围(消耗更多 file descriptors)
sudo ./PortTripper -maxports 4096
# 绑定整个范围(要求 ulimit -n 262144 或更高)
sudo ./PortTripper -maxports 0
# 禁用 UDP 以将 socket 和 goroutine 数量减半
sudo ./PortTripper -udp=false
# 使用自定义 whitelist 路径
sudo ./PortTripper -portfile /etc/PortTripper/whitelist.txt
```
## 白名单文件
`whitelist.txt` 是在首次运行时通过探测哪些端口已被绑定而自动创建的。每个无法绑定的端口(已在使用中、权限被拒绝等)都会被添加到列表中,这样 PortTripper 就永远不会与真实服务发生冲突。
你可以随时自由编辑该文件。重启 PortTripper 以使更改生效。
```
# PortTripper – 端口 whitelist(首次运行时自动生成)
# 以下端口在启动时已被其他进程绑定。
# 可自由编辑:以 '#' 开头的行和空行将被忽略。
22
80
443
5432
```
要从头重新生成白名单,请删除该文件并重启 PortTripper。
## 日志记录
### 纯文本(默认)
```
2026-01-15T09:12:03Z [INFO] connection src=203.0.113.42 port=4444 proto=tcp
2026-01-15T09:12:05Z [WARN] rate limit exceeded src=203.0.113.42 port=9999
```
### JSON (`-jsonlog`)
```
{"level":"INFO","msg":"connection","port":4444,"proto":"tcp","src":"203.0.113.42","ts":"2026-01-15T09:12:03.112Z"}
{"level":"WARN","msg":"rate limit exceeded","port":9999,"src":"203.0.113.42","ts":"2026-01-15T09:12:05.004Z"}
```
JSON 输出旨在直接导入 Splunk、Loki、Datadog 或任何接收换行符分隔 JSON 的 SIEM 中。
## Prometheus 指标
使用 `-metrics 127.0.0.1:9100` 启动,以 Prometheus 文本格式公开 `/metrics` 端点:
```
PortTripper_connections_total 48291
PortTripper_connections_rejected_total 312
PortTripper_connections_active 7
PortTripper_global_throttled_total 45
PortTripper_perip_throttled_total 18
PortTripper_ports_bound 2048
PortTripper_ports_failed 0
PortTripper_ports_skipped 8
```
| 指标 | 类型 | 描述 |
|--------|------|-------------|
| `PortTripper_connections_total` | counter | 接受的连接总数 |
| `PortTripper_connections_rejected_total` | counter | 拒绝的连接总数(所有原因) |
| `PortTripper_connections_active` | gauge | 当前同时连接数 |
| `PortTripper_global_throttled_total` | counter | 因全局速率上限 (`-global-rate`) 而丢弃的连接数 |
| `PortTripper_perip_throttled_total` | counter | 因单 IP 同时连接上限 (`-maxconns-per-ip`) 而丢弃的连接数 |
| `PortTripper_ports_bound` | gauge | 成功绑定的端口数 |
| `PortTripper_ports_failed` | gauge | 绑定失败的端口数 |
| `PortTripper_ports_skipped` | gauge | 跳过的白名单端口数 |
在 Alertmanager 中添加的一个实用警报:
```
- alert: PortTripperScanSpike
expr: rate(PortTripper_connections_total[1m]) > 500
for: 30s
annotations:
summary: "High connection rate on honeypot ports, possible active scan!"
```
## 资源使用情况
在默认的 `-maxports 1024` 且启用 UDP 的情况下,PortTripper 大约持有 **2,048 个开放的 socket**(每个选定的端口一个 TCP + 一个 UDP)和 **约 2,048 个空闲的 goroutine**(每个监听器一个接受循环)。测得的稳态 RSS 大约为 **15–20 MB**。
资源消耗随绑定的端口数量呈线性增长:
| `-maxports` | Sockets (TCP+UDP) | 空闲 goroutine 数 | 预估 RSS |
|-------------|-------------------|-----------------|-------------|
| 512 | ~1,024 | ~1,024 | ~12 MB |
| 1,024 _(默认)_ | ~2,048 | ~2,048 | ~20 MB |
| 4,096 | ~8,192 | ~8,192 | ~50 MB |
| 0 (完整范围) | ~128,000 | ~128,000 | ~250 MB |
全局连接上限 (`-maxconns`) 可防止在不论端口数量多少的情况下,因泛洪攻击而导致的内存增长。
在部署前检查文件描述符限制:
```
ulimit -n # soft limit (usually 1024 for interactive shells)
cat /proc/sys/fs/file-max # system-wide hard limit
```
对于生产环境,在启动 PortTripper 之前请提高该限制:
```
ulimit -n 262144
```
## 安全考量
- PortTripper 是一个诱骗工具,而不是防火墙。请将其与 `iptables`/`nftables` 和适当的网络隔离结合使用,而不是替代它们。
- 端口选择使用 `crypto/rand`(操作系统熵池),因此即使攻击者知道配置的范围和白名单,开放端口集对他们来说也是不可预测的。
- `-ratelimit` 限制每个源 IP 每秒的新 TCP 连接数。`-maxconns-per-ip` 限制单个 IP 的同时 TCP 连接总数。`-global-rate` 限制所有端口每秒的新连接总数。请根据预期流量调整这三项参数。
- 日志行包含源 IP。将它们输入到 SIEM 或 fail2ban 中,以便自动对扫描器 IP 采取行动。
- 将 `-metrics` 绑定到 `127.0.0.1`(或私有网络接口),绝不要绑定到 `0.0.0.0`。该指标端点未经身份验证。
- 不要将 PortTripper 运行在与任何真实服务相同的端口上。如有疑问,请在调整白名单之前检查 `ss -tlnp`。
## 许可证
基于 **Apache 2.0 License** 分发,完整条款请参阅 [`LICENSE`](LICENSE)。
标签:EVTX分析, Go, Ruby工具, TLS, 密码管理, 插件系统, 日志审计, 网络安全, 自定义请求头, 蜜罐, 证书利用, 防御工具, 隐私保护