Compare commits

...

39 Commits

Author SHA1 Message Date
世界
f376683fc3 Update documentation 2022-09-07 23:10:36 +08:00
世界
4b61d6e875 Fix hysteria stream error 2022-09-07 19:16:20 +08:00
世界
7d83e350fd Refine test 2022-09-07 19:16:20 +08:00
世界
500ba69548 Fix processing vmess termination signal 2022-09-07 19:16:20 +08:00
世界
9a422549b1 Fix json format error message 2022-09-07 13:23:26 +08:00
世界
3b48fa455e Fix naive inbound temporary 2022-09-07 12:30:54 +08:00
zakuwaki
ef013e0639 Suppress accept proxyproto failed #65 2022-09-06 23:16:31 +08:00
世界
8f8437a88d Fix wireguard reconnect 2022-09-06 00:11:43 +08:00
世界
1b091c9b07 Update documentation 2022-09-04 13:15:10 +08:00
世界
4801b6f057 Fix DNS routing 2022-09-04 12:49:38 +08:00
世界
9078bc2de5 Fix write trojan udp 2022-09-03 16:58:55 +08:00
世界
b69464dfe9 Update documentation for dial fields 2022-09-03 13:02:41 +08:00
世界
62fa48293a Merge dialer options 2022-09-03 12:55:10 +08:00
世界
b206d0889b Fix dial parallel in direct outbound 2022-09-03 12:01:48 +08:00
世界
ee691d81bf Fix write zero 2022-09-03 09:25:30 +08:00
void aire()
56876a67cc Fix documentation typo (#60) 2022-09-02 19:04:03 +08:00
世界
4a0df713aa Add ws compatibility test 2022-09-01 20:32:47 +08:00
世界
ef801cbfbe Fix server install script 2022-09-01 20:32:47 +08:00
世界
9378fc88d2 Add with_wireguard to default server tag 2022-09-01 20:16:20 +08:00
世界
f46bfcc3d8 Move unstable branch to dev-next 2022-08-31 23:45:42 +08:00
0x7d274284
ccdb238843 Fix documentation typo (#57) 2022-08-31 23:42:36 +08:00
世界
f1f61b4e2b Fix install documentation 2022-08-31 23:37:30 +08:00
世界
a44cb745d9 Fix write log timestamp 2022-08-31 23:35:43 +08:00
世界
f5f5cb023c Update documentation 2022-08-31 14:34:32 +08:00
世界
5813e0ce7a Add shadowtls (#49)
* Add shadowtls outbound

* Add shadowtls inbound

* Add shadowtls example

* Add shadowtls documentation
2022-08-31 14:21:53 +08:00
dyhkwong
5a9c2b1e80 darwin pf support (#52) 2022-08-31 14:21:37 +08:00
世界
bda34fdb3b Refactor outbound documentation 2022-08-31 13:42:30 +08:00
世界
426b677eb8 Fix process_name rule item 2022-08-31 12:51:38 +08:00
世界
67c7e9fd86 Refactor inbound documetation 2022-08-31 12:50:26 +08:00
世界
d8028a8632 Fix smux session status 2022-08-31 10:00:15 +08:00
dyhkwong
374743d022 Add process_path rule item (#51)
* process matching supports full path
* Remove strings.ToLower
2022-08-30 10:44:40 +08:00
世界
cd98ea5008 Fix socksaddr type condition 2022-08-29 19:58:58 +08:00
世界
dbda0ed98a Add chained inbound support 2022-08-29 19:50:28 +08:00
世界
f5e0ead01c Fix inject conn 2022-08-29 19:02:41 +08:00
0x7d274284
44818701bc Fix issue template (#48)
The correct command to get the version is `sing-box version`
2022-08-29 16:52:15 +08:00
世界
e0f7387dff Fix search android package in non-owner users 2022-08-29 12:02:29 +08:00
世界
d440a01792 Add grpc compatibility test 2022-08-29 10:15:25 +08:00
世界
665c84ee42 Fix log item on document menu 2022-08-28 12:47:23 +08:00
Hellojack
e0de96eb4c Minor fixes (#45)
* Cleanup code
* Fix documentation typo
2022-08-28 12:40:44 +08:00
173 changed files with 3359 additions and 3750 deletions

View File

@@ -31,7 +31,7 @@ body:
<details> <details>
```console ```console
$ sing-box --version $ sing-box version
# Paste output here # Paste output here
``` ```

View File

@@ -1,10 +1,5 @@
#!/usr/bin/env bash #!/usr/bin/env bash
PROJECTS=$(dirname "$0")/../.. PROJECTS=$(dirname "$0")/../..
go get -x github.com/sagernet/$1@$(git -C $PROJECTS/$1 rev-parse HEAD)
go get -x github.com/sagernet/sing@$(git -C $PROJECTS/sing rev-parse HEAD)
go get -x github.com/sagernet/sing-dns@$(git -C $PROJECTS/sing-dns rev-parse HEAD)
go get -x github.com/sagernet/sing-tun@$(git -C $PROJECTS/sing-tun rev-parse HEAD)
go get -x github.com/sagernet/sing-shadowsocks@$(git -C $PROJECTS/sing-shadowsocks rev-parse HEAD)
go get -x github.com/sagernet/sing-vmess@$(git -C $PROJECTS/sing-vmess rev-parse HEAD)
go mod tidy go mod tidy

View File

@@ -4,6 +4,7 @@ on:
push: push:
branches: branches:
- dev - dev
- dev-next
paths-ignore: paths-ignore:
- '**.md' - '**.md'
- '.github/**' - '.github/**'
@@ -11,6 +12,7 @@ on:
pull_request: pull_request:
branches: branches:
- dev - dev
- dev-next
jobs: jobs:
build: build:

View File

@@ -2,7 +2,7 @@ name: Generate Documents
on: on:
push: push:
branches: branches:
- main - dev
paths: paths:
- docs/** - docs/**
- .github/workflows/mkdocs.yml - .github/workflows/mkdocs.yml

View File

@@ -7,8 +7,8 @@ ENV GOPROXY ${GOPROXY}
ENV CGO_ENABLED=0 ENV CGO_ENABLED=0
RUN set -ex \ RUN set -ex \
&& apk add git build-base \ && apk add git build-base \
&& export COMMIT=$(git rev-parse HEAD) \ && export COMMIT=$(git rev-parse --short HEAD) \
&& go build -v -trimpath -tags 'with_quic,with_acme,with_wireguard,with_clash_api' \ && go build -v -trimpath -tags 'no_gvisor,with_quic,with_wireguard,with_acme' \
-o /go/bin/sing-box \ -o /go/bin/sing-box \
-ldflags "-X github.com/sagernet/sing-box/constant.Commit=${COMMIT} -w -s -buildid=" \ -ldflags "-X github.com/sagernet/sing-box/constant.Commit=${COMMIT} -w -s -buildid=" \
./cmd/sing-box ./cmd/sing-box

View File

@@ -2,11 +2,13 @@ package adapter
import ( import (
"context" "context"
"net"
"net/netip" "net/netip"
"github.com/sagernet/sing-box/common/process" "github.com/sagernet/sing-box/common/process"
"github.com/sagernet/sing-dns" "github.com/sagernet/sing-dns"
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
) )
type Inbound interface { type Inbound interface {
@@ -15,6 +17,13 @@ type Inbound interface {
Tag() string Tag() string
} }
type InjectableInbound interface {
Inbound
Network() []string
NewConnection(ctx context.Context, conn net.Conn, metadata InboundContext) error
NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata InboundContext) error
}
type InboundContext struct { type InboundContext struct {
Inbound string Inbound string
InboundType string InboundType string
@@ -29,6 +38,8 @@ type InboundContext struct {
// cache // cache
InboundDetour string
LastInbound string
OriginDestination M.Socksaddr OriginDestination M.Socksaddr
DomainStrategy dns.DomainStrategy DomainStrategy dns.DomainStrategy
SniffEnabled bool SniffEnabled bool

2
box.go
View File

@@ -138,7 +138,7 @@ func New(ctx context.Context, options option.Options) (*Box, error) {
} }
outbounds = append(outbounds, out) outbounds = append(outbounds, out)
} }
err = router.Initialize(outbounds, func() adapter.Outbound { err = router.Initialize(inbounds, outbounds, func() adapter.Outbound {
out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), option.Outbound{Type: "direct", Tag: "default"}) out, oErr := outbound.New(ctx, router, logFactory.NewLogger("outbound/direct"), option.Outbound{Type: "direct", Tag: "default"})
common.Must(oErr) common.Must(oErr)
outbounds = append(outbounds, out) outbounds = append(outbounds, out)

View File

@@ -38,7 +38,7 @@ func format() error {
return E.Cause(err, "read config") return E.Cause(err, "read config")
} }
var options option.Options var options option.Options
err = json.Unmarshal(configContent, &options) err = options.UnmarshalJSON(configContent)
if err != nil { if err != nil {
return E.Cause(err, "decode config") return E.Cause(err, "decode config")
} }

View File

@@ -9,7 +9,6 @@ import (
"syscall" "syscall"
"github.com/sagernet/sing-box" "github.com/sagernet/sing-box"
"github.com/sagernet/sing-box/common/json"
"github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
@@ -46,7 +45,7 @@ func readConfig() (option.Options, error) {
return option.Options{}, E.Cause(err, "read config") return option.Options{}, E.Cause(err, "read config")
} }
var options option.Options var options option.Options
err = json.Unmarshal(configContent, &options) err = options.UnmarshalJSON(configContent)
if err != nil { if err != nil {
return option.Options{}, E.Cause(err, "decode config") return option.Options{}, E.Cause(err, "decode config")
} }

View File

@@ -0,0 +1,62 @@
package baderror
import (
"context"
"io"
"net"
"strings"
E "github.com/sagernet/sing/common/exceptions"
)
func Contains(err error, msgList ...string) bool {
for _, msg := range msgList {
if strings.Contains(err.Error(), msg) {
return true
}
}
return false
}
func WrapH2(err error) error {
if err == nil {
return nil
}
err = E.Unwrap(err)
if err == io.ErrUnexpectedEOF {
return io.EOF
}
if Contains(err, "client disconnected", "body closed by handler") {
return net.ErrClosed
}
return err
}
func WrapGRPC(err error) error {
// grpc uses stupid internal error types
if err == nil {
return nil
}
if Contains(err, "EOF") {
return io.EOF
}
if Contains(err, "Canceled") {
return context.Canceled
}
if Contains(err,
"the client connection is closing",
"server closed the stream without sending trailers") {
return net.ErrClosed
}
return err
}
func WrapQUIC(err error) error {
if err == nil {
return nil
}
if Contains(err, "canceled with error code 0") {
return net.ErrClosed
}
return err
}

View File

@@ -11,6 +11,7 @@ import (
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
"github.com/sagernet/sing/common/control" "github.com/sagernet/sing/common/control"
E "github.com/sagernet/sing/common/exceptions"
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"
@@ -130,6 +131,9 @@ func NewDefault(router adapter.Router, options option.DialerOptions) *DefaultDia
} }
func (d *DefaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) { func (d *DefaultDialer) DialContext(ctx context.Context, network string, address M.Socksaddr) (net.Conn, error) {
if !address.IsValid() {
return nil, E.New("invalid address")
}
switch N.NetworkName(network) { switch N.NetworkName(network) {
case N.NetworkUDP: case N.NetworkUDP:
return d.udpDialer.DialContext(ctx, network, address.String()) return d.udpDialer.DialContext(ctx, network, address.String())

View File

@@ -10,15 +10,12 @@ import (
) )
func New(router adapter.Router, options option.DialerOptions) N.Dialer { func New(router adapter.Router, options option.DialerOptions) N.Dialer {
var dialer N.Dialer
if options.Detour == "" { if options.Detour == "" {
return NewDefault(router, options) dialer = NewDefault(router, options)
} else { } else {
return NewDetour(router, options.Detour) dialer = NewDetour(router, options.Detour)
} }
}
func NewOutbound(router adapter.Router, options option.OutboundDialerOptions) N.Dialer {
dialer := New(router, options.DialerOptions)
domainStrategy := dns.DomainStrategy(options.DomainStrategy) domainStrategy := dns.DomainStrategy(options.DomainStrategy)
if domainStrategy != dns.DomainStrategyAsIS || options.Detour == "" { if domainStrategy != dns.DomainStrategyAsIS || options.Detour == "" {
dialer = NewResolveDialer(router, dialer, domainStrategy, time.Duration(options.FallbackDelay)) dialer = NewResolveDialer(router, dialer, domainStrategy, time.Duration(options.FallbackDelay))

View File

@@ -51,7 +51,7 @@ func (d *ResolveDialer) DialContext(ctx context.Context, network string, destina
} }
func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) { func (d *ResolveDialer) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
if !destination.IsFqdn() || destination.Fqdn == "" { if !destination.IsFqdn() {
return d.dialer.ListenPacket(ctx, destination) return d.dialer.ListenPacket(ctx, destination)
} }
ctx, metadata := adapter.AppendContext(ctx) ctx, metadata := adapter.AppendContext(ctx)

View File

@@ -22,13 +22,13 @@ func (s *androidSearcher) FindProcessInfo(ctx context.Context, network string, s
if err != nil { if err != nil {
return nil, err return nil, err
} }
if sharedPackage, loaded := s.packageManager.SharedPackageByID(uid); loaded { if sharedPackage, loaded := s.packageManager.SharedPackageByID(uid % 100000); loaded {
return &Info{ return &Info{
UserId: int32(uid), UserId: int32(uid),
PackageName: sharedPackage, PackageName: sharedPackage,
}, nil }, nil
} }
if packageName, loaded := s.packageManager.PackageByID(uid); loaded { if packageName, loaded := s.packageManager.PackageByID(uid % 100000); loaded {
return &Info{ return &Info{
UserId: int32(uid), UserId: int32(uid),
PackageName: packageName, PackageName: packageName,

View File

@@ -0,0 +1,64 @@
package redir
import (
"net"
"net/netip"
"syscall"
"unsafe"
M "github.com/sagernet/sing/common/metadata"
)
const (
PF_OUT = 0x2
DIOCNATLOOK = 0xc0544417
)
func GetOriginalDestination(conn net.Conn) (destination netip.AddrPort, err error) {
fd, err := syscall.Open("/dev/pf", 0, syscall.O_RDONLY)
if err != nil {
return netip.AddrPort{}, err
}
defer syscall.Close(fd)
nl := struct {
saddr, daddr, rsaddr, rdaddr [16]byte
sxport, dxport, rsxport, rdxport [4]byte
af, proto, protoVariant, direction uint8
}{
af: syscall.AF_INET,
proto: syscall.IPPROTO_TCP,
direction: PF_OUT,
}
la := conn.LocalAddr().(*net.TCPAddr)
ra := conn.RemoteAddr().(*net.TCPAddr)
raIP, laIP := ra.IP, la.IP
raPort, laPort := ra.Port, la.Port
switch {
case raIP.To4() != nil:
copy(nl.saddr[:net.IPv4len], raIP.To4())
copy(nl.daddr[:net.IPv4len], laIP.To4())
nl.af = syscall.AF_INET
default:
copy(nl.saddr[:], raIP.To16())
copy(nl.daddr[:], laIP.To16())
nl.af = syscall.AF_INET6
}
nl.sxport[0], nl.sxport[1] = byte(raPort>>8), byte(raPort)
nl.dxport[0], nl.dxport[1] = byte(laPort>>8), byte(laPort)
if _, _, errno := syscall.Syscall(syscall.SYS_IOCTL, uintptr(fd), DIOCNATLOOK, uintptr(unsafe.Pointer(&nl))); errno != 0 {
return netip.AddrPort{}, errno
}
var ip net.IP
switch nl.af {
case syscall.AF_INET:
ip = make(net.IP, net.IPv4len)
copy(ip, nl.rdaddr[:net.IPv4len])
case syscall.AF_INET6:
ip = make(net.IP, net.IPv6len)
copy(ip, nl.rdaddr[:])
}
port := uint16(nl.rdxport[0])<<8 | uint16(nl.rdxport[1])
destination = netip.AddrPortFrom(M.AddrFromIP(ip), port)
return
}

View File

@@ -1,4 +1,4 @@
//go:build !linux //go:build !linux && !darwin
package redir package redir

View File

@@ -18,6 +18,7 @@ const (
TypeHysteria = "hysteria" TypeHysteria = "hysteria"
TypeTor = "tor" TypeTor = "tor"
TypeSSH = "ssh" TypeSSH = "ssh"
TypeShadowTLS = "shadowtls"
) )
const ( const (

View File

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

View File

@@ -1,3 +1,35 @@
#### 1.0
* Fix wireguard reconnect
* Fix naive inbound
* Fix json format error message
* Fix processing vmess termination signal
* Fix hysteria stream error
* Fix listener close when proxyproto failed
#### 1.0-rc1
* Fix write log timestamp
* Fix write zero
* Fix dial parallel in direct outbound
* Fix write trojan udp
* Fix DNS routing
* Add attribute support for geosite
* Update documentation for [Dial Fields](/configuration/shared/dial)
#### 1.0-beta3
* Add [chained inbound](/configuration/shared/listen#detour) support
* Add process_path rule item
* Add macOS redirect support
* Add ShadowTLS [Inbound](/configuration/inbound/shadowtls), [Outbound](/configuration/outbound/shadowtls)
and [Examples](/examples/shadowtls)
* Fix search android package in non-owner users
* Fix socksaddr type condition
* Fix smux session status
* Refactor inbound and outbound documentation
* Minor fixes
#### 1.0-beta2 #### 1.0-beta2
* Add strict_route option for [Tun inbound](/configuration/inbound/tun#strict_route) * Add strict_route option for [Tun inbound](/configuration/inbound/tun#strict_route)
@@ -111,4 +143,4 @@
No changelog before. No changelog before.
[#9]: https://github.com/SagerNet/sing-box/pull/9 [#9]: https://github.com/SagerNet/sing-box/pull/9

View File

@@ -61,6 +61,9 @@
"process_name": [ "process_name": [
"curl" "curl"
], ],
"process_path": [
"/usr/bin/curl"
],
"package_name": [ "package_name": [
"com.termux" "com.termux"
], ],
@@ -177,6 +180,14 @@ Match port range.
Match process name. Match process name.
#### process_path
!!! error ""
Only supported on Linux, Windows, and macOS.
Match process path.
#### package_name #### package_name
Match android package name. Match android package name.

View File

@@ -60,6 +60,9 @@
"process_name": [ "process_name": [
"curl" "curl"
], ],
"process_path": [
"/usr/bin/curl"
],
"package_name": [ "package_name": [
"com.termux" "com.termux"
], ],
@@ -176,6 +179,14 @@
匹配进程名称。 匹配进程名称。
#### process_path
!!! error ""
仅支持 Linux、Windows 和 macOS.
匹配进程路径。
#### package_name #### package_name
匹配 Android 应用包名。 匹配 Android 应用包名。

View File

@@ -4,29 +4,22 @@
```json ```json
{ {
"inbounds": [ "type": "direct",
{ "tag": "direct-in",
"type": "direct",
"tag": "direct-in", ... // Listen Fields
"listen": "::",
"listen_port": 5353,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"proxy_protocol": false,
"network": "udp", "network": "udp",
"override_address": "1.0.0.1", "override_address": "1.0.0.1",
"override_port": 53 "override_port": 53
}
]
} }
``` ```
### Direct Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### network #### network
@@ -40,50 +33,4 @@ Override the connection destination address.
#### override_port #### override_port
Override the connection destination port. Override the connection destination port.
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### udp_timeout
UDP NAT expiration time in seconds, default is 300 (5 minutes).
#### proxy_protocol
Parse [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.

View File

@@ -4,29 +4,22 @@
```json ```json
{ {
"inbounds": [ "type": "direct",
{ "tag": "direct-in",
"type": "direct",
"tag": "direct-in",
"listen": "::", ... // 监听字段
"listen_port": 5353,
"tcp_fast_open": false, "network": "udp",
"sniff": false, "override_address": "1.0.0.1",
"sniff_override_destination": false, "override_port": 53
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"network": "udp",
"proxy_protocol": false,
"override_address": "1.0.0.1",
"override_port": 53
}
]
} }
``` ```
### Direct 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### network #### network
@@ -42,48 +35,3 @@
覆盖连接目标端口。 覆盖连接目标端口。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### udp_timeout
UDP NAT 过期时间,以秒为单位,默认为 3005 分钟)。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -2,33 +2,27 @@
```json ```json
{ {
"inbounds": [ "type": "http",
"tag": "http-in",
... // Listen Fields
"users": [
{ {
"type": "http", "username": "admin",
"tag": "http-in", "password": "admin"
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [
{
"username": "admin",
"password": "admin"
}
],
"tls": {},
"set_system_proxy": false
} }
] ],
"tls": {},
"set_system_proxy": false
} }
``` ```
### HTTP Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### tls #### tls
@@ -47,45 +41,3 @@ No authentication required if empty.
Only supported on Linux, Android, Windows, and macOS. Only supported on Linux, Android, Windows, and macOS.
Automatically set system proxy configuration when start and clean up when stop. Automatically set system proxy configuration when start and clean up when stop.
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### proxy_protocol
Parse [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.

View File

@@ -2,33 +2,27 @@
```json ```json
{ {
"inbounds": [ "type": "http",
"tag": "http-in",
... // 监听字段
"users": [
{ {
"type": "http", "username": "admin",
"tag": "http-in", "password": "admin"
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [
{
"username": "admin",
"password": "admin"
}
],
"tls": {},
"set_system_proxy": false
} }
] ],
"tls": {},
"set_system_proxy": false
} }
``` ```
### HTTP 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### tls #### tls
@@ -38,7 +32,7 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
HTTP 用户 HTTP 用户
默认不需要验证。 如果为空则不需要验证。
#### set_system_proxy #### set_system_proxy
@@ -46,46 +40,4 @@ HTTP 用户
仅支持 Linux、Android、Windows 和 macOS。 仅支持 Linux、Android、Windows 和 macOS。
启动时自动设置系统代理,停止时自动清理。 启动时自动设置系统代理,停止时自动清理。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -2,31 +2,23 @@
```json ```json
{ {
"inbounds": [ "type": "hysteria",
{ "tag": "hysteria-in",
"type": "hysteria",
"tag": "hysteria-in", ... // Listen Fields
"listen": "::", "up": "100 Mbps",
"listen_port": 443, "up_mbps": 100,
"sniff": false, "down": "100 Mbps",
"sniff_override_destination": false, "down_mbps": 100,
"domain_strategy": "prefer_ipv6", "obfs": "fuck me till the daylight",
"auth": "",
"up": "100 Mbps", "auth_str": "password",
"up_mbps": 100, "recv_window_conn": 0,
"down": "100 Mbps", "recv_window_client": 0,
"down_mbps": 100, "max_conn_client": 0,
"obfs": "fuck me till the daylight", "disable_mtu_discovery": false,
"auth": "", "tls": {}
"auth_str": "password",
"recv_window_conn": 0,
"recv_window_client": 0,
"max_conn_client": 0,
"disable_mtu_discovery": false,
"tls": {}
}
]
} }
``` ```
@@ -34,7 +26,11 @@
QUIC, which is required by hysteria is not included by default, see [Installation](/#installation). QUIC, which is required by hysteria is not included by default, see [Installation](/#installation).
### Hysteria Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### up, down #### up, down
@@ -101,38 +97,4 @@ Force enabled on for systems other than Linux and Windows (according to upstream
==Required== ==Required==
TLS configuration, see [TLS](/configuration/shared/tls/#inbound). TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.

View File

@@ -2,31 +2,23 @@
```json ```json
{ {
"inbounds": [ "type": "hysteria",
{ "tag": "hysteria-in",
"type": "hysteria",
"tag": "hysteria-in", ... // 监听字段
"listen": "::", "up": "100 Mbps",
"listen_port": 443, "up_mbps": 100,
"sniff": false, "down": "100 Mbps",
"sniff_override_destination": false, "down_mbps": 100,
"domain_strategy": "prefer_ipv6", "obfs": "fuck me till the daylight",
"auth": "",
"up": "100 Mbps", "auth_str": "password",
"up_mbps": 100, "recv_window_conn": 0,
"down": "100 Mbps", "recv_window_client": 0,
"down_mbps": 100, "max_conn_client": 0,
"obfs": "fuck me till the daylight", "disable_mtu_discovery": false,
"auth": "", "tls": {}
"auth_str": "password",
"recv_window_conn": 0,
"recv_window_client": 0,
"max_conn_client": 0,
"disable_mtu_discovery": false,
"tls": {}
}
]
} }
``` ```
@@ -34,7 +26,11 @@
默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#_2)。 默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#_2)。
### Hysteria 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### up, down #### up, down
@@ -101,38 +97,4 @@ base64 编码的认证密码。
==必填== ==必填==
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。 TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。

View File

@@ -15,20 +15,20 @@
### Fields ### Fields
| Type | Format | | Type | Format | Injectable |
|---------------|------------------------------| |---------------|------------------------------|------------|
| `direct` | [Direct](./direct) | | `direct` | [Direct](./direct) | X |
| `mixed` | [Mixed](./mixed) | | `mixed` | [Mixed](./mixed) | TCP |
| `socks` | [SOCKS](./socks) | | `socks` | [SOCKS](./socks) | TCP |
| `http` | [HTTP](./http) | | `http` | [HTTP](./http) | TCP |
| `shadowsocks` | [Shadowsocks](./shadowsocks) | | `shadowsocks` | [Shadowsocks](./shadowsocks) | TCP |
| `vmess` | [VMess](./vmess) | | `vmess` | [VMess](./vmess) | TCP |
| `trojan` | [Trojan](./trojan) | | `trojan` | [Trojan](./trojan) | TCP |
| `naive` | [Naive](./naive) | | `naive` | [Naive](./naive) | X |
| `hysteria` | [Hysteria](./hysteria) | | `hysteria` | [Hysteria](./hysteria) | X |
| `tun` | [Tun](./tun) | | `tun` | [Tun](./tun) | X |
| `redirect` | [Redirect](./redirect) | | `redirect` | [Redirect](./redirect) | X |
| `tproxy` | [TProxy](./tproxy) | | `tproxy` | [TProxy](./tproxy) | X |
#### tag #### tag

View File

@@ -15,20 +15,20 @@
### 字段 ### 字段
| 类型 | 格式 | | 类型 | 格式 | 注入支持 |
|---------------|------------------------------| |---------------|------------------------------|------|
| `direct` | [Direct](./direct) | | `direct` | [Direct](./direct) | X |
| `mixed` | [Mixed](./mixed) | | `mixed` | [Mixed](./mixed) | TCP |
| `socks` | [SOCKS](./socks) | | `socks` | [SOCKS](./socks) | TCP |
| `http` | [HTTP](./http) | | `http` | [HTTP](./http) | TCP |
| `shadowsocks` | [Shadowsocks](./shadowsocks) | | `shadowsocks` | [Shadowsocks](./shadowsocks) | TCP |
| `vmess` | [VMess](./vmess) | | `vmess` | [VMess](./vmess) | TCP |
| `trojan` | [Trojan](./trojan) | | `trojan` | [Trojan](./trojan) | TCP |
| `naive` | [Naive](./naive) | | `naive` | [Naive](./naive) | X |
| `hysteria` | [Hysteria](./hysteria) | | `hysteria` | [Hysteria](./hysteria) | X |
| `tun` | [Tun](./tun) | | `tun` | [Tun](./tun) | X |
| `redirect` | [Redirect](./redirect) | | `redirect` | [Redirect](./redirect) | X |
| `tproxy` | [TProxy](./tproxy) | | `tproxy` | [TProxy](./tproxy) | X |
#### tag #### tag

View File

@@ -4,32 +4,26 @@
```json ```json
{ {
"inbounds": [ "type": "mixed",
"tag": "mixed-in",
... // Listen Fields
"users": [
{ {
"type": "mixed", "username": "admin",
"tag": "mixed-in", "password": "admin"
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [
{
"username": "admin",
"password": "admin"
}
],
"set_system_proxy": false
} }
] ],
"set_system_proxy": false
} }
``` ```
### Mixed Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### users #### users
@@ -39,52 +33,6 @@ No authentication required if empty.
#### set_system_proxy #### set_system_proxy
!!! error ""
Only supported on Linux, Android, Windows, and macOS.
Automatically set system proxy configuration when start and clean up when stop.
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### set_system_proxy
!!! error "" !!! error ""
Only supported on Linux, Android, Windows, and macOS. Only supported on Linux, Android, Windows, and macOS.

View File

@@ -4,38 +4,32 @@
```json ```json
{ {
"inbounds": [ "type": "mixed",
"tag": "mixed-in",
... // 监听字段
"users": [
{ {
"type": "mixed", "username": "admin",
"tag": "mixed-in", "password": "admin"
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [
{
"username": "admin",
"password": "admin"
}
],
"set_system_proxy": false
} }
] ],
"set_system_proxy": false
} }
``` ```
### Mixed 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### users #### users
SOCKS 和 HTTP 用户 SOCKS 和 HTTP 用户
默认不需要验证。 如果为空则不需要验证。
#### set_system_proxy #### set_system_proxy
@@ -43,46 +37,4 @@ SOCKS 和 HTTP 用户
仅支持 Linux、Android、Windows 和 macOS。 仅支持 Linux、Android、Windows 和 macOS。
启动时自动设置系统代理,停止时自动清理。 启动时自动设置系统代理,停止时自动清理。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -2,29 +2,19 @@
```json ```json
{ {
"inbounds": [ "type": "naive",
"tag": "naive-in",
"network": "udp",
... // Listen Fields
"users": [
{ {
"type": "naive", "username": "sekai",
"tag": "naive-in", "password": "password"
"listen": "::",
"listen_port": 443,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"network": "udp",
"users": [
{
"username": "sekai",
"password": "password"
}
],
"tls": {}
} }
] ],
"tls": {}
} }
``` ```
@@ -32,7 +22,11 @@
HTTP3 transport is not included by default, see [Installation](/#installation). HTTP3 transport is not included by default, see [Installation](/#installation).
### Naive Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### network #### network
@@ -48,46 +42,4 @@ Naive users.
#### tls #### tls
TLS configuration, see [TLS](/configuration/shared/tls/#inbound). TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### proxy_protocol
Parse [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.

View File

@@ -2,29 +2,19 @@
```json ```json
{ {
"inbounds": [ "type": "naive",
{ "tag": "naive-in",
"type": "naive", "network": "udp",
"tag": "naive-in",
"listen": "::",
"listen_port": 443,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"network": "udp", ... // 监听字段
"users": [
{ "users": [
"username": "sekai", {
"password": "password" "username": "sekai",
} "password": "password"
],
"tls": {}
} }
] ],
"tls": {}
} }
``` ```
@@ -32,7 +22,11 @@
默认安装不包含 HTTP3 传输层, 参阅 [安装](/zh/#_2)。 默认安装不包含 HTTP3 传输层, 参阅 [安装](/zh/#_2)。
### Naive 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### network #### network
@@ -48,46 +42,4 @@ Naive 用户。
#### tls #### tls
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。 TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -1,52 +1,18 @@
!!! error ""
Only supported on Linux and macOS.
### Structure ### Structure
```json ```json
{ {
"inbounds": [ "type": "redirect",
{ "tag": "redirect-in",
"type": "redirect",
"tag": "redirect-in", ... // Listen Fields
"listen": "::",
"listen_port": 5353,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6"
}
]
} }
``` ```
### Listen Fields ### Listen Fields
#### listen See [Listen Fields](/configuration/shared/listen) for details.
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.

View File

@@ -1,52 +1,17 @@
!!! error ""
仅支持 Linux 和 macOS。
### 结构 ### 结构
```json ```json
{ {
"inbounds": [ "type": "redirect",
{ "tag": "redirect-in",
"type": "redirect",
"tag": "redirect-in", ... // 监听字段
"listen": "::",
"listen_port": 5353,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6"
}
]
} }
``` ```
### 监听字段 ### 监听字段
#### listen 参阅 [监听字段](/zh/configuration/shared/listen/)。
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。

View File

@@ -2,25 +2,13 @@
```json ```json
{ {
"inbounds": [ "type": "shadowsocks",
{ "tag": "ss-in",
"type": "shadowsocks",
"tag": "ss-in", ... // Listen Fields
"listen": "::", "method": "2022-blake3-aes-128-gcm",
"listen_port": 5353, "password": "8JCsPssfgS8tiRwiMlhARg=="
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"network": "udp",
"proxy_protocol": false,
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg=="
}
]
} }
``` ```
@@ -28,17 +16,12 @@
```json ```json
{ {
"inbounds": [ "method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg==",
"users": [
{ {
"type": "shadowsocks", "name": "sekai",
"method": "2022-blake3-aes-128-gcm", "password": "PCD2Z4o12bKUoFa3cC97Hw=="
"password": "8JCsPssfgS8tiRwiMlhARg==",
"users": [
{
"name": "sekai",
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
]
} }
] ]
} }
@@ -48,25 +31,25 @@
```json ```json
{ {
"inbounds": [ "type": "shadowsocks",
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg==",
"destinations": [
{ {
"type": "shadowsocks", "name": "test",
"method": "2022-blake3-aes-128-gcm", "server": "example.com",
"password": "8JCsPssfgS8tiRwiMlhARg==", "server_port": 8080,
"destinations": [ "password": "PCD2Z4o12bKUoFa3cC97Hw=="
{
"name": "test",
"server": "example.com",
"server_port": 8080,
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
]
} }
] ]
} }
``` ```
### Shadowsocks Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### network #### network

View File

@@ -2,25 +2,13 @@
```json ```json
{ {
"inbounds": [ "type": "shadowsocks",
{ "tag": "ss-in",
"type": "shadowsocks",
"tag": "ss-in", ... // 监听字段
"listen": "::", "method": "2022-blake3-aes-128-gcm",
"listen_port": 5353, "password": "8JCsPssfgS8tiRwiMlhARg=="
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"network": "udp",
"proxy_protocol": false,
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg=="
}
]
} }
``` ```
@@ -28,17 +16,12 @@
```json ```json
{ {
"inbounds": [ "method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg==",
"users": [
{ {
"type": "shadowsocks", "name": "sekai",
"method": "2022-blake3-aes-128-gcm", "password": "PCD2Z4o12bKUoFa3cC97Hw=="
"password": "8JCsPssfgS8tiRwiMlhARg==",
"users": [
{
"name": "sekai",
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
]
} }
] ]
} }
@@ -48,25 +31,25 @@
```json ```json
{ {
"inbounds": [ "type": "shadowsocks",
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg==",
"destinations": [
{ {
"type": "shadowsocks", "name": "test",
"method": "2022-blake3-aes-128-gcm", "server": "example.com",
"password": "8JCsPssfgS8tiRwiMlhARg==", "server_port": 8080,
"destinations": [ "password": "PCD2Z4o12bKUoFa3cC97Hw=="
{
"name": "test",
"server": "example.com",
"server_port": 8080,
"password": "PCD2Z4o12bKUoFa3cC97Hw=="
}
]
} }
] ]
} }
``` ```
### Shadowsocks 字段 ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### 字段
#### network #### network
@@ -98,50 +81,4 @@
|---------------|-------------------------------| |---------------|-------------------------------|
| none | / | | none | / |
| 2022 methods | `openssl rand -base64 <密钥长度>` | | 2022 methods | `openssl rand -base64 <密钥长度>` |
| other methods | 任意字符串 | | other methods | 任意字符串 |
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### udp_timeout
UDP NAT 过期时间,以秒为单位,默认为 3005 分钟)。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -0,0 +1,31 @@
### Structure
```json
{
"type": "shadowtls",
"tag": "st-in",
... // Listen Fields
"handshake": {
"server": "google.com",
"server_port": 443,
... // Dial Fields
}
}
```
### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### handshake
==Required==
Handshake server address and [dial options](/configuration/shared/dial).

View File

@@ -0,0 +1,29 @@
### 结构
```json
{
"type": "shadowtls",
"tag": "st-in",
... // 监听字段
"handshake": {
"server": "google.com",
"server_port": 443,
... // 拨号字段
}
}
```
### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### handshake
==必填==
握手服务器地址和 [拨号参数](/zh/configuration/shared/dial/)。

View File

@@ -4,76 +4,28 @@
```json ```json
{ {
"inbounds": [ "type": "socks",
{ "tag": "socks-in",
"type": "socks",
"tag": "socks-in",
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [ ... // Listen Fields
{
"username": "admin", "users": [
"password": "admin" {
} "username": "admin",
] "password": "admin"
} }
] ]
} }
``` ```
### SOCKS Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### users #### users
SOCKS users. SOCKS users.
No authentication required if empty. No authentication required if empty.
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### proxy_protocol
Parse [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.

View File

@@ -4,76 +4,28 @@
```json ```json
{ {
"inbounds": [ "type": "socks",
{ "tag": "socks-in",
"type": "socks",
"tag": "socks-in",
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [ ... // 监听字段
{
"username": "admin", "users": [
"password": "admin" {
} "username": "admin",
] "password": "admin"
} }
] ]
} }
``` ```
### SOCKS 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### users #### users
SOCKS 用户 SOCKS 用户
默认不需要验证。 如果为空则不需要验证。
### Listen Fields
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -1,67 +1,28 @@
!!! error ""
Only supported on Linux.
### Structure ### Structure
```json ```json
{ {
"inbounds": [ "type": "tproxy",
{ "tag": "tproxy-in",
"type": "tproxy",
"tag": "tproxy-in", ... // Listen Fields
"listen": "::", "network": "udp"
"listen_port": 5353,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"network": "udp"
}
]
} }
``` ```
### TProxy Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### network #### network
Listen network, one of `tcp` `udp`. Listen network, one of `tcp` `udp`.
Both if empty. Both if empty.
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### udp_timeout
UDP NAT expiration time in seconds, default is 300 (5 minutes).

View File

@@ -1,67 +1,28 @@
!!! error ""
仅支持 Linux。
### 结构 ### 结构
```json ```json
{ {
"inbounds": [ "type": "tproxy",
{ "tag": "tproxy-in",
"type": "tproxy",
"tag": "tproxy-in", ... // 监听字段
"listen": "::", "network": "udp"
"listen_port": 5353,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"network": "udp"
}
]
} }
``` ```
### TProxy 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### network #### network
监听的网络协议,`tcp` `udp` 之一。 监听的网络协议,`tcp` `udp` 之一。
默认所有。 默认所有。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### udp_timeout
UDP NAT 过期时间,以秒为单位,默认为 3005 分钟)。

View File

@@ -2,43 +2,37 @@
```json ```json
{ {
"inbounds": [ "type": "trojan",
{ "tag": "trojan-in",
"type": "trojan",
"tag": "trojan-in",
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [ ... // Listen Fields
{
"name": "sekai", "users": [
"password": "8JCsPssfgS8tiRwiMlhARg==" {
} "name": "sekai",
], "password": "8JCsPssfgS8tiRwiMlhARg=="
"tls": {},
"fallback": {
"server": "127.0.0.1",
"server_port": 8080
},
"fallback_for_alpn": {
"http/1.1": {
"server": "127.0.0.1",
"server_port": 8081
}
},
"transport": {}
} }
] ],
"tls": {},
"fallback": {
"server": "127.0.0.1",
"server_port": 8080
},
"fallback_for_alpn": {
"http/1.1": {
"server": "127.0.0.1",
"server_port": 8081
}
},
"transport": {}
} }
``` ```
### Trojan Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### users #### users
@@ -67,45 +61,3 @@ If not empty, TLS fallback requests with ALPN not in this table will be rejected
#### transport #### transport
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport). V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### proxy_protocol
Parse [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.

View File

@@ -2,41 +2,37 @@
```json ```json
{ {
"inbounds": [ "type": "trojan",
"tag": "trojan-in",
... // 监听字段
"users": [
{ {
"type": "trojan", "name": "sekai",
"tag": "trojan-in", "password": "8JCsPssfgS8tiRwiMlhARg=="
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [
{
"name": "sekai",
"password": "8JCsPssfgS8tiRwiMlhARg=="
}
],
"tls": {},
"fallback": {
"server": "127.0.0.1",
"server_port": 8080
},
"fallback_for_alpn": {
"http/1.1": {
"server": "127.0.0.1",
"server_port": 8081
}
},
"transport": {}
} }
] ],
"tls": {},
"fallback": {
"server": "127.0.0.1",
"server_port": 8080
},
"fallback_for_alpn": {
"http/1.1": {
"server": "127.0.0.1",
"server_port": 8081
}
},
"transport": {}
} }
``` ```
### Trojan 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### users #### users
@@ -54,7 +50,7 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
!!! error "" !!! error ""
没有证据表明 GFW 基于 HTTP 响应检测并阻止木马服务器,并且在服务器上打开标准 http/s 端口是一个更大的特征。 没有证据表明 GFW 基于 HTTP 响应检测并阻止 Trojan 服务器,并且在服务器上打开标准 http/s 端口是一个更大的特征。
回退服务器配置。如果 `fallback``fallback_for_alpn` 为空,则禁用回退。 回退服务器配置。如果 `fallback``fallback_for_alpn` 为空,则禁用回退。
@@ -66,46 +62,4 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
#### transport #### transport
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。 V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -6,48 +6,41 @@
```json ```json
{ {
"inbounds": [ "type": "tun",
{ "tag": "tun-in",
"type": "tun",
"tag": "tun-in", "interface_name": "tun0",
"interface_name": "tun0", "inet4_address": "172.19.0.1/30",
"inet4_address": "172.19.0.1/30", "inet6_address": "fdfe:dcba:9876::1/128",
"inet6_address": "fdfe:dcba:9876::1/128", "mtu": 1500,
"mtu": 1500, "auto_route": true,
"auto_route": true, "strict_route": true,
"strict_route": true, "endpoint_independent_nat": false,
"endpoint_independent_nat": false, "stack": "gvisor",
"udp_timeout": 300, "include_uid": [
"stack": "gvisor", 0
"include_uid": [ ],
0 "include_uid_range": [
], "1000-99999"
"include_uid_range": [ ],
[ "exclude_uid": [
"1000-99999" 1000
] ],
], "exclude_uid_range": [
"exclude_uid": [ "1000-99999"
1000 ],
], "include_android_user": [
"exclude_uid_range": [ 0,
"1000-99999" 10
], ],
"include_android_user": [ "include_package": [
0, "com.android.chrome"
10 ],
], "exclude_package": [
"include_package": [ "com.android.captiveportallogin"
"com.android.chrome" ],
],
"exclude_package": [ ... // Listen Fields
"com.android.captiveportallogin"
],
"sniff": true,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv4"
}
]
} }
``` ```
@@ -59,7 +52,7 @@
If tun is running in non-privileged mode, addresses and MTU will not be configured automatically, please make sure the settings are accurate. If tun is running in non-privileged mode, addresses and MTU will not be configured automatically, please make sure the settings are accurate.
### Tun Fields ### Fields
#### interface_name #### interface_name
@@ -163,22 +156,4 @@ Exclude android packages in route.
### Listen Fields ### Listen Fields
#### sniff See [Listen Fields](/configuration/shared/listen) for details.
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.

View File

@@ -6,48 +6,41 @@
```json ```json
{ {
"inbounds": [ "type": "tun",
{ "tag": "tun-in",
"type": "tun",
"tag": "tun-in", "interface_name": "tun0",
"interface_name": "tun0", "inet4_address": "172.19.0.1/30",
"inet4_address": "172.19.0.1/30", "inet6_address": "fdfe:dcba:9876::1/128",
"inet6_address": "fdfe:dcba:9876::1/128", "mtu": 1500,
"mtu": 1500, "auto_route": true,
"auto_route": true, "strict_route": true,
"strict_route": true, "endpoint_independent_nat": false,
"endpoint_independent_nat": false, "stack": "gvisor",
"udp_timeout": 300, "include_uid": [
"stack": "gvisor", 0
"include_uid": [ ],
0 "include_uid_range": [
], "1000-99999"
"include_uid_range": [ ],
[ "exclude_uid": [
"1000-99999" 1000
] ],
], "exclude_uid_range": [
"exclude_uid": [ "1000-99999"
1000 ],
], "include_android_user": [
"exclude_uid_range": [ 0,
"1000-99999" 10
], ],
"include_android_user": [ "include_package": [
0, "com.android.chrome"
10 ],
], "exclude_package": [
"include_package": [ "com.android.captiveportallogin"
"com.android.chrome" ],
],
"exclude_package": [ ... // 监听字段
"com.android.captiveportallogin"
],
"sniff": true,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv4"
}
]
} }
``` ```
@@ -162,22 +155,4 @@ TCP/IP 栈。
### 监听字段 ### 监听字段
#### sniff 参阅 [监听字段](/zh/configuration/shared/listen/)。
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。

View File

@@ -2,34 +2,28 @@
```json ```json
{ {
"inbounds": [ "type": "vmess",
{ "tag": "vmess-in",
"type": "vmess",
"tag": "vmess-in",
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [ ... // Listen Fields
{
"name": "sekai", "users": [
"uuid": "bf000d23-0752-40b4-affe-68f7707a9661", {
"alterId": 0 "name": "sekai",
} "uuid": "bf000d23-0752-40b4-affe-68f7707a9661",
], "alterId": 0
"tls": {},
"transport": {}
} }
] ],
"tls": {},
"transport": {}
} }
``` ```
### VMess Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen) for details.
### Fields
#### users #### users
@@ -53,45 +47,3 @@ TLS configuration, see [TLS](/configuration/shared/tls/#inbound).
#### transport #### transport
V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport). V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray-transport).
### Listen Fields
#### listen
==Required==
Listen address.
#### listen_port
==Required==
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### proxy_protocol
Parse [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.

View File

@@ -2,34 +2,28 @@
```json ```json
{ {
"inbounds": [ "type": "vmess",
{ "tag": "vmess-in",
"type": "vmess",
"tag": "vmess-in",
"listen": "::",
"listen_port": 2080,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"proxy_protocol": false,
"users": [ ... // 监听字段
{
"name": "sekai", "users": [
"uuid": "bf000d23-0752-40b4-affe-68f7707a9661", {
"alterId": 0 "name": "sekai",
} "uuid": "bf000d23-0752-40b4-affe-68f7707a9661",
], "alterId": 0
"tls": {},
"transport": {}
} }
] ],
"tls": {},
"transport": {}
} }
``` ```
### VMess 字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。
### 字段
#### users #### users
@@ -53,45 +47,3 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#inbound)。
#### transport #### transport
V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。 V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-transport)。
### 监听字段
#### listen
==必填==
监听地址。
#### listen_port
==必填==
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)。
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。

View File

@@ -8,8 +8,8 @@ sing-box uses JSON for configuration files.
{ {
"log": {}, "log": {},
"dns": {}, "dns": {},
"inbounds": {}, "inbounds": [],
"outbounds": {}, "outbounds": [],
"route": {}, "route": {},
"experimental": {} "experimental": {}
} }

View File

@@ -8,8 +8,8 @@ sing-box 使用 JSON 作为配置文件格式。
{ {
"log": {}, "log": {},
"dns": {}, "dns": {},
"inbounds": {}, "inbounds": [],
"outbounds": {}, "outbounds": [],
"route": {}, "route": {},
"experimental": {} "experimental": {}
} }

View File

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

View File

@@ -1,3 +1,5 @@
# 日志
### 结构 ### 结构
```json ```json

View File

@@ -4,12 +4,8 @@
```json ```json
{ {
"outbounds": [ "type": "block",
{ "tag": "block"
"type": "block",
"tag": "block"
}
]
} }
``` ```

View File

@@ -4,12 +4,8 @@
```json ```json
{ {
"outbounds": [ "type": "block",
{ "tag": "block"
"type": "block",
"tag": "block"
}
]
} }
``` ```

View File

@@ -4,30 +4,18 @@
```json ```json
{ {
"outbounds": [ "type": "direct",
{ "tag": "direct-out",
"type": "direct",
"tag": "direct-out", "override_address": "1.0.0.1",
"override_port": 53,
"override_address": "1.0.0.1", "proxy_protocol": 0,
"override_port": 53,
"proxy_protocol": 0, ... // Dial Fields
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### Direct Fields ### Fields
#### override_address #### override_address
@@ -45,54 +33,4 @@ Protocol value can be `1` or `2`.
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before connect.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -4,30 +4,18 @@
```json ```json
{ {
"outbounds": [ "type": "direct",
{ "tag": "direct-out",
"type": "direct",
"tag": "direct-out", "override_address": "1.0.0.1",
"override_port": 53,
"override_address": "1.0.0.1", "proxy_protocol": 0,
"override_port": 53,
"proxy_protocol": 0, ... // 拨号字段
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### Direct 字段 ### 字段
#### override_address #### override_address
@@ -45,51 +33,4 @@
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,域名将在请求发出之前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -4,12 +4,8 @@
```json ```json
{ {
"outbounds": [ "type": "dns",
{ "tag": "dns-out"
"type": "dns",
"tag": "dns-out"
}
]
} }
``` ```

View File

@@ -4,12 +4,8 @@
```json ```json
{ {
"outbounds": [ "type": "dns",
{ "tag": "dns-out"
"type": "dns",
"tag": "dns-out"
}
]
} }
``` ```

View File

@@ -4,32 +4,20 @@
```json ```json
{ {
"outbounds": [ "type": "http",
{ "tag": "http-out",
"type": "http",
"tag": "http-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "username": "sekai",
"server_port": 1080, "password": "admin",
"username": "sekai", "tls": {},
"password": "admin",
"tls": {}, ... // Dial Fields
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### HTTP Fields ### Fields
#### server #### server
@@ -57,54 +45,4 @@ TLS configuration, see [TLS](/configuration/shared/tls/#outbound).
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -4,32 +4,20 @@
```json ```json
{ {
"outbounds": [ "type": "http",
{ "tag": "http-out",
"type": "http",
"tag": "http-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "username": "sekai",
"server_port": 1080, "password": "admin",
"username": "sekai", "tls": {},
"password": "admin",
"tls": {}, ... // 拨号字段
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### HTTP 字段 ### 字段
#### server #### server
@@ -57,51 +45,4 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#outbound)。
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -2,37 +2,25 @@
```json ```json
{ {
"outbounds": [ "type": "hysteria",
{ "tag": "hysteria-out",
"type": "hysteria",
"tag": "hysteria-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "up": "100 Mbps",
"server_port": 1080, "up_mbps": 100,
"down": "100 Mbps",
"up": "100 Mbps", "down_mbps": 100,
"up_mbps": 100, "obfs": "fuck me till the daylight",
"down": "100 Mbps", "auth": "",
"down_mbps": 100, "auth_str": "password",
"obfs": "fuck me till the daylight", "recv_window_conn": 0,
"auth": "", "recv_window": 0,
"auth_str": "password", "disable_mtu_discovery": false,
"recv_window_conn": 0, "network": "tcp",
"recv_window": 0, "tls": {},
"disable_mtu_discovery": false,
"network": "tcp", ... // Dial Fields
"tls": {},
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
@@ -40,7 +28,7 @@
QUIC, which is required by hysteria is not included by default, see [Installation](/#installation). QUIC, which is required by hysteria is not included by default, see [Installation](/#installation).
### Hysteria Fields ### Fields
#### server #### server
@@ -125,54 +113,4 @@ Both is enabled by default.
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -2,37 +2,25 @@
```json ```json
{ {
"outbounds": [ "type": "hysteria",
{ "tag": "hysteria-out",
"type": "hysteria",
"tag": "hysteria-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "up": "100 Mbps",
"server_port": 1080, "up_mbps": 100,
"down": "100 Mbps",
"up": "100 Mbps", "down_mbps": 100,
"up_mbps": 100, "obfs": "fuck me till the daylight",
"down": "100 Mbps", "auth": "",
"down_mbps": 100, "auth_str": "password",
"obfs": "fuck me till the daylight", "recv_window_conn": 0,
"auth": "", "recv_window": 0,
"auth_str": "password", "disable_mtu_discovery": false,
"recv_window_conn": 0, "network": "tcp",
"recv_window": 0, "tls": {},
"disable_mtu_discovery": false,
"network": "tcp", ... // 拨号字段
"tls": {},
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
@@ -40,7 +28,7 @@
默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#_2)。 默认安装不包含被 Hysteria 依赖的 QUIC参阅 [安装](/zh/#_2)。
### Hysteria 字段 ### 字段
#### server #### server
@@ -123,51 +111,4 @@ TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#outbound)。
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -2,19 +2,15 @@
```json ```json
{ {
"type": "selector",
"tag": "select",
"outbounds": [ "outbounds": [
{ "proxy-a",
"type": "selector", "proxy-b",
"tag": "select", "proxy-c"
],
"outbounds": [ "default": "proxy-c"
"proxy-a",
"proxy-b",
"proxy-c"
],
"default": "proxy-c"
}
]
} }
``` ```

View File

@@ -2,19 +2,15 @@
```json ```json
{ {
"type": "selector",
"tag": "select",
"outbounds": [ "outbounds": [
{ "proxy-a",
"type": "selector", "proxy-b",
"tag": "select", "proxy-c"
],
"outbounds": [ "default": "proxy-c"
"proxy-a",
"proxy-b",
"proxy-c"
],
"default": "proxy-c"
}
]
} }
``` ```

View File

@@ -2,34 +2,22 @@
```json ```json
{ {
"outbounds": [ "type": "shadowsocks",
{ "tag": "ss-out",
"type": "shadowsocks",
"tag": "ss-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "method": "2022-blake3-aes-128-gcm",
"server_port": 1080, "password": "8JCsPssfgS8tiRwiMlhARg==",
"method": "2022-blake3-aes-128-gcm", "network": "udp",
"password": "8JCsPssfgS8tiRwiMlhARg==", "udp_over_tcp": false,
"network": "udp", "multiplex": {},
"udp_over_tcp": false,
"multiplex": {}, ... // Dial Fields
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### Shadowsocks Fields ### Fields
#### server #### server
@@ -97,54 +85,4 @@ Multiplex configuration, see [Multiplex](/configuration/shared/multiplex).
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -1,35 +1,23 @@
### Structure ### 结构
```json ```json
{ {
"outbounds": [ "type": "shadowsocks",
{ "tag": "ss-out",
"type": "shadowsocks",
"tag": "ss-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "method": "2022-blake3-aes-128-gcm",
"server_port": 1080, "password": "8JCsPssfgS8tiRwiMlhARg==",
"method": "2022-blake3-aes-128-gcm", "network": "udp",
"password": "8JCsPssfgS8tiRwiMlhARg==", "udp_over_tcp": false,
"network": "udp", "multiplex": {},
"udp_over_tcp": false,
"multiplex": {}, ... // 拨号字段
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### Shadowsocks 字段 ### 字段
#### server #### server
@@ -97,51 +85,4 @@ Shadowsocks 密码。
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -0,0 +1,38 @@
### Structure
```json
{
"type": "shadowtls",
"tag": "st-out",
"server": "127.0.0.1",
"server_port": 1080,
"tls": {},
... // Dial Fields
}
```
### Fields
#### server
==Required==
The server address.
#### server_port
==Required==
The server port.
#### tls
==Required==
TLS configuration, see [TLS](/configuration/shared/tls/#outbound).
### Dial Fields
See [Dial Fields](/configuration/shared/dial) for details.

View File

@@ -0,0 +1,38 @@
### 结构
```json
{
"type": "shadowtls",
"tag": "st-out",
"server": "127.0.0.1",
"server_port": 1080,
"tls": {},
... // 拨号字段
}
```
### 字段
#### server
==必填==
服务器地址。
#### server_port
==必填==
服务器端口。
#### tls
==必填==
TLS 配置, 参阅 [TLS](/zh/configuration/shared/tls/#outbound)。
### 拨号字段
参阅 [拨号字段](/zh/configuration/shared/dial/)。

View File

@@ -4,34 +4,22 @@
```json ```json
{ {
"outbounds": [ "type": "socks",
{ "tag": "socks-out",
"type": "socks",
"tag": "socks-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "version": "5",
"server_port": 1080, "username": "sekai",
"version": "5", "password": "admin",
"username": "sekai", "network": "udp",
"password": "admin", "udp_over_tcp": false,
"network": "udp",
"udp_over_tcp": false,
"detour": "upstream-out", ... // Dial Fields
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### SOCKS Fields ### Fields
#### server #### server
@@ -73,54 +61,4 @@ Enable the UDP over TCP protocol.
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -1,37 +1,25 @@
`socks` 出站是 socks4/socks4a/socks5 客户端 `socks` 出站是 socks4/socks4a/socks5 客户端
### Structure ### 结构
```json ```json
{ {
"outbounds": [ "type": "socks",
{ "tag": "socks-out",
"type": "socks",
"tag": "socks-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "version": "5",
"server_port": 1080, "username": "sekai",
"version": "5", "password": "admin",
"username": "sekai", "network": "udp",
"password": "admin", "udp_over_tcp": false,
"network": "udp",
"udp_over_tcp": false,
"detour": "upstream-out", ... // 拨号字段
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### SOCKS 字段 ### 字段
#### server #### server
@@ -73,51 +61,4 @@ SOCKS5 密码。
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -2,36 +2,24 @@
```json ```json
{ {
"outbounds": [ "type": "ssh",
{ "tag": "ssh-out",
"type": "ssh",
"tag": "ssh-out", "server": "127.0.0.1",
"server_port": 22,
"server": "127.0.0.1", "user": "root",
"server_port": 22, "password": "admin",
"user": "root", "private_key": "",
"password": "admin", "private_key_path": "$HOME/.ssh/id_rsa",
"private_key": "", "private_key_passphrase": "",
"private_key_path": "$HOME/.ssh/id_rsa", "host_key_algorithms": [],
"private_key_passphrase": "", "client_version": "SSH-2.0-OpenSSH_7.4p1",
"host_key_algorithms": [],
"client_version": "SSH-2.0-OpenSSH_7.4p1", ... // Dial Fields
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### SSH Fields ### Fields
#### server #### server
@@ -73,54 +61,4 @@ Client version. Random version will be used if empty.
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -1,37 +1,25 @@
### Structure ### 结构
```json ```json
{ {
"outbounds": [ "type": "ssh",
{ "tag": "ssh-out",
"type": "ssh",
"tag": "ssh-out", "server": "127.0.0.1",
"server_port": 22,
"server": "127.0.0.1", "user": "root",
"server_port": 22, "password": "admin",
"user": "root", "private_key": "",
"password": "admin", "private_key_path": "$HOME/.ssh/id_rsa",
"private_key": "", "private_key_passphrase": "",
"private_key_path": "$HOME/.ssh/id_rsa", "host_key_algorithms": [],
"private_key_passphrase": "", "client_version": "SSH-2.0-OpenSSH_7.4p1",
"host_key_algorithms": [],
"client_version": "SSH-2.0-OpenSSH_7.4p1", ... // 拨号字段
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### SSH 字段 ### 字段
#### server #### server
@@ -73,51 +61,4 @@ SSH 用户, 默认使用 root。
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -2,29 +2,17 @@
```json ```json
{ {
"outbounds": [ "type": "tor",
{ "tag": "tor-out",
"type": "tor",
"tag": "tor-out", "executable_path": "/usr/bin/tor",
"extra_args": [],
"executable_path": "/usr/bin/tor", "data_directory": "$HOME/.cache/tor",
"extra_args": [], "torrc": {
"data_directory": "$HOME/.cache/tor", "ClientOnly": 1
"torrc": { },
"ClientOnly": 1
}, ... // Dial Fields
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
@@ -32,7 +20,7 @@
Embedded tor is not included by default, see [Installation](/#installation). Embedded tor is not included by default, see [Installation](/#installation).
### Tor Fields ### Fields
#### executable_path #### executable_path
@@ -56,58 +44,8 @@ Each start will be very slow if not specified.
Map of torrc options. Map of torrc options.
See [tor(1)](https://linux.die.net/man/1/tor) See [tor(1)](https://linux.die.net/man/1/tor) for details.
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -2,29 +2,17 @@
```json ```json
{ {
"outbounds": [ "type": "tor",
{ "tag": "tor-out",
"type": "tor",
"tag": "tor-out", "executable_path": "/usr/bin/tor",
"extra_args": [],
"executable_path": "/usr/bin/tor", "data_directory": "$HOME/.cache/tor",
"extra_args": [], "torrc": {
"data_directory": "$HOME/.cache/tor", "ClientOnly": 1
"torrc": { },
"ClientOnly": 1
}, ... // 拨号字段
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
@@ -32,7 +20,7 @@
默认安装不包含嵌入式 Tor, 参阅 [安装](/zh/#_2)。 默认安装不包含嵌入式 Tor, 参阅 [安装](/zh/#_2)。
### Tor 字段 ### 字段
#### executable_path #### executable_path
@@ -60,51 +48,4 @@ torrc 参数表。
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -2,34 +2,22 @@
```json ```json
{ {
"outbounds": [ "type": "trojan",
{ "tag": "trojan-out",
"type": "trojan",
"tag": "trojan-out",
"server": "127.0.0.1",
"server_port": 1080,
"password": "8JCsPssfgS8tiRwiMlhARg==",
"network": "tcp",
"tls": {},
"multiplex": {},
"transport": {},
"detour": "upstream-out", "server": "127.0.0.1",
"bind_interface": "en0", "server_port": 1080,
"bind_address": "0.0.0.0", "password": "8JCsPssfgS8tiRwiMlhARg==",
"routing_mark": 1234, "network": "tcp",
"reuse_addr": false, "tls": {},
"connect_timeout": "5s", "multiplex": {},
"tcp_fast_open": false, "transport": {},
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms" ... // Dial Fields
}
]
} }
``` ```
### Trojan Fields ### Fields
#### server #### server
@@ -71,54 +59,4 @@ V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -2,34 +2,22 @@
```json ```json
{ {
"outbounds": [ "type": "trojan",
{ "tag": "trojan-out",
"type": "trojan",
"tag": "trojan-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "password": "8JCsPssfgS8tiRwiMlhARg==",
"server_port": 1080, "network": "tcp",
"password": "8JCsPssfgS8tiRwiMlhARg==", "tls": {},
"network": "tcp", "multiplex": {},
"tls": {}, "transport": {},
"multiplex": {},
"transport": {},
"detour": "upstream-out", ... // 拨号字段
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### Trojan 字段 ### 字段
#### server #### server
@@ -71,51 +59,4 @@ V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-tra
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -2,39 +2,27 @@
```json ```json
{ {
"outbounds": [ "type": "vmess",
{ "tag": "vmess-out",
"type": "vmess",
"tag": "vmess-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "uuid": "bf000d23-0752-40b4-affe-68f7707a9661",
"server_port": 1080, "security": "auto",
"uuid": "bf000d23-0752-40b4-affe-68f7707a9661", "alter_id": 0,
"security": "auto", "global_padding": false,
"alter_id": 0, "authenticated_length": true,
"global_padding": false, "network": "tcp",
"authenticated_length": true, "tls": {},
"network": "tcp", "packet_addr": false,
"tls": {}, "multiplex": {},
"packet_addr": false, "transport": {},
"multiplex": {},
"transport": {},
"detour": "upstream-out", ... // Dial Fields
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### VMess Fields ### Fields
#### server #### server
@@ -110,54 +98,4 @@ V2Ray Transport configuration, see [V2Ray Transport](/configuration/shared/v2ray
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -2,39 +2,27 @@
```json ```json
{ {
"outbounds": [ "type": "vmess",
{ "tag": "vmess-out",
"type": "vmess",
"tag": "vmess-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "uuid": "bf000d23-0752-40b4-affe-68f7707a9661",
"server_port": 1080, "security": "auto",
"uuid": "bf000d23-0752-40b4-affe-68f7707a9661", "alter_id": 0,
"security": "auto", "global_padding": false,
"alter_id": 0, "authenticated_length": true,
"global_padding": false, "network": "tcp",
"authenticated_length": true, "tls": {},
"network": "tcp", "packet_addr": false,
"tls": {}, "multiplex": {},
"packet_addr": false, "transport": {},
"multiplex": {},
"transport": {}, ... // 拨号字段
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
### VMess 字段 ### 字段
#### server #### server
@@ -110,51 +98,4 @@ V2Ray 传输配置,参阅 [V2Ray 传输层](/zh/configuration/shared/v2ray-tra
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -2,34 +2,22 @@
```json ```json
{ {
"outbounds": [ "type": "wireguard",
{ "tag": "wireguard-out",
"type": "wireguard",
"tag": "wireguard-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "local_address": [
"server_port": 1080, "10.0.0.1",
"local_address": [ "10.0.0.2/32"
"10.0.0.1", ],
"10.0.0.2/32" "private_key": "YNXtAzepDqRv9H52osJVDQnznT5AM11eCK3ESpwSt04=",
], "peer_public_key": "Z1XXLsKYkYxuiYjJIkRvtIKFepCYHTgON+GwPq7SOV4=",
"private_key": "YNXtAzepDqRv9H52osJVDQnznT5AM11eCK3ESpwSt04=", "pre_shared_key": "31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=",
"peer_public_key": "Z1XXLsKYkYxuiYjJIkRvtIKFepCYHTgON+GwPq7SOV4=", "mtu": 1408,
"pre_shared_key": "31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=", "network": "tcp",
"mtu": 1408,
"network": "tcp", ... // Dial Fields
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
@@ -37,7 +25,7 @@
WireGuard is not included by default, see [Installation](/#installation). WireGuard is not included by default, see [Installation](/#installation).
### WireGuard Fields ### Fields
#### server #### server
@@ -92,54 +80,4 @@ Both is enabled by default.
### Dial Fields ### Dial Fields
#### detour See [Dial Fields](/configuration/shared/dial) for details.
The tag of the upstream outbound.
Other dial fields will be ignored when enabled.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the server domain name will be resolved to IP before connecting.
`dns.strategy` will be used if empty.
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for IPv6 to succeed before assuming
that IPv6 is misconfigured and falling back to IPv4 if `prefer_ipv4` is set.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is `prefer_ipv4` or `prefer_ipv6`.

View File

@@ -2,34 +2,22 @@
```json ```json
{ {
"outbounds": [ "type": "wireguard",
{ "tag": "wireguard-out",
"type": "wireguard",
"tag": "wireguard-out", "server": "127.0.0.1",
"server_port": 1080,
"server": "127.0.0.1", "local_address": [
"server_port": 1080, "10.0.0.1",
"local_address": [ "10.0.0.2/32"
"10.0.0.1", ],
"10.0.0.2/32" "private_key": "YNXtAzepDqRv9H52osJVDQnznT5AM11eCK3ESpwSt04=",
], "peer_public_key": "Z1XXLsKYkYxuiYjJIkRvtIKFepCYHTgON+GwPq7SOV4=",
"private_key": "YNXtAzepDqRv9H52osJVDQnznT5AM11eCK3ESpwSt04=", "pre_shared_key": "31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=",
"peer_public_key": "Z1XXLsKYkYxuiYjJIkRvtIKFepCYHTgON+GwPq7SOV4=", "mtu": 1408,
"pre_shared_key": "31aIhAPwktDGpH4JDhA8GNvjFXEf/a6+UaQRyOAiyfM=", "network": "tcp",
"mtu": 1408,
"network": "tcp", ... // 拨号字段
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
]
} }
``` ```
@@ -37,7 +25,7 @@
默认安装不包含 WireGuard, 参阅 [安装](/zh/#_2)。 默认安装不包含 WireGuard, 参阅 [安装](/zh/#_2)。
### WireGuard 字段 ### 字段
#### server #### server
@@ -94,51 +82,4 @@ WireGuard MTU。 默认1408。
### 拨号字段 ### 拨号字段
#### detour 参阅 [拨号字段](/zh/configuration/shared/dial/)。
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,服务器域名将在连接前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -68,6 +68,9 @@
"process_name": [ "process_name": [
"curl" "curl"
], ],
"process_path": [
"/usr/bin/curl"
],
"package_name": [ "package_name": [
"com.termux" "com.termux"
], ],
@@ -188,6 +191,14 @@ Match port range.
Match process name. Match process name.
#### process_path
!!! error ""
Only supported on Linux, Windows, and macOS.
Match process path.
#### package_name #### package_name
Match android package name. Match android package name.

View File

@@ -66,6 +66,9 @@
"process_name": [ "process_name": [
"curl" "curl"
], ],
"process_path": [
"/usr/bin/curl"
],
"package_name": [ "package_name": [
"com.termux" "com.termux"
], ],
@@ -186,6 +189,14 @@
匹配进程名称。 匹配进程名称。
#### process_path
!!! error ""
仅支持 Linux、Windows 和 macOS.
匹配进程路径。
#### package_name #### package_name
匹配 Android 应用包名。 匹配 Android 应用包名。

View File

@@ -0,0 +1,74 @@
### Structure
```json
{
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
```
### Fields
| Field | Available Context |
|-----------------------------------------------------------------------------------|-------------------|
| `bind_interface` /`bind_address` /`routing_mark` /`reuse_addr` /`connect_timeout` | `detour` not set |
#### detour
The tag of the upstream outbound.
#### bind_interface
The network interface to bind to.
#### bind_address
The address to bind to.
#### routing_mark
!!! error ""
Only supported on Linux.
Set netfilter routing mark.
#### reuse_addr
Reuse listener address.
#### connect_timeout
Connect timeout, in golang's Duration format.
A duration string is a possibly signed sequence of
decimal numbers, each with optional fraction and a unit suffix,
such as "300ms", "-1.5h" or "2h45m".
Valid time units are "ns", "us" (or "µs"), "ms", "s", "m", "h".
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before connect.
| Outbound | Effected domains | Fallback Value |
|----------|--------------------------|-------------------------------------------|
| `direct` | Domain in request | Take `inbound.domain_strategy` if not set |
| others | Domain in server address | / |
#### fallback_delay
The length of time to wait before spawning a RFC 6555 Fast Fallback connection.
That is, is the amount of time to wait for connection to succeed before assuming
that IPv4/IPv6 is misconfigured and falling back to other type of addresses.
If zero, a default delay of 300ms is used.
Only take effect when `domain_strategy` is set.

View File

@@ -0,0 +1,66 @@
### 结构
```json
{
"detour": "upstream-out",
"bind_interface": "en0",
"bind_address": "0.0.0.0",
"routing_mark": 1234,
"reuse_addr": false,
"connect_timeout": "5s",
"tcp_fast_open": false,
"domain_strategy": "prefer_ipv6",
"fallback_delay": "300ms"
}
```
### 字段
#### detour
上游出站的标签。
启用时,其他拨号字段将被忽略。
#### bind_interface
要绑定到的网络接口。
#### bind_address
要绑定的地址。
#### routing_mark
!!! error ""
仅支持 Linux。
设置 netfilter 路由标记。
#### reuse_addr
重用监听地址。
#### connect_timeout
连接超时,采用 golang 的 Duration 格式。
持续时间字符串是一个可能有符号的序列十进制数,每个都有可选的分数和单位后缀, 例如 "300ms"、"-1.5h" 或 "2h45m"。
有效时间单位为 "ns"、"us"(或 "µs")、"ms"、"s"、"m"、"h"。
#### domain_strategy
可选值:`prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,域名将在请求发出之前解析为 IP。
默认使用 `dns.strategy`
#### fallback_delay
在生成 RFC 6555 快速回退连接之前等待的时间长度。
也就是说,是在假设之前等待 IPv6 成功的时间量如果设置了 "prefer_ipv4",则 IPv6 配置错误并回退到 IPv4。
如果为零,则使用 300 毫秒的默认延迟。
仅当 `domain_strategy``prefer_ipv4``prefer_ipv6` 时生效。

View File

@@ -0,0 +1,73 @@
### Structure
```json
{
"listen": "::",
"listen_port": 5353,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"proxy_protocol": false,
"detour": "another-in"
}
```
### Fields
| Field | Available Context |
|------------------|-------------------------------------------------------------------|
| `listen` | Needs to listen on TCP or UDP. |
| `listen_port` | Needs to listen on TCP or UDP. |
| `tcp_fast_open` | Needs to listen on TCP. |
| `udp_timeout` | Needs to assemble UDP connections, currently Tun and Shadowsocks. |
| `proxy_protocol` | Needs to listen on TCP. |
#### listen
==Required==
Listen address.
#### listen_port
Listen port.
#### tcp_fast_open
Enable tcp fast open for listener.
#### sniff
Enable sniffing.
See [Protocol Sniff](/configuration/route/sniff/) for details.
#### sniff_override_destination
Override the connection destination address with the sniffed domain.
If the domain name is invalid (like tor), this will not work.
#### domain_strategy
One of `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`.
If set, the requested domain name will be resolved to IP before routing.
If `sniff_override_destination` is in effect, its value will be taken as a fallback.
#### udp_timeout
UDP NAT expiration time in seconds, default is 300 (5 minutes).
#### proxy_protocol
Parse [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.
#### detour
If set, connections will be forwarded to the specified inbound.
Requires target inbound support, see [Injectable](/configuration/inbound/#fields).

View File

@@ -0,0 +1,72 @@
### 结构
```json
{
"listen": "::",
"listen_port": 5353,
"tcp_fast_open": false,
"sniff": false,
"sniff_override_destination": false,
"domain_strategy": "prefer_ipv6",
"udp_timeout": 300,
"detour": "another-in"
}
```
| 字段 | 可用上下文 |
|------------------|-------------------------------------|
| `listen` | 需要监听 TCP 或 UDP。 |
| `listen_port` | 需要监听 TCP 或 UDP。 |
| `tcp_fast_open` | 需要监听 TCP。 |
| `udp_timeout` | 需要组装 UDP 连接, 当前为 Tun 和 Shadowsocks。 |
| `proxy_protocol` | 需要监听 TCP。 |
### 字段
#### listen
==必填==
监听地址。
#### listen_port
监听端口。
#### tcp_fast_open
为监听器启用 TCP 快速打开。
#### sniff
启用协议探测。
参阅 [协议探测](/zh/configuration/route/sniff/)
#### sniff_override_destination
用探测出的域名覆盖连接目标地址。
如果域名无效(如 Tor将不生效。
#### domain_strategy
可选值: `prefer_ipv4` `prefer_ipv6` `ipv4_only` `ipv6_only`
如果设置,请求的域名将在路由之前解析为 IP。
如果 `sniff_override_destination` 生效,它的值将作为后备。
#### udp_timeout
UDP NAT 过期时间,以秒为单位,默认为 3005 分钟)。
#### proxy_protocol
解析连接头中的 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt)。
#### detour
如果设置,连接将被转发到指定的入站。
需要目标入站支持,参阅 [注入支持](/zh/configuration/inbound/#_3)。

View File

@@ -0,0 +1,55 @@
#### Server
```json
{
"inbounds": [
{
"type": "shadowtls",
"listen": "::",
"listen_port": 4443,
"handshake": {
"server": "google.com",
"server_port": 443
},
"detour": "shadowsocks-in"
},
{
"type": "shadowsocks",
"tag": "shadowsocks-in",
"listen": "127.0.0.1",
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg=="
}
]
}
```
#### Client
```json
{
"outbounds": [
{
"type": "shadowsocks",
"method": "2022-blake3-aes-128-gcm",
"password": "8JCsPssfgS8tiRwiMlhARg==",
"detour": "shadowtls-out",
"multiplex": {
"enabled": true,
"max_connections": 4,
"min_streams": 4
}
},
{
"type": "shadowtls",
"tag": "shadowtls-out",
"server": "127.0.0.1",
"server_port": 4443,
"tls": {
"enabled": true,
"server_name": "google.com"
}
}
]
}
```

View File

@@ -11,7 +11,7 @@ the public internet.
##### on Linux ##### on Linux
`auto-route` cannot automatically hijack DNS requests with `systemd-resoled` enabled, you can switch to NetworkManager. `auto-route` cannot automatically hijack DNS requests with `systemd-resolved` enabled, you can switch to NetworkManager.
#### System proxy #### System proxy

View File

@@ -10,7 +10,7 @@
##### Linux ##### Linux
`auto-route` 无法自动劫持 DNS 请求如果 `systemd-resoled` 开启, 您可以切换到 NetworkManager. `auto-route` 无法自动劫持 DNS 请求如果 `systemd-resolved` 开启, 您可以切换到 NetworkManager.
#### 系统代理 #### 系统代理

View File

@@ -13,13 +13,13 @@ The universal proxy platform.
sing-box requires Golang **1.18.5** or a higher version. sing-box requires Golang **1.18.5** or a higher version.
```bash ```bash
go install -v github.com/sagernet/sing-box/cmd/sing-box@latest go install -v github.com/sagernet/sing-box/cmd/sing-box@v1.0-beta2
``` ```
Install with options: Install with options:
```bash ```bash
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@v1.0-beta2
``` ```
| Build Tag | Description | | Build Tag | Description |

View File

@@ -13,13 +13,13 @@ description: 欢迎来到该 sing-box 项目的文档页。
sing-box 需要 Golang **1.18.5** 或更高版本。 sing-box 需要 Golang **1.18.5** 或更高版本。
```bash ```bash
go install -v github.com/sagernet/sing-box/cmd/sing-box@latest go install -v github.com/sagernet/sing-box/cmd/sing-box@v1.0-beta2
``` ```
自定义安装: 自定义安装:
```bash ```bash
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@v1.0-beta2
``` ```
| 构建标志 | 描述 | | 构建标志 | 描述 |

14
go.mod
View File

@@ -20,25 +20,27 @@ require (
github.com/pires/go-proxyproto v0.6.2 github.com/pires/go-proxyproto v0.6.2
github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a github.com/sagernet/certmagic v0.0.0-20220819042630-4a57f8b6853a
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-20220826124916-d4ba8fdfac88 github.com/sagernet/sing v0.0.0-20220903085538-02b9ca1cc133
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-20220828031750-185b6c880a83 github.com/sagernet/sing-tun v0.0.0-20220828031750-185b6c880a83
github.com/sagernet/sing-vmess v0.0.0-20220827032426-01665c9c4e31 github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195
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 go4.org/netipx v0.0.0-20220812043211-3cc044ffd68d
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90
golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b golang.org/x/net v0.0.0-20220826154423-83b083e8dc8b
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 golang.org/x/sys v0.0.0-20220829200755-d48e67d00261
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b
google.golang.org/grpc v1.49.0 google.golang.org/grpc v1.49.0
google.golang.org/protobuf v1.28.1 google.golang.org/protobuf v1.28.1
gvisor.dev/gvisor v0.0.0-20220819163037-ba6e795b139a gvisor.dev/gvisor v0.0.0-20220819163037-ba6e795b139a
) )
//replace github.com/sagernet/sing => ../sing
require ( require (
github.com/ajg/form v1.5.1 // indirect github.com/ajg/form v1.5.1 // indirect
github.com/davecgh/go-spew v1.1.1 // indirect github.com/davecgh/go-spew v1.1.1 // indirect

24
go.sum
View File

@@ -135,18 +135,18 @@ 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-20220826124916-d4ba8fdfac88 h1:wxUQfVBqiUtAemytzP9mNjAkSiI0nVsRZBQvCLP8r5g= github.com/sagernet/sing v0.0.0-20220903085538-02b9ca1cc133 h1:krnb8wKEFIdXhmJYlhJMbEcPsJFISy2fz90uHVz7hMU=
github.com/sagernet/sing v0.0.0-20220826124916-d4ba8fdfac88/go.mod h1:kZvzh1VDa/Dg/Bt5WaYKU0jl5ept8KKDpl3Ay4gRtRQ= github.com/sagernet/sing v0.0.0-20220903085538-02b9ca1cc133/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-20220828031750-185b6c880a83 h1:SoWiHYuOCVedqA7T/CJSZUUrcPGKQb2wFKEq8DphiAI= github.com/sagernet/sing-tun v0.0.0-20220828031750-185b6c880a83 h1:SoWiHYuOCVedqA7T/CJSZUUrcPGKQb2wFKEq8DphiAI=
github.com/sagernet/sing-tun v0.0.0-20220828031750-185b6c880a83/go.mod h1:76r07HS1WRcEI4mE9pFsohfTBUt1j/G9Avz6DaOP3VU= github.com/sagernet/sing-tun v0.0.0-20220828031750-185b6c880a83/go.mod h1:76r07HS1WRcEI4mE9pFsohfTBUt1j/G9Avz6DaOP3VU=
github.com/sagernet/sing-vmess v0.0.0-20220827032426-01665c9c4e31 h1:FAsJsVwpPcoITcj6/9JxRKxy8n3bIKLqKmDGVzmfeOo= github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f h1:6l9aXZqAl1JqXJWi89KHpWnM/moQUPGG+XiwMc+yD0A=
github.com/sagernet/sing-vmess v0.0.0-20220827032426-01665c9c4e31/go.mod h1:82O6gzbxLha/W/jxSVQbsqf2lVdRTjMIgyLug0lpJps= github.com/sagernet/sing-vmess v0.0.0-20220907073918-72d7fdf6825f/go.mod h1:u66Vv7NHXJWfeAmhh7JuJp/cwxmuQlM56QoZ7B7Mmd0=
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939 h1:pB1Dh1NbwVrLhQhotr4O4Hs3yhiBzmg3AvnUyYjL4x4= github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195 h1:5VBIbVw9q7aKbrFdT83mjkyvQ+VaRsQ6yflTepfln38=
github.com/sagernet/smux v0.0.0-20220812084127-e2d085ee3939/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8= github.com/sagernet/smux v0.0.0-20220831015742-e0f1988e3195/go.mod h1:yedWtra8nyGJ+SyI+ziwuaGMzBatbB10P1IOOZbbSK8=
github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU= github.com/spf13/cobra v1.5.0 h1:X+jTBEBqF0bHN+9cSMgmfuvv2VHJ9ezmFNf9Y/XstYU=
github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM= github.com/spf13/cobra v1.5.0/go.mod h1:dWXEIy2H428czQCjInthrTRUg7yKbok+2Qi/yBIJoUM=
github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA= github.com/spf13/pflag v1.0.5 h1:iy+VFUOCP1a+8yFto/drg2CJ5u0yRoB7fZw3DKv/JXA=
@@ -181,8 +181,8 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
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=
golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto= golang.org/x/crypto v0.0.0-20200622213623-75b288015ac9/go.mod h1:LzIPMQfyMNhhGPhUkYOs5KpL4U8rLKemX1yGLhDgUto=
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8= golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d h1:3qF+Z8Hkrw9sOhrFHti9TlB1Hkac1x+DNRkv0XQiFjo= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90 h1:Y/gsMcFOcR+6S6f3YeMKl5g+dZMEWqcz5Czj/GWYbkM=
golang.org/x/crypto v0.0.0-20220826181053-bd7e27e6170d/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4= golang.org/x/crypto v0.0.0-20220829220503-c86fa9a7ed90/go.mod h1:IxCIyHEi3zRg3s0A5j5BB6A9Jmi73HwBIUl50j+osU4=
golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA= golang.org/x/exp v0.0.0-20190121172915-509febef88a4/go.mod h1:CJ0aWSM057203Lf6IL+f9T1iT9GByDxfZKAQTCR3kQA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e h1:+WEEuIdZHnUeJJmEUjyYC2gfUMj69yZXw17EnHg/otA=
golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA= golang.org/x/exp v0.0.0-20220722155223-a9213eeb770e/go.mod h1:Kr81I6Kryrl9sr8s2FK3vxD90NdsKWRuOIl2O4CvYbA=
@@ -244,8 +244,8 @@ golang.org/x/sys v0.0.0-20220412211240-33da011f77ad/go.mod h1:oPkhp1MJrh7nUepCBc
golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220704084225-05e143d24a9e/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220731174439-a90be440212d/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64 h1:UiNENfZ8gDvpiWw7IpOMQ27spWmThO1RwwdQVbJahJM= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261 h1:v6hYoSR9T5oet+pMXwUWkbiVqx/63mlHjefrHmxwfeY=
golang.org/x/sys v0.0.0-20220825204002-c680a09ffe64/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220829200755-d48e67d00261/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211 h1:JGgROgKl9N8DuW20oFS5gxc+lE67/N3FcwmBPMe7ArY=
golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8=
@@ -276,8 +276,8 @@ golang.org/x/xerrors v0.0.0-20191204190536-9bdfabe68543/go.mod h1:I/5z698sn9Ka8T
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=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478 h1:vDy//hdR+GnROE3OdYbQKt9rdtNdHkDtONvpRwmls/0= golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b h1:qgrKnOfe1zyURRNdmDlGbN32i38Zjmw0B1+TMdHcOvg=
golang.zx2c4.com/wireguard v0.0.0-20220703234212-c31a7b1ab478/go.mod h1:bVQfyl2sCM/QIIGHpWbFGfHPuDvqnCNkT6MQLTCjO/U= golang.zx2c4.com/wireguard v0.0.0-20220829161405-d1d08426b27b/go.mod h1:6y4CqPAy54NwiN4nC8K+R1eMpQDB1P2d25qmunh2RSA=
google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM= google.golang.org/appengine v1.1.0/go.mod h1:EbEs0AVv82hx2wNQdGPgUI5lhzA/G0D9YwlJXL52JkM=
google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4= google.golang.org/appengine v1.4.0/go.mod h1:xpcJRLb0r/rnEns0DIKYYv+WjYCduHsrkT7/EB5XEv4=
google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc= google.golang.org/genproto v0.0.0-20180817151627-c66870c02cf8/go.mod h1:JiN7NxoALGmiZfu7CAH4rXhgtRTLTxftemlI0sWmxmc=

View File

@@ -39,6 +39,8 @@ func New(ctx context.Context, router adapter.Router, logger log.ContextLogger, o
return NewNaive(ctx, router, logger, options.Tag, options.NaiveOptions) return NewNaive(ctx, router, logger, options.Tag, options.NaiveOptions)
case C.TypeHysteria: case C.TypeHysteria:
return NewHysteria(ctx, router, logger, options.Tag, options.HysteriaOptions) return NewHysteria(ctx, router, logger, options.Tag, options.HysteriaOptions)
case C.TypeShadowTLS:
return NewShadowTLS(ctx, router, logger, options.Tag, options.ShadowTLSOptions)
default: default:
return nil, E.New("unknown inbound type: ", options.Type) return nil, E.New("unknown inbound type: ", options.Type)
} }

View File

@@ -3,25 +3,18 @@ package inbound
import ( import (
"context" "context"
"net" "net"
"net/netip"
"os"
"sync" "sync"
"time"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/proxyproto"
"github.com/sagernet/sing-box/common/settings" "github.com/sagernet/sing-box/common/settings"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log" "github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option" "github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-dns" "github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common" "github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
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"
"github.com/database64128/tfo-go"
) )
var _ adapter.Inbound = (*myInboundAdapter)(nil) var _ adapter.Inbound = (*myInboundAdapter)(nil)
@@ -62,6 +55,10 @@ func (a *myInboundAdapter) Tag() string {
return a.tag return a.tag
} }
func (a *myInboundAdapter) Network() []string {
return a.network
}
func (a *myInboundAdapter) Start() error { func (a *myInboundAdapter) Start() error {
var err error var err error
if common.Contains(a.network, N.NetworkTCP) { if common.Contains(a.network, N.NetworkTCP) {
@@ -102,38 +99,6 @@ func (a *myInboundAdapter) Start() error {
return nil return nil
} }
func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
var err error
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
var tcpListener net.Listener
if !a.listenOptions.TCPFastOpen {
tcpListener, err = net.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
} else {
tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
}
if err == nil {
a.logger.Info("tcp server started at ", tcpListener.Addr())
}
if a.listenOptions.ProxyProtocol {
a.logger.Debug("proxy protocol enabled")
tcpListener = &proxyproto.Listener{Listener: tcpListener}
}
a.tcpListener = tcpListener
return tcpListener, err
}
func (a *myInboundAdapter) ListenUDP() (net.PacketConn, error) {
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
udpConn, err := net.ListenUDP(M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.UDPAddr())
if err != nil {
return nil, err
}
a.udpConn = udpConn
a.udpAddr = bindAddr
a.logger.Info("udp server started at ", udpConn.LocalAddr())
return udpConn, err
}
func (a *myInboundAdapter) Close() error { func (a *myInboundAdapter) Close() error {
var err error var err error
if a.clearSystemProxy != nil { if a.clearSystemProxy != nil {
@@ -170,20 +135,10 @@ func (a *myInboundAdapter) newPacketConnection(ctx context.Context, conn N.Packe
return a.router.RoutePacketConnection(ctx, conn, metadata) return a.router.RoutePacketConnection(ctx, conn, metadata)
} }
func (a *myInboundAdapter) loopTCPIn() {
tcpListener := a.tcpListener
for {
conn, err := tcpListener.Accept()
if err != nil {
return
}
go a.injectTCP(conn)
}
}
func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.InboundContext) adapter.InboundContext { func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.InboundContext) adapter.InboundContext {
metadata.Inbound = a.tag metadata.Inbound = a.tag
metadata.InboundType = a.protocol metadata.InboundType = a.protocol
metadata.InboundDetour = a.listenOptions.Detour
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)
@@ -199,166 +154,6 @@ func (a *myInboundAdapter) createMetadata(conn net.Conn, metadata adapter.Inboun
return metadata return metadata
} }
func (a *myInboundAdapter) injectTCP(conn net.Conn) {
ctx := log.ContextWithNewID(a.ctx)
metadata := a.createMetadata(conn, adapter.InboundContext{})
a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
hErr := a.connHandler.NewConnection(ctx, conn, metadata)
if hErr != nil {
conn.Close()
a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source))
}
}
func (a *myInboundAdapter) routeTCP(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) {
a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
hErr := a.newConnection(ctx, conn, metadata)
if hErr != nil {
conn.Close()
a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source))
}
}
func (a *myInboundAdapter) loopUDPIn() {
defer close(a.packetOutboundClosed)
_buffer := buf.StackNewPacket()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()
packetService := (*myInboundPacketAdapter)(a)
for {
buffer.Reset()
n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
if err != nil {
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
if err != nil {
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPOOBIn() {
defer close(a.packetOutboundClosed)
_buffer := buf.StackNewPacket()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()
packetService := (*myInboundPacketAdapter)(a)
oob := make([]byte, 1024)
for {
buffer.Reset()
n, oobN, _, addr, err := a.udpConn.ReadMsgUDPAddrPort(buffer.FreeBytes(), oob)
if err != nil {
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)
if err != nil {
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPInThreadSafe() {
defer close(a.packetOutboundClosed)
packetService := (*myInboundPacketAdapter)(a)
for {
buffer := buf.NewPacket()
n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
if err != nil {
buffer.Release()
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
if err != nil {
buffer.Release()
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPOOBInThreadSafe() {
defer close(a.packetOutboundClosed)
packetService := (*myInboundPacketAdapter)(a)
oob := make([]byte, 1024)
for {
buffer := buf.NewPacket()
n, oobN, _, addr, err := a.udpConn.ReadMsgUDPAddrPort(buffer.FreeBytes(), oob)
if err != nil {
buffer.Release()
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)
if err != nil {
buffer.Release()
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPOut() {
for {
select {
case packet := <-a.packetOutbound:
err := a.writePacket(packet.buffer, packet.destination)
if err != nil && !E.IsClosed(err) {
a.newError(E.New("write back udp: ", err))
}
continue
case <-a.packetOutboundClosed:
}
for {
select {
case packet := <-a.packetOutbound:
packet.buffer.Release()
default:
return
}
}
}
}
func (a *myInboundAdapter) newError(err error) { func (a *myInboundAdapter) newError(err error) {
a.logger.Error(err) a.logger.Error(err)
} }
@@ -375,72 +170,3 @@ func NewError(logger log.ContextLogger, ctx context.Context, err error) {
} }
logger.ErrorContext(ctx, err) logger.ErrorContext(ctx, err)
} }
func (a *myInboundAdapter) writePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
defer buffer.Release()
if destination.IsFqdn() {
udpAddr, err := net.ResolveUDPAddr(N.NetworkUDP, destination.String())
if err != nil {
return err
}
return common.Error(a.udpConn.WriteTo(buffer.Bytes(), udpAddr))
}
return common.Error(a.udpConn.WriteToUDPAddrPort(buffer.Bytes(), destination.AddrPort()))
}
type myInboundPacketAdapter myInboundAdapter
func (s *myInboundPacketAdapter) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
n, addr, err := s.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
if err != nil {
return M.Socksaddr{}, err
}
buffer.Truncate(n)
return M.SocksaddrFromNetIP(addr), nil
}
func (s *myInboundPacketAdapter) WriteIsThreadUnsafe() {
}
type myInboundPacket struct {
buffer *buf.Buffer
destination M.Socksaddr
}
func (s *myInboundPacketAdapter) Upstream() any {
return s.udpConn
}
func (s *myInboundPacketAdapter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
s.packetAccess.RLock()
defer s.packetAccess.RUnlock()
select {
case <-s.packetOutboundClosed:
return os.ErrClosed
default:
}
s.packetOutbound <- &myInboundPacket{buffer, destination}
return nil
}
func (s *myInboundPacketAdapter) Close() error {
return s.udpConn.Close()
}
func (s *myInboundPacketAdapter) LocalAddr() net.Addr {
return s.udpConn.LocalAddr()
}
func (s *myInboundPacketAdapter) SetDeadline(t time.Time) error {
return s.udpConn.SetDeadline(t)
}
func (s *myInboundPacketAdapter) SetReadDeadline(t time.Time) error {
return s.udpConn.SetReadDeadline(t)
}
func (s *myInboundPacketAdapter) SetWriteDeadline(t time.Time) error {
return s.udpConn.SetWriteDeadline(t)
}

71
inbound/default_tcp.go Normal file
View File

@@ -0,0 +1,71 @@
package inbound
import (
"context"
"net"
"net/netip"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/proxyproto"
"github.com/sagernet/sing-box/log"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
"github.com/database64128/tfo-go"
)
func (a *myInboundAdapter) ListenTCP() (net.Listener, error) {
var err error
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
var tcpListener net.Listener
if !a.listenOptions.TCPFastOpen {
tcpListener, err = net.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
} else {
tcpListener, err = tfo.ListenTCP(M.NetworkFromNetAddr(N.NetworkTCP, bindAddr.Addr), bindAddr.TCPAddr())
}
if err == nil {
a.logger.Info("tcp server started at ", tcpListener.Addr())
}
if a.listenOptions.ProxyProtocol {
a.logger.Debug("proxy protocol enabled")
tcpListener = &proxyproto.Listener{Listener: tcpListener}
}
a.tcpListener = tcpListener
return tcpListener, err
}
func (a *myInboundAdapter) loopTCPIn() {
tcpListener := a.tcpListener
for {
conn, err := tcpListener.Accept()
if err != nil {
if E.IsClosed(err) {
return
}
a.logger.Error("accept: ", err)
continue
}
go a.injectTCP(conn, adapter.InboundContext{})
}
}
func (a *myInboundAdapter) injectTCP(conn net.Conn, metadata adapter.InboundContext) {
ctx := log.ContextWithNewID(a.ctx)
metadata = a.createMetadata(conn, metadata)
a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
hErr := a.connHandler.NewConnection(ctx, conn, metadata)
if hErr != nil {
conn.Close()
a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source))
}
}
func (a *myInboundAdapter) routeTCP(ctx context.Context, conn net.Conn, metadata adapter.InboundContext) {
a.logger.InfoContext(ctx, "inbound connection from ", metadata.Source)
hErr := a.newConnection(ctx, conn, metadata)
if hErr != nil {
conn.Close()
a.NewError(ctx, E.Cause(hErr, "process connection from ", metadata.Source))
}
}

237
inbound/default_udp.go Normal file
View File

@@ -0,0 +1,237 @@
package inbound
import (
"net"
"net/netip"
"os"
"time"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-dns"
"github.com/sagernet/sing/common"
"github.com/sagernet/sing/common/buf"
E "github.com/sagernet/sing/common/exceptions"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
func (a *myInboundAdapter) ListenUDP() (net.PacketConn, error) {
bindAddr := M.SocksaddrFrom(netip.Addr(a.listenOptions.Listen), a.listenOptions.ListenPort)
udpConn, err := net.ListenUDP(M.NetworkFromNetAddr(N.NetworkUDP, bindAddr.Addr), bindAddr.UDPAddr())
if err != nil {
return nil, err
}
a.udpConn = udpConn
a.udpAddr = bindAddr
a.logger.Info("udp server started at ", udpConn.LocalAddr())
return udpConn, err
}
func (a *myInboundAdapter) loopUDPIn() {
defer close(a.packetOutboundClosed)
_buffer := buf.StackNewPacket()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()
packetService := (*myInboundPacketAdapter)(a)
for {
buffer.Reset()
n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
if err != nil {
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
if err != nil {
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPOOBIn() {
defer close(a.packetOutboundClosed)
_buffer := buf.StackNewPacket()
defer common.KeepAlive(_buffer)
buffer := common.Dup(_buffer)
defer buffer.Release()
buffer.IncRef()
defer buffer.DecRef()
packetService := (*myInboundPacketAdapter)(a)
oob := make([]byte, 1024)
for {
buffer.Reset()
n, oobN, _, addr, err := a.udpConn.ReadMsgUDPAddrPort(buffer.FreeBytes(), oob)
if err != nil {
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)
if err != nil {
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPInThreadSafe() {
defer close(a.packetOutboundClosed)
packetService := (*myInboundPacketAdapter)(a)
for {
buffer := buf.NewPacket()
n, addr, err := a.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
if err != nil {
buffer.Release()
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.packetHandler.NewPacket(a.ctx, packetService, buffer, metadata)
if err != nil {
buffer.Release()
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPOOBInThreadSafe() {
defer close(a.packetOutboundClosed)
packetService := (*myInboundPacketAdapter)(a)
oob := make([]byte, 1024)
for {
buffer := buf.NewPacket()
n, oobN, _, addr, err := a.udpConn.ReadMsgUDPAddrPort(buffer.FreeBytes(), oob)
if err != nil {
buffer.Release()
return
}
buffer.Truncate(n)
var metadata adapter.InboundContext
metadata.Inbound = a.tag
metadata.InboundType = a.protocol
metadata.SniffEnabled = a.listenOptions.SniffEnabled
metadata.SniffOverrideDestination = a.listenOptions.SniffOverrideDestination
metadata.DomainStrategy = dns.DomainStrategy(a.listenOptions.DomainStrategy)
metadata.Source = M.SocksaddrFromNetIP(addr)
metadata.OriginDestination = a.udpAddr
err = a.oobPacketHandler.NewPacket(a.ctx, packetService, buffer, oob[:oobN], metadata)
if err != nil {
buffer.Release()
a.newError(E.Cause(err, "process packet from ", metadata.Source))
}
}
}
func (a *myInboundAdapter) loopUDPOut() {
for {
select {
case packet := <-a.packetOutbound:
err := a.writePacket(packet.buffer, packet.destination)
if err != nil && !E.IsClosed(err) {
a.newError(E.New("write back udp: ", err))
}
continue
case <-a.packetOutboundClosed:
}
for {
select {
case packet := <-a.packetOutbound:
packet.buffer.Release()
default:
return
}
}
}
}
func (a *myInboundAdapter) writePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
defer buffer.Release()
if destination.IsFqdn() {
udpAddr, err := net.ResolveUDPAddr(N.NetworkUDP, destination.String())
if err != nil {
return err
}
return common.Error(a.udpConn.WriteTo(buffer.Bytes(), udpAddr))
}
return common.Error(a.udpConn.WriteToUDPAddrPort(buffer.Bytes(), destination.AddrPort()))
}
type myInboundPacketAdapter myInboundAdapter
func (s *myInboundPacketAdapter) ReadPacket(buffer *buf.Buffer) (M.Socksaddr, error) {
n, addr, err := s.udpConn.ReadFromUDPAddrPort(buffer.FreeBytes())
if err != nil {
return M.Socksaddr{}, err
}
buffer.Truncate(n)
return M.SocksaddrFromNetIP(addr), nil
}
func (s *myInboundPacketAdapter) WriteIsThreadUnsafe() {
}
type myInboundPacket struct {
buffer *buf.Buffer
destination M.Socksaddr
}
func (s *myInboundPacketAdapter) Upstream() any {
return s.udpConn
}
func (s *myInboundPacketAdapter) WritePacket(buffer *buf.Buffer, destination M.Socksaddr) error {
s.packetAccess.RLock()
defer s.packetAccess.RUnlock()
select {
case <-s.packetOutboundClosed:
return os.ErrClosed
default:
}
s.packetOutbound <- &myInboundPacket{buffer, destination}
return nil
}
func (s *myInboundPacketAdapter) Close() error {
return s.udpConn.Close()
}
func (s *myInboundPacketAdapter) LocalAddr() net.Addr {
return s.udpConn.LocalAddr()
}
func (s *myInboundPacketAdapter) SetDeadline(t time.Time) error {
return s.udpConn.SetDeadline(t)
}
func (s *myInboundPacketAdapter) SetReadDeadline(t time.Time) error {
return s.udpConn.SetReadDeadline(t)
}
func (s *myInboundPacketAdapter) SetWriteDeadline(t time.Time) error {
return s.udpConn.SetWriteDeadline(t)
}

View File

@@ -5,6 +5,7 @@ import (
"context" "context"
"crypto/tls" "crypto/tls"
"net" "net"
"os"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
@@ -17,7 +18,10 @@ import (
"github.com/sagernet/sing/protocol/http" "github.com/sagernet/sing/protocol/http"
) )
var _ adapter.Inbound = (*HTTP)(nil) var (
_ adapter.Inbound = (*HTTP)(nil)
_ adapter.InjectableInbound = (*HTTP)(nil)
)
type HTTP struct { type HTTP struct {
myInboundAdapter myInboundAdapter
@@ -74,6 +78,10 @@ func (h *HTTP) NewConnection(ctx context.Context, conn net.Conn, metadata adapte
return http.HandleConnection(ctx, conn, std_bufio.NewReader(conn), h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata)) return http.HandleConnection(ctx, conn, std_bufio.NewReader(conn), h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata))
} }
func (h *HTTP) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
return os.ErrInvalid
}
func (a *myInboundAdapter) upstreamUserHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter { func (a *myInboundAdapter) upstreamUserHandler(metadata adapter.InboundContext) adapter.UpstreamHandlerAdapter {
return adapter.NewUpstreamHandler(metadata, a.newUserConnection, a.streamUserPacketConnection, a) return adapter.NewUpstreamHandler(metadata, a.newUserConnection, a.streamUserPacketConnection, a)
} }

View File

@@ -4,6 +4,7 @@ import (
std_bufio "bufio" std_bufio "bufio"
"context" "context"
"net" "net"
"os"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
@@ -20,7 +21,10 @@ import (
"github.com/sagernet/sing/protocol/socks/socks5" "github.com/sagernet/sing/protocol/socks/socks5"
) )
var _ adapter.Inbound = (*Mixed)(nil) var (
_ adapter.Inbound = (*Mixed)(nil)
_ adapter.InjectableInbound = (*Mixed)(nil)
)
type Mixed struct { type Mixed struct {
myInboundAdapter myInboundAdapter
@@ -57,3 +61,7 @@ func (h *Mixed) NewConnection(ctx context.Context, conn net.Conn, metadata adapt
reader := std_bufio.NewReader(bufio.NewCachedReader(conn, buf.As([]byte{headerType}))) reader := std_bufio.NewReader(bufio.NewCachedReader(conn, buf.As([]byte{headerType})))
return http.HandleConnection(ctx, conn, reader, h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata)) return http.HandleConnection(ctx, conn, reader, h.authenticator, h.upstreamUserHandler(metadata), adapter.UpstreamMetadata(metadata))
} }
func (h *Mixed) NewPacketConnection(ctx context.Context, conn N.PacketConn, metadata adapter.InboundContext) error {
return os.ErrInvalid
}

Some files were not shown because too many files have changed in this diff Show More