Name | sing-box-config JSON |
Version |
0.4.0
JSON |
| download |
home_page | None |
Summary | The configuration generator for sing-box |
upload_time | 2025-08-04 15:44:27 |
maintainer | None |
docs_url | None |
author | None |
requires_python | >=3.11 |
license | None |
keywords |
ansible
tproxy
sing-box
|
VCS |
 |
bugtrack_url |
|
requirements |
No requirements were recorded.
|
Travis-CI |
No Travis.
|
coveralls test coverage |
No coveralls.
|
# sing-box-tproxy
## 项目简介
本项目使用 Ansible 将 [SagerNet/sing-box](https://github.com/SagerNet/sing-box) 配置为 [Tproxy](https://sing-box.sagernet.org/configuration/inbound/tproxy/) 模式透明代理.
## 项目结构
### PyPI package [sing-box-config](https://pypi.org/project/sing-box-config/)
sing-box-config 只是整个项目中用于生成 sing-box 配置文件的一部分.
由于 [SagerNet/sing-box](https://github.com/SagerNet/sing-box) 不像 [Dreamacro/clash](https://github.com/Dreamacro/clash) 那样支持 proxy-providers, 因此在使用第三方的代理节点时, 需要自行处理节点更新. 再加上我有一些自定义 routes 和 proxy groups 的需求, 于是编写了这个 sing-box-config, 用于定时更新 sing-box 配置文件.
sing-box-config 需要读取 `config/` 目录下的两个 Jinja2 template, Ansible 将其渲染为 .json 文件作为 sing-box-config 工具的输入文件, 根据 subscriptions.url 获取到 proxies 后将两个 .json 文件合并为最终的 /etc/sing-box/config.json 文件.
- [config/base.json.j2](./config/base.json.j2)
- sing-box 的基础配置文件, 包含 `dns`, `route` 和 `inbounds` 等不容易发生变更的配置段
- [config/subscriptions.json.j2](./config/subscriptions.json.j2)
- `subscriptions` 配置是 sing-box-config 工具的自定义配置段, 合并最终配置文件前会被移除
- `subscriptions.type` 当前仅支持 Shadowsocks `SIP002`, 后续如有需求可另行适配
- `outbounds` 配置段中包含一些按地区分组与预定义的 proxy groups
### playbook.yaml 与 Ansible roles
- [playbook.yaml](./playbook.yaml) 是 ansible-playbook 的入口文件.
- 在 playbook 的 tasks 中使用 `import_role` 静态导入了项目中的 Ansible roles.
- 使用 Ansible roles 封装复杂任务可以简化 playbook 的结构.
- [roles/sing_box_install](./roles/sing_box_install/)
- 用于在远程主机上设置 sing-box 的 apt 仓库并安装 sing-box.
- [roles/sing_box_config](./roles/sing_box_config/)
- 在远程主机上创建 proxy 用户和工作目录
- 安装 sing-box-config 命令行工具
- 可选配置 sing-box-config-updater.timer 以实现定时更新 sing-box config.json
- [roles/sing_box_tproxy](./roles/sing_box_tproxy/)
- 用于将远程主机配置为 Tproxy 模式的透明代理.
- 包括加载必要的内核模块, 启用 IP 转发, 配置 nftables 防火墙规则, 开启 TCP BBR 拥塞控制协议等.
- 配置 sing-box-reload.path 监听 /etc/sing-box/config.json 文件的变化, 如发生变化则 reload sing-box 进程
## 使用指南
要顺利使用本项目, 需要具备一定的 Linux 和 Ansible 基础. 如果您对 Ansible 完全不了解, 可以参考 [Getting started with Ansible](https://docs.ansible.com/ansible/latest/getting_started/index.html) 快速入门.
1. 安装 Ansible:
使用 `pipx` 安装 Ansible, 具体步骤请参考 [Installing and upgrading Ansible with pipx](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-and-upgrading-ansible-with-pipx), 注意安装后将 `${HOME}/.local/bin` 目录加入系统 PATH,
```ShellSession
$ pipx install --include-deps ansible
installed package ansible 11.5.0, installed using Python 3.11.2
```
2. 配置 Linux 虚拟机, SSH credentials 和 [Ansible Inventory](https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html). 以下是示例配置:
```yaml
# ~/.ansible/inventory/pve-sing-box-tproxy.yaml
all:
hosts:
pve-sing-box-tproxy-253:
ansible_host: 10.42.0.253
ansible_user: debian
pve-sing-box-tproxy:
hosts:
pve-sing-box-tproxy-253:
```
3. 验证主机连接:
```ShellSession
$ ansible -m ping pve-sing-box-tproxy
pve-sing-box-tproxy-253 | SUCCESS => {
"ansible_facts": {
"discovered_interpreter_python": "/usr/bin/python3"
},
"changed": false,
"ping": "pong"
}
```
4. 修改 `config/subscriptions.json.j2` 文件中的 `subscriptions` 配置段, 注意将示例配置中的 example 和 url 替换为真实的值, 目前 type 仅支持 Shadowsocks `SIP002`.
```json
{
"subscriptions": {
"example": {
"type": "SIP002",
"exclude": [
"过期|Expire|\\d+(\\.\\d+)? ?GB|流量|Traffic|QQ群|官网|Premium"
],
"url": "https://sub.example.com/subscriptions.txt"
}
}
}
```
5. 执行 playbook.yaml:
```ShellSession
$ ansible-playbook playbook.yaml -e 'playbook_hosts=pve-sing-box-tproxy'
```
## 参考资料
- [sing-box](https://github.com/SagerNet/sing-box)
- [Tproxy](https://sing-box.sagernet.org/configuration/inbound/tproxy/)
- [sing-box tproxy](https://lhy.life/20231012-sing-box-tproxy/)
- [SagerNet/serenity](https://github.com/SagerNet/serenity)
- [SIP002](https://github.com/shadowsocks/shadowsocks-org/wiki/SIP002-URI-Scheme)
Raw data
{
"_id": null,
"home_page": null,
"name": "sing-box-config",
"maintainer": null,
"docs_url": null,
"requires_python": ">=3.11",
"maintainer_email": null,
"keywords": "ansible, tproxy, sing-box",
"author": null,
"author_email": "ak1ra <git@ak1ra.xyz>",
"download_url": "https://files.pythonhosted.org/packages/4c/b1/e832bd02e0809ebb5d5fd2fbe256f5848188a5f3f16a2edab111096c0dae/sing_box_config-0.4.0.tar.gz",
"platform": null,
"description": "# sing-box-tproxy\n\n## \u9879\u76ee\u7b80\u4ecb\n\n\u672c\u9879\u76ee\u4f7f\u7528 Ansible \u5c06 [SagerNet/sing-box](https://github.com/SagerNet/sing-box) \u914d\u7f6e\u4e3a [Tproxy](https://sing-box.sagernet.org/configuration/inbound/tproxy/) \u6a21\u5f0f\u900f\u660e\u4ee3\u7406.\n\n## \u9879\u76ee\u7ed3\u6784\n\n### PyPI package [sing-box-config](https://pypi.org/project/sing-box-config/)\n\nsing-box-config \u53ea\u662f\u6574\u4e2a\u9879\u76ee\u4e2d\u7528\u4e8e\u751f\u6210 sing-box \u914d\u7f6e\u6587\u4ef6\u7684\u4e00\u90e8\u5206.\n\n\u7531\u4e8e [SagerNet/sing-box](https://github.com/SagerNet/sing-box) \u4e0d\u50cf [Dreamacro/clash](https://github.com/Dreamacro/clash) \u90a3\u6837\u652f\u6301 proxy-providers, \u56e0\u6b64\u5728\u4f7f\u7528\u7b2c\u4e09\u65b9\u7684\u4ee3\u7406\u8282\u70b9\u65f6, \u9700\u8981\u81ea\u884c\u5904\u7406\u8282\u70b9\u66f4\u65b0. \u518d\u52a0\u4e0a\u6211\u6709\u4e00\u4e9b\u81ea\u5b9a\u4e49 routes \u548c proxy groups \u7684\u9700\u6c42, \u4e8e\u662f\u7f16\u5199\u4e86\u8fd9\u4e2a sing-box-config, \u7528\u4e8e\u5b9a\u65f6\u66f4\u65b0 sing-box \u914d\u7f6e\u6587\u4ef6.\n\nsing-box-config \u9700\u8981\u8bfb\u53d6 `config/` \u76ee\u5f55\u4e0b\u7684\u4e24\u4e2a Jinja2 template, Ansible \u5c06\u5176\u6e32\u67d3\u4e3a .json \u6587\u4ef6\u4f5c\u4e3a sing-box-config \u5de5\u5177\u7684\u8f93\u5165\u6587\u4ef6, \u6839\u636e subscriptions.url \u83b7\u53d6\u5230 proxies \u540e\u5c06\u4e24\u4e2a .json \u6587\u4ef6\u5408\u5e76\u4e3a\u6700\u7ec8\u7684 /etc/sing-box/config.json \u6587\u4ef6.\n\n- [config/base.json.j2](./config/base.json.j2)\n - sing-box \u7684\u57fa\u7840\u914d\u7f6e\u6587\u4ef6, \u5305\u542b `dns`, `route` \u548c `inbounds` \u7b49\u4e0d\u5bb9\u6613\u53d1\u751f\u53d8\u66f4\u7684\u914d\u7f6e\u6bb5\n- [config/subscriptions.json.j2](./config/subscriptions.json.j2)\n - `subscriptions` \u914d\u7f6e\u662f sing-box-config \u5de5\u5177\u7684\u81ea\u5b9a\u4e49\u914d\u7f6e\u6bb5, \u5408\u5e76\u6700\u7ec8\u914d\u7f6e\u6587\u4ef6\u524d\u4f1a\u88ab\u79fb\u9664\n - `subscriptions.type` \u5f53\u524d\u4ec5\u652f\u6301 Shadowsocks `SIP002`, \u540e\u7eed\u5982\u6709\u9700\u6c42\u53ef\u53e6\u884c\u9002\u914d\n - `outbounds` \u914d\u7f6e\u6bb5\u4e2d\u5305\u542b\u4e00\u4e9b\u6309\u5730\u533a\u5206\u7ec4\u4e0e\u9884\u5b9a\u4e49\u7684 proxy groups\n\n### playbook.yaml \u4e0e Ansible roles\n\n- [playbook.yaml](./playbook.yaml) \u662f ansible-playbook \u7684\u5165\u53e3\u6587\u4ef6.\n - \u5728 playbook \u7684 tasks \u4e2d\u4f7f\u7528 `import_role` \u9759\u6001\u5bfc\u5165\u4e86\u9879\u76ee\u4e2d\u7684 Ansible roles.\n - \u4f7f\u7528 Ansible roles \u5c01\u88c5\u590d\u6742\u4efb\u52a1\u53ef\u4ee5\u7b80\u5316 playbook \u7684\u7ed3\u6784.\n- [roles/sing_box_install](./roles/sing_box_install/)\n - \u7528\u4e8e\u5728\u8fdc\u7a0b\u4e3b\u673a\u4e0a\u8bbe\u7f6e sing-box \u7684 apt \u4ed3\u5e93\u5e76\u5b89\u88c5 sing-box.\n- [roles/sing_box_config](./roles/sing_box_config/)\n - \u5728\u8fdc\u7a0b\u4e3b\u673a\u4e0a\u521b\u5efa proxy \u7528\u6237\u548c\u5de5\u4f5c\u76ee\u5f55\n - \u5b89\u88c5 sing-box-config \u547d\u4ee4\u884c\u5de5\u5177\n - \u53ef\u9009\u914d\u7f6e sing-box-config-updater.timer \u4ee5\u5b9e\u73b0\u5b9a\u65f6\u66f4\u65b0 sing-box config.json\n- [roles/sing_box_tproxy](./roles/sing_box_tproxy/)\n - \u7528\u4e8e\u5c06\u8fdc\u7a0b\u4e3b\u673a\u914d\u7f6e\u4e3a Tproxy \u6a21\u5f0f\u7684\u900f\u660e\u4ee3\u7406.\n - \u5305\u62ec\u52a0\u8f7d\u5fc5\u8981\u7684\u5185\u6838\u6a21\u5757, \u542f\u7528 IP \u8f6c\u53d1, \u914d\u7f6e nftables \u9632\u706b\u5899\u89c4\u5219, \u5f00\u542f TCP BBR \u62e5\u585e\u63a7\u5236\u534f\u8bae\u7b49.\n - \u914d\u7f6e sing-box-reload.path \u76d1\u542c /etc/sing-box/config.json \u6587\u4ef6\u7684\u53d8\u5316, \u5982\u53d1\u751f\u53d8\u5316\u5219 reload sing-box \u8fdb\u7a0b\n\n## \u4f7f\u7528\u6307\u5357\n\n\u8981\u987a\u5229\u4f7f\u7528\u672c\u9879\u76ee, \u9700\u8981\u5177\u5907\u4e00\u5b9a\u7684 Linux \u548c Ansible \u57fa\u7840. \u5982\u679c\u60a8\u5bf9 Ansible \u5b8c\u5168\u4e0d\u4e86\u89e3, \u53ef\u4ee5\u53c2\u8003 [Getting started with Ansible](https://docs.ansible.com/ansible/latest/getting_started/index.html) \u5feb\u901f\u5165\u95e8.\n\n1. \u5b89\u88c5 Ansible:\n \u4f7f\u7528 `pipx` \u5b89\u88c5 Ansible, \u5177\u4f53\u6b65\u9aa4\u8bf7\u53c2\u8003 [Installing and upgrading Ansible with pipx](https://docs.ansible.com/ansible/latest/installation_guide/intro_installation.html#installing-and-upgrading-ansible-with-pipx), \u6ce8\u610f\u5b89\u88c5\u540e\u5c06 `${HOME}/.local/bin` \u76ee\u5f55\u52a0\u5165\u7cfb\u7edf PATH,\n\n ```ShellSession\n $ pipx install --include-deps ansible\n installed package ansible 11.5.0, installed using Python 3.11.2\n ```\n\n2. \u914d\u7f6e Linux \u865a\u62df\u673a, SSH credentials \u548c [Ansible Inventory](https://docs.ansible.com/ansible/latest/inventory_guide/intro_inventory.html). \u4ee5\u4e0b\u662f\u793a\u4f8b\u914d\u7f6e:\n\n ```yaml\n # ~/.ansible/inventory/pve-sing-box-tproxy.yaml\n all:\n hosts:\n pve-sing-box-tproxy-253:\n ansible_host: 10.42.0.253\n ansible_user: debian\n\n pve-sing-box-tproxy:\n hosts:\n pve-sing-box-tproxy-253:\n ```\n\n3. \u9a8c\u8bc1\u4e3b\u673a\u8fde\u63a5:\n\n ```ShellSession\n $ ansible -m ping pve-sing-box-tproxy\n pve-sing-box-tproxy-253 | SUCCESS => {\n \"ansible_facts\": {\n \"discovered_interpreter_python\": \"/usr/bin/python3\"\n },\n \"changed\": false,\n \"ping\": \"pong\"\n }\n ```\n\n4. \u4fee\u6539 `config/subscriptions.json.j2` \u6587\u4ef6\u4e2d\u7684 `subscriptions` \u914d\u7f6e\u6bb5, \u6ce8\u610f\u5c06\u793a\u4f8b\u914d\u7f6e\u4e2d\u7684 example \u548c url \u66ff\u6362\u4e3a\u771f\u5b9e\u7684\u503c, \u76ee\u524d type \u4ec5\u652f\u6301 Shadowsocks `SIP002`.\n\n ```json\n {\n \"subscriptions\": {\n \"example\": {\n \"type\": \"SIP002\",\n \"exclude\": [\n \"\u8fc7\u671f|Expire|\\\\d+(\\\\.\\\\d+)? ?GB|\u6d41\u91cf|Traffic|QQ\u7fa4|\u5b98\u7f51|Premium\"\n ],\n \"url\": \"https://sub.example.com/subscriptions.txt\"\n }\n }\n }\n ```\n\n5. \u6267\u884c playbook.yaml:\n\n ```ShellSession\n $ ansible-playbook playbook.yaml -e 'playbook_hosts=pve-sing-box-tproxy'\n ```\n\n## \u53c2\u8003\u8d44\u6599\n\n- [sing-box](https://github.com/SagerNet/sing-box)\n- [Tproxy](https://sing-box.sagernet.org/configuration/inbound/tproxy/)\n- [sing-box tproxy](https://lhy.life/20231012-sing-box-tproxy/)\n- [SagerNet/serenity](https://github.com/SagerNet/serenity)\n- [SIP002](https://github.com/shadowsocks/shadowsocks-org/wiki/SIP002-URI-Scheme)\n",
"bugtrack_url": null,
"license": null,
"summary": "The configuration generator for sing-box",
"version": "0.4.0",
"project_urls": {
"Changelog": "https://github.com/ak1ra-lab/sing-box-tproxy/blob/master/CHANGELOG.md",
"Homepage": "https://github.com/ak1ra-lab/sing-box-tproxy"
},
"split_keywords": [
"ansible",
" tproxy",
" sing-box"
],
"urls": [
{
"comment_text": null,
"digests": {
"blake2b_256": "56b0dc8e2a31c17efe2b4eade6138d885b52b3d7581eb4fd20aa0715d8be1a18",
"md5": "be54592707a8cdcbb18f960ee13add03",
"sha256": "4125f90dba07cc6023c56fdba342c97dc3e4d17d7b4ed907cab3a1335e8a8903"
},
"downloads": -1,
"filename": "sing_box_config-0.4.0-py3-none-any.whl",
"has_sig": false,
"md5_digest": "be54592707a8cdcbb18f960ee13add03",
"packagetype": "bdist_wheel",
"python_version": "py3",
"requires_python": ">=3.11",
"size": 26238,
"upload_time": "2025-08-04T15:44:25",
"upload_time_iso_8601": "2025-08-04T15:44:25.862714Z",
"url": "https://files.pythonhosted.org/packages/56/b0/dc8e2a31c17efe2b4eade6138d885b52b3d7581eb4fd20aa0715d8be1a18/sing_box_config-0.4.0-py3-none-any.whl",
"yanked": false,
"yanked_reason": null
},
{
"comment_text": null,
"digests": {
"blake2b_256": "4cb1e832bd02e0809ebb5d5fd2fbe256f5848188a5f3f16a2edab111096c0dae",
"md5": "9eeff02d7f9cbc75414d6520504720ba",
"sha256": "6bb248b5273709bcbb7be52beba8dd537e0eb5ec5af6249544777b020c704d04"
},
"downloads": -1,
"filename": "sing_box_config-0.4.0.tar.gz",
"has_sig": false,
"md5_digest": "9eeff02d7f9cbc75414d6520504720ba",
"packagetype": "sdist",
"python_version": "source",
"requires_python": ">=3.11",
"size": 19913,
"upload_time": "2025-08-04T15:44:27",
"upload_time_iso_8601": "2025-08-04T15:44:27.049978Z",
"url": "https://files.pythonhosted.org/packages/4c/b1/e832bd02e0809ebb5d5fd2fbe256f5848188a5f3f16a2edab111096c0dae/sing_box_config-0.4.0.tar.gz",
"yanked": false,
"yanked_reason": null
}
],
"upload_time": "2025-08-04 15:44:27",
"github": true,
"gitlab": false,
"bitbucket": false,
"codeberg": false,
"github_user": "ak1ra-lab",
"github_project": "sing-box-tproxy",
"travis_ci": false,
"coveralls": false,
"github_actions": true,
"lcname": "sing-box-config"
}