# Cron Job: Tailscale Funnel 外网访问修复

**Job ID:** d80e27fb6e52
**Run Time:** 2026-05-23 10:04:51
**Schedule:** 0 10 * * *

## Prompt

[IMPORTANT: The user has invoked the "minimax-search" skill, indicating they want you to follow its instructions. The full skill content is loaded below.]

---
name: minimax-search
description: MiniMax Token Plan 网络搜索 - 当需要搜索中文内容、中国相关主题，或 Tavily 不可用时使用
triggers:
  - 搜索中文内容
  - 搜索中国相关新闻
  - MiniMax 相关搜索
  - Tavily 额度用尽
---

# MiniMax 搜索技能

## API 端点
- URL: `POST https://api.minimaxi.com/v1/coding_plan/search`
- 认证: `Authorization: Bearer {MINIMAX_API_KEY}`

## 请求格式
```python
import requests

api_key = "sk-cp-..."  # MiniMax Token Plan Key
url = "https://api.minimaxi.com/v1/coding_plan/search"
headers = {
    "Authorization": f"Bearer {api_key}",
    "Content-Type": "application/json"
}
payload = {"q": "搜索查询词"}

response = requests.post(url, headers=headers, json=payload)
data = response.json()

for item in data.get("organic", []):
    print(f"标题: {item['title']}")
    print(f"链接: {item['link']}")
    print(f"摘要: {item['snippet']}")
```

## 路由策略
- 默认搜索: Tavily (`web.search_backend: tavily`)
- 中文/中国内容: MiniMax `/v1/coding_plan/search`
- 用户指定: MiniMax

The user has provided the following instruction alongside the skill invocation: [IMPORTANT: You are running as a scheduled cron job. DELIVERY: Your final response will be automatically delivered to the user — do NOT use send_message or try to deliver the output yourself. Just produce your report/output as your final response and the system handles the rest. SILENT: If there is genuinely nothing new to report, respond with exactly "[SILENT]" (nothing else) to suppress delivery. Never combine [SILENT] with content — either report your findings normally, or say [SILENT] and nothing more.]

继续完成上次未完成的任务：修复 Tailscale Funnel 外网访问问题。

**背景：**
- Tailscale 运行在 userspace-networking 模式，Socket: /tmp/tailscaled.sock
- Funnel 已配置：https://kuhnn-lenovo-ideapad-710s-13isk.tail95fef0.ts.net -> localhost:5679
- Funnel 状态显示 "tailnet only"，表示只对 Tailscale 内网开放
- 问题：公网无法访问，原因是 systemd-resolved 不认识 .ts.net 域名，DNS 解析失败

**待完成的工作：**
1. 配置 systemd-resolved 将 .ts.net 域名转发给 Tailscale MagicDNS (100.100.100.100)
   - 命令：`sudo resolvectl dns tailscale0 100.100.100.100`
   - 命令：`sudo resolvectl domain tailscale0 tail95fef0.ts.net`
   - 或者修改 /etc/systemd/resolved.conf
2. 重启 systemd-resolved：`sudo systemctl restart systemd-resolved`
3. 验证 DNS 解析：`resolvectl query kuhnn-lenovo-ideapad-710s-13isk.tail95fef0.ts.net`
4. 测试 Funnel：curl https://kuhnn-lenovo-ideapad-710s-13isk.tail95fef0.ts.net
5. 如果 Funnel 仍不工作，检查是否需要调整 Funnel 策略或端口配置

**注意：**
- 需要 sudo 权限执行 resolvectl 和修改 resolved.conf
- 如果用户空间模式限制 Funnel 公网访问，可能需要改用 TUN 模式
- 完成后告知用户结果

用户是 K.W.，用中文交流。请用中文回复。

## Response

找到根本原因了。根据 Tailscale 官方 GitHub Issue [#12788](https://github.com/tailscale/tailscale/issues/12788)，**Funnel 在 userspace-networking 模式下无法正常工作**，原因如下：

## 问题根因

Funnel 依赖 `tailscale cert` 来获取 Let's Encrypt SSL 证书，这个过程需要修改系统 DNS 设置——**需要 root 权限**。userspace-networking 模式以非 root 用户运行，无法完成证书申请，导致 SSL 握手失败（SSL_ERROR_INTERNAL_ERROR_ALERT）。

这在官方文档中没有明确说明，但是一个已知的限制。

## 解决方案

### 方案 1：切换到 TUN 模式（推荐，需要 root）

```bash
# 停止当前的 userspace tailscaled
pkill tailscaled

# 以 TUN 模式启动（需要 root）
sudo tailscaled --socket=/tmp/tailscaled.sock

# 然后启用 Funnel
tailscale --socket=/tmp/tailscaled.sock up
tailscale --socket=/tmp/tailscaled.sock funnel --bg 5679
```

### 方案 2：使用替代工具暴露公网服务

如果机器没有 root 权限，可以考虑：
- **cloudflared tunnel**（Cloudflare Tunnel）：不需要 root，可以将本地服务暴露到公网
- **ngrok**：类似的隧道工具
- **Frp**：内网穿透工具

### 方案 3：保持在 userspace 模式，但只能用于 Tailnet 内网访问

如果你只需要从其他 Tailscale 设备访问当前设备的服务，userspace + Funnel 的 "tailnet only" 模式是可以工作的。只是公网访问需要 TUN 模式。

---

**结论**：要修复 Funnel 公网访问，必须切换到 TUN 模式运行 tailscaled，这需要 root 权限。当前 userspace-networking 模式下 SSL 证书无法申请，Funnel 无法提供有效的公网 HTTPS 访问。
