mirror of
https://github.com/SagerNet/sing-box.git
synced 2026-04-13 20:28:32 +10:00
Compare commits
12 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
4db7eb9d9e | ||
|
|
fd4efd6104 | ||
|
|
19a35ec6a4 | ||
|
|
2012c0ca1e | ||
|
|
187421c754 | ||
|
|
b3fb86d415 | ||
|
|
88fafd4e30 | ||
|
|
8056932f9c | ||
|
|
c8af003bfc | ||
|
|
4999441a85 | ||
|
|
09b001e795 | ||
|
|
3b3a251008 |
@@ -117,8 +117,6 @@ nfpms:
|
|||||||
dst: /etc/systemd/system/sing-box@.service
|
dst: /etc/systemd/system/sing-box@.service
|
||||||
- src: LICENSE
|
- src: LICENSE
|
||||||
dst: /usr/share/licenses/sing-box/LICENSE
|
dst: /usr/share/licenses/sing-box/LICENSE
|
||||||
scripts:
|
|
||||||
postremove: release/config/postremove.sh
|
|
||||||
source:
|
source:
|
||||||
enabled: false
|
enabled: false
|
||||||
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
|
name_template: '{{ .ProjectName }}-{{ .Version }}.source'
|
||||||
|
|||||||
3
LICENSE
3
LICENSE
@@ -12,3 +12,6 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
In addition, no derivative work may use the name or imply association
|
||||||
|
with this application without prior consent.
|
||||||
|
|||||||
@@ -25,4 +25,7 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
In addition, no derivative work may use the name or imply association
|
||||||
|
with this application without prior consent.
|
||||||
```
|
```
|
||||||
@@ -1,3 +1,18 @@
|
|||||||
|
#### 1.2.2
|
||||||
|
|
||||||
|
* Accept `any` outbound in dns rule **1**
|
||||||
|
* Fix bugs and update dependencies
|
||||||
|
|
||||||
|
*1*:
|
||||||
|
|
||||||
|
Now you can use the `any` outbound rule to match server address queries instead of filling in all server domains to `domain` rule.
|
||||||
|
|
||||||
|
#### 1.2.1
|
||||||
|
|
||||||
|
* Fix missing default host in v2ray http transport`s request
|
||||||
|
* Flush DNS cache for macOS when tun start/close
|
||||||
|
* Fix tun's DNS hijacking compatibility with systemd-resolved
|
||||||
|
|
||||||
#### 1.2.0
|
#### 1.2.0
|
||||||
|
|
||||||
* Fix bugs and update dependencies
|
* Fix bugs and update dependencies
|
||||||
|
|||||||
@@ -232,6 +232,8 @@ Invert match result.
|
|||||||
|
|
||||||
Match outbound.
|
Match outbound.
|
||||||
|
|
||||||
|
`any` can be used as a value to match any outbound.
|
||||||
|
|
||||||
#### server
|
#### server
|
||||||
|
|
||||||
==Required==
|
==Required==
|
||||||
@@ -255,17 +257,3 @@ Disable cache and save cache in this query.
|
|||||||
#### rules
|
#### rules
|
||||||
|
|
||||||
Included default rules.
|
Included default rules.
|
||||||
|
|
||||||
#### invert
|
|
||||||
|
|
||||||
Invert match result.
|
|
||||||
|
|
||||||
#### server
|
|
||||||
|
|
||||||
==Required==
|
|
||||||
|
|
||||||
Tag of the target dns server.
|
|
||||||
|
|
||||||
#### disable_cache
|
|
||||||
|
|
||||||
Disable cache and save cache in this query.
|
|
||||||
@@ -231,6 +231,8 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
|
|||||||
|
|
||||||
匹配出站。
|
匹配出站。
|
||||||
|
|
||||||
|
`any` 可作为值用于匹配任意出站。
|
||||||
|
|
||||||
#### server
|
#### server
|
||||||
|
|
||||||
==必填==
|
==必填==
|
||||||
@@ -254,17 +256,3 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
|
|||||||
#### rules
|
#### rules
|
||||||
|
|
||||||
包括的默认规则。
|
包括的默认规则。
|
||||||
|
|
||||||
#### invert
|
|
||||||
|
|
||||||
反选匹配结果。
|
|
||||||
|
|
||||||
#### server
|
|
||||||
|
|
||||||
==必填==
|
|
||||||
|
|
||||||
目标 DNS 服务器的标签。
|
|
||||||
|
|
||||||
#### disable_cache
|
|
||||||
|
|
||||||
在此查询中禁用缓存。
|
|
||||||
@@ -107,8 +107,7 @@ Enforce strict routing rules when `auto_route` is enabled:
|
|||||||
* Let unsupported network unreachable
|
* Let unsupported network unreachable
|
||||||
* Route all connections to tun
|
* Route all connections to tun
|
||||||
|
|
||||||
It prevents address leaks and makes DNS hijacking work on Android and Linux with systemd-resolved, but your device will
|
It prevents address leaks and makes DNS hijacking work on Android, but your device will not be accessible by others.
|
||||||
not be accessible by others.
|
|
||||||
|
|
||||||
*In Windows*:
|
*In Windows*:
|
||||||
|
|
||||||
|
|||||||
@@ -107,7 +107,7 @@ tun 接口的 IPv6 前缀。
|
|||||||
* 让不支持的网络无法到达
|
* 让不支持的网络无法到达
|
||||||
* 将所有连接路由到 tun
|
* 将所有连接路由到 tun
|
||||||
|
|
||||||
它可以防止地址泄漏,并使 DNS 劫持在 Android 和使用 systemd-resolved 的 Linux 上工作,但你的设备将无法其他设备被访问。
|
它可以防止地址泄漏,并使 DNS 劫持在 Android 上工作,但你的设备将无法其他设备被访问。
|
||||||
|
|
||||||
*在 Windows 中*:
|
*在 Windows 中*:
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
#### Install
|
#### Install
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git clone https://github.com/SagerNet/sing-box
|
git clone -b main https://github.com/SagerNet/sing-box
|
||||||
cd sing-box
|
cd sing-box
|
||||||
./release/local/install_go.sh # skip if you have go1.19 already installed
|
./release/local/install_go.sh # skip if you have golang already installed
|
||||||
./release/local/install.sh
|
./release/local/install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -7,9 +7,9 @@
|
|||||||
#### 安装
|
#### 安装
|
||||||
|
|
||||||
```shell
|
```shell
|
||||||
git clone https://github.com/SagerNet/sing-box
|
git clone -b main https://github.com/SagerNet/sing-box
|
||||||
cd sing-box
|
cd sing-box
|
||||||
./release/local/install_go.sh # 如果已安装 go1.19 则跳过
|
./release/local/install_go.sh # 如果已安装 golang 则跳过
|
||||||
./release/local/install.sh
|
./release/local/install.sh
|
||||||
```
|
```
|
||||||
|
|
||||||
|
|||||||
@@ -23,7 +23,10 @@
|
|||||||
"disable_cache": true
|
"disable_cache": true
|
||||||
},
|
},
|
||||||
{
|
{
|
||||||
"domain": "mydomain.com",
|
"outbound": "any",
|
||||||
|
"server": "local"
|
||||||
|
},
|
||||||
|
{
|
||||||
"geosite": "cn",
|
"geosite": "cn",
|
||||||
"server": "local"
|
"server": "local"
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -9,10 +9,6 @@ the public internet.
|
|||||||
|
|
||||||
`auto-route` cannot automatically hijack DNS requests when Android's `Private DNS` enabled or `strict_route` disabled.
|
`auto-route` cannot automatically hijack DNS requests when Android's `Private DNS` enabled or `strict_route` disabled.
|
||||||
|
|
||||||
##### on Linux
|
|
||||||
|
|
||||||
`auto-route` cannot automatically hijack DNS requests with `systemd-resolved` enabled and `strict_route` disabled.
|
|
||||||
|
|
||||||
#### System proxy
|
#### System proxy
|
||||||
|
|
||||||
##### on Linux
|
##### on Linux
|
||||||
|
|||||||
@@ -8,10 +8,6 @@
|
|||||||
|
|
||||||
`auto-route` 无法自动劫持 DNS 请求如果 `私人 DNS` 开启或 `strict_route` 禁用。
|
`auto-route` 无法自动劫持 DNS 请求如果 `私人 DNS` 开启或 `strict_route` 禁用。
|
||||||
|
|
||||||
##### Linux
|
|
||||||
|
|
||||||
`auto-route` 无法自动劫持 DNS 请求如果 `systemd-resolved` 开启且 `strict_route` 禁用。
|
|
||||||
|
|
||||||
#### 系统代理
|
#### 系统代理
|
||||||
|
|
||||||
##### Linux
|
##### Linux
|
||||||
|
|||||||
@@ -25,4 +25,7 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
In addition, no derivative work may use the name or imply association
|
||||||
|
with this application without prior consent.
|
||||||
```
|
```
|
||||||
|
|||||||
@@ -25,4 +25,7 @@ GNU General Public License for more details.
|
|||||||
|
|
||||||
You should have received a copy of the GNU General Public License
|
You should have received a copy of the GNU General Public License
|
||||||
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||||
|
|
||||||
|
In addition, no derivative work may use the name or imply association
|
||||||
|
with this application without prior consent.
|
||||||
```
|
```
|
||||||
|
|||||||
8
go.mod
8
go.mod
@@ -17,7 +17,7 @@ require (
|
|||||||
github.com/insomniacslk/dhcp v0.0.0-20230307103557-e252950ab961
|
github.com/insomniacslk/dhcp v0.0.0-20230307103557-e252950ab961
|
||||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||||
github.com/mholt/acmez v1.1.0
|
github.com/mholt/acmez v1.1.0
|
||||||
github.com/miekg/dns v1.1.52
|
github.com/miekg/dns v1.1.53
|
||||||
github.com/ooni/go-libtor v1.1.7
|
github.com/ooni/go-libtor v1.1.7
|
||||||
github.com/oschwald/maxminddb-golang v1.10.0
|
github.com/oschwald/maxminddb-golang v1.10.0
|
||||||
github.com/pires/go-proxyproto v0.7.0
|
github.com/pires/go-proxyproto v0.7.0
|
||||||
@@ -25,11 +25,11 @@ require (
|
|||||||
github.com/sagernet/gomobile v0.0.0-20221130124640-349ebaa752ca
|
github.com/sagernet/gomobile v0.0.0-20221130124640-349ebaa752ca
|
||||||
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
github.com/sagernet/quic-go v0.0.0-20230202071646-a8c8afb18b32
|
||||||
github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f
|
github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f
|
||||||
github.com/sagernet/sing v0.2.1-0.20230323071235-f8038854d286
|
github.com/sagernet/sing v0.2.1
|
||||||
github.com/sagernet/sing-dns v0.1.4
|
github.com/sagernet/sing-dns v0.1.5-0.20230331013337-06044a57b1da
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.0
|
github.com/sagernet/sing-shadowsocks v0.2.0
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0
|
github.com/sagernet/sing-shadowtls v0.1.0
|
||||||
github.com/sagernet/sing-tun v0.1.3-0.20230323073325-35d565af6515
|
github.com/sagernet/sing-tun v0.1.4-0.20230326080954-8848c0e4cbab
|
||||||
github.com/sagernet/sing-vmess v0.1.3
|
github.com/sagernet/sing-vmess v0.1.3
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37
|
||||||
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
github.com/sagernet/tfo-go v0.0.0-20230303015439-ffcfd8c41cf9
|
||||||
|
|||||||
16
go.sum
16
go.sum
@@ -70,8 +70,8 @@ github.com/logrusorgru/aurora v2.0.3+incompatible h1:tOpm7WcpBTn4fjmVfgpQq0EfczG
|
|||||||
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
github.com/logrusorgru/aurora v2.0.3+incompatible/go.mod h1:7rIyQOR62GCctdiQpZ/zOJlFyk6y+94wXzv6RNZgaR4=
|
||||||
github.com/mholt/acmez v1.1.0 h1:IQ9CGHKOHokorxnffsqDvmmE30mDenO1lptYZ1AYkHY=
|
github.com/mholt/acmez v1.1.0 h1:IQ9CGHKOHokorxnffsqDvmmE30mDenO1lptYZ1AYkHY=
|
||||||
github.com/mholt/acmez v1.1.0/go.mod h1:zwo5+fbLLTowAX8o8ETfQzbDtwGEXnPhkmGdKIP+bgs=
|
github.com/mholt/acmez v1.1.0/go.mod h1:zwo5+fbLLTowAX8o8ETfQzbDtwGEXnPhkmGdKIP+bgs=
|
||||||
github.com/miekg/dns v1.1.52 h1:Bmlc/qsNNULOe6bpXcUTsuOajd0DzRHwup6D9k1An0c=
|
github.com/miekg/dns v1.1.53 h1:ZBkuHr5dxHtB1caEOlZTLPo7D3L3TWckgUUs/RHfDxw=
|
||||||
github.com/miekg/dns v1.1.52/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
github.com/miekg/dns v1.1.53/go.mod h1:uInx36IzPl7FYnDcMeVWxj9byh7DutNykX4G9Sj60FY=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e h1:fD57ERR4JtEqsWbfPhv4DMiApHyliiK5xCTNVSPiaAs=
|
||||||
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
github.com/niemeyer/pretty v0.0.0-20200227124842-a10e7caefd8e/go.mod h1:zD1mROLANZcx1PVRCS0qkT7pwLkGfwJo4zjcN/Tysno=
|
||||||
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
github.com/onsi/ginkgo/v2 v2.2.0 h1:3ZNA3L1c5FYDFTTxbFeVGGD8jYvjYauHD30YgLxVsNI=
|
||||||
@@ -111,16 +111,16 @@ github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f h1:plVtFF9NVw5Py4
|
|||||||
github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
github.com/sagernet/reality v0.0.0-20230323230523-5fa25e693e7f/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||||
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
github.com/sagernet/sing v0.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
|
||||||
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
github.com/sagernet/sing v0.1.8/go.mod h1:jt1w2u7lJQFFSGLiRrRIs5YWmx4kAPfWuOejuDW9qMk=
|
||||||
github.com/sagernet/sing v0.2.1-0.20230323071235-f8038854d286 h1:0Td2b5l1KgrdlOnbRWgFFWsyb0TLoq/tP6j9Lut4JN0=
|
github.com/sagernet/sing v0.2.1 h1:r0STYeyfKBBtoAHsBtW1dQonxG+3Qidde7/1VAMhdn8=
|
||||||
github.com/sagernet/sing v0.2.1-0.20230323071235-f8038854d286/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
github.com/sagernet/sing v0.2.1/go.mod h1:9uHswk2hITw8leDbiLS/xn0t9nzBcbePxzm9PJhwdlw=
|
||||||
github.com/sagernet/sing-dns v0.1.4 h1:7VxgeoSCiiazDSaXXQVcvrTBxFpOePPq/4XdgnUDN+0=
|
github.com/sagernet/sing-dns v0.1.5-0.20230331013337-06044a57b1da h1:pZV4DRBArbgkajeCZWn3VqwLF+Wl7HOlAt5aSJuuKDk=
|
||||||
github.com/sagernet/sing-dns v0.1.4/go.mod h1:1+6pCa48B1AI78lD+/i/dLgpw4MwfnsSpZo0Ds8wzzk=
|
github.com/sagernet/sing-dns v0.1.5-0.20230331013337-06044a57b1da/go.mod h1:8x+rlRnPE/5/IagjlAUqR9TceRYRL2WyqmP5QYK3dkI=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.0 h1:ILDWL7pwWfkPLEbviE/MyCgfjaBmJY/JVVY+5jhSb58=
|
github.com/sagernet/sing-shadowsocks v0.2.0 h1:ILDWL7pwWfkPLEbviE/MyCgfjaBmJY/JVVY+5jhSb58=
|
||||||
github.com/sagernet/sing-shadowsocks v0.2.0/go.mod h1:ysYzszRLpNzJSorvlWRMuzU6Vchsp7sd52q+JNY4axw=
|
github.com/sagernet/sing-shadowsocks v0.2.0/go.mod h1:ysYzszRLpNzJSorvlWRMuzU6Vchsp7sd52q+JNY4axw=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
github.com/sagernet/sing-shadowtls v0.1.0 h1:05MYce8aR5xfKIn+y7xRFsdKhKt44QZTSEQW+lG5IWQ=
|
||||||
github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
github.com/sagernet/sing-shadowtls v0.1.0/go.mod h1:Kn1VUIprdkwCgkS6SXYaLmIpKzQbqBIKJBMY+RvBhYc=
|
||||||
github.com/sagernet/sing-tun v0.1.3-0.20230323073325-35d565af6515 h1:r25BJqn3o34g+bDdhoRU65zimKPfGCTv7nHuysyJojo=
|
github.com/sagernet/sing-tun v0.1.4-0.20230326080954-8848c0e4cbab h1:a9oeWuPBuIZ70qMhIIH6RrYhp886xN9jJIwsuu4ZFUo=
|
||||||
github.com/sagernet/sing-tun v0.1.3-0.20230323073325-35d565af6515/go.mod h1:1xzFt4zJ7CzXdbgPcy7+Lsg4ypZo0ivDNZ0oQdL3zEY=
|
github.com/sagernet/sing-tun v0.1.4-0.20230326080954-8848c0e4cbab/go.mod h1:4YxIDEkkCjGXDOTMPw1SXpLmCQUFAWuaQN250oo+928=
|
||||||
github.com/sagernet/sing-vmess v0.1.3 h1:q/+tsF46dvvapL6CpQBgPHJ6nQrDUZqEtLHCbsjO7iM=
|
github.com/sagernet/sing-vmess v0.1.3 h1:q/+tsF46dvvapL6CpQBgPHJ6nQrDUZqEtLHCbsjO7iM=
|
||||||
github.com/sagernet/sing-vmess v0.1.3/go.mod h1:GVXqAHwe9U21uS+Voh4YBIrADQyE4F9v0ayGSixSQAE=
|
github.com/sagernet/sing-vmess v0.1.3/go.mod h1:GVXqAHwe9U21uS+Voh4YBIrADQyE4F9v0ayGSixSQAE=
|
||||||
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
github.com/sagernet/smux v0.0.0-20230312102458-337ec2a5af37 h1:HuE6xSwco/Xed8ajZ+coeYLmioq0Qp1/Z2zczFaV8as=
|
||||||
|
|||||||
@@ -36,15 +36,16 @@ func (f Formatter) Format(ctx context.Context, level Level, tag string, message
|
|||||||
if tag != "" {
|
if tag != "" {
|
||||||
message = tag + ": " + message
|
message = tag + ": " + message
|
||||||
}
|
}
|
||||||
var id uint32
|
var id ID
|
||||||
var hasId bool
|
var hasId bool
|
||||||
if ctx != nil {
|
if ctx != nil {
|
||||||
id, hasId = IDFromContext(ctx)
|
id, hasId = IDFromContext(ctx)
|
||||||
}
|
}
|
||||||
if hasId {
|
if hasId {
|
||||||
|
activeDuration := formatDuration(time.Since(id.CreatedAt))
|
||||||
if !f.DisableColors {
|
if !f.DisableColors {
|
||||||
var color aurora.Color
|
var color aurora.Color
|
||||||
color = aurora.Color(uint8(id))
|
color = aurora.Color(uint8(id.ID))
|
||||||
color %= 215
|
color %= 215
|
||||||
row := uint(color / 36)
|
row := uint(color / 36)
|
||||||
column := uint(color % 36)
|
column := uint(color % 36)
|
||||||
@@ -62,9 +63,9 @@ func (f Formatter) Format(ctx context.Context, level Level, tag string, message
|
|||||||
color += 16
|
color += 16
|
||||||
color = color << 16
|
color = color << 16
|
||||||
color |= 1 << 14
|
color |= 1 << 14
|
||||||
message = F.ToString("[", aurora.Colorize(id, color).String(), "] ", message)
|
message = F.ToString("[", aurora.Colorize(id.ID, color).String(), " ", activeDuration, "] ", message)
|
||||||
} else {
|
} else {
|
||||||
message = F.ToString("[", id, "] ", message)
|
message = F.ToString("[", id.ID, " ", activeDuration, "] ", message)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
@@ -99,15 +100,16 @@ func (f Formatter) FormatWithSimple(ctx context.Context, level Level, tag string
|
|||||||
message = tag + ": " + message
|
message = tag + ": " + message
|
||||||
}
|
}
|
||||||
messageSimple := message
|
messageSimple := message
|
||||||
var id uint32
|
var id ID
|
||||||
var hasId bool
|
var hasId bool
|
||||||
if ctx != nil {
|
if ctx != nil {
|
||||||
id, hasId = IDFromContext(ctx)
|
id, hasId = IDFromContext(ctx)
|
||||||
}
|
}
|
||||||
if hasId {
|
if hasId {
|
||||||
|
activeDuration := formatDuration(time.Since(id.CreatedAt))
|
||||||
if !f.DisableColors {
|
if !f.DisableColors {
|
||||||
var color aurora.Color
|
var color aurora.Color
|
||||||
color = aurora.Color(uint8(id))
|
color = aurora.Color(uint8(id.ID))
|
||||||
color %= 215
|
color %= 215
|
||||||
row := uint(color / 36)
|
row := uint(color / 36)
|
||||||
column := uint(color % 36)
|
column := uint(color % 36)
|
||||||
@@ -125,11 +127,11 @@ func (f Formatter) FormatWithSimple(ctx context.Context, level Level, tag string
|
|||||||
color += 16
|
color += 16
|
||||||
color = color << 16
|
color = color << 16
|
||||||
color |= 1 << 14
|
color |= 1 << 14
|
||||||
message = F.ToString("[", aurora.Colorize(id, color).String(), "] ", message)
|
message = F.ToString("[", aurora.Colorize(id.ID, color).String(), " ", activeDuration, "] ", message)
|
||||||
} else {
|
} else {
|
||||||
message = F.ToString("[", id, "] ", message)
|
message = F.ToString("[", id.ID, " ", activeDuration, "] ", message)
|
||||||
}
|
}
|
||||||
messageSimple = F.ToString("[", id, "] ", messageSimple)
|
messageSimple = F.ToString("[", id.ID, " ", activeDuration, "] ", messageSimple)
|
||||||
|
|
||||||
}
|
}
|
||||||
switch {
|
switch {
|
||||||
@@ -153,3 +155,13 @@ func xd(value int, x int) string {
|
|||||||
}
|
}
|
||||||
return message
|
return message
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func formatDuration(duration time.Duration) string {
|
||||||
|
if duration < time.Second {
|
||||||
|
return F.ToString(duration.Milliseconds(), "ms")
|
||||||
|
} else if duration < time.Minute {
|
||||||
|
return F.ToString(int64(duration.Seconds()), ".", int64(duration.Seconds()*100)%100, "s")
|
||||||
|
} else {
|
||||||
|
return F.ToString(int64(duration.Minutes()), "m", int64(duration.Seconds())%60, "s")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
17
log/id.go
17
log/id.go
@@ -3,6 +3,7 @@ package log
|
|||||||
import (
|
import (
|
||||||
"context"
|
"context"
|
||||||
"math/rand"
|
"math/rand"
|
||||||
|
"time"
|
||||||
|
|
||||||
"github.com/sagernet/sing/common/random"
|
"github.com/sagernet/sing/common/random"
|
||||||
)
|
)
|
||||||
@@ -13,11 +14,19 @@ func init() {
|
|||||||
|
|
||||||
type idKey struct{}
|
type idKey struct{}
|
||||||
|
|
||||||
func ContextWithNewID(ctx context.Context) context.Context {
|
type ID struct {
|
||||||
return context.WithValue(ctx, (*idKey)(nil), rand.Uint32())
|
ID uint32
|
||||||
|
CreatedAt time.Time
|
||||||
}
|
}
|
||||||
|
|
||||||
func IDFromContext(ctx context.Context) (uint32, bool) {
|
func ContextWithNewID(ctx context.Context) context.Context {
|
||||||
id, loaded := ctx.Value((*idKey)(nil)).(uint32)
|
return context.WithValue(ctx, (*idKey)(nil), ID{
|
||||||
|
ID: rand.Uint32(),
|
||||||
|
CreatedAt: time.Now(),
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
func IDFromContext(ctx context.Context) (ID, bool) {
|
||||||
|
id, loaded := ctx.Value((*idKey)(nil)).(ID)
|
||||||
return id, loaded
|
return id, loaded
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -11,6 +11,11 @@ import (
|
|||||||
)
|
)
|
||||||
|
|
||||||
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.Outbound) (adapter.Outbound, error) {
|
func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, options option.Outbound) (adapter.Outbound, error) {
|
||||||
|
var metadata *adapter.InboundContext
|
||||||
|
if options.Tag != "" {
|
||||||
|
ctx, metadata = adapter.AppendContext(ctx)
|
||||||
|
metadata.Outbound = options.Tag
|
||||||
|
}
|
||||||
if options.Type == "" {
|
if options.Type == "" {
|
||||||
return nil, E.New("missing outbound type")
|
return nil, E.New("missing outbound type")
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -136,6 +136,9 @@ var _ N.Dialer = (*shadowsocksDialer)(nil)
|
|||||||
type shadowsocksDialer Shadowsocks
|
type shadowsocksDialer Shadowsocks
|
||||||
|
|
||||||
func (h *shadowsocksDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *shadowsocksDialer) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
switch N.NetworkName(network) {
|
switch N.NetworkName(network) {
|
||||||
case N.NetworkTCP:
|
case N.NetworkTCP:
|
||||||
var outConn net.Conn
|
var outConn net.Conn
|
||||||
@@ -161,6 +164,9 @@ func (h *shadowsocksDialer) DialContext(ctx context.Context, network string, des
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *shadowsocksDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (h *shadowsocksDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
|
outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return nil, err
|
return nil, err
|
||||||
|
|||||||
@@ -99,6 +99,9 @@ func NewShadowsocksR(ctx context.Context, router adapter.Router, logger log.Cont
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksR) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *ShadowsocksR) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
switch network {
|
switch network {
|
||||||
case N.NetworkTCP:
|
case N.NetworkTCP:
|
||||||
h.logger.InfoContext(ctx, "outbound connection to ", destination)
|
h.logger.InfoContext(ctx, "outbound connection to ", destination)
|
||||||
@@ -131,6 +134,9 @@ func (h *ShadowsocksR) DialContext(ctx context.Context, network string, destinat
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (h *ShadowsocksR) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (h *ShadowsocksR) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
h.logger.InfoContext(ctx, "outbound packet connection to ", destination)
|
||||||
outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
|
outConn, err := h.dialer.DialContext(ctx, N.NetworkUDP, h.serverAddr)
|
||||||
if err != nil {
|
if err != nil {
|
||||||
|
|||||||
@@ -86,23 +86,26 @@ func NewShadowTLS(ctx context.Context, router adapter.Router, logger log.Context
|
|||||||
return outbound, nil
|
return outbound, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ShadowTLS) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
func (h *ShadowTLS) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
|
||||||
|
ctx, metadata := adapter.AppendContext(ctx)
|
||||||
|
metadata.Outbound = h.tag
|
||||||
|
metadata.Destination = destination
|
||||||
switch N.NetworkName(network) {
|
switch N.NetworkName(network) {
|
||||||
case N.NetworkTCP:
|
case N.NetworkTCP:
|
||||||
return s.client.DialContext(ctx)
|
return h.client.DialContext(ctx)
|
||||||
default:
|
default:
|
||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ShadowTLS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
func (h *ShadowTLS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
|
||||||
return nil, os.ErrInvalid
|
return nil, os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ShadowTLS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
func (h *ShadowTLS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
|
||||||
return NewConnection(ctx, s, conn, metadata)
|
return NewConnection(ctx, h, conn, metadata)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *ShadowTLS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
func (h *ShadowTLS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
|
||||||
return os.ErrInvalid
|
return os.ErrInvalid
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
#!/bin/sh
|
|
||||||
|
|
||||||
rm -rf /var/lib/sing-box
|
|
||||||
@@ -4,10 +4,9 @@ Documentation=https://sing-box.sagernet.org
|
|||||||
After=network.target nss-lookup.target
|
After=network.target nss-lookup.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
WorkingDirectory=/var/lib/sing-box
|
|
||||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
ExecStart=/usr/bin/sing-box run -c /etc/sing-box/config.json
|
ExecStart=/usr/bin/sing-box -D /var/lib/sing-box -C /etc/sing-box run
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=10s
|
RestartSec=10s
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ Documentation=https://sing-box.sagernet.org
|
|||||||
After=network.target nss-lookup.target
|
After=network.target nss-lookup.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
WorkingDirectory=/var/lib/sing-box-%i
|
|
||||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
ExecStart=/usr/bin/sing-box run -c /etc/sing-box/%i.json
|
ExecStart=/usr/bin/sing-box -D /var/lib/sing-box-%i -c /etc/sing-box/%i.json run
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=10s
|
RestartSec=10s
|
||||||
|
|||||||
@@ -1,7 +1,9 @@
|
|||||||
#!/usr/bin/env bash
|
#!/usr/bin/env bash
|
||||||
|
|
||||||
set -e -o pipefail
|
set -e -o pipefail
|
||||||
curl -Lo go.tar.gz https://go.dev/dl/go1.20.1.linux-amd64.tar.gz
|
|
||||||
|
go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g')
|
||||||
|
curl -Lo go.tar.gz "https://go.dev/dl/go$go_version.linux-amd64.tar.gz"
|
||||||
sudo rm -rf /usr/local/go
|
sudo rm -rf /usr/local/go
|
||||||
sudo tar -C /usr/local -xzf go.tar.gz
|
sudo tar -C /usr/local -xzf go.tar.gz
|
||||||
rm go.tar.gz
|
rm go.tar.gz
|
||||||
|
|||||||
@@ -4,10 +4,9 @@ Documentation=https://sing-box.sagernet.org
|
|||||||
After=network.target nss-lookup.target
|
After=network.target nss-lookup.target
|
||||||
|
|
||||||
[Service]
|
[Service]
|
||||||
WorkingDirectory=/var/lib/sing-box
|
|
||||||
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
CapabilityBoundingSet=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
AmbientCapabilities=CAP_NET_ADMIN CAP_NET_BIND_SERVICE CAP_SYS_PTRACE CAP_DAC_READ_SEARCH
|
||||||
ExecStart=/usr/local/bin/sing-box run -c /usr/local/etc/sing-box/config.json
|
ExecStart=/usr/local/bin/sing-box -D /var/lib/sing-box -C /usr/local/etc/sing-box run
|
||||||
ExecReload=/bin/kill -HUP $MAINPID
|
ExecReload=/bin/kill -HUP $MAINPID
|
||||||
Restart=on-failure
|
Restart=on-failure
|
||||||
RestartSec=10s
|
RestartSec=10s
|
||||||
|
|||||||
@@ -12,17 +12,25 @@ var _ RuleItem = (*OutboundItem)(nil)
|
|||||||
type OutboundItem struct {
|
type OutboundItem struct {
|
||||||
outbounds []string
|
outbounds []string
|
||||||
outboundMap map[string]bool
|
outboundMap map[string]bool
|
||||||
|
matchAny bool
|
||||||
}
|
}
|
||||||
|
|
||||||
func NewOutboundRule(outbounds []string) *OutboundItem {
|
func NewOutboundRule(outbounds []string) *OutboundItem {
|
||||||
rule := &OutboundItem{outbounds, make(map[string]bool)}
|
rule := &OutboundItem{outbounds: outbounds, outboundMap: make(map[string]bool)}
|
||||||
for _, outbound := range outbounds {
|
for _, outbound := range outbounds {
|
||||||
rule.outboundMap[outbound] = true
|
if outbound == "any" {
|
||||||
|
rule.matchAny = true
|
||||||
|
} else {
|
||||||
|
rule.outboundMap[outbound] = true
|
||||||
|
}
|
||||||
}
|
}
|
||||||
return rule
|
return rule
|
||||||
}
|
}
|
||||||
|
|
||||||
func (r *OutboundItem) Match(metadata *adapter.InboundContext) bool {
|
func (r *OutboundItem) Match(metadata *adapter.InboundContext) bool {
|
||||||
|
if r.matchAny && metadata.Outbound != "" {
|
||||||
|
return true
|
||||||
|
}
|
||||||
return r.outboundMap[metadata.Outbound]
|
return r.outboundMap[metadata.Outbound]
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -12,6 +12,7 @@ import (
|
|||||||
"github.com/sagernet/sing-box/adapter"
|
"github.com/sagernet/sing-box/adapter"
|
||||||
"github.com/sagernet/sing-box/common/tls"
|
"github.com/sagernet/sing-box/common/tls"
|
||||||
"github.com/sagernet/sing-box/option"
|
"github.com/sagernet/sing-box/option"
|
||||||
|
"github.com/sagernet/sing-box/transport/v2rayhttp"
|
||||||
M "github.com/sagernet/sing/common/metadata"
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
|
|
||||||
@@ -93,3 +94,8 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
|
|||||||
}()
|
}()
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) Close() error {
|
||||||
|
v2rayhttp.CloseIdleConnections(c.transport)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
@@ -111,6 +111,7 @@ func (c *Client) dialHTTP(ctx context.Context) (net.Conn, error) {
|
|||||||
request = request.WithContext(ctx)
|
request = request.WithContext(ctx)
|
||||||
switch hostLen := len(c.host); hostLen {
|
switch hostLen := len(c.host); hostLen {
|
||||||
case 0:
|
case 0:
|
||||||
|
request.Host = c.serverAddr.AddrString()
|
||||||
case 1:
|
case 1:
|
||||||
request.Host = c.host[0]
|
request.Host = c.host[0]
|
||||||
default:
|
default:
|
||||||
@@ -144,6 +145,8 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
|
|||||||
request = request.WithContext(ctx)
|
request = request.WithContext(ctx)
|
||||||
switch hostLen := len(c.host); hostLen {
|
switch hostLen := len(c.host); hostLen {
|
||||||
case 0:
|
case 0:
|
||||||
|
// https://github.com/v2fly/v2ray-core/blob/master/transport/internet/http/config.go#L13
|
||||||
|
request.Host = "www.example.com"
|
||||||
case 1:
|
case 1:
|
||||||
request.Host = c.host[0]
|
request.Host = c.host[0]
|
||||||
default:
|
default:
|
||||||
@@ -164,3 +167,8 @@ func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
|
|||||||
}()
|
}()
|
||||||
return conn, nil
|
return conn, nil
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (c *Client) Close() error {
|
||||||
|
CloseIdleConnections(c.transport)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|||||||
13
transport/v2rayhttp/pool.go
Normal file
13
transport/v2rayhttp/pool.go
Normal file
@@ -0,0 +1,13 @@
|
|||||||
|
package v2rayhttp
|
||||||
|
|
||||||
|
import "net/http"
|
||||||
|
|
||||||
|
type ConnectionPool interface {
|
||||||
|
CloseIdleConnections()
|
||||||
|
}
|
||||||
|
|
||||||
|
func CloseIdleConnections(transport http.RoundTripper) {
|
||||||
|
if connectionPool, ok := transport.(ConnectionPool); ok {
|
||||||
|
connectionPool.CloseIdleConnections()
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user