---
title: "出站代理"
description: "配置可复用的代理和路由规则，控制 Kiln 访问节目源、节目单和台标时使用的网络出口。"
---

> Documentation Index
> Fetch the complete documentation index at: https://kiln.wbxdocs.com/llms.txt
> Use this file to discover all available pages before exploring further.

# 出站代理

Kiln 用两层配置管理出站流量：`[[proxies]]` 定义可复用的代理，`[egress]` 决定哪些请求使用哪个出口。节目源、节目单和台标共用同一套路由，无需分别设置。

## 模型总览

每个待请求的地址都会独立走一次判定：

1. **按优先级匹配规则**

   规则按 `priority` 升序遍历，命中的第一条决定出口，后面的规则不再参与。
2. **使用默认出口**

   没有任何规则命中时使用 `egress.default`。
3. **解析线路**

   出口是 `direct` 就直连；是某条线路的 id 就走该线路；引用的线路不存在或已停用时退回直连。

```toml title="kiln.toml"
[[proxies]]
id = "proxy-http"
name = "HTTP 线路"
url = "http://127.0.0.1:7890"

[[proxies]]
id = "proxy-socks"
name = "SOCKS5 线路"
url = "socks5h://127.0.0.1:7891"

[egress]
default = "direct"
playlist_policy = "rewrite"
# docker_proxy_host = "host.docker.internal"

[[egress.rules]]
id = "example-cdn"
priority = 10
kind = "host_suffix"
pattern = "example-cdn.com"
proxy = "proxy-http"
```

> **首次启动后请使用控制台**
>
> 出站配置和频道一样保存在 SQLite 中。只有数据库中还没有线路记录时，Kiln 才会写入配置文件里的 `[[proxies]]` 与 `[[egress.rules]]`；`default`、`playlist_policy`、`docker_proxy_host` 也只会在对应设置尚不存在时写入。首次启动后，请在 [管理控制台](/guide/admin/) 中修改。

## 定义线路

- `id` 唯一，被 `egress.default`、路由规则和节目单源引用；`name` 只用于界面显示。
- `url` 支持 `http`、`https`、`socks5`、`socks5h` 四种 scheme，例如 `http://127.0.0.1:7890` 或 `socks5h://127.0.0.1:7891`。
- 需要认证时把凭据放进 URL，例如 `http://user:password@127.0.0.1:7890`，控制台会显示该线路已配置凭据而不回显密码。
- `socks5h` 由代理侧解析域名，`socks5` 先在本机解析再连接。回源地址依赖境外 DNS 时优先选 `socks5h`。
- 线路可以停用而不删除。被 `egress.default` 或启用中的规则引用的线路不允许处于停用状态。

> **两种引擎都支持全部四种 scheme**
>
> ffmpeg 引擎不直接使用你配置的线路，它通过 Kiln 在本地开的一次性 HTTP 代理取数据，出站仍由 Kiln 按路由完成，因此线路是 HTTP 还是 SOCKS 对它同样透明。频道走哪个引擎见 [媒体引擎](/guide/media-engine/)。

## 默认出口与规则

`egress.default` 取 `direct` 或某条线路的 id，所有未命中规则的请求都走它。

规则由 `id`、`priority`、`kind`、`pattern`、`proxy` 组成，可以单独停用。`priority` 数字越小越优先，`proxy` 也可以填 `direct`，用来在默认走代理的部署里为个别域名开一个直连口子。

| `kind` | 匹配对象 |
| --- | --- |
| `host_suffix` | 主机名后缀。`example.com` 同时命中 `example.com` 与 `cdn.example.com`，不会命中 `notexample.com` |
| `host_exact` | 完整主机名，需要完全相等 |
| `host_regex` | 对主机名做正则匹配 |
| `channel_id` | 频道 ID 完全相等 |
| `url_regex` | 对完整地址做正则匹配 |

省略 `kind` 时按 `host_suffix` 处理。正则类规则在保存前会做编译校验，编译失败的规则不会生效。

## 播放列表处理

`playlist_policy` 决定 Kiln 转发上游 HLS 播放列表时，里面的源站绝对地址如何呈现给播放器。

| 取值 | 行为 |
| --- | --- |
| `rewrite`（默认） | 全部改写回 Kiln，播放器只与 Kiln 通信 |
| `passthrough` | 原样保留源站地址，播放器直连源站 |
| `auto` | 只改写需要走代理的地址，其余保留源站地址 |

`rewrite` 的具体行为是：Kiln 把播放列表里的每条媒体地址，以及标签中的 `URI="..."`，先解析成绝对地址，再替换成自身的 `/v1/play/<频道 ID>/u/<编码后的地址>?sig=...`；通过播放密钥分发时，前缀相应变成 `/p/<密钥>/play/<频道 ID>/u/`。地址用 URL-safe Base64 编码并保留可识别的扩展名，签名是按频道 ID 与目标地址计算的 HMAC，密钥在进程启动时随机生成，因此重启后旧地址立即失效。播放器取到这些地址后仍然只连 Kiln，回源由 Kiln 按出站路由完成。嵌套的变体播放列表在被取回时会再走一次同样的改写。

`passthrough` 让播放器直接访问源站，这些请求不会经过 Kiln 的代理线路，也不会带上频道自定义的请求头，只有在播放器自身能够直连源站时才适用。`auto` 是折中：需要走代理的地址改写回 Kiln，其余保持源站地址，让能直连的流量少绕一跳。

> **并发上限优先**
>
> 设置了 `max_viewers` 的频道无论采用哪种策略都会被改写，否则 Kiln 无法统计并发观看数。

## 在容器里访问代理

Kiln 不会改写线路里的地址。在容器里运行时，`url` 必须是**从 Kiln 容器内部**连得上的地址：宿主机上好用的 `127.0.0.1` 在容器里指向容器自己，直接照抄会连不通。

### 代理跑在宿主机上

用 `host.docker.internal` 回连宿主机。这个名字在 Docker Desktop 上自带，Linux 上需要显式映射到网关：

```yaml title="compose.yaml" ins={6,7}
services:
  kiln:
image: ghcr.io/babywbx/kiln:core
ports:
  - "8080:8080"
extra_hosts:
  - "host.docker.internal:host-gateway"
volumes:
  - ./kiln.toml:/etc/kiln/kiln.toml:ro
  - kiln-data:/var/lib/kiln/data
restart: unless-stopped

volumes:
  kiln-data:
```

线路填这个主机名，端口用代理在宿主机上监听的端口：

```toml title="kiln.toml"
[[proxies]]
id = "proxy-host"
name = "宿主机代理"
url = "http://host.docker.internal:7890"
```

> **宿主机代理必须允许局域网连接**
>
> 这个场景最常见的失败原因不在 Kiln：代理只监听 `127.0.0.1` 时收不到来自容器的连接。请把它改为监听 `0.0.0.0` 或网桥地址，多数代理程序里对应「允许局域网连接」一类的开关。

### 代理是另一个容器

两个容器接在同一个 Docker 网络上时，直接用服务名寻址，代理不需要把端口映射到宿主机：

```yaml title="compose.yaml"
services:
  proxy:
image: your-proxy-image
container_name: proxy
volumes:
  - ./proxy-config:/etc/proxy:ro
restart: unless-stopped
networks: [kiln-net]

  kiln:
image: ghcr.io/babywbx/kiln:core
depends_on: [proxy]
ports:
  - "8080:8080"
volumes:
  - ./kiln.toml:/etc/kiln/kiln.toml:ro
  - kiln-data:/var/lib/kiln/data
restart: unless-stopped
networks: [kiln-net]

networks:
  kiln-net:

volumes:
  kiln-data:
```

线路用服务名加代理在**容器内**监听的端口，这里不是它映射到宿主机的那个端口：

```toml title="kiln.toml"
[[proxies]]
id = "proxy-sidecar"
name = "代理容器"
url = "http://proxy:7890"

[[proxies]]
id = "proxy-sidecar-socks"
name = "代理容器 SOCKS"
url = "socks5h://proxy:7891"
```

同一个网络内的流量不出宿主机，所以代理容器不必对外暴露端口，也不需要 `extra_hosts`。

### 代理在局域网另一台机器上

这种情况不需要任何 Docker 侧的特殊配置。容器默认的 bridge 网络本来就能访问宿主机所在的局域网，把线路填成那台机器的地址即可：

```toml title="kiln.toml"
[[proxies]]
id = "proxy-lan"
name = "局域网代理"
url = "http://192.168.1.100:7890"
```

既不需要 `extra_hosts`，也不需要和谁共享网络，写法与 Kiln 直接跑在宿主机上时完全一致。要求同样是那台机器上的代理必须监听 `0.0.0.0` 或对应网卡，并且防火墙放行该端口。

### `docker_proxy_host` 不参与这件事

`docker_proxy_host` 只在 `ffmpeg.mode = "docker"` 时生效，作用是告诉 Kiln 拉起的 ffmpeg 子容器怎么回连 Kiln 进程自己，与线路地址无关。上面两种拓扑都不需要动它。

### 验证

控制台的「出站代理」页要求线路先通过一次连通性测试才允许应用，这次测试正是从 Kiln 容器内部发起的，通过即说明地址在容器视角可达。测试失败时按这个顺序排查：代理是否允许非本机连接、容器是否解析得到那个主机名或服务名、端口填的是不是容器视角的端口。

## 受路由控制的流量

| 流量 | 说明 |
| --- | --- |
| 频道回源 | 播放列表与分片的拉取，原生引擎与 ffmpeg 引擎都会应用路由结果 |
| 节目单抓取 | 仅当该源的出口设为 `auto` 时按规则路由，设为 `direct` 或具体线路时按源的设置执行，详见 [EPG 节目单](/guide/epg/) |
| 频道台标 | `/v1/logo/{id}` 的回源抓取，按频道 ID 参与规则匹配 |
| 管理端探测 | 频道探测、预览与出站连通性测试 |

规则里的 `channel_id` 匹配只在请求带有频道上下文时才可能命中，节目单抓取没有频道上下文，因此不会被这类规则选中。

## 控制台与连通性测试

「出站代理」页采用草稿式编辑：新增或修改线路与规则只会改动草稿，必须先运行一次通过的连通性测试，「应用」按钮才会可用；任何后续改动都会重置这个状态，需要重新测试。这样可以避免把一条填错的代理地址直接推送到运行中的服务。

测试对应 `POST /v1/admin/egress/test`，需要 `refresh` 权限，可选参数包括：

- `target`：省略时使用内置的公共探测目标；填 `source` 或 `custom` 时必须给出 `url`，且目标必须是公网地址。
- `channel_id`：带上频道后按该频道解析路由，用于验证 `channel_id` 类规则。
- `proxy_id` 或 `proxy_url`：只测某条线路或某个尚未保存的代理地址。
- `draft`：直接用草稿配置解析路由，不影响正在运行的配置。

响应会给出实际选中的出口 `proxy_id`、命中原因 `reason`、是否会改写播放列表 `rewrite`、耗时 `dur_ms`，以及是否可达、HTTP 状态与最终地址。代理要求认证时会单独标记出来。

## 常见拓扑

- **默认直连，个别域走代理** — `default = "direct"`，为需要代理的域名加一条 `host_suffix` 规则指向线路。适合大部分源可直连、只有个别源需要绕行的部署。
- **默认代理，个别域直连** — `default = "proxy-http"`，再为内网或本地源加一条 `proxy = "direct"` 的规则。局域网上游不必绕出去，也避免代理看到内网地址。
- **Kiln 在容器里，代理在宿主机** — 线路填 `http://host.docker.internal:7890`，并给 Kiln 容器加上 `host.docker.internal:host-gateway` 映射。见 [在容器里访问代理](#在容器里访问代理)。
- **Kiln 与代理各在一个容器** — 两者接同一个 Docker 网络，线路填 `http://<服务名>:<容器内端口>`，代理无需对外映射端口。见 [在容器里访问代理](#在容器里访问代理)。

配置改动的排查思路与日志字段见 [故障排查](/guide/troubleshooting/)。

Source: https://kiln.wbxdocs.com/guide/proxy/index.mdx
