
# LanLens
**自托管网络监控与文档仪表板**
[](https://github.com/AlexRosbach/LanLens)
[](LICENSE)
[](https://hub.docker.com/r/alexrosbach/lanlens)
LanLens 扫描本地网络,通过 MAC/IP 识别设备,并提供一个简洁的 Web UI 用于记录、分类和连接设备。
## 功能特性
- 通过 ARP 扫描自动发现局域网
- 设备分类与离线 MAC 厂商查询
- DHCP 徽章检测
- 带颜色、范围和 IP 使用情况的网段
- 每台设备的文档字段
- 每台设备的服务清单
- 一键连接操作(SSH、RDP、HTTP、HTTPS)
- 通过 nmap 进行端口扫描
- **深度扫描**:通过 SSH(Linux)和 WinRM(Windows)进行——硬件、操作系统、服务、容器、虚拟机清单
- **加密凭证保险库**:用于 SSH 和 WinRM 访问(Fernet,密钥由 `SECRET_KEY` 派生)
- **虚拟机智能**:检测 Proxmox、KVM 和 Hyper-V 主机;枚举虚拟机;映射虚拟机到已知设备
- **自动深度扫描**:按设备计划扫描,可配置间隔
- Telegram 新设备与更新通知
- 英文、德文、意大利文界面
- 适用于桌面和移动端的响应式仪表板
## 截图
| 仪表板 | 设备详情 |
|---|---|
|  |  |
| 网段 | 设备文档 |
|---|---|
|  |  |
## 快速开始
### 要求
- Docker 20.10+ 并启用 `docker compose`
- 建议在 Linux 主机上运行以支持原始 ARP 扫描(`network_mode: host`)
### 1. 获取 compose 文件
```
curl -O https://raw.githubusercontent.com/AlexRosbach/LanLens/main/docker-compose.yml
```
### 2. 生成密钥
```
python3 -c "import secrets; print(secrets.token_hex(32))"
```
在 `docker-compose.yml` 中将 `CHANGE_THIS_TO_A_LONG_RANDOM_STRING` 替换为生成的值。
### 3. 可选:选择 HTTP 端口
在 `docker-compose.yml` 中可以修改:
```
- LANLENS_PORT=7765
```
示例:
- `LANLENS_PORT=80` 用于主机模式下的 80 端口直连
- `LANLENS_PORT=8080` 用于 8080 端口
### 4. 启动 LanLens
```
docker compose up -d
```
### 5. 打开 UI
访问:
```
http://
:
```
默认凭据:
```
admin / admin
```
首次登录时将被强制更改密码。
## 配置
### 环境变量
| 变量 | 默认值 | 说明 |
|---|---|---|
| `SECRET_KEY` | — | 必需,至少 32 个随机字符 |
| `DEFAULT_ADMIN_PASSWORD` | `admin` | 初始管理员密码 |
| `LANLENS_PORT` | `7765` | nginx 暴露的 HTTP 端口,也可在主机模式下使用 |
| `BACKEND_PORT` | `17765` | 后端 FastAPI 端口,位于 nginx 后方 |
| `DB_PATH` | `/data/lanlens.db` | SQLite 数据库路径 |
| `TZ` | `UTC` | 容器时区 |
### DHCP 标记与扫描范围
在 **设置 → 网络** 中,LanLens 现在将这两者分离:
- **DHCP 范围**:仅用于 DHCP 标记/分类
- **扫描范围**:用于活动的 ARP 网络扫描
- **扫描间隔**:控制计划扫描频率
说明:
- 未设置显式扫描范围时,LanLens 会自动检测主机子网作为默认扫描范围。
- 配置的 `扫描起始` 和 `扫描结束` 定义实际的 IPv4 扫描范围,因此支持直接可达本地网络内的更大范围。
- ARP 扫描仅在本地可达的第 2 层网络直接有效。输入另一个 IP 范围不会自动到达路由后的远程子网。
### Telegram
在 **设置 → 通知** 中配置 Telegram:
- Bot 令牌
- 聊天 ID
- 可选测试消息
## 使用 MariaDB / 外部数据库
默认情况下,LanLens 使用 **SQLite**,数据存储在 `/data/lanlens.db` 中。对于生产环境或需要共享数据库访问的场景,可以切换到 **MariaDB** 或 **MySQL**。
### 要求
在容器中安装 `PyMySQL` 驱动:
```
RUN pip install PyMySQL
```
或添加到 `requirements.txt`:
```
PyMySQL>=1.1.0
```
### docker-compose 配置
```
services:
lanlens:
image: ghcr.io/alexrosbach/lanlens:latest
environment:
DATABASE_URL: mysql+pymysql://lanlens:yourpassword@mariadb:3306/lanlens
SECRET_KEY: your-secret-key-here
depends_on:
- mariadb
mariadb:
image: mariadb:11
environment:
MYSQL_ROOT_PASSWORD: rootpassword
MYSQL_DATABASE: lanlens
MYSQL_USER: lanlens
MYSQL_PASSWORD: yourpassword
volumes:
- mariadb_data:/var/lib/mysql
volumes:
mariadb_data:
```
### 连接字符串格式
| 数据库 | 格式 |
|------------|--------|
| MariaDB/MySQL | `mysql+pymysql://user:pass@host:3306/dbname` |
| PostgreSQL | `postgresql+psycopg2://user:pass@host:5432/dbname` |
| SQLite(默认) | 通过 `DB_PATH` 环境变量设置,而非 `DATABASE_URL` |
### 备份
使用 MariaDB 时,请使用 `mysqldump` 进行备份:
```
mysqldump -u lanlens -p lanlens > lanlens-backup.sql
```
恢复:
```
mysql -u lanlens -p lanlens < lanlens-backup.sql
```
## 深度扫描 — 所需权限
深度扫描通过 SSH(Linux)或 WinRM(Windows)连接设备并运行只读命令。
不会向目标系统写入任何数据。
### Linux SSH
建议使用**专用的非 root 用户**。该用户需要读取相关系统文件和命令的权限:
```
# 在目标 Linux 系统上创建专用的扫描用户
sudo useradd -m -s /bin/bash lanlens-scan
sudo passwd lanlens-scan
# 授予对所需命令的只读 sudo 访问权限(添加到 /etc/sudoers.d/lanlens)
cat <<'EOF' | sudo tee /etc/sudoers.d/lanlens
lanlens-scan ALL=(ALL) NOPASSWD: /usr/bin/lscpu, /usr/bin/free, /usr/bin/lsblk, \
/usr/bin/systemctl, /usr/bin/docker, /usr/bin/podman, \
/usr/sbin/virsh, /usr/sbin/qm, /usr/sbin/pct, /usr/bin/k3s
EOF
```
**每个配置文件的最小权限要求:**
| 配置文件 | 最小权限 |
|---|---|
| `hardware_only` | 读取 `/sys/class/dmi/id/` 和 `/proc` |
| `os_services` | + `systemctl` 读取权限 |
| `linux_container_host` | + `docker ps` / `podman ps` |
| `hypervisor_inventory` | + `virsh list`、`qm list`、`pct list`、`qm config`、`pct config` |
| `full` | 以上全部 |
对于 **Proxmox** 主机,扫描用户必须是 `kvm` 组的成员(或 root):
```
sudo usermod -aG kvm lanlens-scan
```
### Windows WinRM
必须在目标上启用 WinRM(Windows 远程管理):
```
# 以管理员身份在目标 Windows 系统上运行
Enable-PSRemoting -Force
# 允许从 LanLens 主机连接(替换为您的 LanLens 服务器 IP)
Set-Item WSMan:\localhost\Client\TrustedHosts -Value "YOUR_LANLENS_IP" -Force
```
**推荐账户:** 本地 **Administrators** 组或 **Remote Management Users** 组的成员。
在域环境中,拥有目标主机本地管理员权限的域账户即可。
```
# 将用户添加到远程管理用户(权限低于完全管理员)
Add-LocalGroupMember -Group "Remote Management Users" -Member "lanlens-scan"
# 某些 WMI 查询(许可、功能)需要本地管理员权限
Add-LocalGroupMember -Group "Administrators" -Member "lanlens-scan"
```
## 更新
```
docker compose pull
docker compose up -d
```
本地构建:
```
docker compose up -d --build
```
数据库迁移会在容器启动时自动运行。
## 发行版本
- Docker 镜像发布于 [`alexrosbach/lanlens`](https://hub.docker.com/r/alexrosbach/lanlens)
- GitHub 发行版本应用于基于发行的更新检查和 Telegram 更新通知
- 详细项目历史记录位于 [CHANGELOG.md](CHANGELOG.md)
## 密码重置
```
docker exec -it lanlens reset-password
```
非交互方式:
```
docker exec -it lanlens reset-password --password "MyNewPassword123"
```
## 开发
### 后端
```
python3 -m venv .venv && source .venv/bin/activate
pip install -r backend/requirements.txt
export SECRET_KEY=dev-secret-key-at-least-32-chars-long
export DB_PATH=./data/lanlens.db
mkdir -p data
python backend/cli/init_db.py
python backend/cli/init_admin.py
uvicorn backend.main:app --reload --port 8000
```
### 前端
```
cd frontend
npm install
npm run dev
```
## 架构
- **后端:** FastAPI、SQLAlchemy、SQLite、APScheduler
- **前端:** React、TypeScript、Tailwind、Vite
- **扫描:** scapy 和 nmap
- **通知:** Telegram Bot API
- **服务:** nginx + uvicorn(单容器)
## 版本控制与变更日志
LanLens 遵循 **语义化版本控制**。
- 当前应用版本显示在 UI 和 `GET /api/health` 中
- 项目历史记录维护在 [CHANGELOG.md]( 标签:ARPs扫描, Docker Compose, Docker容器, Docker 部署, Fernet, HTTP/HTTPS访问, Hyper-V, Hypervisor, IP地址, IP范围管理, KVM, MAC地址, Maven构建, Nmap, Proxmox, RDP连接, SSH深度扫描, SSH连接, Telegram通知, VPN连接, Web仪表盘, WinRM, 凭据保险库, 加密凭证存储, 响应式UI, 多语言界面, 安全运营中心, 局域网监控, 德文, 意大利文, 攻击面发现, 数据统计, 暗色主题, 服务清单, 测试用例, 深度扫描, 硬件清单, 移动适配, 端口扫描, 网络分段, 网络发现, 网络巡检, 网络文档, 网络映射, 网络监控平台, 网络资产盘点, 网络运维, 自动化攻击, 自托管, 自托管网络工具, 英文, 虚拟机发现, 虚拟驱动器, 设备台账, 设备文档, 设备识别, 请求拦截, 通知告警, 颜色标记