sartoopjj/thefeed

GitHub: sartoopjj/thefeed

基于 DNS 隧道的订阅阅读器与轻量级端到端加密即时通讯工具,专为仅有 DNS 查询可用的审查网络环境设计。

Stars: 1476 | Forks: 85

# thefeed 基于 DNS 的订阅阅读器 **及轻量级即时通讯工具**,专为仅有 DNS 查询能够正常工作的环境设计。阅读 Telegram 频道和公开的 X 账号,并与其他用户交换端到端加密的消息——所有这一切均通过 DNS 完成。 [English](README.md) | [فارسی](README-FA.md) | [简体中文](README-ZH.md) | [Русский](README-RU.md) ## 下载 - **最新版本** —— 包含适用于各平台的服务器/客户端二进制文件,以及 Android APK。请选择您可访问的镜像:[GitLab](https://gitlab.com/sartoopjj/thefeed/-/releases) / [GitHub](https://github.com/sartoopjj/thefeed/releases/latest)。 - **服务器一键安装脚本** (Linux + systemd) —— 请选择可用的镜像: # GitHub 镜像 sudo bash -c "$(curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh)" # GitLab 镜像 (在 GitHub 账号不可用时使用) sudo bash -c "$(curl -Ls https://gitlab.com/sartoopjj/thefeed/-/raw/main/scripts/install.sh)" -- --gitlab - **Android APK** (Android 7.0+):对于 2017 年之后推出的手机,请选择 `arm64-v8a`;对于较早的纯 32 位设备,请选择 `armeabi-v7a`。 - **iOS** (iOS 14+):App Store 版本正在计划中。源码位于 [ios/](ios/) —— 请参阅下方的 [iOS 开发](#ios-development)。 - **Windows** (10/11):该 `.exe` **未签名**,因此首次运行时 SmartScreen 会显示 *"Windows 已保护你的电脑"*,且 Defender 可能会将其隔离 —— 这是 DNS 隧道工具常见的误报,**并非恶意软件**。请点击 **更多信息 → 仍要运行**;如果文件被删除,请从 Defender → *保护历史记录* 中将其还原,如有疑问,请在发布页面核对 SHA-256。(未来计划引入代码签名以消除此警告。) 可用于测试的公开配置:[@thefeedconfig](https://t.me/thefeedconfig)。 ## 截图
Main feed
Main feed
Messenger
Messenger
Reading a post
Reading a post
Telemirror
Telemirror
Resolver scanner
Resolver scanner
Resolver bank
Resolver bank
Settings
Settings
## 工作原理 ``` Encrypted DNS TXT ┌──────────────┐ feed meta + small media ┌──────────────────┐ MTProto ┌──────────┐ │ │ ─────────────────────────▸ │ Server │ ─────────────▸ │ Telegram │ │ Client │ ◂───────────────────────── │ (DNS auth + │ ◂───────────── │ API │ │ (Web UI) │ │ media relays) │ RSS / HTTP ┌──────────┐ │ │ large media (fast relay) │ │ ─────────────▸ │ Nitter │ │ │ ◂───── api.github.com ◂── │ │ ◂───────────── │ (X feed) │ └──────────────┘ (uploaded by server) └──────────────────┘ └──────────┘ ``` **服务器**(运行在审查网络之外): - 连接到 Telegram,读取已配置频道的消息 - 通过兼容 RSS 的镜像获取公开的 X 帖子(无需登录) - 将订阅元数据和小型媒体作为加密的 DNS TXT 响应提供服务 - **媒体中继** —— 同一文件,多种分发路径: - **DNS 中继**(速度慢,抗审查)将字节拆分到多个 DNS 数据块中 - **GitHub 中继**(速度快,默认关闭)将字节上传到代码库,以便客户端通过普通 HTTPS 拉取;适用于对 DNS 而言过大的文件 - 未来的中继可以在不破坏旧客户端的情况下并列加入 - 对响应进行随机填充(抵抗 DPI) - **多域名** (`--extra-domains` / `THEFEED_EXTRA_DOMAINS`):服务器在主域名和任意数量的额外子域上响应订阅查询,客户端将数据块请求分散到所有域名上(负载分配 + 单个域名被封锁时的弹性)。主域名依然是中继路径的规范域名。导入 URI 通过 `d=` 字段携带额外域名。 - **即时通讯** (`--chat-domains` / `THEFEED_CHAT_DOMAINS`):在同一服务器的用户之间提供可选的存储转发即时通讯功能,在专用子域上提供服务 —— 参见 [即时通讯](#messenger) - 会话持久化 —— 登录一次,永久运行 - 无 Telegram 模式 (`--no-telegram`) —— 无需凭证即可读取公开频道 - 所有数据均存储在单一目录中 **客户端**(运行在受审查的网络内): - 基于浏览器的 Web UI,支持 RTL/波斯语(VazirMatn 字体) - 通过解析器池发送加密的 DNS TXT 查询 - **解析器池**:所有配置文件共享的 DNS 解析器集合。可以通过扫描器、导入或手动添加解析器,并自动进行评分 - **内置入门配置**:导入对话框提供现成的配置(附带预设的解析器),可一键导入 - **解析器评分**:每个解析器的成功率 + 延迟计分板,带有持久化分数;优先选择更健康的解析器。可以清理低分项目 - **分散模式**:将同一个 DNS 请求分发到多个解析器,并使用最快的响应(默认:2 个并发) - **支持中继的媒体下载** —— 当清单通告存在快速中继时,会优先选择快速中继;在遇到暂时性故障时会重试;在回退到较慢的 DNS 路径之前会先询问用户。每次下载都会校验哈希值和大小 - **即时通讯**:用户之间通过纯 DNS 发送的简短端到端加密消息 —— 送达状态标记 (✓/✓✓)、发送/接收进度、配额显示、仅限本地的联系人列表 - 向频道和私聊发送消息(需要服务器开启 `--allow-manage` 并登录 Telegram) - 频道管理(开启 `--allow-manage` 后,可通过管理员命令远程添加/移除频道) - **按频道自动更新**:置顶特定频道以进行定期后台刷新,按配置文件持久化保存 - 消息压缩 (deflate),实现高效传输 - Web UI 密码保护(客户端使用 `--password`) - 新消息指示器(频道列表的新消息徽章 + 聊天内的分隔线)、下次获取倒计时 - 频道类型徽章(私密/公开/X),具有不同的颜色 - 媒体类型检测(`[IMAGE]`、`[VIDEO]` 等)和内联渲染 - 浏览器中的实时 DNS 查询日志 ## 协议 所有通信均经过加密 (AES-256),并搭载于标准的 DNS TXT 查询/响应之上,采用可变填充和基于解析器的评分机制,使流量与正常的 DNS 活动融为一体。消息数据在加密前会先进行 deflate 压缩。 ## 图片和文件下载 带有照片、文件、GIF、音频和视频附件的消息可以缓存在服务器上,并通过同样加密的 DNS 通道进行下载。 服务器会下载每个附带的媒体文件(根据上游 ID 和内容哈希进行去重),将字节流推送到每个已启用的中继,并在消息文本中添加一个小型的元数据头: ``` [IMAGE]::::[:] optional caption ``` `` 是一个逗号分隔的列表,表示各中继的可用位(`1`=可用,`0`=不可用)。位 0 是 DNS,位 1 是 GitHub 中继;未来的中继将依次追加。旧版客户端会忽略它们不识别的位。 每个 DNS 缓存文件的第 0 块以一个 16 字节的协议头开始 —— 包含(解压后)内容的 4 字节 CRC32、1 字节版本号、1 字节压缩格式,以及保留给未来字段的 10 字节。客户端在交付任何字节之前,会对照预期值检查 CRC。其余字节根据压缩位进行解压。下载内容会缓存在客户端(IndexedDB,7 天)和本地的 thefeed-client 服务器上(`/media-cache/`,7 天)。并发下载数量受限,额外的点击会被加入队列。 ### 媒体中继 每个中继都是独立的 —— 同一个文件可以同时通过 DNS *和* GitHub *以及* 未来的中继提供服务。客户端会选择消息清单中通告的中继,并优先使用最快的可用中继;在失败时,它们会进行重试,然后在回退到较慢的中继之前先询问用户。每次下载都会校验哈希值和大小。 目前已提供两种中继: - **DNS 中继**(速度慢,默认关闭)。字节被拆分到 DNS 数据块中。能在受审查的网络中生存。默认上限:100 KB。 - **GitHub 中继**(速度快,默认关闭)。字节被上传到代码库,客户端通过纯 HTTPS 拉取。需要具有 `contents:write` 权限的 personal access token。文件位于 `//_` 路径下,因此多个部署可以共享同一个代码库。默认上限:15 MB。 每个 DNS 缓存文件的第 0 块以一个 16 字节的协议头开始 —— 包含(解压后)内容的 4 字节 CRC32、1 字节版本号、1 字节压缩格式,以及 10 个保留字节。其余字节根据压缩位进行解压。下载内容会缓存在客户端(IndexedDB,7 天)和本地的 thefeed-client 服务器上(`/media-cache/`,7 天)。并发下载数量受限,额外的点击会被加入队列。 服务器标志 / 环境变量: | 标志 | 环境变量 | 默认值 | 说明 | |-------------------------------|--------------------------------------|-------------|------------------------------------| | `--dns-media-enabled` | `THEFEED_DNS_MEDIA_ENABLED` | `false` | 切换 DNS 中继 | | `--dns-media-max-size` | `THEFEED_DNS_MEDIA_MAX_SIZE_KB` | `100` (KB) | 单个文件上限 | | `--dns-media-cache-ttl` | `THEFEED_DNS_MEDIA_CACHE_TTL_MIN` | `600` (分钟) | TTL | | `--dns-media-compression` | `THEFEED_DNS_MEDIA_COMPRESSION` | `gzip` | `none`、`gzip` 或 `deflate` | | `--github-relay-enabled` | `THEFEED_GITHUB_RELAY_ENABLED` | `false` | 切换 GitHub 中继 | | `--github-relay-token` | `THEFEED_GITHUB_RELAY_TOKEN` | — | PAT,`contents:write` | | `--github-relay-repo` | `THEFEED_GITHUB_RELAY_REPO` | — | `owner/repo` | | `--github-relay-branch` | `THEFEED_GITHUB_RELAY_BRANCH` | `main` | 提交中继对象的分支 | | `--github-relay-max-size` | `THEFEED_GITHUB_RELAY_MAX_SIZE_KB` | `15360` (KB) | 单个文件上限 | | `--github-relay-ttl` | `THEFEED_GITHUB_RELAY_TTL_MIN` | `600` (分钟) | 孤立文件在下次刷新周期被清理 | 每小时的 DNS 报告包含 `totalMediaQueries` 和一个 `mediaCache` 块(条目数、字节数、命中数、未命中数、驱逐数)。 ## 即时通讯 这是一个可选的、独立的存储转发式即时通讯工具,供同一服务器的用户之间使用(它不会与 Telegram 交互)。只需为服务器提供一个或多个专用子域(不同于订阅域名)即可启用: ``` thefeed-server ... --chat-domains c.example.com # 或者:THEFEED_CHAT_DOMAINS=c.example.com ``` - **端到端加密**:只有对话双方才能阅读消息 —— 服务器仅存储不透明的数据块,并在不读取任何内容的情况下验证发送者。联系人名称永远不会离开设备。 - **身份标识**:客户端在本地生成一个恢复码;您的地址是由其派生出的 20 个字符。通过带外方式分享您的地址以便他人联系您;同一个恢复码可在任何服务器上使用。 - **失败即关闭安全机制**:只有当配置固定了服务器密钥 (`sk=`) 并且服务器的聊天能力数据通过签名验证时,客户端才会启用聊天。订阅元数据中的签名位会通告该服务器支持聊天,因此*没有*密钥的客户端会提示“此服务器支持即时通讯——请使用其密钥重新导入配置”,而不是静默失败,而连接在不支持聊天的服务器上的客户端绝不会浪费探测请求。 - **在不移除域名的情况下关闭**:`--chat-enabled=false`(或 `THEFEED_CHAT_ENABLED=0`)会保留已配置的域名,但会通告聊天功能已禁用;客户端会显示“此服务器已禁用即时通讯”。 - **滥用限制**,自动向客户端通告:`--chat-send-per-hour` (30)、`--chat-inbox-cap` (50)、`--chat-per-pair-cap` (10)、`--chat-max-msg-bytes` (500)。未送达的消息将在 `--chat-ttl-hours` (72) 小时后过期。 - **默认保留账户** (`--chat-account-ttl-days 0`) 以确保报告准确;可以设置具体天数以在繁忙的服务器上回收闲置账户。`--chat-max-accounts` (0 = 不限制) 限制总账户数。 - **持久性与吞吐量的权衡** (`--chat-sync-seconds`,默认为 1):消息存储每 N 秒刷新到磁盘一次,因此崩溃可能会丢失最多约 N 秒刚接收到的消息(这是可接受的——聊天是端到端加密的,发送者会重新发送)。设置为 `0` 则在每条消息上执行 fsync,以在较低吞吐量下实现严格的持久性。 -客户端 UI 中,从底部导航栏打开 **聊天**。✓ = 已存储在服务器上,✓✓ = 已被接收方接收。在两台设备上匹配的安全表情符号可确认对话是安全的。 每小时的 DNS 报告包含 `totalChatQueries` 和一个 `chat` 块(账户数、消息数、注册数、会话数)。 ### 运营者报告 (TUI) 服务器会将每小时的报告作为一行 JSON 追加到 `/dns_hourly.jsonl` 中(按大小轮转,保留少量备份)。服务器二进制文件本身使用 `--report` 从该文件渲染出一个终端仪表板——它不会在网络上提供服务,仅读取数据目录: ``` thefeed-server --report # reads ./data/dns_hourly.jsonl + ./data/chat.db thefeed-server --data-dir /srv/thefeed --report thefeed-server --report --report-refresh 5s # live, redraw every 5s thefeed-server --report --report-from 2026-06-10 --report-to "2026-06-11 18:00" # only this UTC range ``` 它显示总计/频道获取/元数据/媒体/聊天查询、带条形图的各频道平均值、各域名总计、各报告迷你图、每小时查询分布,以及聊天统计信息(包括来自 `chat.db` 的实时账户数)——与 `scripts/thefeed_log_report.py` 聚合出的结果相同,并在终端中绘制出来。 ## 链接 - 我的 Telegram 频道:[@networkti](https://t.me/networkti) - 公开 TheFeed 配置:[@thefeedconfig](https://t.me/thefeedconfig) - TheFeed 服务器搭建指南:[@networkti](https://t.me/networkti/25) - 使用 SlipGate 搭建 TheFeed 服务器指南:[@networkti](https://t.me/networkti/200) - 路线图 / 任务看板:[GitHub 项目](https://github.com/users/sartoopjj/projects/1/views/1) ## 快速安装(服务器) 安装程序可以从 GitHub 或 GitLab 镜像获取二进制文件。 默认情况下,它会自动检测(先尝试 GitHub,如果失败则回退到 GitLab);当 GitHub 账号不可用时,传递 `--gitlab` 以强制使用 GitLab。 ``` # GitHub 镜像 sudo bash -c "$(curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh)" # GitLab 镜像 sudo bash -c "$(curl -Ls https://gitlab.com/sartoopjj/thefeed/-/raw/main/scripts/install.sh)" -- --gitlab ``` 或手动操作: ``` # 在你的服务器上(带有 systemd 的 Linux) curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh -o install.sh sudo bash install.sh # auto: GitHub, then GitLab fallback sudo bash install.sh --gitlab # force GitLab mirror sudo bash install.sh --source github ``` 该脚本将执行: 1. 从 GitHub 下载最新版本的二进制文件 2. 询问您的域名、密码、Telegram 频道和 X 账号 3. 询问是否使用 Telegram 登录(推荐:**否** —— 公开频道无需登录即可使用) 4. 如果是 Telegram 模式:询问 API 凭证并登录 5. 设置 systemd 服务 更新: ``` sudo bash -c "$(curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh)" ``` 安装特定版本(回滚、测试版或 rc 版): ``` # 回滚到已知正常的 tag curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --version v0.9.2 # 安装最新的预发布版本(beta / rc) curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --pre # 列出最近的版本(stable / pre-release 标签) curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --list ``` 简写形式:`-v ` 与 `--version ` 相同。旧版位置参数形式 `sudo bash install.sh v1.0.0` 依然有效。 重新登录:`curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --login` 显示配置(导入 URI —— 域名、密钥、`sk=` 服务器密钥、引导解析器):`curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --config` 卸载:`curl -Ls https://raw.githubusercontent.com/sartoopjj/thefeed/main/scripts/install.sh | sudo bash -s -- --uninstall` **如果出现问题 —— 立即移除重定向:** ``` # 移除 iptables 规则(恢复原始行为) sudo iptables -t nat -D PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300 sudo iptables -D INPUT -p udp --dport 5300 -j ACCEPT sudo netfilter-persistent save ``` ## Docker 部署(服务器) 使用 Docker 运行服务器 —— 无需 Go 工具链。 ### 快速开始(公开频道,无需登录 Telegram) ``` # 1. 配置环境 cp .env.example .env nano .env # set THEFEED_DOMAIN and THEFEED_KEY # 2. 使用你的频道准备数据目录 mkdir -p data cp configs/channels.txt data/ cp configs/x_accounts.txt data/ # optional # 3. 构建并运行 docker compose up -d # 4. 将外部 DNS 流量重定向到容器 # 将 eth0 替换为你的网络接口(使用以下命令检查:ip a) sudo iptables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300 sudo iptables -I INPUT -p udp --dport 5300 -j ACCEPT sudo ip6tables -t nat -I PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300 sudo ip6tables -I INPUT -p udp --dport 5300 -j ACCEPT # 使 iptables 规则在重启后保持持久 sudo apt install -y iptables-persistent sudo netfilter-persistent save # 5. 查看日志 docker compose logs -f ``` ### 配合 Telegram 使用(一次性交互式登录) ``` # 1. 配置环境(在 .env 中取消注释 Telegram 变量) cp .env.example .env nano .env # 2. 一次性登录(交互式——在提示时输入验证码) docker compose run -it --rm server \ --login-only --data-dir /data \ --domain YOUR_DOMAIN --key YOUR_KEY \ --api-id YOUR_API_ID --api-hash YOUR_HASH \ --phone YOUR_PHONE # 3. 编辑 docker-compose.yml:移除 --no-telegram 并添加 Telegram 标志 # 4. 启动服务器 docker compose up -d # 5. 设置 iptables 重定向(与快速入门第 4 步相同) ``` ### Docker 细节 | 项目 | 值 | |------|-------| | 基础镜像 | `alpine:3.21`(总计约 23 MB) | | 构建 | 多阶段 (`golang:1.26-alpine` → `alpine`) | | 用户 | `thefeed`(UID 1000,非 root) | | 容器端口 | `:5300/udp`(主机 `:5300/udp` + 从 `:53` 进行 iptables 重定向) | | 数据 | `./data` 数据卷(频道、会话、缓存) | | 配置 | `.env` 文件(被 git 忽略) | ``` # 代码更改后重新构建 docker compose build # 停止 docker compose down ``` ### 端口 53 和服务安全性 容器监听 **5300** 端口(而不是 53),以避免与主机上的 `systemd-resolved` 或其他 DNS 服务发生冲突。外部 DNS 流量通过 `iptables PREROUTING` 重定向,这仅影响到达外部网络接口的数据包 —— 本地 DNS 解析**不受影响**。 **在设置之前 —— 检查哪些程序占用了 53 端口:** ``` # 检查端口 53 是否被占用 ss -ulnp | grep ':53 ' # 预期:systemd-resolved 仅在 127.0.0.53 上(安全) # UNCONN 127.0.0.53%lo:53 users:(("systemd-resolve",...)) ``` **设置完成后 —— 验证没有发生故障:** ``` # 1. 本地 DNS 仍然正常工作(服务器可以解析域名) dig +short google.com @127.0.0.53 # 2. thefeed 容器正在运行 docker ps --filter name=thefeed # 3. thefeed 正在获取频道 docker logs thefeed-server --tail 5 # 4. iptables 规则处于活动状态 iptables -t nat -L PREROUTING -n | grep 5300 # 5. 其他容器运行正常 docker ps --format 'table {{.Names}}\t{{.Status}}' | head -10 ``` **如果出现问题 —— 立即移除重定向:** ``` # 移除 iptables 规则(恢复原始行为) sudo iptables -t nat -D PREROUTING -i eth0 -p udp --dport 53 -j REDIRECT --to-ports 5300 sudo iptables -D INPUT -p udp --dport 5300 -j ACCEPT sudo netfilter-persistent save ``` ## 手动设置 ### 前置条件 - Go 1.26+ - 一个拥有指向您服务器的 NS 记录的域名 - 来自 https://my.telegram.org 的 Telegram API 凭证(仅在您需要私密频道时使用) ### 服务器 ``` # 构建 make build-server # 首次运行:登录 Telegram 并保存会话 ./build/thefeed-server \ --login-only \ --data-dir ./data \ --domain t.example.com \ --key "your-secret-passphrase" \ --api-id 12345 \ --api-hash "your-api-hash" \ --phone "+1234567890" # 正常运行(使用数据目录中保存的会话) ./build/thefeed-server \ --data-dir ./data \ --domain t.example.com \ --key "your-secret-passphrase" \ --api-id 12345 \ --api-hash "your-api-hash" \ --phone "+1234567890" \ --listen ":53" ``` 所有数据文件(会话、频道、X 账号)都存储在 `--data-dir` 目录(默认:`./data`)中。 环境变量:`THEFEED_DOMAIN`、`THEFEED_KEY`、`THEFEED_MSG_LIMIT`、`THEFEED_FETCH_INTERVAL`、`THEFEED_ALLOW_MANAGE`(设置为 `0` 可强制禁用,即使该标志已硬编码到服务中)、`THEFEED_X_RSS_INSTANCES`、`TELEGRAM_API_ID`、`TELEGRAM_API_HASH`、`TELEGRAM_PHONE`、`TELEGRAM_PASSWORD` #### 服务器标志 | 标志 | 默认值 | 说明 | |------|---------|-------------| | `--data-dir` | `./data` | 用于频道、会话、配置的数据目录 | | `--domain` | | DNS 域名(必填) | | `--key` | | 加密密码短语(必填) | | `--channels` | `{data-dir}/channels.txt` | 频道列表文件路径 | | `--x-accounts` | `{data-dir}/x_accounts.txt` | X 用户名文件路径 | | `--x-rss-instances` | `https://nitter.net,http://nitter.net` | 逗号分隔的 X RSS 基础 URL | | `--api-id` | | Telegram API ID(必填) | | `--api-hash` | | Telegram API Hash(必填) | | `--phone` | | Telegram 手机号码(必填) | | `--session` | `{data-dir}/session.json` | Telegram 会话文件路径 | | `--login-only` | `false` | 认证至 Telegram,保存会话后退出 | | `--no-telegram` | `false` | 在不登录 Telegram 的情况下运行(仅限公开频道) | | `--listen` | `:5300` | DNS 监听地址 | | `--padding` | `32` | 最大随机填充字节数(0=禁用) | | `--msg-limit` | `15` | 每个 Telegram 频道获取的最大消息数 | | `--fetch-interval` | `10` | 获取周期间隔(分钟,最小为 3) | | `--allow-manage` | `false` | 允许远程发送/频道管理(默认:禁用) | | `--debug` | `false` | 记录每一个解码后的 DNS 查询 | | `--dns-media-enabled` | `false` | 通过 DNS 提供媒体服务(慢速中继) | | `--dns-media-max-size` | `100` | DNS 中继的单个文件上限(KB)(0 = 无上限) | | `--dns-media-cache-ttl` | `600` | DNS 中继 TTL,以分钟为单位 | | `--dns-media-compression` | `gzip` | DNS 中继压缩:`none`、`gzip` 或 `deflate` | | `--github-relay-enabled` | `false` | 通过 GitHub 快速中继提供媒体服务 | | `--github-relay-token` | | 具有 `contents:write` 权限的 PAT(或使用 `THEFEED_GITHUB_RELAY_TOKEN`) | | `--github-relay-repo` | | 中继的 `owner/repo` | | `--github-relay-branch` | `main` | 用于提交中继对象的分支 | | `--github-relay-max-size` | `15360` | GitHub 中继的单个文件上限(KB) | | `--github-relay-ttl` | `600` | GitHub 中继 TTL,以分钟为单位(孤立文件在下次周期清理) | | `--version` | | 显示版本号并退出 | ### 客户端 ``` # 构建 make build-client # 运行(在浏览器中打开 Web UI) ./build/thefeed-client # 自定义数据目录和端口 ./build/thefeed-client --data-dir ./mydata --port 9090 # 启用远程管理的情况下 ./build/thefeed-client --password "your-secret" ``` 首次运行时,客户端会在您运行它的同级目录下创建一个 `./thefeeddata/` 目录。在浏览器中打开 `http://127.0.0.1:8080`,并从 **Settings → Configs** 导入配置(或输入您的域名和密码)。DNS 解析器在底部的 **Resolver** 部分进行管理 —— 这是一个由所有配置共享使用的 Bank,以及用于寻找更多解析器的扫描器。 所有配置、缓存和数据文件都存储在该数据目录中。 #### 客户端标志 | 标志 | 默认值 | 说明 | |------|---------|-------------| | `--data-dir` | `./thefeeddata` | 用于配置、缓存的数据目录 | | `--port` | `8080` | Web UI 端口 | | `--password` | | Web UI 密码(留空 = 无身份验证) | | `--version` | | 显示版本号并退出 | **并发请求(分散)** 设置以及所有其他配置选项(解析器、速率限制、查询模式、超时)都是通过 Web UI 的配置编辑器进行配置的,而不是通过 CLI 标志。 #### macOS(.app / .dmg) 每个版本都会发布一个通用的 `thefeed-macos-.dmg`,将客户端打包为可直接拖拽安装的 `Thefeed.app`。同一个二进制文件可在 Intel 和 Apple Silicon 架构上运行。该应用会启动本地 Web UI 并打开您的浏览器;数据持久化保存在 `~/Library/Application Support/Thefeed` 目录下。运行后,它会作为一个 "Thefeed" 项目出现在(屏幕右上角的)菜单栏中,包含 **打开 Thefeed** 和 **退出 Thefeed** 选项 —— 这是一种干净停止服务器的标准方式。子进程的日志会输出到 `~/Library/Application Support/Thefeed/launcher.log`,以供调试。 该 DMG 未签名,因此首次启动时需要以下操作之一: ``` # A) 右键点击 → 在 Finder 中打开一次(Gatekeeper 提示会清除 # 隔离标志以供后续启动使用) # B) 从终端清除它 xattr -dr com.apple.quarantine /Applications/Thefeed.app ``` 在 macOS 上进行本地构建: ``` make mac-dmg # → build/Thefeed.app + build/thefeed-macos-.dmg ``` #### Android (Termux) ``` # 从 F-Droid 安装 Termux pkg update && pkg install curl # 下载 Android 二进制文件 curl -Lo thefeed-client https://github.com/sartoopjj/thefeed/releases/latest/download/thefeed-client-android-arm64 chmod +x thefeed-client ./thefeed-client # 在浏览器中打开:http://127.0.0.1:8080 ``` #### Android (原生 APK 包装) Android 应用在首次启动时会自动请求忽略电池优化,以便后台服务不会被操作系统杀死。 您可以构建或下载一个原生的 Android 应用,它可以: - 在前台/后台服务中运行 thefeed 客户端二进制文件 - 在应用内的 WebView 中打开本地 Web UI 项目路径: - `android/` 构建步骤: ``` # 1) 从项目根目录构建 Android 二进制文件 make build-android-arm64 # 2) 将二进制文件复制到 Android 应用 assets 中(必需的文件名) cp build/thefeed-client-android-arm64 android/app/src/main/assets/thefeed-client # 3) 构建 debug APK cd android gradle wrapper --gradle-version 8.10.2 ./gradlew assembleDebug ``` APK 输出: ``` android/app/build/outputs/apk/debug/app-debug.apk ``` 在设备上安装: ``` adb install -r android/app/build/outputs/apk/debug/app-debug.apk ``` ### Web UI 采用单一 Telegram 风格的界面外壳,带有一个**底部导航栏**,可在五个完整的板块之间切换(不再有模态框): - **订阅** —— 频道/X 订阅源:按类型(公开/X/私密)分组的频道列表及徽章,带有原生 RTL/波斯语渲染的消息(VazirMatn 字体),一个悬浮的圆形撰写按钮(当 Telegram 连接时可发送至频道/私聊),各频道的新消息徽章,下次获取倒计时,媒体标签高亮(`[IMAGE]`、`[VIDEO]` 等),频道内搜索,导出到剪贴板,一个点击即开的链接列表,以及实时 DNS 查询日志。**收藏消息**(加密的本地笔记 + 书签)也位于此处。 - **镜像** (Telemirror) —— 一个 Telegram 网页风格的只读频道镜像,具有照片/相册渲染功能,会预留每张图片的精确宽高比,确保订阅源在加载时不会跳动。 - **聊天** —— 端到端加密的[即时通讯](#messenger):会话列表、送达状态标记 (✓/✓✓)、发送/接收进度、每个会话的发送配额环、安全表情符号验证,以及仅限本地的联系人列表。 - **解析器** —— 统一的 DNS 解析器中心:共享的 **Bank**、您命名的解析器**列表**(激活/重命名/删除/清空),以及发现新解析器的**扫描器** —— 全部集中在一个板块(见下文)。 - **设置** —— 每个偏好设置都有专属页面:**显示**(主题、字体大小、语言、壁纸)、**连接**(查询模式、限制、分散度、超时、应用密码、头像、调试)、**存储**(磁盘缓存预算)、**备份**(加密导出/导入)、**关于**,以及**配置**(导入/管理列表,附带现成的入门配置)。所有字段均会自动保存。 主题默认遵循**设备**设置(系统),并提供明确的**深色** / **浅色**选项。每个配置都会保留其专属的 1 小时浏览器缓存,以确保重新打开时能即时显示数据;**分散**并发数、DNS 超时和其他针对特定配置的选项均可在配置编辑器中进行修改。 ### 解析器板块 **解析器**板块(位于底部导航栏)将解析器 **Bank**、已命名的**列表**和**扫描器**合并到了同一个位置。扫描器会探测 IP 范围,以发现能够连接到您 thefeed 服务器的 DNS 服务器。功能包括: - **灵活的目标**:输入单个 IP、CIDR(例如 `5.1.0.0/16`)或域名 —— 每行一个 - **默认 CIDR 预设**:一键按钮加载内置的精选 CIDR 范围列表 - **清除目标**:用于快速清除扫描器 CIDR/IP 列表的按钮 - **感知配置文件**:选择使用哪个配置文件的域名和密码进行探测 - **可配置**:设置并发数(默认 50)、超时时间(默认 15 秒)以及最大扫描 IP 数 - **扩展 /24**:找到可用的解析器后,自动扫描同一 /24 子网中的所有相邻 IP - **暂停 / 恢复 / 停止**:完全掌控长时间运行的扫描任务(暂停实际上会停止分发新的探测请求) - **响应时间**:结果按延迟排序,因此最快的解析器会优先显示 - **可选结果**:通过复选框选择要应用或复制的解析器 - **应用结果**:直接从扫描器追加或覆盖您配置文件中的解析器列表 - **复制**:每个 IP 单独的复制按钮,复制选中项,或复制所有发现的解析器 IP - **重新扫描**:在扫描完成后重置 UI 以开始新的扫描 - **调试日志**:启用调试模式后,将记录单个探测的查询/响应 - **配置编辑器快捷方式**:在配置文件的编辑页面中通过 "查找解析器" 按钮直接打开扫描器 ## 开发 ``` make test # Run tests with race detector make build # Build both binaries make build-all # Cross-compile all platforms (incl. Android) make upx # Compress Linux/Windows/Android binaries with UPX make vet # Go vet make fmt # Format code make clean # Remove build artifacts ``` ## iOS 开发 将 Go 客户端封装为通过 gomobile 绑定的 xcframework,并由位于 `ios/` 目录下的 SwiftUI 应用调用。服务器在进程内的 `127.0.0.1:<随机端口>` 上运行;仅限前台(iOS 不允许长期运行的后台服务)。 macOS 上的前置条件:Xcode 15+,Go 1.26+,gomobile。 ``` go install golang.org/x/mobile/cmd/gomobile@latest gomobile init ``` 常用目标: ``` make ios-bind # build Mobile.xcframework (iOS device + Simulator) make ios-bind-catalyst # also include Mac Catalyst slice make ios-build # build the app for the Simulator make ios-test # run unit tests on the Simulator make ios-list-sims # list available simulator destinations ``` 使用 `IOS_SIM_NAME='iPhone 16'` 覆盖默认的模拟器。 在执行 `make ios-bind` 后,通过 Xcode 打开 `ios/Thefeed.xcodeproj` 即可从 Xcode 运行。 ## 发布 推送以 `v` 开头的标签会触发 CI 构建和 GitHub Release。 - 稳定版发布标签示例:`v1.4.0` - 预发布标签示例:`v1.4.0-rc1`、`v1.4.0-beta.2` 规则: - 如果标签包含 `-`,则该版本会被自动标记为**预发布版**。 发布的资产包括: - 适用于所有当前目标平台的服务器/客户端二进制文件 - 原生 Android 包装 APK(64 位,推荐):`thefeed-android--arm64-v8a.apk` - 原生 Android 包装 APK(32 位,旧设备):`thefeed-android--armeabi-v7a.apk` ## DNS 记录设置 您的域名需要 **两条 DNS 记录**。假设您的服务器 IP 是 `203.0.113.10`,并且您想使用 `example.com`: ### 1. 用于 NS 服务器的 A 记录 | 类型 | 名称 | 值 | |------|------|-------| | A | `ns.example.com` | `203.0.113.10` | 这会将主机名指向您的服务器 IP。 ### 2. 用于隧道子域的 NS 记录 | 类型 | 名称 | 值 | |------|------|-------| | NS | `t.example.com` | `ns.example.com` | 这会将所有针对 `t.example.com`(及其子域)的 DNS 查询委托给您的服务器。 ## channels.txt 格式 ``` # 注释以 # 开头 @VahidOnline ``` ## x_accounts.txt 格式 ``` # 注释以 # 开头 Vahid ``` ## X 获取安全性 - X 获取仅使用 RSS/XML。 - 实例 URL 会进行验证(仅限 `http`/`https`,仅限主机名,无路径/查询参数/片段)。 - 响应体大小有上限限制,并且强制执行请求超时。 - 如果镜像返回 `403` 或失败,服务器会自动尝试下一个配置的实例。 - 推荐:使用 `--x-rss-instances`(或 `THEFEED_X_RSS_INSTANCES`)设置您自己信任的镜像列表。 ## 安全性 ### 两段式访问控制 **加密密码短语 (`--key`):** 服务器和客户端均需提供。任何拥有此密码短语的人都可以阅读所有频道消息(包括私密频道)。您可以将其分享给信任的朋友,以便他们也能阅读。 **远程管理(服务器使用 `--allow-manage`):** 开启后,任何拥有加密密钥的人还可以发送消息和管理频道。默认禁用。仅在受信任的服务器上启用。 **客户端 Web 密码 (`--password`):** 使用 HTTP Basic Auth 保护所有 Web UI 端点。这仅是本地保护 —— 它**不会**影响 DNS 层面的访问。 ### 安全属性 - 所有通信均为端到端加密 (AES-256) - 客户端和服务器均需要预共享密码短语 - 每个查询都是独立的 —— 网络传输中无会话状态 - 双向的随机填充可防止流量分析 - 写入操作受服务器端 `--allow-manage` 标志控制 - Telegram 双重验证密码以交互方式提示输入(绝不存储在参数中) - 会话文件以受限权限 (0600) 存储 ## 服务管理 ``` # 运行 install.sh 之后 systemctl status thefeed-server systemctl restart thefeed-server journalctl -u thefeed-server -f # 更新频道 sudo vi /opt/thefeed/data/channels.txt sudo systemctl restart thefeed-server # 更新二进制文件 sudo bash scripts/install.sh ``` ## 许可证 MIT
**为了自由的伊朗** Lion-and-Sun *每个人都应享有自由获取信息的权利*
标签:DNS隧道, EVTX分析, RSS阅读器, 信息加密, 即时通讯, 抗审查网络, 日志审计, 网络通信