# ファイル転送と LAN 直接接続

> HTML: https://remote.ivjn.us/docs/ja/files-and-lan/

Agent、Exchange、CLI、Web コンソール、モバイルコントローラーはファイル転送に対応します。対応デバイスは `files` 機能を宣言します。

## ファイル転送

```sh
remote-cli file i5m ls /tmp
remote-cli file i5m upload ./example.zip /tmp/example.zip
remote-cli file i5m download /tmp/example.zip ./downloaded.zip
remote-cli file i5m fetch https://example.com/example.zip ./example.zip
```

既定では既存ファイルを上書きしません。アップロードまたはダウンロードに `--overwrite` を付けた場合のみ上書きを許可します。CLI では Ctrl+C でキャンセルし、Web とモバイルにはキャンセルボタンがあります。Web ではデバイス詳細の「ファイル」ページ、モバイルではデバイス詳細の「ファイル転送」から操作します。

転送は 64 KiB ごとのチャンクに分割し、確認を受けてから次に進みます。1 ファイルの上限は 1 GiB、Web ダウンロードの上限は 128 MiB です。大きなファイルには CLI またはモバイルを使用してください。ディレクトリは最大 1000 項目を返し、再帰的なディレクトリアップロードには対応しません。アップロードは宛先ディレクトリに一時ファイルを書き込み、受信完了後にアトミックに置き換えます。キャンセル、切断、タイムアウトでは未完了の一時ファイルを削除します。CLI のダウンロードも一時ファイルを使用します。モバイルではキャッシュにダウンロードしてからシステムの共有・保存機能を呼び出します。

ファイルアクセスには Agent プロセスのシステム権限を使用し、特定の共有ディレクトリには制限しません。読み取り専用アカウントはディレクトリ一覧、アップロード、ダウンロードを使用できません。Exchange はデバイスの所属ワークスペース、セッション分離、操作監査を適用し、ファイル内容は記録しません。Android では `.` は Agent アプリのファイルディレクトリを指し、他のディレクトリへのアクセスは Android の権限に制限されます。システムのサンドボックスは回避できません。

## Agent 経由のインターネットダウンロード

Web のファイル画面に HTTP/HTTPS URL を入力するか、`file DEVICE fetch URL LOCAL` を実行します。Agent 自身のネットワークから取得し、Agent に保存せず Console のコンピューターへ転送します。Web は 128 MiB、CLI は 1 GiB までです。中断・切断・失敗時は未完了ファイルを保存しません。CLI で既存ファイルを置換する場合は `--overwrite` が必要です。デスクトップ、Linux、Android、OpenWrt のネイティブ Agent が対応します。ブラウザー拡張にはファイル転送がありません。証明書を検証し、認証情報入り URL と HTTPS からのダウングレードを拒否します。リダイレクトは最大 5 回です。

ダウンロードは管理サーバーの `--insecure` を継承しません。

## curl 形式の HTTP リクエスト

デバイスの HTTP リクエスト画面に curl を貼り付けると、Console が密封したリクエストを Agent に送り、ステータス、時間、ヘッダー、本文を表示します。`-X/--request`、`-H/--header`、`-d/--data`、`--data-raw`、インラインの `--data-binary`、`--json`、`-I/--head`、`-L/--location`、`-m/--max-time`、`--url` に対応します。shell や `@file` は実行・読み込みしません。ネイティブ Agent に curl のインストールは不要です。拡張はサイト権限が必要で、ブラウザー Cookie を送信せず、禁止ヘッダーを拒否します。Chromium が隠すリダイレクトでは最終 URL を使用してください。読み取り専用権限では送信できません。本文上限は 256 KiB、タイムアウトは 120 秒です。応答はネイティブ 1 MiB、拡張 128 KiB で切り詰めを表示します。バイナリや大きいファイルにはファイル取得を使用してください。

密封メッセージは `net_req` です。ブラウザー機能：`net`。CLI の対応コマンド：`remote-cli net DEVICE http URL -X POST -H 'Content-Type: application/json' -d '{"message":"hello"}'`

```sh
curl -X POST 'https://example.com/api' -H 'Content-Type: application/json' --data-raw '{"message":"hello"}'
```

## LAN 制御ポート

LAN 制御は既定で無効で、既定の TCP ポートは **7277** です。信頼できる LAN 内でのみ有効にしてください。有効にする前に、デバイスでワークスペースのルートを固定する必要があります（`remote-agent seal root`、または先に Exchange に接続して TOFU を完了）。LAN アクセストークンはありません。このポートを公開インターネットに転送しないでください。

既存の Agent JSON 設定に追加します。

```json
{
  "lan_enabled": true,
  "lan_port": 7277
}
```

設定内の既存の `server`、`device_id`、`token` は保持してください。`--lan-enabled`、`--lan-port`、または `REMOTE_LAN_ENABLED`、`REMOTE_LAN_PORT` も使用できます。ワークスペースのルートが固定されていない状態で LAN を有効にすると、起動を拒否します。

デスクトップ設定ページと LuCI 設定ページの両方にスイッチがあります。変更後は Agent を再起動してください。デスクトップ設定ページでは、変更前に接続を停止する必要があります。スイッチを無効にして再起動すると、このポートの待受を停止します。プログラムはファイアウォールの許可ルールを自動作成しません。

CLI の直接接続は専用の設定を作成し、`login` は使わないでください（空でないトークンを要求するため）。`server` にデバイスの `http://IP:7277` を設定し、`token` は空にします。リクエストに `Authorization` は付きません。

```toml
server = "http://192.168.1.20:7277"
token = ""
```

`REMOTE_CLI_CONFIG` でこのファイルを指定すれば、クラウド用ログインを別に維持できます。密封 ID と認可のキャッシュはこの設定ファイルと同じディレクトリに保存されます。`seal-grants.json` にはオフライン grant、`seal-chains.json` にはルート発行の証明書を先頭にした証明書チェーンがあります。すべてのデバイス操作は密封セッションのみを開きます。デバイスカードに `local` があるデバイスや、LAN アドレスの `/api/auth/me` が 401 を返す直接接続デバイスも同様です。Agent はこれらの認可を発行・更新しません。クラウドがオフラインのときは、キャッシュ内でまだ有効なルートチェーンの認可のみを使用できます。`sessions` と `session-kill` は使用できません。LAN にはセッションディレクトリがなく、デバイスのセッションは引き続き Exchange が管理します。

直接接続が公開するのはローカルデバイスだけです。外側の層はプライベート、リンクローカル、ループバックのアドレスのみを受け入れ、Origin を検証します。`GET /api/devices` はこれらの検査後に、デバイス ID と密封ハンドシェイク開始に必要な `seal_key` / `seal_mode` だけを返します。`GET /api/auth/me` は密封ハンドシェイク前にオペレーター ID 情報を返しません。`GET /ws/operator` は密封セッションのみを受け付け、平文の互換経路は提供しません。

クライアントは `open_sealed` の hello に、オペレーター公開鍵の証明、上記オフラインキャッシュの grant（`hello.grant`）、任意の証明書チェーン（`hello.chain`、ルート発行分が先頭）をインラインで送信します。デバイスは Exchange 経由と同じ規則でローカルのルート、デバイス範囲、view/manage を検証し、セッション内容は密封状態を維持します。Web コンソールは引き続き Exchange 経由で接続します。既定では IPv4 の全インターフェースで待ち受け、クラウドがオフラインでも使用できます。LAN のバインドに失敗した場合はエラーを記録し、クラウドへの再接続は継続します。

## 回帰検証

```sh
python scripts/file-transfer-smoke.py --agent target/debug/remote-agent --cli target/debug/remote-cli
python scripts/agent-ui-smoke.py --agent target/debug/remote-agent --platform linux
```

Python 3.11 以降と `websockets` が必要です。Windows では `.exe` のパスと `--platform windows` を使います。テストは一時設定と一時ファイルを使用し、既存のログインやデバイスは変更しません。
