sing-box-config


Namesing-box-config JSON
Version 0.4.0 PyPI version JSON
download
home_pageNone
SummaryThe configuration generator for sing-box
upload_time2025-08-04 15:44:27
maintainerNone
docs_urlNone
authorNone
requires_python>=3.11
licenseNone
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"
}
        
Elapsed time: 0.74470s