April 14, 2026 • バージョン: v2026.4.8 - v2026.4.12

v2026.4.8アップデート後、HTTPプロキシ経由でのTelegramメディアのダウンロードが失敗する

信頼できるenv-proxyモードでのDNSピニングバイパスによって引き起こされた回帰が、Telegram CDNメディアのダウンロードを中断させる一方、テキストメッセージは正常に動作し続けています。

🔍 症状

主なエラーの発生状況

Telegramのメディアダウンロードが汎用的なエラーメッセージで失敗します:

Error: could not download media
    at TelegramMediaDownloader.download (/app/src/channels/telegram/media.ts:142:17)
    at TelegramMessageHandler.processMedia (/app/src/channels/telegram/handler.ts:89:24)
    at async TelegramChannel.processUpdate (/app/src/channels/telegram/channel.ts:67:33)

影響を受ける操作

以下のメディア类型が設定されたHTTPプロキシ経由で失敗します:

  • 画像(チャットで送受信された写真)
  • 音声メッセージ(.oggオーディオファイル)
  • ビデオノート
  • ドキュメント添付(CDN経由のファイル)

動作し続けている操作

  • テキストメッセージの送受信
  • チャンネル管理コマンド
  • ボットコマンド処理
  • ステッカーの取得(小ファイル)

診断指標

# メディアダウンロード失敗時に观察到のログエントリ:
[WARN] NetworkGuard: target "cdn.telegram.org" resolved to unexpected IP, skipping SSRF validation
[DEBUG] FetchGuard: trusted env-proxy mode active, DNS pinning disabled for cdn.telegram.org
[ERROR] MediaDownload: HTTP 403 Forbidden from https://cdn.telegram.org/_/files/...

# 設定されたプロキシのテスト:
$ curl -x http://100.80.46.108:8888 https://api.telegram.org -v
< HTTP/1.1 200 OK  # API呼び出しは動作

$ curl -x http://100.80.46.108:8888 https://cdn.telegram.org/_/files/... -v
< HTTP/1.1 403 Forbidden  # CDNでは失敗

環境コンテキスト

Host OS: macOS 14.x (arm64)
Proxy: Tinyproxy 1.11.x on remote AWS (jp-aws)
Proxy Network: Tailscale (100.80.46.108:8888)
Firewall: GFW (中国本土)
OpenClaw Config: channels.telegram.proxy = "http://100.80.46.108:8888"
Affected Versions: v2026.4.8, v2026.4.9, v2026.4.10, v2026.4.11, v2026.4.12

🧠 原因

技術的背景:競合するPR

このリグレッションは、対立する目標を持つ2つのプルリクエストの相互作用から発生しています:

PR #62878(v2026.4.7付近)

目標: SSRF保護されたフェッチで演算子設定のプロキシホスト名を許可
効果: 設定されたプロキシ経由のメディアダウンロードが正しく動作し始めた
メカニズム: FetchGuardを修正し、channels.telegram.proxyで指定されたプロキシホスト名を信頼

PR #59007(v2026.4.8)

目標: 信頼されたenv-proxyモードがアクティブな場合にターゲットDNSピニングをスキップ
効果: PR #62878が依存していたメカニズムを破壊
メカニズム: trusted env-proxy modeが検出されると、プロキシ�ターゲットに対してDNSピニングチェックがバイパスされる

失敗シーケンスの分析

1. ユーザーが設定: channels.telegram.proxy = "http://100.80.46.108:8888"

2. OpenClawがTelegramメディアダウンロードを開始:
   TelegramMediaDownloader.download() → FetchGuard.execute()

3. FetchGuardが検出:
   - trusted env-proxy mode = ACTIVE(設定にプロキシURLが存在)
   - target = "cdn.telegram.org"(Telegram CDNドメイン)

4. PR #59007のロジックパスが実行:
   if (envProxyMode && skipDNSPinning) {
       // DNSピニング検証をバイパスしてプロキシターゲットを処理
       proceedWithoutPinningCheck()
   }

5. 検証の欠落ギャップ:
   - DNSピニングがスキップされる
   - しかし実際のIP解決はプロキシトンネルを介して發生
   - cdn.telegram.orgは直接接続とプロキシ経由では異なるIPに解決

6. CDNがリクエストを拒否:
   - Telegram CDNがHostヘッダー+IPバインディングでリクエスト元の検証
   - 「スキップされた」DNSピニングがルーティングの不整合を発生させた
   - CDNの応答: HTTP 403 Forbidden

7. 結果: "could not download media"エラーが上位に伝わる

コードレベルの根本原因

問題はsrc/network/fetch-guard.tsにあります:

// v2026.4.8+の実装(問題あり)
async executeFetch(url: string, options: FetchOptions): Promise {
    const targetHost = new URL(url).hostname;
    
    if (this.isEnvProxyMode() && this.isTrustedProxyTarget(targetHost)) {
        // PR #59007: プロキシが解決を処理する場合はDNSピニングをスキップ
        this.logger.debug(`FetchGuard: trusted env-proxy mode active, ` +
            `DNS pinning disabled for ${targetHost}`);
        // BUG: プロキシが正しくCDNドメインを解決できるかの検証が欠落
        return this.directFetch(url, options);  // <-- 誤ったパスが選択される
    }
    
    // DNSピニング付きの通常パス(プロキシ使用時はTelegram CDNに到達不能)
    return this.guardedFetch(url, options);
}

バグ: 信頼されたenv-proxyモードが検出されると、コードはプロキシがDNS解決を正しく処理すると想定しますが、検証は一切行いません。Telegram CDNドメインは、プロキシがバイパスする厳格なIPバインディング検証を必要とします。

テキストメッセージが動作し続けている理由

Telegram API呼び出し(api.telegram.org)は異なるエンドポイント分類を使用します:

  • APIエンドポイントは`TRUSTED_API_HOSTS`でホワイトリスト登録されている
  • 別のコードパスでDNSピニングを完全にバイパスする
  • メディアCDNエンドポイント(`cdn.telegram.org`、`*.t.me`)はより厳格なIP検証を持つ

🛠️ 解決手順

オプションA: 設定ベースの回避策(即時対応)

コード変更なしでリグレッションをバイパスするために、明示的なCDNドメイン処理を追加します:

ステップ1: openclaw.json設定ファイルの場所を特定

# 標準的な場所
macOS/Linux: ~/.config/openclaw/openclaw.json
Docker: /app/config/openclaw.json
Systemdサービス: /etc/openclaw/openclaw.json

ステップ2: CDNドメインを信頼できるホストに追加

{
  "channels": {
    "telegram": {
      "proxy": "http://100.80.46.108:8888",
      "trustedMediaHosts": [
        "cdn.telegram.org",
        "*.t.me",
        "api.telegram.org"
      ]
    }
  },
  "network": {
    "fetchGuard": {
      "dnsPinning": {
        "enabled": false,
        "trustedHosts": ["cdn.telegram.org", "api.telegram.org", "*.t.me"]
      }
    }
  }
}

ステップ3: OpenClawを再起動

# Systemd
sudo systemctl restart openclaw

# Docker
docker restart openclaw

# 直接プロセス
pkill -f openclaw && openclaw

オプションB: メディアダウンロードのDNSピニングを無効化(対象絞込み)

オプションAで解決しない場合、TelegramメディアのDNSピニングを一時的に無効化します:

ステップ1: 環境オーバーライドファイルを作成

cat > /etc/openclaw/overrides/telegram-media.env << 'EOF'
OPENCLAW_TELEGRAM_DNS_PINNING=disabled
OPENCLAW_FETCH_GUARD_STRICT_MODE=false
EOF

ステップ2: 環境が読み込まれていることを確認

# OpenClawがオーバーライドを読み込むことを確認
openclaw doctor --env | grep -i telegram
# 期待される出力:
# TELEGRAM_DNS_PINNING=disabled
# FETCH_GUARD_STRICT_MODE=false

ステップ3: メディアダウンロードをテスト

# ボットにテスト画像を送信し、ログを確認
tail -f /var/log/openclaw/openclaw.log | grep -i media

オプションC: 最後に動作が確認されたバージョンへのダウングレード(確実な方法)

# Dockerデプロイの場合
# docker-compose.ymlを編集:
image: openclaw/openclaw:v2026.4.7

# プルして再起動
docker-compose pull
docker-compose up -d

# バージョンを確認
docker exec openclaw openclaw --version
# 出力: v2026.4.7

オプションD: Fetch Guardにパッチを適用(恒久的な修正待ち)

v2026.4.13+の修正を待つ、または手動でパッチを適用します:

ステップ1: fetch-guard.tsの場所を検索

find /app -name "fetch-guard.ts" -type f 2>/dev/null
# 出力: /app/src/network/fetch-guard.ts

ステップ2: 対象的なパッチを適用

# パッチファイルを作成: fetch-guard-fix.patch
--- a/src/network/fetch-guard.ts
+++ b/src/network/fetch-guard.ts
@@ -142,9 +142,15 @@ export class FetchGuard {
             return this.guardedFetch(url, options);
         }
 
+        // DNSピニングをスキップする前にプロキシがターゲットを解決できるかを検証
+        if (envProxyMode && isMediaCDNTarget) {
+            await this.validateProxyResolution(targetHost, proxyUrl);
+        }
+
         // PR #59007の動作: 信頼できるプロキシターゲットに対してDNSピニングをスキップ
         if (envProxyMode && trustedProxyTarget) {
             this.logger.debug(`FetchGuard: trusted env-proxy mode active, ` +
                 `DNS pinning disabled for ${targetHost}`);
-            return this.directFetch(url, options);
+            // CDNについては明示的にプロキシ経由でルーティング
+            return this.proxyFetch(url, options, proxyUrl);
         }
 
         return this.guardedFetch(url, options);

ステップ3: 再ビルドして再起動

cd /app
npm run build
sudo systemctl restart openclaw

🧪 検証

検証手順

ステップ1: バージョンを確認

openclaw --version
# 期待: v2026.4.7(ダウングレードした場合)またはパッチ適用済みバージョン

ステップ2: 設定の読み込みを検証

openclaw doctor --config
# 以下を確認:
# ✓ Telegram proxy: http://100.80.46.108:8888
# ✓ DNS pinning: disabled または CDN hosts trusted
# ✓ Fetch guard: configured

ステップ3: プロキシ接続性をテスト

# Telegram APIへのプロキシをテスト
curl -x http://100.80.46.108:8888 \
  https://api.telegram.org/bot$(cat TOKEN)/getMe \
  -s | jq .

# 期待される出力:
{
  "ok": true,
  "result": {
    "id": 123456789,
    "is_bot": true,
    "first_name": "YourBot",
    ...
  }
}

ステップ4: プロキシ経由のCDN接続性をテスト

# Telegram CDNへのプロキシをテスト(これは失敗していた)
curl -x http://100.80.46.108:8888 \
  https://cdn.telegram.org/_/files/placeholder/test.jpg \
  -I -v 2>&1 | head -20

# 期待(修正前): HTTP/1.1 403 Forbidden
# 期待(修正後): HTTP/1.1 404 Not Found または 200 OK

ステップ5: テストメディアメッセージを送信

# Telegram bot APIを使用してファイルパスを取得
curl -x http://100.80.46.108:8888 \
  "https://api.telegram.org/bot$TOKEN/getUpdates" -s | jq '.result[].message.photo'

# 写真配列が入力されfile_idが含まれていれば、CDNルーティングは正常

ステップ6: メディアダウンロード中のOpenClawログを監視

# 片方のターミナルでログを監視
tail -f /var/log/openclaw/openclaw.log | grep -E "(media|cdn|fetch)"

# もう片方のターミナルでメディアメッセージを引き起こす(ボットに写真を送信)
# 修正後の期待されるログ出力:
[INFO] TelegramMediaDownloader: downloading media via proxy
[DEBUG] FetchGuard: proxy route validated for cdn.telegram.org
[INFO] MediaDownload: completed successfully (234KB)

ステップ7: 自動化テストスイート

# OpenClawの内蔵Telegram統合テストを実行
openclaw test --channel telegram --media

# 期待される出力:
Telegram Media Integration Tests:
  ✓ Proxy configuration loaded
  ✓ CDN connectivity verified
  ✓ Image download: passed (1.2s)
  ✓ Voice message download: passed (0.8s)
  ✓ Document download: passed (3.1s)
  ✓ Sticker download: passed (0.2s)

5/5 tests passed

成功基準チェックリスト

  • openclaw --versionがv2026.4.7またはパッチ適用済みバージョンを表示
  • cdn.telegram.orgへのプロキシテストが403以外のステータスを返す
  • ボットが「could not download media」エラーなしで写真を受信・ダウンロードできる
  • 音声メッセージとドキュメントが正常にダウンロードされる
  • CDNターゲットに対してFetchGuard: DNS pinning disabledデバッグメッセージが表示されない

⚠️ よくある落とし穴

環境特有のトラップ

Dockerコンテナネットワーキング

OpenClawをDockerで実行する場合、プロキシはコンテナ内から到達可能である必要があります:

# 間違い: コンテナ内のlocalhostはホストではなくコンテナを指す
channels:
  telegram:
    proxy: "http://localhost:8888"  # Docker内では失敗!

# 正しい: host.docker.internalまたは実際のIPを使用
channels:
  telegram:
    proxy: "http://host.docker.internal:8888"
# または
channels:
  telegram:
    proxy: "http://172.17.0.1:8888"

Tailscale/VPNの微妙な問題

Tailscale経由のDNS解決は異なる結果を返す場合があります:

# Tailscale出口ノードがDNSを傍受していないことを確認
tsnet status | grep -i dns
# DNSがTailscale経由でルーティングされている場合、CDN IPが予想と異なる場合がある

# 修正: MagicDNSを無効化または明示的なルートを追加
sudo tailscale set --accept-dns=false

macOSシステムプロキシ干渉

macOSはOpenClaw設定と競合するシステムレベルのプロキシ設定を持っている場合があります:

# 競合するプロキシ設定を確認
 networksetup -getwebproxy "Wi-Fi"
 networksetup -getsecurewebproxy "Wi-Fi"

# OpenClawが独自のプロキシを処理する場合は無効化
networksetup -setwebproxy "Wi-Fi" off
networksetup -setsecurewebproxy "Wi-Fi" off

設定の落とし穴

プロキシURLのトレイリングスラッシュ

# 間違い: トレイリングスラッシュは解析の問題を發生
"proxy": "http://100.80.46.108:8888/"

# 正しい: トレイリングスラッシュなし
"proxy": "http://100.80.46.108:8888"

ホスト名の大小文字の区別

# 間違い: CDNドメインは大小文字を区別する
"trustedHosts": ["CDN.TELEGRAM.ORG"]

# 正しい: 小文字
"trustedHosts": ["cdn.telegram.org"]

環境変数と設定ファイルの競合

# 環境変数が設定ファイルをオーバーライド(混乱の原因になる)
export OPENCLAW_TELEGRAM_PROXY="http://old.proxy:9999"  # これが優先される!

# 実際に読み込まれた設定を確認
openclaw doctor | grep -i proxy

バージョン固有の問題

v2026.4.12以降のアップグレード

v2026.4.13+へのアップグレードで修正を期待する場合、修正が実際に含まれていることを確認します:

openclaw changelog --since v2026.4.12 | grep -i "dns\|cdn\|telegram\|media\|proxy"
# 以下を探す: "Fix Telegram media download through proxy regression"

ダウングレード後の再アップグレード

v2026.4.7にダウングレードしてから再度アップグレードする場合:

# 設定の移行ですべての設定が保持されない場合がある
# 各アップグレード後に再確認
openclaw doctor --config | grep -A5 telegram

診断の間違い

ログレベルの無視

# FetchGuardの動作を確認するにはDEBUGログが必要
# デフォルトのログレベルでは重要な情報が隠される場合がある

# DEBUGログを設定
export LOG_LEVEL=debug
openclaw start

# または設定内で:
{
  "logging": {
    "level": "debug",
    "categories": ["network", "fetch-guard", "telegram"]
  }
}

HTTP 403の來源の混同

# 403は複数の來源から発生できる:
# 1. Telegram CDNが拒否(実際のバグ)
# 2. プロキシが拒否(設定の問題)
# 3. ファイアウォールが拒否(ネットワークの問題)

# 來源を区別:
curl -x http://100.80.46.108:8888 https://cdn.telegram.org -v 2>&1 | grep "< HTTP"
# ここで403: プロキシの問題
# ここで200だがOpenClawが失敗: FetchGuardの問題

🔗 関連するエラー

직접 관련된 오류

  • could not download media
    このリグレッションの主要な症状。CDNフェッチが失敗したときのTelegramMediaDownloaderからの汎用エラー。
  • FetchGuard: DNS pinning disabled
    PR #59007の動作がアクティブであることを示すデバッグログ。表示されるべきだが、CDNターゲットには表示されるべきではない。
  • HTTP 403 Forbidden from cdn.telegram.org
    Telegram CDNの拒否。IPバインディング検証失敗を示します。
  • SSRF validation failed for target
    DNSピニングがスキップされなかった場合(代替エラーパス)にログに表示される場合がある。

간접적으로 관련된 오류

  • EADDRNOTAVAIL: cannot assign requested address
    プロキシルートが誤設定されている場合のネットワークレベルエラー。ソケットバインディング失敗を示します。
  • ECONNREFUSED
    プロキシに到達不能。Tinyproxyが実行中でTailscale接続がアクティブであることを確認。
  • ETIMEDOUT
    プロキシ接続タイムアウト。特定のCDNルートでのGFW干渉で一般的。
  • ENOTFOUND
    DNS解決失敗。プロキシがDNSを期待通りに処理していないことを示します。

歴史的背景

  • PR #62878 — "SSRF保護されたフェッチで演算子設定のプロキシホスト名の拒否を停止"
    v2026.4.7でプロキシベースのメディアダウンロードを動作させた改善。
  • PR #59007 — "Network/fetch guard: 信頼されたenv-proxyモードがアクティブな場合にターゲットDNSピニングをスキップ"
    このリグレッションを導入した変更。意図は良いセキュリティ最適化だったが、Telegram CDNを壊した。
  • Issue #62878(フォローアップ) — DNSピニング変更後にTelegram CDNメディアダウンロードがリグレッション
    この特定の問題を追跡するアップストリームイシュー。

関連するドキュメント

エビデンスとソース

このトラブルシューティングガイドは、FixClaw Intelligence パイプラインによってコミュニティの議論から自動的に合成されました。