## 四层转发 (`streams`)

TCP/UDP 端口转发规则。每条规则含监听端口与协议、源站列表、负载方式;(协议, 端口) 全平台唯一。

鉴权: 用户（部分参数仅管理员） · 文档: https://www-demo.kuxitong.com/zh/docs/api/streams

### GET `/api/v2/streams`

列出四层转发 · 鉴权: 用户（部分参数仅管理员）

查询参数:

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `page` | integer |  | 页码,从 1 开始。 默认: 1 |
| `page_size` | integer |  | 每页条数。 默认: 20 |
| `sort` | string |  | 排序字段,逗号分隔,前缀 `-` 表示降序,如 `-created_at,id`。 |
| `tenant_id` | integer |  | 仅管理员可用:按租户过滤。租户凭据调用时忽略,只返回本租户数据。 |
| `port` | integer |  | 只列监听该端口的转发。 |
| `group_id` | integer |  | 只列该分组里的转发。 |
| `upid` | integer |  | 只列该用户套餐下的转发。 |
| `enabled` | boolean |  | 按启停过滤。 |
| `id` | integer |  | 按转发 id 精确过滤。 |
| `origin` | string |  | 按源站 IP 子串过滤。 |
| `protocol` | string |  | 只列有该协议监听的转发。 可选值: ["tcp","udp"] |
| `stop_code` | integer |  | 按停用码过滤;0 = 正常。 |
| `package_id` | integer |  | 按基础套餐过滤。 |
| `region_id` | integer |  | 按区域过滤:接入名的主线路分组属于该区域;没有自己接入名的按所属已售套餐的共用接入名算。 |
| `node_group_id` | integer |  | 按线路分组过滤:接入名的主线路分组或备用线路分组是它。 |
| `cname_domain_id` | integer |  | 按接入根域过滤。 |
| `cname_hostname` | string |  | 按接入名主机记录精确过滤。 |
| `sync_state` | string |  | 按配置同步状态过滤:behind = 配置落后(还有在线节点没装上它最近一次修改后的配置版本); 可选值: ["behind","synced"] |

```sh
curl "https://panel.example.com/api/v2/streams" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### POST `/api/v2/streams`

创建四层转发 · 鉴权: 用户（部分参数仅管理员）

查询参数:

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `tenant_id` | integer |  | 管理员代建时的属主租户(必填);租户调用时忽略,属主恒为本人。 |

请求体:

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `acl` | StreamAcl |  | 四层访问控制:逐条按来源 IP/网段匹配,首条命中定结果,都不中按 default_action;deny 直接断开连接。 |
| `balance` | StreamBalance |  | 负载方式:rr 轮询、ip_hash 按来源 IP 哈希、least_conn 最少连接、random 随机。 可选值: ["rr","ip_hash","least_conn","random"] |
| `cname` | CnameBinding |  | 接入名(CNAME):用户把域名 CNAME 到 fqdn,解析由平台按节点组生成;没有接入名时为 null。 |
| `conn_limit` | integer |  | 单 IP 并发连接上限,0 = 不限。 |
| `enabled` | boolean |  | 是否启用 |
| `expected_updated_at` | string |  | 乐观锁(修改时用):调用方读到的该资源 updated_at。与库里当前值不等则回 409 stale_version、不保存;不带则不检查;创建时忽略。 |
| `group_ids` | integer[] |  | 所属转发分组 id 列表。 |
| `listen` | StreamListen[] | 有 | 监听列表:每项为端口与协议。 |
| `name` | string |  | 名称 |
| `origin_port` | integer | 有 | 回源端口。 |
| `origins` | StreamOrigin[] | 有 | 源站列表:每项为源站 IP、权重与备用/下线标记。 |
| `proxy_protocol` | boolean |  | 是否向源站发送 PROXY protocol 头。 |
| `stop_code` | integer |  | 0 = 正常;非 0 = 新连接直接断开(管理员/计费设置;用户套餐到期时快照里为 512)。 |
| `udp_responses` | integer |  | UDP 应答数:1~100 = 每个 UDP 会话收到源站这么多个包就结束(不再等 UDP 空闲超时),0 = 不设。只适合一问一答(DNS、探测);一问多答的游戏/语音别设,会被提前断开。 |
| `upid` | integer |  | 用户套餐 id(空 = 不核配额;快照里空时取 tenant_id)。 |

```sh
curl -X POST "https://panel.example.com/api/v2/streams" \
  -H "X-API-Key: $GOCDN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listen":[{"port":30001}],"name":"demo","origin_port":22,"origins":[{"host":"203.0.113.10"}]}'
```

### POST `/api/v2/streams/batch`

批量操作四层转发 · 鉴权: 用户（部分参数仅管理员）

查询参数:

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `tenant_id` | integer |  | 管理员代建时的属主租户(必填);租户调用时忽略,属主恒为本人。 |

请求体:

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `action` | string | 有 | 操作类型:set_enabled 启停、delete 删除、set_groups 换分组、update 批量修改、create 批量新建、 set_lines 改接入名的主/备线路分组(仅管理员)、set_cname_domain 改接入名的根域(仅管理员,主机记录不变)。 可选值: ["set_enabled","delete","set_groups","update","create","set_lines","set_cname_domain"] |
| `backup_group_id` | integer |  | set_lines 用:备用线路分组;0 = 清空,不给 = 不动。 |
| `cname_domain_id` | integer |  | set_cname_domain 用:新的接入根域。 |
| `enabled` | boolean |  | 是否启用 |
| `group_ids` | integer[] |  | 所属转发分组 id 列表。 |
| `ids` | integer[] |  | 要操作的转发 id 列表,一次最多 100 条(create 以外的操作必填)。 |
| `items` | StreamWrite[] |  | create 用:要新建的转发(最多 100 条),每条同 POST /streams 的请求体。 |
| `node_group_id` | integer |  | set_lines 用:主线路分组(必填)。 |
| `patch` | StreamPatch |  | 批量 update 用:给了的字段改到每一条上,规则同单条修改。 |
| `region_id` | integer |  | set_lines 用:区域;给了就校验主/备线路分组都属于它(不给不校验)。 |

```sh
curl -X POST "https://panel.example.com/api/v2/streams/batch" \
  -H "X-API-Key: $GOCDN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"action":"set_enabled","enabled":false,"ids":[1]}'
```

### GET `/api/v2/streams/{id}`

获取四层转发 · 鉴权: 用户（部分参数仅管理员）

```sh
curl "https://panel.example.com/api/v2/streams/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

### PUT `/api/v2/streams/{id}`

修改四层转发 · 鉴权: 用户（部分参数仅管理员）

请求体:

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `acl` | StreamAcl |  | 四层访问控制:逐条按来源 IP/网段匹配,首条命中定结果,都不中按 default_action;deny 直接断开连接。 |
| `balance` | StreamBalance |  | 负载方式:rr 轮询、ip_hash 按来源 IP 哈希、least_conn 最少连接、random 随机。 可选值: ["rr","ip_hash","least_conn","random"] |
| `cname` | CnameBinding |  | 接入名(CNAME):用户把域名 CNAME 到 fqdn,解析由平台按节点组生成;没有接入名时为 null。 |
| `conn_limit` | integer |  | 单 IP 并发连接上限,0 = 不限。 |
| `enabled` | boolean |  | 是否启用 |
| `expected_updated_at` | string |  | 乐观锁(修改时用):调用方读到的该资源 updated_at。与库里当前值不等则回 409 stale_version、不保存;不带则不检查;创建时忽略。 |
| `group_ids` | integer[] |  | 所属转发分组 id 列表。 |
| `listen` | StreamListen[] | 有 | 监听列表:每项为端口与协议。 |
| `name` | string |  | 名称 |
| `origin_port` | integer | 有 | 回源端口。 |
| `origins` | StreamOrigin[] | 有 | 源站列表:每项为源站 IP、权重与备用/下线标记。 |
| `proxy_protocol` | boolean |  | 是否向源站发送 PROXY protocol 头。 |
| `stop_code` | integer |  | 0 = 正常;非 0 = 新连接直接断开(管理员/计费设置;用户套餐到期时快照里为 512)。 |
| `udp_responses` | integer |  | UDP 应答数:1~100 = 每个 UDP 会话收到源站这么多个包就结束(不再等 UDP 空闲超时),0 = 不设。只适合一问一答(DNS、探测);一问多答的游戏/语音别设,会被提前断开。 |
| `upid` | integer |  | 用户套餐 id(空 = 不核配额;快照里空时取 tenant_id)。 |

```sh
curl -X PUT "https://panel.example.com/api/v2/streams/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY" \
  -H "Content-Type: application/json" \
  -d '{"listen":[{"port":30001}],"name":"demo","origin_port":22,"origins":[{"host":"203.0.113.10"}]}'
```

### DELETE `/api/v2/streams/{id}`

删除四层转发 · 鉴权: 用户（部分参数仅管理员）

```sh
curl -X DELETE "https://panel.example.com/api/v2/streams/{id}" \
  -H "X-API-Key: $GOCDN_API_KEY"
```

四层转发对象:

| 字段 | 类型 | 必填 | 说明 |
|---|---|---|---|
| `acl` | StreamAcl |  | 四层访问控制:逐条按来源 IP/网段匹配,首条命中定结果,都不中按 default_action;deny 直接断开连接。 |
| `action` | string | 有 | 操作类型:set_enabled 启停、delete 删除、set_groups 换分组、update 批量修改、create 批量新建、 set_lines 改接入名的主/备线路分组(仅管理员)、set_cname_domain 改接入名的根域(仅管理员,主机记录不变)。 可选值: ["set_enabled","delete","set_groups","update","create","set_lines","set_cname_domain"] |
| `affected` | integer |  | 受影响的条数 |
| `backup_group_id` | integer |  | set_lines 用:备用线路分组;0 = 清空,不给 = 不动。 |
| `balance` | StreamBalance |  | 负载方式:rr 轮询、ip_hash 按来源 IP 哈希、least_conn 最少连接、random 随机。 可选值: ["rr","ip_hash","least_conn","random"] |
| `cname` | CnameBinding |  | 接入名(CNAME):用户把域名 CNAME 到 fqdn,解析由平台按节点组生成;没有接入名时为 null。 |
| `cname_domain_id` | integer |  | set_cname_domain 用:新的接入根域。 |
| `conn_limit` | integer |  | 单 IP 并发连接上限,0 = 不限。 |
| `created_at` | string |  | 创建时间 (只读) |
| `enabled` | boolean |  | 是否启用 |
| `expected_updated_at` | string |  | 乐观锁(修改时用):调用方读到的该资源 updated_at。与库里当前值不等则回 409 stale_version、不保存;不带则不检查;创建时忽略。 |
| `group_ids` | integer[] |  | 所属转发分组 id 列表。 |
| `id` | integer |  | 记录 ID (只读) |
| `ids` | integer[] |  | 要操作的转发 id 列表,一次最多 100 条(create 以外的操作必填)。 |
| `items` | StreamWrite[] |  | create 用:要新建的转发(最多 100 条),每条同 POST /streams 的请求体。 |
| `listen` | StreamListen[] |  | 监听列表:每项为端口与协议。 |
| `name` | string |  | 名称 |
| `node_group_id` | integer |  | set_lines 用:主线路分组(必填)。 |
| `node_issues` | NodeIssue[] |  | 在线节点上这条转发没完全生效的口或原因(列表与详情里给);都正常时不给这个字段。 (只读) |
| `origin_port` | integer |  | 回源端口。 |
| `origins` | StreamOrigin[] |  | 源站列表:每项为源站 IP、权重与备用/下线标记。 |
| `patch` | StreamPatch |  | 批量 update 用:给了的字段改到每一条上,规则同单条修改。 |
| `proxy_protocol` | boolean |  | 是否向源站发送 PROXY protocol 头。 |
| `region_id` | integer |  | set_lines 用:区域;给了就校验主/备线路分组都属于它(不给不校验)。 |
| `stop_code` | integer |  | 0 = 正常;非 0 = 新连接直接断开(管理员/计费设置;用户套餐到期时快照里为 512)。 |
| `tenant_id` | integer |  | 所属租户(用户)ID (只读) |
| `udp_responses` | integer |  | UDP 应答数:1~100 = 每个 UDP 会话收到源站这么多个包就结束(不再等 UDP 空闲超时),0 = 不设。只适合一问一答(DNS、探测);一问多答的游戏/语音别设,会被提前断开。 |
| `updated_at` | string |  | 更新时间 (只读) |
| `upid` | integer |  | 用户套餐 id(空 = 不核配额;快照里空时取 tenant_id)。 |
