Kiln 用两层配置管理出站流量:[[proxies]] 定义可复用的代理,[egress] 决定哪些请求使用哪个出口。节目源、节目单和台标共用同一套路由,无需分别设置。
模型总览
每个待请求的地址都会独立走一次判定:
按优先级匹配规则
规则按 priority 升序遍历,命中的第一条决定出口,后面的规则不再参与。
使用默认出口
没有任何规则命中时使用 egress.default。
解析线路
出口是 direct 就直连;是某条线路的 id 就走该线路;引用的线路不存在或已停用时退回直连。
[[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"定义线路
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或启用中的规则引用的线路不允许处于停用状态。
默认出口与规则
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,其余保持源站地址,让能直连的流量少绕一跳。
在容器里访问代理
Kiln 不会改写线路里的地址。在容器里运行时,url 必须是从 Kiln 容器内部连得上的地址:宿主机上好用的 127.0.0.1 在容器里指向容器自己,直接照抄会连不通。
代理跑在宿主机上
用 host.docker.internal 回连宿主机。这个名字在 Docker Desktop 上自带,Linux 上需要显式映射到网关:
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:线路填这个主机名,端口用代理在宿主机上监听的端口:
[[proxies]]
id = "proxy-host"
name = "宿主机代理"
url = "http://host.docker.internal:7890"代理是另一个容器
两个容器接在同一个 Docker 网络上时,直接用服务名寻址,代理不需要把端口映射到宿主机:
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:线路用服务名加代理在容器内监听的端口,这里不是它映射到宿主机的那个端口:
[[proxies]]
id = "proxy-sidecar"
name = "代理容器"
url = "http://proxy:7890"
[[proxies]]
id = "proxy-sidecar-socks"
name = "代理容器 SOCKS"
url = "socks5h://proxy:7891"同一个网络内的流量不出宿主机,所以代理容器不必对外暴露端口,也不需要 extra_hosts。
代理在局域网另一台机器上
这种情况不需要任何 Docker 侧的特殊配置。容器默认的 bridge 网络本来就能访问宿主机所在的局域网,把线路填成那台机器的地址即可:
[[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 节目单 |
| 频道台标 | /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://<服务名>:<容器内端口>,代理无需对外映射端口。见 在容器里访问代理。
配置改动的排查思路与日志字段见 故障排查。