Compare commits

...

17 Commits

Author SHA1 Message Date
世界
0348ace253 Initial release 2022-08-26 16:40:37 +08:00
世界
c5e38203eb Fix read DNS message 2022-08-26 13:35:27 +08:00
世界
9ac31d0233 Fix ipv6 route on linux 2022-08-26 12:30:31 +08:00
世界
9d8d1cd69d Update documentation 2022-08-26 11:10:02 +08:00
世界
07a0381f8b Cleanup vmessws 2022-08-26 10:22:29 +08:00
世界
f841459004 Cleanup vmesshttp 2022-08-26 08:41:45 +08:00
世界
78a26fc139 Update documentation 2022-08-25 22:49:23 +08:00
世界
9f6628445e Improve ip_cidr rule 2022-08-25 22:23:26 +08:00
世界
fa017b5977 Add contributing documentation 2022-08-25 21:08:29 +08:00
世界
58f4a970f2 Fix route connections 2022-08-25 20:48:59 +08:00
世界
021aa8faed Fix ipv6 route on linux 2022-08-25 18:57:36 +08:00
世界
83f6e037d6 Fix http proxy with compressed response 2022-08-25 18:40:13 +08:00
世界
baf153434d Fix issue template 2022-08-25 18:40:13 +08:00
世界
d481bd7993 Fix bind_address 2022-08-25 14:50:10 +08:00
Steven Tang
e859c0a6ef Fix typo in features.md (#32) 2022-08-25 13:42:22 +08:00
zakuwaki
59a39e66b1 Add trojan fallback for ALPN #31 2022-08-25 13:37:32 +08:00
世界
fd5ac69a35 Let vmess use zero instead of auto if TLS enabled 2022-08-25 11:51:17 +08:00
51 changed files with 502 additions and 220 deletions

View File

@@ -1,6 +1,5 @@
name: Bug Report name: Bug Report
description: "Create a report to help us improve." description: "Create a report to help us improve."
labels: [ bug ]
body: body:
- type: checkboxes - type: checkboxes
id: terms id: terms
@@ -56,7 +55,7 @@ body:
required: true required: true
- type: textarea - type: textarea
id: config id: log
attributes: attributes:
label: Server and client log file label: Server and client log file
value: |- value: |-

View File

@@ -49,7 +49,14 @@ snapshot:
ghr --delete --draft --prerelease -p 1 nightly dist/release ghr --delete --draft --prerelease -p 1 nightly dist/release
rm -r dist rm -r dist
snapshot_install: release:
goreleaser release --rm-dist --skip-publish
mkdir dist/release
mv dist/*.tar.gz dist/*.zip dist/*.deb dist/*.rpm dist/release
ghr --delete --draft --prerelease -p 3 $(shell git describe --tags) dist/release
rm -r dist
release_install:
go install -v github.com/goreleaser/goreleaser@latest go install -v github.com/goreleaser/goreleaser@latest
go install -v github.com/tcnksm/ghr@latest go install -v github.com/tcnksm/ghr@latest

View File

@@ -38,7 +38,7 @@ func printVersion(cmd *cobra.Command, args []string) {
version += runtime.Version() version += runtime.Version()
version += ", " version += ", "
version += runtime.GOOS version += runtime.GOOS
version += ", " version += "/"
version += runtime.GOARCH version += runtime.GOARCH
version += ", " version += ", "
version += "CGO " version += "CGO "

View File

@@ -113,7 +113,10 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
} }
var bindUDPAddr string var bindUDPAddr string
udpDialer := dialer udpDialer := dialer
bindAddress := netip.Addr(options.BindAddress) var bindAddress netip.Addr
if options.BindAddress != nil {
bindAddress = options.BindAddress.Build()
}
if bindAddress.IsValid() { if bindAddress.IsValid() {
dialer.LocalAddr = &net.TCPAddr{ dialer.LocalAddr = &net.TCPAddr{
IP: bindAddress.AsSlice(), IP: bindAddress.AsSlice(),

View File

@@ -22,7 +22,7 @@ func StreamDomainNameQuery(readCtx context.Context, reader io.Reader) (*adapter.
if err != nil { if err != nil {
return nil, err return nil, err
} }
if length > 512 { if length == 0 {
return nil, os.ErrInvalid return nil, os.ErrInvalid
} }
_buffer := buf.StackNewSize(int(length)) _buffer := buf.StackNewSize(int(length))

View File

@@ -1,6 +1,6 @@
package constant package constant
var ( var (
Version = "1.0" Version = "1.0-beta1"
Commit = "" Commit = ""
) )

View File

@@ -1,4 +1,22 @@
#### 2022/08/24 #### 1.0-beta1
* Initial release
##### 2022/08/26
* Fix ipv6 route on linux
* Fix read DNS message
##### 2022/08/25
* Let vmess use zero instead of auto if TLS enabled
* Add trojan fallback for ALPN
* Improve ip_cidr rule
* Fix format bind_address
* Fix http proxy with compressed response
* Fix route connections
##### 2022/08/24
* Fix naive padding * Fix naive padding
* Fix unix search path * Fix unix search path
@@ -7,7 +25,7 @@
* Fix early close on windows and catch any * Fix early close on windows and catch any
* Initial zh-CN document translation * Initial zh-CN document translation
#### 2022/08/23 ##### 2022/08/23
* Add [V2Ray Transport](/configuration/shared/v2ray-transport) support for VMess and Trojan * Add [V2Ray Transport](/configuration/shared/v2ray-transport) support for VMess and Trojan
* Allow plain http request in Naive inbound (It can now be used with nginx) * Allow plain http request in Naive inbound (It can now be used with nginx)
@@ -16,17 +34,17 @@
* Parse X-Forward-For in HTTP requests * Parse X-Forward-For in HTTP requests
* Handle SIGHUP signal * Handle SIGHUP signal
#### 2022/08/22 ##### 2022/08/22
* Add strategy setting for each [DNS server](/configuration/dns/server) * Add strategy setting for each [DNS server](/configuration/dns/server)
* Add bind address to outbound options * Add bind address to outbound options
#### 2022/08/21 ##### 2022/08/21
* Add [Tor outbound](/configuration/outbound/tor) * Add [Tor outbound](/configuration/outbound/tor)
* Add [SSH outbound](/configuration/outbound/ssh) * Add [SSH outbound](/configuration/outbound/ssh)
#### 2022/08/20 ##### 2022/08/20
* Attempt to unwrap ip-in-fqdn socksaddr * Attempt to unwrap ip-in-fqdn socksaddr
* Fix read packages in android 12 * Fix read packages in android 12
@@ -36,52 +54,52 @@
* Skip bind connection with private destination to interface * Skip bind connection with private destination to interface
* Add [Trojan connection fallback](/configuration/inbound/trojan#fallback) * Add [Trojan connection fallback](/configuration/inbound/trojan#fallback)
#### 2022/08/19 ##### 2022/08/19
* Add Hysteria [Inbound](/configuration/inbound/hysteria) and [Outbund](/configuration/outbound/hysteria) * Add Hysteria [Inbound](/configuration/inbound/hysteria) and [Outbund](/configuration/outbound/hysteria)
* Add [ACME TLS certificate issuer](/configuration/shared/tls) * Add [ACME TLS certificate issuer](/configuration/shared/tls)
* Allow read config from stdin (-c stdin) * Allow read config from stdin (-c stdin)
* Update gVisor to 20220815.0 * Update gVisor to 20220815.0
#### 2022/08/18 ##### 2022/08/18
* Fix find process with lwip stack * Fix find process with lwip stack
* Fix crash on shadowsocks server * Fix crash on shadowsocks server
* Fix crash on darwin tun * Fix crash on darwin tun
* Fix write log to file * Fix write log to file
#### 2022/08/17 ##### 2022/08/17
* Improve async dns transports * Improve async dns transports
#### 2022/08/16 ##### 2022/08/16
* Add ip_version (route/dns) rule item * Add ip_version (route/dns) rule item
* Add [WireGuard](/configuration/outbound/wireguard) outbound * Add [WireGuard](/configuration/outbound/wireguard) outbound
#### 2022/08/15 ##### 2022/08/15
* Add uid, android user and package rules support in [Tun](/configuration/inbound/tun) routing. * Add uid, android user and package rules support in [Tun](/configuration/inbound/tun) routing.
#### 2022/08/13 ##### 2022/08/13
* Fix dns concurrent write * Fix dns concurrent write
#### 2022/08/12 ##### 2022/08/12
* Performance improvements * Performance improvements
* Add UoT option for [SOCKS](/configuration/outbound/socks) outbound * Add UoT option for [SOCKS](/configuration/outbound/socks) outbound
#### 2022/08/11 ##### 2022/08/11
* Add UoT option for [Shadowsocks](/configuration/outbound/shadowsocks) outbound, UoT support for all inbounds * Add UoT option for [Shadowsocks](/configuration/outbound/shadowsocks) outbound, UoT support for all inbounds
#### 2022/08/10 ##### 2022/08/10
* Add full-featured [Naive](/configuration/inbound/naive) inbound * Add full-featured [Naive](/configuration/inbound/naive) inbound
* Fix default dns server option [#9] by iKirby * Fix default dns server option [#9] by iKirby
#### 2022/08/09 ##### 2022/08/09
No changelog before. No changelog before.

View File

@@ -1,3 +1,5 @@
# DNS
### Structure ### Structure
```json ```json

View File

@@ -38,7 +38,8 @@
"private" "private"
], ],
"source_ip_cidr": [ "source_ip_cidr": [
"10.0.0.0/24" "10.0.0.0/24",
"192.168.0.1"
], ],
"source_port": [ "source_port": [
12345 12345

View File

@@ -47,7 +47,7 @@ DNS 服务器的地址。
!!! warning "" !!! warning ""
默认安装不包含 QUIC 和 HTTP3 传输层,请参阅 [安装](/zh/#installation)。 默认安装不包含 QUIC 和 HTTP3 传输层,请参阅 [安装](/zh/#_2)。
!!! info "" !!! info ""

View File

@@ -1,3 +1,5 @@
# Experimental
### Structure ### Structure
```json ```json

View File

@@ -18,7 +18,7 @@
!!! error "" !!! error ""
默认安装不包含 Clash API参阅 [安装](/zh/#installation)。 默认安装不包含 Clash API参阅 [安装](/zh/#_2)。
!!! note "" !!! note ""

View File

@@ -32,7 +32,7 @@
!!! warning "" !!! warning ""
默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#installation)。 默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#_2)。
### Hysteria 字段 ### Hysteria 字段

View File

@@ -1,3 +1,5 @@
# Inbound
### Structure ### Structure
```json ```json

View File

@@ -30,7 +30,7 @@
!!! warning "" !!! warning ""
默认安装不包含 HTTP3 传输层, 参阅 [安装](/zh/#installation)。 默认安装不包含 HTTP3 传输层, 参阅 [安装](/zh/#_2)。
### Naive 字段 ### Naive 字段

View File

@@ -23,9 +23,15 @@
], ],
"tls": {}, "tls": {},
"fallback": { "fallback": {
"server": "127.0.0.0.1", "server": "127.0.0.1",
"server_port": 8080 "server_port": 8080
}, },
"fallback_for_alpn": {
"http/1.1": {
"server": "127.0.0.1",
"server_port": 8081
}
},
"transport": {} "transport": {}
} }
] ]
@@ -50,7 +56,13 @@ TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
There is no evidence that GFW detects and blocks Trojan servers based on HTTP responses, and opening the standard http/s port on the server is a much bigger signature. There is no evidence that GFW detects and blocks Trojan servers based on HTTP responses, and opening the standard http/s port on the server is a much bigger signature.
Fallback server configuration. Disabled if empty. Fallback server configuration. Disabled if `fallback` and `fallback_for_alpn` are empty.
#### fallback_for_alpn
Fallback server configuration for specified ALPN.
If not empty, TLS fallback requests with ALPN not in this table will be rejected.
#### transport #### transport

View File

@@ -6,7 +6,6 @@
{ {
"type": "trojan", "type": "trojan",
"tag": "trojan-in", "tag": "trojan-in",
"listen": "::", "listen": "::",
"listen_port": 2080, "listen_port": 2080,
"tcp_fast_open": false, "tcp_fast_open": false,
@@ -14,7 +13,6 @@
"sniff_override_destination": false, "sniff_override_destination": false,
"domain_strategy": "prefer_ipv6", "domain_strategy": "prefer_ipv6",
"proxy_protocol": false, "proxy_protocol": false,
"users": [ "users": [
{ {
"name": "sekai", "name": "sekai",
@@ -23,9 +21,15 @@
], ],
"tls": {}, "tls": {},
"fallback": { "fallback": {
"server": "127.0.0.0.1", "server": "127.0.0.1",
"server_port": 8080 "server_port": 8080
}, },
"fallback_for_alpn": {
"http/1.1": {
"server": "127.0.0.1",
"server_port": 8081
}
},
"transport": {} "transport": {}
} }
] ]
@@ -52,7 +56,13 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
没有证据表明 GFW 基于 HTTP 响应检测并阻止木马服务器,并且在服务器上打开标准 http/s 端口是一个更大的特征。 没有证据表明 GFW 基于 HTTP 响应检测并阻止木马服务器,并且在服务器上打开标准 http/s 端口是一个更大的特征。
备用服务器配置。默认禁用 回退服务器配置。如果 `fallback``fallback_for_alpn` 为空,则禁用回退
#### fallback_for_alpn
为 ALPN 指定回退服务器配置。
如果不为空ALPN 不在此列表中的 TLS 回退请求将被拒绝。
#### transport #### transport

View File

@@ -107,7 +107,7 @@ TCP/IP 栈。
!!! warning "" !!! warning ""
默认安装不包含 LWIP 栈,请参阅 [安装](/zh/#installation)。 默认安装不包含 LWIP 栈,请参阅 [安装](/zh/#_2)。
#### include_uid #### include_uid

View File

@@ -38,7 +38,7 @@
!!! warning "" !!! warning ""
默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#installation)。 默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#_2)。
### Hysteria 字段 ### Hysteria 字段

View File

@@ -1,3 +1,5 @@
# Outbound
### Structure ### Structure
```json ```json

View File

@@ -30,7 +30,7 @@
!!! info "" !!! info ""
默认安装不包含嵌入式 Tor, 参阅 [安装](/zh/#installation)。 默认安装不包含嵌入式 Tor, 参阅 [安装](/zh/#_2)。
### Tor 字段 ### Tor 字段

View File

@@ -35,7 +35,7 @@
!!! warning "" !!! warning ""
默认安装不包含 WireGuard, 参阅 [安装](/zh/#installation)。 默认安装不包含 WireGuard, 参阅 [安装](/zh/#_2)。
### WireGuard 字段 ### WireGuard 字段

View File

@@ -1,3 +1,5 @@
# Route
### Structure ### Structure
```json ```json

View File

@@ -41,10 +41,12 @@
"cn" "cn"
], ],
"source_ip_cidr": [ "source_ip_cidr": [
"10.0.0.0/24" "10.0.0.0/24",
"192.168.0.1"
], ],
"ip_cidr": [ "ip_cidr": [
"10.0.0.0/24" "10.0.0.0/24",
"192.168.0.1"
], ],
"source_port": [ "source_port": [
12345 12345

View File

@@ -32,7 +32,7 @@
!!! warning "" !!! warning ""
默认安装不包含 ACME参阅 [安装](/zh/#installation)。 默认安装不包含 ACME参阅 [安装](/zh/#_2)。
### 出站 ### 出站

View File

@@ -108,6 +108,10 @@ It needs to be consistent with the server.
} }
``` ```
!!! warning ""
QUIC is not included by default, see [Installation](/#installation).
!!! warning "Difference from v2ray-core" !!! warning "Difference from v2ray-core"
No additional encryption support: No additional encryption support:

View File

@@ -107,6 +107,10 @@ HTTP 请求的额外标头。
} }
``` ```
!!! warning ""
默认安装不包含 QUIC, 参阅 [安装](/zh/#_2)。
!!! warning "与 v2ray-core 的区别" !!! warning "与 v2ray-core 的区别"
没有额外的加密支持: 没有额外的加密支持:
@@ -116,7 +120,7 @@ HTTP 请求的额外标头。
!!! warning "" !!! warning ""
默认安装不包含 gRPC, 参阅 [安装](/zh/#installation)。 默认安装不包含 gRPC, 参阅 [安装](/zh/#_2)。
```json ```json
{ {

View File

@@ -0,0 +1,50 @@
# Development environment
#### For the documentation
##### Setup
You need to configure python3 and pip first.
```shell
pip install mkdocs-material mkdocs-static-i18n
```
##### Run the site locally
```shell
mkdocs serve
```
or
```shell
python3 -m mkdocs serve
```
#### For the project
By default you have the latest Go installed (currently 1.19), and added `GOPATH/bin` to the PATH environment variable.
##### Setup
```shell
make fmt_insall
make lint_install
```
This installs the formatting and lint tools, which can be used via `make fmt` and `make lint`.
For ProtoBuffer changes, you also need `make proto_install` and `make proto`.
##### Build binary to the project directory
```shell
make
```
##### Install binary to GOPATH/bin
```shell
make install
```

View File

@@ -0,0 +1,17 @@
# Contributing to sing-box
An introduction to contributing to the sing-box project.
The sing-box project welcomes, and depends, on contributions from developers and users in the open source community.
Contributions can be made in a number of ways, a few examples are:
* Code patches via pull requests
* Documentation improvements
* Bug reports and patch reviews
### Reporting an Issue?
Please follow
the [issue template](https://github.com/SagerNet/sing-box/issues/new?assignees=&labels=&template=bug_report.yml) to
submit bugs. Always include **FULL** log content, especially if you don't understand the code that generates it.

View File

@@ -0,0 +1,78 @@
The sing-box uses the following projects which also need to be maintained:
#### sing
Link: [GitHub repository](https://github.com/SagerNet/sing)
As a base tool library, there are no dependencies other than `golang.org/x/sys`.
#### sing-dns
Link: [GitHub repository](https://github.com/SagerNet/sing-dns)
Handles DNS lookups and caching.
#### sing-tun
Link: [GitHub repository](https://github.com/SagerNet/sing-tun)
Handle Tun traffic forwarding, configure routing, monitor network and routing.
This library needs to periodically update its dependency gVisor (according to tags), including checking for changes to
the used parts of the code and updating its usage. If you are involved in maintenance, you also need to check that if it
works or contains memory leaks.
#### sing-shadowsocks
Link: [GitHub repository](https://github.com/SagerNet/sing-shadowsocks)
Provides Shadowsocks client and server
#### sing-vmess
Link: [GitHub repository](https://github.com/SagerNet/sing-vmess)
Provides VMess client and server
#### netlink
Link: [GitHub repository](https://github.com/SagerNet/netlink)
Fork of `vishvananda/netlink`, with some rule fixes.
The library needs to be updated with the upstream.
#### quic-go
Link: [GitHub repository](https://github.com/SagerNet/quic-go)
Fork of `lucas-clemente/quic-go` and `HyNetwork/quic-go`, contains quic flow control and other fixes used by Hysteria.
Since the author of Hysteria does not follow the upstream updates in time, and the provided fork needs to use replace,
we need to do this.
The library needs to be updated with the upstream.
#### certmagic
Link: [GitHub repository](https://github.com/SagerNet/certmagic)
Fork of `caddyserver/certmagic`
Since upstream uses `miekg/dns` and we use `x/net/dnsmessage`, we need to replace its DNS part with our own
implementation.
The library needs to be updated with the upstream.
#### smux
Link: [GitHub repository](https://github.com/SagerNet/smux)
Fork of `xtaci/smux`
Modify the code to support the writev it uses internally and unify the buffer pool, which prevents it from allocating
64k buffers for per connection and improves performance.
Upstream doesn't seem to be updated anymore, maybe a replacement is needed.
Note: while yamux is still actively maintained and better known, it seems to be less performant.

View File

@@ -81,7 +81,7 @@
| Feature | clash-premium | | Feature | clash-premium |
|-------------------------------------------|---------------| |-------------------------------------------|---------------|
| Full IPv6 support | X | | Full IPv6 support | X |
| Auto route on Linux/Windows/maxOS/Android | ✔ | | Auto route on Linux/Windows/macOS/Android | ✔ |
| Embed windows driver | X | | Embed windows driver | X |
| Custom address/mtu | X | | Custom address/mtu | X |
| Limit uid (Linux) in routing | X | | Limit uid (Linux) in routing | X |

View File

@@ -1,3 +1,7 @@
---
description: Welcome to the wiki page for the sing-box project.
---
# Home # Home
Welcome to the wiki page for the sing-box project. Welcome to the wiki page for the sing-box project.
@@ -18,16 +22,16 @@ Install with options:
go install -v -tags with_clash_api github.com/sagernet/sing-box/cmd/sing-box@latest go install -v -tags with_clash_api github.com/sagernet/sing-box/cmd/sing-box@latest
``` ```
| Build Tag | Description | | Build Tag | Description |
|------------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |------------------------------------|---------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `with_quic` | Build with QUIC support, see [QUIC and HTTP3 dns transports](./configuration/dns/server), [Naive inbound](./configuration/inbound/naive), [Hysteria Inbound](./configuration/inbound/hysteria) and [Hysteria Outbound](./configuration/outbound/hysteria). | | `with_quic` | Build with QUIC support, see [QUIC and HTTP3 dns transports](./configuration/dns/server), [Naive inbound](./configuration/inbound/naive), [Hysteria Inbound](./configuration/inbound/hysteria), [Hysteria Outbound](./configuration/outbound/hysteria) and [V2Ray Transport#QUIC](./configuration/shared/v2ray-transport#quic). |
| `with_grpc` | Build with gRPC support, see [V2Ray Transport#gRPC](/configuration/shared/v2ray-transport#grpc). | | `with_grpc` | Build with gRPC support, see [V2Ray Transport#gRPC](./configuration/shared/v2ray-transport#grpc). |
| `with_wireguard` | Build with WireGuard support, see [WireGuard outbound](./configuration/outbound/wireguard). | | `with_wireguard` | Build with WireGuard support, see [WireGuard outbound](./configuration/outbound/wireguard). |
| `with_acme` | Build with ACME TLS certificate issuer support, see [TLS](./configuration/shared/tls). | | `with_acme` | Build with ACME TLS certificate issuer support, see [TLS](./configuration/shared/tls). |
| `with_clash_api` | Build with Clash API support, see [Experimental](./configuration/experimental#clash-api-fields). | | `with_clash_api` | Build with Clash API support, see [Experimental](./configuration/experimental#clash-api-fields). |
| `no_gvisor` | Build without gVisor Tun stack support, see [Tun inbound](./configuration/inbound/tun#stack). | | `no_gvisor` | Build without gVisor Tun stack support, see [Tun inbound](./configuration/inbound/tun#stack). |
| `with_embedded_tor` (CGO required) | Build with embedded Tor support, see [Tor outbound](./configuration/outbound/tor). | | `with_embedded_tor` (CGO required) | Build with embedded Tor support, see [Tor outbound](./configuration/outbound/tor). |
| `with_lwip` (CGO required) | Build with LWIP Tun stack support, see [Tun inbound](./configuration/inbound/tun#stack). | | `with_lwip` (CGO required) | Build with LWIP Tun stack support, see [Tun inbound](./configuration/inbound/tun#stack). |
The binary is built under $GOPATH/bin The binary is built under $GOPATH/bin

View File

@@ -1,3 +1,7 @@
---
description: 欢迎来到该 sing-box 项目的文档页。
---
# 开始 # 开始
欢迎来到该 sing-box 项目的文档页。 欢迎来到该 sing-box 项目的文档页。
@@ -18,16 +22,16 @@ go install -v github.com/sagernet/sing-box/cmd/sing-box@latest
go install -v -tags with_clash_api github.com/sagernet/sing-box/cmd/sing-box@latest go install -v -tags with_clash_api github.com/sagernet/sing-box/cmd/sing-box@latest
``` ```
| 构建标志 | 描述 | | 构建标志 | 描述 |
|------------------------------|-------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------| |------------------------------|------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------|
| `with_quic` | 启用 QUIC 支持,参阅 [QUIC 和 HTTP3 DNS 传输层](./configuration/dns/server)[Naive 入站](./configuration/inbound/naive)[Hysteria 入站](./configuration/inbound/hysteria)[Hysteria 出站](./configuration/outbound/hysteria)。 | | `with_quic` | 启用 QUIC 支持,参阅 [QUIC 和 HTTP3 DNS 传输层](./configuration/dns/server)[Naive 入站](./configuration/inbound/naive)[Hysteria 入站](./configuration/inbound/hysteria)[Hysteria 出站](./configuration/outbound/hysteria) 和 [V2Ray 传输层#QUIC](./configuration/shared/v2ray-transport#quic)。 |
| `with_grpc` | 启用 gRPC 支持,参阅 [V2Ray 传输层#gRPC](/configuration/shared/v2ray-transport#grpc)。 | | `with_grpc` | 启用 gRPC 支持,参阅 [V2Ray 传输层#gRPC](./configuration/shared/v2ray-transport#grpc)。 |
| `with_wireguard` | 启用 WireGuard 支持,参阅 [WireGuard 出站](./configuration/outbound/wireguard)。 | | `with_wireguard` | 启用 WireGuard 支持,参阅 [WireGuard 出站](./configuration/outbound/wireguard)。 |
| `with_acme` | 启用 ACME TLS 证书签发支持,参阅 [TLS](./configuration/shared/tls)。 | | `with_acme` | 启用 ACME TLS 证书签发支持,参阅 [TLS](./configuration/shared/tls)。 |
| `with_clash_api` | 启用 Clash api 支持,参阅 [实验性](./configuration/experimental#clash-api-fields)。 | | `with_clash_api` | 启用 Clash api 支持,参阅 [实验性](./configuration/experimental#clash-api-fields)。 |
| `no_gvisor` | 禁用 gVisor Tun 栈支持,参阅 [Tun 入站](./configuration/inbound/tun#stack)。 | | `no_gvisor` | 禁用 gVisor Tun 栈支持,参阅 [Tun 入站](./configuration/inbound/tun#stack)。 |
| `with_embedded_tor` (需要 CGO) | 启用 嵌入式 Tor 支持,参阅 [Tor 出站](./configuration/outbound/tor)。 | | `with_embedded_tor` (需要 CGO) | 启用 嵌入式 Tor 支持,参阅 [Tor 出站](./configuration/outbound/tor)。 |
| `with_lwip` (需要 CGO) | 启用 LWIP Tun 栈支持,参阅 [Tun 入站](./configuration/inbound/tun#stack)。 | | `with_lwip` (需要 CGO) | 启用 LWIP Tun 栈支持,参阅 [Tun 入站](./configuration/inbound/tun#stack)。 |
二进制文件将被构建在 `$GOPATH/bin` 下。 二进制文件将被构建在 `$GOPATH/bin` 下。

10
go.mod
View File

@@ -21,15 +21,16 @@ require (
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a
github.com/sagernet/netlink v0.0.0-20220820041223-3cd8365d17ac github.com/sagernet/netlink v0.0.0-20220820041223-3cd8365d17ac
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb
github.com/sagernet/sing v0.0.0-20220824062950-7bfd820739a8 github.com/sagernet/sing v0.0.0-20220825093630-185d87918290
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6
github.com/sagernet/sing-tun v0.0.0-20220824105617-e5c59fc756a6 github.com/sagernet/sing-tun v0.0.0-20220826042514-409136e64474
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939
github.com/spf13/cobra v1.5.0 github.com/spf13/cobra v1.5.0
github.com/stretchr/testify v1.8.0 github.com/stretchr/testify v1.8.0
go.uber.org/atomic v1.10.0 go.uber.org/atomic v1.10.0
go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d
golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8 golang.org/x/crypto v0.0.0-20220817201139-bc19a97f63c8
golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c golang.org/x/net v0.0.0-20220822230855-b0a4917ee28c
golang.org/x/sys v0.0.0-20220818161305-2296e01440c6 golang.org/x/sys v0.0.0-20220818161305-2296e01440c6
@@ -62,11 +63,10 @@ require (
go.uber.org/multierr v1.6.0 // indirect go.uber.org/multierr v1.6.0 // indirect
go.uber.org/zap v1.22.0 // indirect go.uber.org/zap v1.22.0 // indirect
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e // indirect
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 // indirect golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 // indirect
golang.org/x/text v0.3.7 // indirect golang.org/x/text v0.3.7 // indirect
golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect golang.org/x/time v0.0.0-20191024005414-555d28b269f0 // indirect
golang.org/x/tools v0.1.10 // indirect golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f // indirect
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 // indirect
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 // indirect
google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect google.golang.org/genproto v0.0.0-20210722135532-667f2b7c528f // indirect
gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect gopkg.in/tomb.v1 v1.0.0-20141024135613-dd632973f1e7 // indirect

19
go.sum
View File

@@ -142,14 +142,14 @@ github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb h1:wc0yQ+SBn4TaTY
github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4= github.com/sagernet/quic-go v0.0.0-20220818150011-de611ab3e2bb/go.mod h1:MIccjRKnPTjWwAOpl+AUGWOkzyTd9tERytudxu+1ra4=
github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY= github.com/sagernet/sing v0.0.0-20220812082120-05f9836bff8f/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.0.0-20220817130738-ce854cda8522/go.mod h1:QVsS5L/ZA2Q5UhQwLrn0Trw+msNd/NPGEhBKR/ioWiY=
github.com/sagernet/sing v0.0.0-20220824062950-7bfd820739a8 h1:kHsinrGrMjEh5KUXC/MPCS+Uy3Z3XO/cMhC8xJtABE8= github.com/sagernet/sing v0.0.0-20220825093630-185d87918290 h1:OAt6dFNrGOpgaPgM3uvAdQE0NkGC7AAygqpo8MwryY8=
github.com/sagernet/sing v0.0.0-20220824062950-7bfd820739a8/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ= github.com/sagernet/sing v0.0.0-20220825093630-185d87918290/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ=
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 h1:XUTocA/Ek0dFxUX+xJCWMPPFZCn2GC/uLrBjTSr1vHY= github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666 h1:XUTocA/Ek0dFxUX+xJCWMPPFZCn2GC/uLrBjTSr1vHY=
github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM= github.com/sagernet/sing-dns v0.0.0-20220822023312-3e086b06d666/go.mod h1:eDyH7AJmqBGjZQdQmpZIzlbTREudZuWDExMuGKgjRVM=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4= github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6 h1:JJfDeYYhWunvtxsU/mOVNTmFQmnzGx9dY034qG6G3g4=
github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM= github.com/sagernet/sing-shadowsocks v0.0.0-20220819002358-7461bb09a8f6/go.mod h1:EX3RbZvrwAkPI2nuGa78T2iQXmrkT+/VQtskjou42xM=
github.com/sagernet/sing-tun v0.0.0-20220824105617-e5c59fc756a6 h1:C0uNMDrjYribl4Pu41Au9UeQROIOeMWaDd7eSUIQ9gQ= github.com/sagernet/sing-tun v0.0.0-20220826042514-409136e64474 h1:dy9dLOSTDtig/s5se7cRqIypUlqtcp4+Zw0+XMpORPE=
github.com/sagernet/sing-tun v0.0.0-20220824105617-e5c59fc756a6/go.mod h1:zMKRFCEoO6Jp5Yxb2NUTqc+SvAtNVAmzfwArAheJy5g= github.com/sagernet/sing-tun v0.0.0-20220826042514-409136e64474/go.mod h1:zMKRFCEoO6Jp5Yxb2NUTqc+SvAtNVAmzfwArAheJy5g=
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 h1:2hLETh97+S4WnfMR27XyC7QVU1SH7FTNoCznP229YJU= github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4 h1:2hLETh97+S4WnfMR27XyC7QVU1SH7FTNoCznP229YJU=
github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps= github.com/sagernet/sing-vmess v0.0.0-20220811135656-4f3f07acf9c4/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps=
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 h1:pB1Dh1NbwVrLhQhotr4O4Hs3yhiBzmg3AvnUyYjL4x4= github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 h1:pB1Dh1NbwVrLhQhotr4O4Hs3yhiBzmg3AvnUyYjL4x4=
@@ -181,6 +181,8 @@ go.uber.org/multierr v1.6.0/go.mod h1:cdWPpRnG4AhwMwsgIHip0KRBQjJy5kYEpYjJxpXp9i
go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw= go.uber.org/zap v1.21.0/go.mod h1:wjWOCqI0f2ZZrJF/UufIOkiC8ii6tm1iqIsLo76RfJw=
go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0= go.uber.org/zap v1.22.0 h1:Zcye5DUgBloQ9BaT4qc9BnjOFog5TvBSAGkJ3Nf70c0=
go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U= go.uber.org/zap v1.22.0/go.mod h1:H4siCOZOrAolnUPJEkfaSjDqyP+BDS0DdDWzwcgt3+U=
go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d h1:ggxwEf5eu0l8v+87VhX1czFh8zJul3hK16Gmruxn7hw=
go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d/go.mod h1:tgPU4N2u9RByaTN3NC2p9xOzyFpte4jYwsIIRF7XlSc=
golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w= golang.org/x/crypto v0.0.0-20190308221718-c2843e01d9a2/go.mod h1:djNgcEr1/C05ACkg1iLfiJU5Ep61QUkGW8qpdssI0+w=
golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE= golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaEeE5yQxYXgSfI8pQAWXbQop6sCtWE=
golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI= golang.org/x/crypto v0.0.0-20191011191535-87dc89f01550/go.mod h1:yigFU9vqHzYiE8UmvKecakEJjdnWj3jj499lnFckfCI=
@@ -199,8 +201,8 @@ golang.org/x/lint v0.0.0-20210508222113-6edffad5e616/go.mod h1:3xt1FjdF8hUf6vQPI
golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg= golang.org/x/mod v0.1.1-0.20191105210325-c90efee705ee/go.mod h1:QqPTAvyqsEbceGzBzNggFXnrqF1CaUcvgkdR5Ot7KZg=
golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.3.0/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA= golang.org/x/mod v0.4.2/go.mod h1:s0Qsj1ACt9ePp/hMypM3fl4fZqREWJwdYDEqhRiZZUA=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3 h1:kQgndtyPBW/JIYERgdxfwMYh3AVStj88WQTlNDi2a+o= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4 h1:6zppjxzCulZykYSLyVDYbneBfbaBIQPYMevg0bEwv2s=
golang.org/x/mod v0.6.0-dev.0.20220106191415-9b9b3d81d5e3/go.mod h1:3p9vT2HGsQu2K1YbXdKPJLVgG5VJdoTa1poYQBtP1AY= golang.org/x/mod v0.6.0-dev.0.20220419223038-86c51ed26bb4/go.mod h1:jJ57K6gSWd91VN4djpZkiMVwK6gcyfeH4XE8wZrZaV4=
golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180724234803-3673e40ba225/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180826012351-8a410e7b638d/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4= golang.org/x/net v0.0.0-20180906233101-161cd47e91fd/go.mod h1:mL1N/T3taQHkDXs73rZJwtUhF3w3ftmwwsq0BUmARs4=
@@ -274,12 +276,11 @@ golang.org/x/tools v0.0.0-20200130002326-2f3ba24bd6e7/go.mod h1:TB2adYChydJhpapK
golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA= golang.org/x/tools v0.0.0-20201224043029-2b0845dc783e/go.mod h1:emZCQorbCU4vsT4fOWvOPXz4eW1wZW4PmDk9uLelYpA=
golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.1/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk= golang.org/x/tools v0.1.5/go.mod h1:o0xws9oXOQQZyjljx8fwUC0k7L1pTE6eaCbjGeHmOkk=
golang.org/x/tools v0.1.10 h1:QjFRCZxdOhBJ/UNgnBZLbNV13DlbnK0quyivTnXJM20= golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f h1:OKYpQQVE3DKSc3r3zHVzq46vq5YH7x8xpR3/k9ixmUg=
golang.org/x/tools v0.1.10/go.mod h1:Uh6Zz+xoGYZom868N8YTex3t7RhtHDBrE8Gzo9bV56E= golang.org/x/tools v0.1.11-0.20220513221640-090b14e8501f/go.mod h1:SgwaegtQh8clINPpECJMqnxLv9I09HLqnW3RMqW0CA4=
golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20190717185122-a985d3407aa7/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191011141410-1b5146add898/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1 h1:go1bK/D/BFZV2I8cIQd1NKEZ+0owSTG1fDTci4IqFcE=
golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0= golang.org/x/xerrors v0.0.0-20200804184101-5ec99f83aff1/go.mod h1:I/5z698sn9Ka8TeJc9MKroUUfqBBauWjQqLJ2OPfmY0=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY= golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224 h1:Ug9qvr1myri/zFN6xL17LSCBGFDnphBBhzmILHsM5TY=
golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI= golang.zx2c4.com/wintun v0.0.0-20211104114900-415007cec224/go.mod h1:deeaetjYA+DHMHg+sMSMI58GrEteJUUzzw7en6TJQcI=

View File

@@ -187,7 +187,6 @@ func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.Inboun
metadata.SniffEnabled = a.listenOptions.SniffEnabled metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy) metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Network = N.NetworkTCP
if !metadata.Source.IsValid() { if !metadata.Source.IsValid() {
metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr()) metadata.Source = M.SocksaddrFromNet(conn.RemoteAddr())
} }
@@ -242,7 +241,6 @@ func (a *myInboundAdapter) loopUDPIn() {
metadata.SniffEnabled = a.listenOptions.SniffEnabled metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy) metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Network = N.NetworkUDP
metadata.Source = M.SocksaddrFromNetIP(addr) metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr metadata.OriginDestination = a.udpAddr
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata) err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
@@ -275,7 +273,6 @@ func (a *myInboundAdapter) loopUDPOOBIn() {
metadata.SniffEnabled = a.listenOptions.SniffEnabled metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy) metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Network = N.NetworkUDP
metadata.Source = M.SocksaddrFromNetIP(addr) metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr metadata.OriginDestination = a.udpAddr
err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata) err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)
@@ -302,7 +299,6 @@ func (a *myInboundAdapter) loopUDPInThreadSafe() {
metadata.SniffEnabled = a.listenOptions.SniffEnabled metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy) metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Network = N.NetworkUDP
metadata.Source = M.SocksaddrFromNetIP(addr) metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr metadata.OriginDestination = a.udpAddr
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata) err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
@@ -331,7 +327,6 @@ func (a *myInboundAdapter) loopUDPOOBInThreadSafe() {
metadata.SniffEnabled = a.listenOptions.SniffEnabled metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy) metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Network = N.NetworkUDP
metadata.Source = M.SocksaddrFromNetIP(addr) metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr metadata.OriginDestination = a.udpAddr
err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata) err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)

View File

@@ -267,7 +267,6 @@ func (h *Hysteria) acceptStream(ctx context.Context, conn quic.Connection, strea
metadata.Destination = M.ParseSocksaddrHostPort(request.Host, request.Port) metadata.Destination = M.ParseSocksaddrHostPort(request.Host, request.Port)
if !request.UDP { if !request.UDP {
h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination) h.logger.InfoContext(ctx, "inbound connection to ", metadata.Destination)
metadata.Network = N.NetworkTCP
return h.router.RouteConnection(ctx, hysteria.NewConn(stream, metadata.Destination), metadata) return h.router.RouteConnection(ctx, hysteria.NewConn(stream, metadata.Destination), metadata)
} else { } else {
h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination) h.logger.InfoContext(ctx, "inbound packet connection to ", metadata.Destination)
@@ -278,7 +277,6 @@ func (h *Hysteria) acceptStream(ctx context.Context, conn quic.Connection, strea
h.udpSessions[id] = nCh h.udpSessions[id] = nCh
h.udpSessionId += 1 h.udpSessionId += 1
h.udpAccess.Unlock() h.udpAccess.Unlock()
metadata.Network = N.NetworkUDP
packetConn := hysteria.NewPacketConn(conn, stream, id, metadata.Destination, nCh, common.Closer(func() error { packetConn := hysteria.NewPacketConn(conn, stream, id, metadata.Destination, nCh, common.Closer(func() error {
h.udpAccess.Lock() h.udpAccess.Lock()
if ch, ok := h.udpSessions[id]; ok { if ch, ok := h.udpSessions[id]; ok {

View File

@@ -24,11 +24,12 @@ var _ adapter.Inbound = (*Trojan)(nil)
type Trojan struct { type Trojan struct {
myInboundAdapter myInboundAdapter
service *trojan.Service[int] service *trojan.Service[int]
users []option.TrojanUser users []option.TrojanUser
tlsConfig *TLSConfig tlsConfig *TLSConfig
fallbackAddr M.Socksaddr fallbackAddr M.Socksaddr
transport adapter.V2RayServerTransport fallbackAddrTLSNextProto map[string]M.Socksaddr
transport adapter.V2RayServerTransport
} }
func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TrojanInboundOptions) (*Trojan, error) { func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.TrojanInboundOptions) (*Trojan, error) {
@@ -44,9 +45,35 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
}, },
users: options.Users, users: options.Users,
} }
if options.TLS != nil {
tlsConfig, err := NewTLSConfig(ctx, logger, common.PtrValueOrDefault(options.TLS))
if err != nil {
return nil, err
}
inbound.tlsConfig = tlsConfig
}
var fallbackHandler N.TCPConnectionHandler var fallbackHandler N.TCPConnectionHandler
if options.Fallback != nil && options.Fallback.Server != "" { if options.Fallback != nil && options.Fallback.Server != "" || len(options.FallbackForALPN) > 0 {
inbound.fallbackAddr = options.Fallback.Build() if options.Fallback != nil && options.Fallback.Server != "" {
inbound.fallbackAddr = options.Fallback.Build()
if !inbound.fallbackAddr.IsValid() {
return nil, E.New("invalid fallback address: ", inbound.fallbackAddr)
}
}
if len(options.FallbackForALPN) > 0 {
if inbound.tlsConfig == nil {
return nil, E.New("fallback for ALPN is not supported without TLS")
}
fallbackAddrNextProto := make(map[string]M.Socksaddr)
for nextProto, destination := range options.FallbackForALPN {
fallbackAddr := destination.Build()
if !fallbackAddr.IsValid() {
return nil, E.New("invalid fallback address for ALPN ", nextProto, ": ", fallbackAddr)
}
fallbackAddrNextProto[nextProto] = fallbackAddr
}
inbound.fallbackAddrTLSNextProto = fallbackAddrNextProto
}
fallbackHandler = adapter.NewUpstreamContextHandler(inbound.fallbackConnection, nil, nil) fallbackHandler = adapter.NewUpstreamContextHandler(inbound.fallbackConnection, nil, nil)
} }
service := trojan.NewService[int](adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), fallbackHandler) service := trojan.NewService[int](adapter.NewUpstreamContextHandler(inbound.newConnection, inbound.newPacketConnection, inbound), fallbackHandler)
@@ -58,13 +85,6 @@ func NewTrojan(ctx context.Context, router adapter.Router, logger log.ContextLog
if err != nil { if err != nil {
return nil, err return nil, err
} }
if options.TLS != nil {
tlsConfig, err := NewTLSConfig(ctx, logger, common.PtrValueOrDefault(options.TLS))
if err != nil {
return nil, err
}
inbound.tlsConfig = tlsConfig
}
if options.Transport != nil { if options.Transport != nil {
var tlsConfig *tls.Config var tlsConfig *tls.Config
if inbound.tlsConfig != nil { if inbound.tlsConfig != nil {
@@ -153,8 +173,22 @@ func (h *Trojan) newConnection(ctx context.Context, conn net.Conn, metadata adap
} }
func (h *Trojan) fallbackConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { func (h *Trojan) fallbackConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
h.logger.InfoContext(ctx, "fallback connection to ", h.fallbackAddr) var fallbackAddr M.Socksaddr
metadata.Destination = h.fallbackAddr if len(h.fallbackAddrTLSNextProto) > 0 {
if tlsConn, loaded := common.Cast[*tls.Conn](conn); loaded {
connectionState := tlsConn.ConnectionState()
if connectionState.NegotiatedProtocol != "" {
if fallbackAddr, loaded = h.fallbackAddrTLSNextProto[connectionState.NegotiatedProtocol]; !loaded {
return E.New("fallback disabled for ALPN: ", connectionState.NegotiatedProtocol)
}
}
}
}
if !fallbackAddr.IsValid() {
fallbackAddr = h.fallbackAddr
}
h.logger.InfoContext(ctx, "fallback connection to ", fallbackAddr)
metadata.Destination = fallbackAddr
return h.router.RouteConnection(ctx, conn, metadata) return h.router.RouteConnection(ctx, conn, metadata)
} }

View File

@@ -165,7 +165,6 @@ func (t *Tun) NewConnection(ctx context.Context, conn net.Conn, upstreamMetadata
var metadata adapter.InboundContext var metadata adapter.InboundContext
metadata.Inbound = t.tag metadata.Inbound = t.tag
metadata.InboundType = C.TypeTun metadata.InboundType = C.TypeTun
metadata.Network = N.NetworkTCP
metadata.Source = upstreamMetadata.Source metadata.Source = upstreamMetadata.Source
metadata.Destination = upstreamMetadata.Destination metadata.Destination = upstreamMetadata.Destination
metadata.SniffEnabled = t.inboundOptions.SniffEnabled metadata.SniffEnabled = t.inboundOptions.SniffEnabled
@@ -188,7 +187,6 @@ func (t *Tun) NewPacketConnection(ctx context.Context, conn N.PacketConn, upstre
var metadata adapter.InboundContext var metadata adapter.InboundContext
metadata.Inbound = t.tag metadata.Inbound = t.tag
metadata.InboundType = C.TypeTun metadata.InboundType = C.TypeTun
metadata.Network = N.NetworkUDP
metadata.Source = upstreamMetadata.Source metadata.Source = upstreamMetadata.Source
metadata.Destination = upstreamMetadata.Destination metadata.Destination = upstreamMetadata.Destination
metadata.SniffEnabled = t.inboundOptions.SniffEnabled metadata.SniffEnabled = t.inboundOptions.SniffEnabled

View File

@@ -49,7 +49,7 @@ nav:
- Route Rule: configuration/route/rule.md - Route Rule: configuration/route/rule.md
- Protocol Sniff: configuration/route/sniff.md - Protocol Sniff: configuration/route/sniff.md
- Experimental: - Experimental:
- configuration/experimental/index.md - configuration/experimental/index.md
- Shared: - Shared:
- TLS: configuration/shared/tls.md - TLS: configuration/shared/tls.md
- Multiplex: configuration/shared/multiplex.md - Multiplex: configuration/shared/multiplex.md
@@ -93,6 +93,11 @@ nav:
- Shadowsocks Client: examples/ss-client.md - Shadowsocks Client: examples/ss-client.md
- Shadowsocks Tun: examples/ss-tun.md - Shadowsocks Tun: examples/ss-tun.md
- DNS Hijack: examples/dns-hijack.md - DNS Hijack: examples/dns-hijack.md
- Contributing:
- contributing/index.md
- Developing:
- Environment: contributing/environment.md
- Sub projects: contributing/sub-projects.md
markdown_extensions: markdown_extensions:
- pymdownx.inlinehilite - pymdownx.inlinehilite
- pymdownx.snippets - pymdownx.snippets

View File

@@ -100,14 +100,14 @@ func (h *Outbound) UnmarshalJSON(bytes []byte) error {
} }
type DialerOptions struct { type DialerOptions struct {
Detour string `json:"detour,omitempty"` Detour string `json:"detour,omitempty"`
BindInterface string `json:"bind_interface,omitempty"` BindInterface string `json:"bind_interface,omitempty"`
BindAddress ListenAddress `json:"bind_address,omitempty"` BindAddress *ListenAddress `json:"bind_address,omitempty"`
ProtectPath string `json:"protect_path,omitempty"` ProtectPath string `json:"protect_path,omitempty"`
RoutingMark int `json:"routing_mark,omitempty"` RoutingMark int `json:"routing_mark,omitempty"`
ReuseAddr bool `json:"reuse_addr,omitempty"` ReuseAddr bool `json:"reuse_addr,omitempty"`
ConnectTimeout Duration `json:"connect_timeout,omitempty"` ConnectTimeout Duration `json:"connect_timeout,omitempty"`
TCPFastOpen bool `json:"tcp_fast_open,omitempty"` TCPFastOpen bool `json:"tcp_fast_open,omitempty"`
} }
type OutboundDialerOptions struct { type OutboundDialerOptions struct {

View File

@@ -2,10 +2,11 @@ package option
type TrojanInboundOptions struct { type TrojanInboundOptions struct {
ListenOptions ListenOptions
Users []TrojanUser `json:"users,omitempty"` Users []TrojanUser `json:"users,omitempty"`
TLS *InboundTLSOptions `json:"tls,omitempty"` TLS *InboundTLSOptions `json:"tls,omitempty"`
Fallback *ServerOptions `json:"fallback,omitempty"` Fallback *ServerOptions `json:"fallback,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"` FallbackForALPN map[string]*ServerOptions `json:"fallback_for_alpn,omitempty"`
Transport *V2RayTransportOptions `json:"transport,omitempty"`
} }
type TrojanUser struct { type TrojanUser struct {

View File

@@ -16,7 +16,7 @@ type ListenAddress netip.Addr
func (a ListenAddress) MarshalJSON() ([]byte, error) { func (a ListenAddress) MarshalJSON() ([]byte, error) {
addr := netip.Addr(a) addr := netip.Addr(a)
if !addr.IsValid() { if !addr.IsValid() {
return json.Marshal("") return nil, nil
} }
return json.Marshal(addr.String()) return json.Marshal(addr.String())
} }
@@ -35,6 +35,10 @@ func (a *ListenAddress) UnmarshalJSON(content []byte) error {
return nil return nil
} }
func (a ListenAddress) Build() netip.Addr {
return (netip.Addr)(a)
}
type NetworkList string type NetworkList string
func (v *NetworkList) UnmarshalJSON(content []byte) error { func (v *NetworkList) UnmarshalJSON(content []byte) error {

View File

@@ -3,13 +3,13 @@ package outbound
import ( import (
"context" "context"
"encoding/binary" "encoding/binary"
"io"
"net" "net"
"os" "os"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/canceler" "github.com/sagernet/sing-box/common/canceler"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf" "github.com/sagernet/sing/common/buf"
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
@@ -47,53 +47,60 @@ func (d *DNS) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.Pa
func (d *DNS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { func (d *DNS) NewConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
defer conn.Close() defer conn.Close()
ctx = adapter.WithContext(ctx, &metadata) ctx = adapter.WithContext(ctx, &metadata)
_buffer := buf.StackNewSize(1024) for {
err := d.handleConnection(ctx, conn, metadata)
if err != nil {
return err
}
}
}
func (d *DNS) handleConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
var queryLength uint16
err := binary.Read(conn, binary.BigEndian, &queryLength)
if err != nil {
return err
}
if queryLength == 0 {
return dns.RCodeFormatError
}
_buffer := buf.StackNewSize(int(queryLength))
defer common.KeepAlive(_buffer) defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer) buffer := common.Dup(_buffer)
defer buffer.Release() defer buffer.Release()
for { _, err = buffer.ReadFullFrom(conn, int(queryLength))
var queryLength uint16 if err != nil {
err := binary.Read(conn, binary.BigEndian, &queryLength) return err
if err != nil {
return err
}
if queryLength > 1024 {
return io.ErrShortBuffer
}
buffer.FullReset()
_, err = buffer.ReadFullFrom(conn, int(queryLength))
if err != nil {
return err
}
var message dnsmessage.Message
err = message.Unpack(buffer.Bytes())
if err != nil {
return err
}
if len(message.Questions) > 0 {
question := message.Questions[0]
metadata.Domain = string(question.Name.Data[:question.Name.Length-1])
}
go func() error {
response, err := d.router.Exchange(ctx, &message)
if err != nil {
return err
}
_responseBuffer := buf.StackNewPacket()
defer common.KeepAlive(_responseBuffer)
responseBuffer := common.Dup(_responseBuffer)
defer responseBuffer.Release()
responseBuffer.Resize(2, 0)
n, err := response.AppendPack(responseBuffer.Index(0))
if err != nil {
return err
}
responseBuffer.Truncate(len(n))
binary.BigEndian.PutUint16(responseBuffer.ExtendHeader(2), uint16(len(n)))
_, err = conn.Write(responseBuffer.Bytes())
return err
}()
} }
var message dnsmessage.Message
err = message.Unpack(buffer.Bytes())
if err != nil {
return err
}
if len(message.Questions) > 0 {
question := message.Questions[0]
metadata.Domain = string(question.Name.Data[:question.Name.Length-1])
}
go func() error {
response, err := d.router.Exchange(ctx, &message)
if err != nil {
return err
}
_responseBuffer := buf.StackNewPacket()
defer common.KeepAlive(_responseBuffer)
responseBuffer := common.Dup(_responseBuffer)
defer responseBuffer.Release()
responseBuffer.Resize(2, 0)
n, err := response.AppendPack(responseBuffer.Index(0))
if err != nil {
return err
}
responseBuffer.Truncate(len(n))
binary.BigEndian.PutUint16(responseBuffer.ExtendHeader(2), uint16(len(n)))
_, err = conn.Write(responseBuffer.Bytes())
return err
}()
return nil
} }
func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
@@ -103,7 +110,7 @@ func (d *DNS) NewPacketConnection(ctx context.Context, conn N.PacketConn, metada
var group task.Group var group task.Group
group.Append0(func(ctx context.Context) error { group.Append0(func(ctx context.Context) error {
defer cancel() defer cancel()
_buffer := buf.StackNewSize(1024) _buffer := buf.StackNewSize(dns.FixedPacketSize)
defer common.KeepAlive(_buffer) defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer) buffer := common.Dup(_buffer)
defer buffer.Release() defer buffer.Release()

View File

@@ -32,17 +32,6 @@ type VMess struct {
} }
func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VMessOutboundOptions) (*VMess, error) { func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogger, tag string, options option.VMessOutboundOptions) (*VMess, error) {
var clientOptions []vmess.ClientOption
if options.GlobalPadding {
clientOptions = append(clientOptions, vmess.ClientWithGlobalPadding())
}
if options.AuthenticatedLength {
clientOptions = append(clientOptions, vmess.ClientWithAuthenticatedLength())
}
client, err := vmess.NewClient(options.UUID, options.Security, options.AlterId, clientOptions...)
if err != nil {
return nil, err
}
outbound := &VMess{ outbound := &VMess{
myOutboundAdapter: myOutboundAdapter{ myOutboundAdapter: myOutboundAdapter{
protocol: C.TypeVMess, protocol: C.TypeVMess,
@@ -52,9 +41,9 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
tag: tag, tag: tag,
}, },
dialer: dialer.NewOutbound(router, options.OutboundDialerOptions), dialer: dialer.NewOutbound(router, options.OutboundDialerOptions),
client: client,
serverAddr: options.ServerOptions.Build(), serverAddr: options.ServerOptions.Build(),
} }
var err error
if options.TLS != nil { if options.TLS != nil {
outbound.tlsConfig, err = dialer.TLSConfig(options.Server, common.PtrValueOrDefault(options.TLS)) outbound.tlsConfig, err = dialer.TLSConfig(options.Server, common.PtrValueOrDefault(options.TLS))
if err != nil { if err != nil {
@@ -71,6 +60,25 @@ func NewVMess(ctx context.Context, router adapter.Router, logger log.ContextLogg
if err != nil { if err != nil {
return nil, err return nil, err
} }
var clientOptions []vmess.ClientOption
if options.GlobalPadding {
clientOptions = append(clientOptions, vmess.ClientWithGlobalPadding())
}
if options.AuthenticatedLength {
clientOptions = append(clientOptions, vmess.ClientWithAuthenticatedLength())
}
security := options.Security
if security == "" {
security = "auto"
}
if security == "auto" && outbound.tlsConfig != nil {
security = "zero"
}
client, err := vmess.NewClient(options.UUID, security, options.AlterId, clientOptions...)
if err != nil {
return nil, err
}
outbound.client = client
return outbound, nil return outbound, nil
} }

View File

@@ -498,13 +498,13 @@ func (r *Router) DefaultOutbound(network string) adapter.Outbound {
} }
func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error { func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) error {
metadata.Network = N.NetworkTCP
switch metadata.Destination.Fqdn { switch metadata.Destination.Fqdn {
case mux.Destination.Fqdn: case mux.Destination.Fqdn:
r.logger.InfoContext(ctx, "inbound multiplex connection") r.logger.InfoContext(ctx, "inbound multiplex connection")
return mux.NewConnection(ctx, r, r, r.logger, conn, metadata) return mux.NewConnection(ctx, r, r, r.logger, conn, metadata)
case uot.UOTMagicAddress: case uot.UOTMagicAddress:
r.logger.InfoContext(ctx, "inbound UoT connection") r.logger.InfoContext(ctx, "inbound UoT connection")
metadata.Network = N.NetworkUDP
metadata.Destination = M.Socksaddr{} metadata.Destination = M.Socksaddr{}
return r.RoutePacketConnection(ctx, uot.NewClientConn(conn), metadata) return r.RoutePacketConnection(ctx, uot.NewClientConn(conn), metadata)
} }
@@ -552,6 +552,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
} }
func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error { func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
metadata.Network = N.NetworkUDP
if metadata.SniffEnabled { if metadata.SniffEnabled {
buffer := buf.NewPacket() buffer := buf.NewPacket()
buffer.FullReset() buffer.FullReset()

View File

@@ -6,51 +6,67 @@ import (
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
F "github.com/sagernet/sing/common/format"
"go4.org/netipx"
) )
var _ RuleItem = (*IPCIDRItem)(nil) var _ RuleItem = (*IPCIDRItem)(nil)
type IPCIDRItem struct { type IPCIDRItem struct {
prefixes []netip.Prefix ipSet *netipx.IPSet
isSource bool isSource bool
description string
} }
func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) { func NewIPCIDRItem(isSource bool, prefixStrings []string) (*IPCIDRItem, error) {
prefixes := make([]netip.Prefix, 0, len(prefixStrings)) var builder netipx.IPSetBuilder
for i, prefixString := range prefixStrings { for i, prefixString := range prefixStrings {
prefix, err := netip.ParsePrefix(prefixString) prefix, err := netip.ParsePrefix(prefixString)
if err != nil { if err == nil {
return nil, E.Cause(err, "parse prefix [", i, "]") builder.AddPrefix(prefix)
continue
} }
prefixes = append(prefixes, prefix) addr, addrErr := netip.ParseAddr(prefixString)
if addrErr == nil {
builder.Add(addr)
continue
}
return nil, E.Cause(err, "parse ip_cidr [", i, "]")
}
var description string
if isSource {
description = "source_ipcidr="
} else {
description = "ipcidr="
}
if dLen := len(prefixStrings); dLen == 1 {
description += prefixStrings[0]
} else if dLen > 3 {
description += "[" + strings.Join(prefixStrings[:3], " ") + "...]"
} else {
description += "[" + strings.Join(prefixStrings, " ") + "]"
}
ipSet, err := builder.IPSet()
if err != nil {
return nil, err
} }
return &IPCIDRItem{ return &IPCIDRItem{
prefixes: prefixes, ipSet: ipSet,
isSource: isSource, isSource: isSource,
description: description,
}, nil }, nil
} }
func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool { func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool {
if r.isSource { if r.isSource {
for _, prefix := range r.prefixes { return r.ipSet.Contains(metadata.Source.Addr)
if prefix.Contains(metadata.Source.Addr) {
return true
}
}
} else { } else {
if metadata.Destination.IsIP() { if metadata.Destination.IsIP() {
for _, prefix := range r.prefixes { return r.ipSet.Contains(metadata.Destination.Addr)
if prefix.Contains(metadata.Destination.Addr) {
return true
}
}
} else { } else {
for _, address := range metadata.DestinationAddresses { for _, address := range metadata.DestinationAddresses {
for _, prefix := range r.prefixes { if r.ipSet.Contains(address) {
if prefix.Contains(address) { return true
return true
}
} }
} }
} }
@@ -59,17 +75,5 @@ func (r *IPCIDRItem) Match(metadata *adapter.InboundContext) bool {
} }
func (r *IPCIDRItem) String() string { func (r *IPCIDRItem) String() string {
var description string return r.description
if r.isSource {
description = "source_ipcidr="
} else {
description = "ipcidr="
}
pLen := len(r.prefixes)
if pLen == 1 {
description += r.prefixes[0].String()
} else {
description += "[" + strings.Join(F.MapToString(r.prefixes), " ") + "]"
}
return description
} }

View File

@@ -74,13 +74,13 @@ func NewClient(ctx context.Context, dialer N.Dialer, serverAddr M.Socksaddr, opt
func (c *Client) DialContext(ctx context.Context) (net.Conn, error) { func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
if !c.http2 { if !c.http2 {
return c.dialHTTP() return c.dialHTTP(ctx)
} else { } else {
return c.dialHTTP2() return c.dialHTTP2(ctx)
} }
} }
func (c *Client) dialHTTP() (net.Conn, error) { func (c *Client) dialHTTP(ctx context.Context) (net.Conn, error) {
conn, err := c.dialer.DialContext(c.ctx, N.NetworkTCP, c.serverAddr) conn, err := c.dialer.DialContext(c.ctx, N.NetworkTCP, c.serverAddr)
if err != nil { if err != nil {
return nil, err return nil, err
@@ -92,6 +92,7 @@ func (c *Client) dialHTTP() (net.Conn, error) {
Proto: "HTTP/1.1", Proto: "HTTP/1.1",
Header: c.headers.Clone(), Header: c.headers.Clone(),
} }
request = request.WithContext(ctx)
switch hostLen := len(c.host); hostLen { switch hostLen := len(c.host); hostLen {
case 0: case 0:
case 1: case 1:
@@ -114,7 +115,7 @@ func (c *Client) dialHTTP() (net.Conn, error) {
return conn, nil return conn, nil
} }
func (c *Client) dialHTTP2() (net.Conn, error) { func (c *Client) dialHTTP2(ctx context.Context) (net.Conn, error) {
pipeInReader, pipeInWriter := io.Pipe() pipeInReader, pipeInWriter := io.Pipe()
request := &http.Request{ request := &http.Request{
Method: c.method, Method: c.method,
@@ -124,6 +125,7 @@ func (c *Client) dialHTTP2() (net.Conn, error) {
Proto: "HTTP/2", Proto: "HTTP/2",
Header: c.headers.Clone(), Header: c.headers.Clone(),
} }
request = request.WithContext(ctx)
switch hostLen := len(c.host); hostLen { switch hostLen := len(c.host); hostLen {
case 0: case 0:
case 1: case 1:

View File

@@ -90,9 +90,8 @@ func (s *Server) ServeHTTP(writer http.ResponseWriter, request *http.Request) {
} }
writer.WriteHeader(http.StatusOK) writer.WriteHeader(http.StatusOK)
if f, ok := writer.(http.Flusher); ok { writer.(http.Flusher).Flush()
f.Flush()
}
var metadata M.Metadata var metadata M.Metadata
metadata.Source = sHttp.SourceAddress(request) metadata.Source = sHttp.SourceAddress(request)
if h, ok := writer.(http.Hijacker); ok { if h, ok := writer.(http.Hijacker); ok {

View File

@@ -70,7 +70,7 @@ func (c *Client) DialContext(ctx context.Context) (net.Conn, error) {
} }
return nil, wrapDialError(response, err) return nil, wrapDialError(response, err)
} else { } else {
return &EarlyWebsocketConn{Client: c, create: make(chan struct{})}, nil return &EarlyWebsocketConn{Client: c, ctx: ctx, create: make(chan struct{})}, nil
} }
} }

View File

@@ -1,6 +1,7 @@
package v2raywebsocket package v2raywebsocket
import ( import (
"context"
"encoding/base64" "encoding/base64"
"io" "io"
"net" "net"
@@ -68,6 +69,7 @@ func (c *WebsocketConn) SetDeadline(t time.Time) error {
type EarlyWebsocketConn struct { type EarlyWebsocketConn struct {
*Client *Client
ctx context.Context
conn *WebsocketConn conn *WebsocketConn
create chan struct{} create chan struct{}
} }
@@ -98,14 +100,14 @@ func (c *EarlyWebsocketConn) Write(b []byte) (n int, err error) {
if len(earlyData) > 0 { if len(earlyData) > 0 {
earlyDataString := base64.RawURLEncoding.EncodeToString(earlyData) earlyDataString := base64.RawURLEncoding.EncodeToString(earlyData)
if c.earlyDataHeaderName == "" { if c.earlyDataHeaderName == "" {
conn, response, err = c.dialer.Dial(c.uri+earlyDataString, c.headers) conn, response, err = c.dialer.DialContext(c.ctx, c.uri+earlyDataString, c.headers)
} else { } else {
headers := c.headers.Clone() headers := c.headers.Clone()
headers.Set(c.earlyDataHeaderName, earlyDataString) headers.Set(c.earlyDataHeaderName, earlyDataString)
conn, response, err = c.dialer.Dial(c.uri, headers) conn, response, err = c.dialer.DialContext(c.ctx, c.uri, headers)
} }
} else { } else {
conn, response, err = c.dialer.Dial(c.uri, c.headers) conn, response, err = c.dialer.DialContext(c.ctx, c.uri, c.headers)
} }
if err != nil { if err != nil {
return 0, wrapDialError(response, err) return 0, wrapDialError(response, err)