mirror of
https://github.com/SagerNet/sing-box.git
synced 2024-12-27 02:35:38 +08:00
Add override destination to route options
This commit is contained in:
parent
ccffca9e13
commit
7aa0c572cc
|
@ -61,9 +61,10 @@ type InboundContext struct {
|
||||||
// cache
|
// cache
|
||||||
|
|
||||||
// Deprecated: implement in rule action
|
// Deprecated: implement in rule action
|
||||||
InboundDetour string
|
InboundDetour string
|
||||||
LastInbound string
|
LastInbound string
|
||||||
OriginDestination M.Socksaddr
|
OriginDestination M.Socksaddr
|
||||||
|
RouteOriginalDestination M.Socksaddr
|
||||||
// Deprecated
|
// Deprecated
|
||||||
InboundOptions option.InboundOptions
|
InboundOptions option.InboundOptions
|
||||||
UDPDisableDomainUnmapping bool
|
UDPDisableDomainUnmapping bool
|
||||||
|
|
|
@ -25,11 +25,7 @@ func NewConnection(ctx context.Context, this N.Dialer, conn net.Conn, metadata a
|
||||||
var outConn net.Conn
|
var outConn net.Conn
|
||||||
var err error
|
var err error
|
||||||
if len(metadata.DestinationAddresses) > 0 {
|
if len(metadata.DestinationAddresses) > 0 {
|
||||||
if parallelDialer, isParallelDialer := this.(dialer.ParallelInterfaceDialer); isParallelDialer {
|
outConn, err = dialer.DialSerialNetwork(ctx, this, N.NetworkTCP, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
|
||||||
outConn, err = dialer.DialSerialNetwork(ctx, parallelDialer, N.NetworkTCP, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
|
|
||||||
} else {
|
|
||||||
outConn, err = N.DialSerial(ctx, this, N.NetworkTCP, metadata.Destination, metadata.DestinationAddresses)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
outConn, err = this.DialContext(ctx, N.NetworkTCP, metadata.Destination)
|
outConn, err = this.DialContext(ctx, N.NetworkTCP, metadata.Destination)
|
||||||
}
|
}
|
||||||
|
@ -73,11 +69,7 @@ func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn,
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
if len(metadata.DestinationAddresses) > 0 {
|
if len(metadata.DestinationAddresses) > 0 {
|
||||||
if parallelDialer, isParallelDialer := this.(dialer.ParallelInterfaceDialer); isParallelDialer {
|
outPacketConn, destinationAddress, err = dialer.ListenSerialNetworkPacket(ctx, this, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
|
||||||
outPacketConn, destinationAddress, err = dialer.ListenSerialNetworkPacket(ctx, parallelDialer, metadata.Destination, metadata.DestinationAddresses, metadata.NetworkStrategy, metadata.NetworkType, metadata.FallbackNetworkType, metadata.FallbackDelay)
|
|
||||||
} else {
|
|
||||||
outPacketConn, destinationAddress, err = N.ListenSerial(ctx, this, metadata.Destination, metadata.DestinationAddresses)
|
|
||||||
}
|
|
||||||
} else {
|
} else {
|
||||||
outPacketConn, err = this.ListenPacket(ctx, metadata.Destination)
|
outPacketConn, err = this.ListenPacket(ctx, metadata.Destination)
|
||||||
}
|
}
|
||||||
|
@ -91,11 +83,17 @@ func NewPacketConnection(ctx context.Context, this N.Dialer, conn N.PacketConn,
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
if destinationAddress.IsValid() {
|
if destinationAddress.IsValid() {
|
||||||
if metadata.Destination.IsFqdn() {
|
var originDestination M.Socksaddr
|
||||||
|
if metadata.RouteOriginalDestination.IsValid() {
|
||||||
|
originDestination = metadata.RouteOriginalDestination
|
||||||
|
} else {
|
||||||
|
originDestination = metadata.Destination
|
||||||
|
}
|
||||||
|
if metadata.Destination != M.SocksaddrFrom(destinationAddress, metadata.Destination.Port) {
|
||||||
if metadata.UDPDisableDomainUnmapping {
|
if metadata.UDPDisableDomainUnmapping {
|
||||||
outPacketConn = bufio.NewUnidirectionalNATPacketConn(bufio.NewPacketConn(outPacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), metadata.Destination)
|
outPacketConn = bufio.NewUnidirectionalNATPacketConn(bufio.NewPacketConn(outPacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), originDestination)
|
||||||
} else {
|
} else {
|
||||||
outPacketConn = bufio.NewNATPacketConn(bufio.NewPacketConn(outPacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), metadata.Destination)
|
outPacketConn = bufio.NewNATPacketConn(bufio.NewPacketConn(outPacketConn), M.SocksaddrFrom(destinationAddress, metadata.Destination.Port), originDestination)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
|
if natConn, loaded := common.Cast[bufio.NATPacketConn](conn); loaded {
|
||||||
|
|
|
@ -13,17 +13,27 @@ import (
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
func DialSerialNetwork(ctx context.Context, dialer ParallelInterfaceDialer, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
|
func DialSerialNetwork(ctx context.Context, dialer N.Dialer, network string, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.Conn, error) {
|
||||||
if parallelDialer, isParallel := dialer.(ParallelNetworkDialer); isParallel {
|
if parallelDialer, isParallel := dialer.(ParallelNetworkDialer); isParallel {
|
||||||
return parallelDialer.DialParallelNetwork(ctx, network, destination, destinationAddresses, strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
return parallelDialer.DialParallelNetwork(ctx, network, destination, destinationAddresses, strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
||||||
}
|
}
|
||||||
var errors []error
|
var errors []error
|
||||||
for _, address := range destinationAddresses {
|
if parallelDialer, isParallel := dialer.(ParallelInterfaceDialer); isParallel {
|
||||||
conn, err := dialer.DialParallelInterface(ctx, network, M.SocksaddrFrom(address, destination.Port), strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
for _, address := range destinationAddresses {
|
||||||
if err == nil {
|
conn, err := parallelDialer.DialParallelInterface(ctx, network, M.SocksaddrFrom(address, destination.Port), strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
||||||
return conn, nil
|
if err == nil {
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, address := range destinationAddresses {
|
||||||
|
conn, err := dialer.DialContext(ctx, network, M.SocksaddrFrom(address, destination.Port))
|
||||||
|
if err == nil {
|
||||||
|
return conn, nil
|
||||||
|
}
|
||||||
|
errors = append(errors, err)
|
||||||
}
|
}
|
||||||
errors = append(errors, err)
|
|
||||||
}
|
}
|
||||||
return nil, E.Errors(errors...)
|
return nil, E.Errors(errors...)
|
||||||
}
|
}
|
||||||
|
@ -106,17 +116,27 @@ func DialParallelNetwork(ctx context.Context, dialer ParallelInterfaceDialer, ne
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func ListenSerialNetworkPacket(ctx context.Context, dialer ParallelInterfaceDialer, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error) {
|
func ListenSerialNetworkPacket(ctx context.Context, dialer N.Dialer, destination M.Socksaddr, destinationAddresses []netip.Addr, strategy C.NetworkStrategy, interfaceType []C.InterfaceType, fallbackInterfaceType []C.InterfaceType, fallbackDelay time.Duration) (net.PacketConn, netip.Addr, error) {
|
||||||
if parallelDialer, isParallel := dialer.(ParallelNetworkDialer); isParallel {
|
if parallelDialer, isParallel := dialer.(ParallelNetworkDialer); isParallel {
|
||||||
return parallelDialer.ListenSerialNetworkPacket(ctx, destination, destinationAddresses, strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
return parallelDialer.ListenSerialNetworkPacket(ctx, destination, destinationAddresses, strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
||||||
}
|
}
|
||||||
var errors []error
|
var errors []error
|
||||||
for _, address := range destinationAddresses {
|
if parallelDialer, isParallel := dialer.(ParallelInterfaceDialer); isParallel {
|
||||||
conn, err := dialer.ListenSerialInterfacePacket(ctx, M.SocksaddrFrom(address, destination.Port), strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
for _, address := range destinationAddresses {
|
||||||
if err == nil {
|
conn, err := parallelDialer.ListenSerialInterfacePacket(ctx, M.SocksaddrFrom(address, destination.Port), strategy, interfaceType, fallbackInterfaceType, fallbackDelay)
|
||||||
return conn, address, nil
|
if err == nil {
|
||||||
|
return conn, address, nil
|
||||||
|
}
|
||||||
|
errors = append(errors, err)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
for _, address := range destinationAddresses {
|
||||||
|
conn, err := dialer.ListenPacket(ctx, M.SocksaddrFrom(address, destination.Port))
|
||||||
|
if err == nil {
|
||||||
|
return conn, address, nil
|
||||||
|
}
|
||||||
|
errors = append(errors, err)
|
||||||
}
|
}
|
||||||
errors = append(errors, err)
|
|
||||||
}
|
}
|
||||||
return nil, netip.Addr{}, E.Errors(errors...)
|
return nil, netip.Addr{}, E.Errors(errors...)
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,16 +1,11 @@
|
||||||
---
|
---
|
||||||
icon: material/new
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.11.0"
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
:material-plus: [cache_capacity](#cache_capacity)
|
:material-plus: [cache_capacity](#cache_capacity)
|
||||||
|
|
||||||
!!! quote "Changes in sing-box 1.9.0"
|
|
||||||
|
|
||||||
:material-plus: [client_subnet](#client_subnet)
|
|
||||||
|
|
||||||
# DNS
|
# DNS
|
||||||
|
|
||||||
### Structure
|
### Structure
|
||||||
|
@ -70,7 +65,7 @@ Make each DNS server's cache independent for special purposes. If enabled, will
|
||||||
|
|
||||||
#### cache_capacity
|
#### cache_capacity
|
||||||
|
|
||||||
!!! quote "Since sing-box 1.11.0"
|
!!! question "Since sing-box 1.11.0"
|
||||||
|
|
||||||
LRU cache capacity.
|
LRU cache capacity.
|
||||||
|
|
||||||
|
|
|
@ -1,15 +1,11 @@
|
||||||
---
|
---
|
||||||
icon: material/new
|
icon: material/new-box
|
||||||
---
|
---
|
||||||
|
|
||||||
!!! quote "自 sing-box 1.11.0 起"
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
:material-plus: [cache_capacity](#cache_capacity)
|
:material-plus: [cache_capacity](#cache_capacity)
|
||||||
|
|
||||||
!!! quote "自 sing-box 1.9.0 起"
|
|
||||||
|
|
||||||
:material-plus: [client_subnet](#client_subnet)
|
|
||||||
|
|
||||||
# DNS
|
# DNS
|
||||||
|
|
||||||
### 结构
|
### 结构
|
||||||
|
@ -68,7 +64,7 @@ icon: material/new
|
||||||
|
|
||||||
#### cache_capacity
|
#### cache_capacity
|
||||||
|
|
||||||
!!! quote "自 sing-box 1.11.0 起"
|
!!! question "自 sing-box 1.11.0 起"
|
||||||
|
|
||||||
LRU 缓存容量。
|
LRU 缓存容量。
|
||||||
|
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
---
|
||||||
|
icon: material/alert-decagram
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "Changes in sing-box 1.11.0"
|
||||||
|
|
||||||
|
:material-alert-decagram: [override_address](#override_address)
|
||||||
|
:material-alert-decagram: [override_port](#override_port)
|
||||||
|
|
||||||
`direct` outbound send requests directly.
|
`direct` outbound send requests directly.
|
||||||
|
|
||||||
### Structure
|
### Structure
|
||||||
|
@ -9,7 +18,6 @@
|
||||||
|
|
||||||
"override_address": "1.0.0.1",
|
"override_address": "1.0.0.1",
|
||||||
"override_port": 53,
|
"override_port": 53,
|
||||||
"proxy_protocol": 0,
|
|
||||||
|
|
||||||
... // Dial Fields
|
... // Dial Fields
|
||||||
}
|
}
|
||||||
|
@ -19,16 +27,20 @@
|
||||||
|
|
||||||
#### override_address
|
#### override_address
|
||||||
|
|
||||||
|
!!! failure "Deprecated in sing-box 1.11.0"
|
||||||
|
|
||||||
|
Destination override fields are deprecated in sing-box 1.11.0 and will be removed in sing-box 1.13.0, see [Migration](/migration/#migrate-destination-override-fields-to-route-options).
|
||||||
|
|
||||||
Override the connection destination address.
|
Override the connection destination address.
|
||||||
|
|
||||||
#### override_port
|
#### override_port
|
||||||
|
|
||||||
|
!!! failure "Deprecated in sing-box 1.11.0"
|
||||||
|
|
||||||
|
Destination override fields are deprecated in sing-box 1.11.0 and will be removed in sing-box 1.13.0, see [Migration](/migration/#migrate-destination-override-fields-to-route-options).
|
||||||
|
|
||||||
Override the connection destination port.
|
Override the connection destination port.
|
||||||
|
|
||||||
#### proxy_protocol
|
|
||||||
|
|
||||||
Write [Proxy Protocol](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) in the connection header.
|
|
||||||
|
|
||||||
Protocol value can be `1` or `2`.
|
Protocol value can be `1` or `2`.
|
||||||
|
|
||||||
### Dial Fields
|
### Dial Fields
|
||||||
|
|
|
@ -1,3 +1,12 @@
|
||||||
|
---
|
||||||
|
icon: material/alert-decagram
|
||||||
|
---
|
||||||
|
|
||||||
|
!!! quote "sing-box 1.11.0 中的更改"
|
||||||
|
|
||||||
|
:material-alert-decagram: [override_address](#override_address)
|
||||||
|
:material-alert-decagram: [override_port](#override_port)
|
||||||
|
|
||||||
`direct` 出站直接发送请求。
|
`direct` 出站直接发送请求。
|
||||||
|
|
||||||
### 结构
|
### 结构
|
||||||
|
@ -9,7 +18,6 @@
|
||||||
|
|
||||||
"override_address": "1.0.0.1",
|
"override_address": "1.0.0.1",
|
||||||
"override_port": 53,
|
"override_port": 53,
|
||||||
"proxy_protocol": 0,
|
|
||||||
|
|
||||||
... // 拨号字段
|
... // 拨号字段
|
||||||
}
|
}
|
||||||
|
@ -19,18 +27,20 @@
|
||||||
|
|
||||||
#### override_address
|
#### override_address
|
||||||
|
|
||||||
|
!!! failure "已在 sing-box 1.11.0 废弃"
|
||||||
|
|
||||||
|
目标覆盖字段在 sing-box 1.11.0 中已废弃,并将在 sing-box 1.13.0 中被移除,参阅 [迁移指南](/migration/#migrate-destination-override-fields-to-route-options)。
|
||||||
|
|
||||||
覆盖连接目标地址。
|
覆盖连接目标地址。
|
||||||
|
|
||||||
#### override_port
|
#### override_port
|
||||||
|
|
||||||
|
!!! failure "已在 sing-box 1.11.0 废弃"
|
||||||
|
|
||||||
|
目标覆盖字段在 sing-box 1.11.0 中已废弃,并将在 sing-box 1.13.0 中被移除,参阅 [迁移指南](/migration/#migrate-destination-override-fields-to-route-options)。
|
||||||
|
|
||||||
覆盖连接目标端口。
|
覆盖连接目标端口。
|
||||||
|
|
||||||
#### proxy_protocol
|
|
||||||
|
|
||||||
写出 [代理协议](https://www.haproxy.org/download/1.8/doc/proxy-protocol.txt) 到连接头。
|
|
||||||
|
|
||||||
可用协议版本值:`1` 或 `2`。
|
|
||||||
|
|
||||||
### 拨号字段
|
### 拨号字段
|
||||||
|
|
||||||
参阅 [拨号字段](/zh/configuration/shared/dial/)。
|
参阅 [拨号字段](/zh/configuration/shared/dial/)。
|
||||||
|
|
|
@ -10,12 +10,8 @@ icon: material/new-box
|
||||||
{
|
{
|
||||||
"action": "route", // default
|
"action": "route", // default
|
||||||
"outbound": "",
|
"outbound": "",
|
||||||
"network_strategy": "",
|
|
||||||
"network_type": [],
|
... // route-options Fields
|
||||||
"fallback_network_type": [],
|
|
||||||
"fallback_delay": "",
|
|
||||||
"udp_disable_domain_unmapping": false,
|
|
||||||
"udp_connect": false
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -31,6 +27,34 @@ icon: material/new-box
|
||||||
|
|
||||||
Tag of target outbound.
|
Tag of target outbound.
|
||||||
|
|
||||||
|
#### route-options Fields
|
||||||
|
|
||||||
|
See `route-options` fields below.
|
||||||
|
|
||||||
|
### route-options
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route-options",
|
||||||
|
"override_address": "",
|
||||||
|
"override_port": 0,
|
||||||
|
"network_strategy": "",
|
||||||
|
"fallback_delay": "",
|
||||||
|
"udp_disable_domain_unmapping": false,
|
||||||
|
"udp_connect": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
`route-options` set options for routing.
|
||||||
|
|
||||||
|
#### override_address
|
||||||
|
|
||||||
|
Override the connection destination address.
|
||||||
|
|
||||||
|
#### override_port
|
||||||
|
|
||||||
|
Override the connection destination port.
|
||||||
|
|
||||||
#### network_strategy
|
#### network_strategy
|
||||||
|
|
||||||
See [Dial Fields](/configuration/shared/dial/#network_strategy) for details.
|
See [Dial Fields](/configuration/shared/dial/#network_strategy) for details.
|
||||||
|
@ -62,20 +86,6 @@ do not support receiving UDP packets with domain addresses, such as Surge.
|
||||||
|
|
||||||
If enabled, attempts to connect UDP connection to the destination instead of listen.
|
If enabled, attempts to connect UDP connection to the destination instead of listen.
|
||||||
|
|
||||||
### route-options
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"action": "route-options",
|
|
||||||
"network_strategy": "",
|
|
||||||
"fallback_delay": "",
|
|
||||||
"udp_disable_domain_unmapping": false,
|
|
||||||
"udp_connect": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
`route-options` set options for routing.
|
|
||||||
|
|
||||||
### reject
|
### reject
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
|
@ -10,12 +10,8 @@ icon: material/new-box
|
||||||
{
|
{
|
||||||
"action": "route", // 默认
|
"action": "route", // 默认
|
||||||
"outbound": "",
|
"outbound": "",
|
||||||
"network_strategy": "",
|
|
||||||
"fallback_delay": "",
|
... // route-options 字段
|
||||||
"network_type": [],
|
|
||||||
"fallback_network_type": [],
|
|
||||||
"udp_disable_domain_unmapping": false,
|
|
||||||
"udp_connect": false
|
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
@ -27,6 +23,38 @@ icon: material/new-box
|
||||||
|
|
||||||
目标出站的标签。
|
目标出站的标签。
|
||||||
|
|
||||||
|
#### route-options 字段
|
||||||
|
|
||||||
|
参阅下方的 `route-options` 字段。
|
||||||
|
|
||||||
|
### route-options
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"action": "route-options",
|
||||||
|
"override_address": "",
|
||||||
|
"override_port": 0,
|
||||||
|
"network_strategy": "",
|
||||||
|
"fallback_delay": "",
|
||||||
|
"udp_disable_domain_unmapping": false,
|
||||||
|
"udp_connect": false
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
!!! note ""
|
||||||
|
|
||||||
|
当内容只有一项时,可以忽略 JSON 数组 [] 标签
|
||||||
|
|
||||||
|
`route-options` 为路由设置选项。
|
||||||
|
|
||||||
|
#### override_address
|
||||||
|
|
||||||
|
覆盖目标地址。
|
||||||
|
|
||||||
|
#### override_port
|
||||||
|
|
||||||
|
覆盖目标端口。
|
||||||
|
|
||||||
#### network_strategy
|
#### network_strategy
|
||||||
|
|
||||||
详情参阅 [拨号字段](/configuration/shared/dial/#network_strategy)。
|
详情参阅 [拨号字段](/configuration/shared/dial/#network_strategy)。
|
||||||
|
@ -56,24 +84,6 @@ icon: material/new-box
|
||||||
|
|
||||||
如果启用,将尝试将 UDP 连接 connect 到目标而不是 listen。
|
如果启用,将尝试将 UDP 连接 connect 到目标而不是 listen。
|
||||||
|
|
||||||
### route-options
|
|
||||||
|
|
||||||
```json
|
|
||||||
{
|
|
||||||
"action": "route-options",
|
|
||||||
"network_strategy": "",
|
|
||||||
"fallback_delay": "",
|
|
||||||
"udp_disable_domain_unmapping": false,
|
|
||||||
"udp_connect": false
|
|
||||||
}
|
|
||||||
```
|
|
||||||
|
|
||||||
!!! note ""
|
|
||||||
|
|
||||||
当内容只有一项时,可以忽略 JSON 数组 [] 标签
|
|
||||||
|
|
||||||
`route-options` 为路由设置选项。
|
|
||||||
|
|
||||||
### reject
|
### reject
|
||||||
|
|
||||||
```json
|
```json
|
||||||
|
|
|
@ -22,6 +22,12 @@ check [Migration](../migration/#migrate-legacy-inbound-fields-to-rule-actions).
|
||||||
|
|
||||||
Old fields will be removed in sing-box 1.13.0.
|
Old fields will be removed in sing-box 1.13.0.
|
||||||
|
|
||||||
|
#### Destination override fields in direct outbound
|
||||||
|
|
||||||
|
Destination override fields (`override_address` / `override_port`) in direct outbound are deprecated
|
||||||
|
and can be replaced by rule actions,
|
||||||
|
check [Migration](../migration/#migrate-destination-override-fields-to-route-options).
|
||||||
|
|
||||||
## 1.10.0
|
## 1.10.0
|
||||||
|
|
||||||
#### TUN address fields are merged
|
#### TUN address fields are merged
|
||||||
|
|
|
@ -20,6 +20,13 @@ icon: material/delete-alert
|
||||||
|
|
||||||
旧字段将在 sing-box 1.13.0 中被移除。
|
旧字段将在 sing-box 1.13.0 中被移除。
|
||||||
|
|
||||||
|
#### direct 出站中的目标地址覆盖字段
|
||||||
|
|
||||||
|
direct 出站中的目标地址覆盖字段(`override_address` / `override_port`)已废弃且可以通过规则动作替代,
|
||||||
|
参阅 [迁移指南](/migration/#migrate-destination-override-fields-to-route-options)。
|
||||||
|
|
||||||
|
旧字段将在 sing-box 1.13.0 中被移除。
|
||||||
|
|
||||||
## 1.10.0
|
## 1.10.0
|
||||||
|
|
||||||
#### Match source 规则项已重命名
|
#### Match source 规则项已重命名
|
||||||
|
|
|
@ -156,6 +156,44 @@ Inbound fields are deprecated and can be replaced by rule actions.
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### Migrate destination override fields to route options
|
||||||
|
|
||||||
|
Destination override fields in direct outbound are deprecated and can be replaced by route options.
|
||||||
|
|
||||||
|
!!! info "References"
|
||||||
|
|
||||||
|
[Rule Action](/configuration/route/rule_action/) /
|
||||||
|
[Direct](/configuration/outbound/direct/)
|
||||||
|
|
||||||
|
=== ":material-card-remove: Deprecated"
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "direct",
|
||||||
|
"override_address": "1.1.1.1",
|
||||||
|
"override_port": 443
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
=== ":material-card-multiple: New"
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"action": "route-options", // or route
|
||||||
|
"override_address": "1.1.1.1",
|
||||||
|
"override_port": 443
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 1.10.0
|
## 1.10.0
|
||||||
|
|
||||||
### TUN address fields are merged
|
### TUN address fields are merged
|
||||||
|
|
|
@ -104,6 +104,7 @@ icon: material/arrange-bring-forward
|
||||||
|
|
||||||
### 迁移旧的入站字段到规则动作
|
### 迁移旧的入站字段到规则动作
|
||||||
|
|
||||||
|
|
||||||
入站选项已被弃用,且可以被规则动作替代。
|
入站选项已被弃用,且可以被规则动作替代。
|
||||||
|
|
||||||
!!! info "参考"
|
!!! info "参考"
|
||||||
|
@ -156,6 +157,45 @@ icon: material/arrange-bring-forward
|
||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
|
### 迁移 direct 出站中的目标地址覆盖字段到路由字段
|
||||||
|
|
||||||
|
direct 出站中的目标地址覆盖字段已废弃,且可以被路由字段替代。
|
||||||
|
|
||||||
|
!!! info "参考"
|
||||||
|
|
||||||
|
[Rule Action](/zh/configuration/route/rule_action/) /
|
||||||
|
[Direct](/zh/configuration/outbound/direct/)
|
||||||
|
|
||||||
|
=== ":material-card-remove: 弃用的"
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"outbounds": [
|
||||||
|
{
|
||||||
|
"type": "direct",
|
||||||
|
"override_address": "1.1.1.1",
|
||||||
|
"override_port": 443
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
=== ":material-card-multiple: 新的"
|
||||||
|
|
||||||
|
```json
|
||||||
|
{
|
||||||
|
"route": {
|
||||||
|
"rules": [
|
||||||
|
{
|
||||||
|
"action": "route-options", // 或 route
|
||||||
|
"override_address": "1.1.1.1",
|
||||||
|
"override_port": 443
|
||||||
|
}
|
||||||
|
]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
## 1.10.0
|
## 1.10.0
|
||||||
|
|
||||||
### TUN 地址字段已合并
|
### TUN 地址字段已合并
|
||||||
|
@ -164,8 +204,6 @@ icon: material/arrange-bring-forward
|
||||||
`inet4_route_address` 和 `inet6_route_address` 已合并为 `route_address`,
|
`inet4_route_address` 和 `inet6_route_address` 已合并为 `route_address`,
|
||||||
`inet4_route_exclude_address` 和 `inet6_route_exclude_address` 已合并为 `route_exclude_address`。
|
`inet4_route_exclude_address` 和 `inet6_route_exclude_address` 已合并为 `route_exclude_address`。
|
||||||
|
|
||||||
旧字段已废弃,且将在 sing-box 1.11.0 中移除。
|
|
||||||
|
|
||||||
!!! info "参考"
|
!!! info "参考"
|
||||||
|
|
||||||
[TUN](/zh/configuration/inbound/tun/)
|
[TUN](/zh/configuration/inbound/tun/)
|
||||||
|
|
|
@ -104,6 +104,15 @@ var OptionInboundOptions = Note{
|
||||||
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-legacy-special-outbounds-to-rule-actions",
|
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-legacy-special-outbounds-to-rule-actions",
|
||||||
}
|
}
|
||||||
|
|
||||||
|
var OptionDestinationOverrideFields = Note{
|
||||||
|
Name: "destination-override-fields",
|
||||||
|
Description: "destination override fields in direct outbound",
|
||||||
|
DeprecatedVersion: "1.11.0",
|
||||||
|
ScheduledVersion: "1.13.0",
|
||||||
|
EnvName: "DESTINATION_OVERRIDE_FIELDS",
|
||||||
|
MigrationLink: "https://sing-box.sagernet.org/migration/#migrate-destination-override-fields-to-route-options",
|
||||||
|
}
|
||||||
|
|
||||||
var Options = []Note{
|
var Options = []Note{
|
||||||
OptionBadMatchSource,
|
OptionBadMatchSource,
|
||||||
OptionGEOIP,
|
OptionGEOIP,
|
||||||
|
@ -111,4 +120,5 @@ var Options = []Note{
|
||||||
OptionTUNAddressX,
|
OptionTUNAddressX,
|
||||||
OptionSpecialOutbounds,
|
OptionSpecialOutbounds,
|
||||||
OptionInboundOptions,
|
OptionInboundOptions,
|
||||||
|
OptionDestinationOverrideFields,
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,5 +1,12 @@
|
||||||
package option
|
package option
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
|
||||||
|
"github.com/sagernet/sing-box/experimental/deprecated"
|
||||||
|
"github.com/sagernet/sing/common/json"
|
||||||
|
)
|
||||||
|
|
||||||
type DirectInboundOptions struct {
|
type DirectInboundOptions struct {
|
||||||
ListenOptions
|
ListenOptions
|
||||||
Network NetworkList `json:"network,omitempty"`
|
Network NetworkList `json:"network,omitempty"`
|
||||||
|
@ -7,9 +14,25 @@ type DirectInboundOptions struct {
|
||||||
OverridePort uint16 `json:"override_port,omitempty"`
|
OverridePort uint16 `json:"override_port,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type DirectOutboundOptions struct {
|
type _DirectOutboundOptions struct {
|
||||||
DialerOptions
|
DialerOptions
|
||||||
|
// Deprecated: Use Route Action instead
|
||||||
OverrideAddress string `json:"override_address,omitempty"`
|
OverrideAddress string `json:"override_address,omitempty"`
|
||||||
OverridePort uint16 `json:"override_port,omitempty"`
|
// Deprecated: Use Route Action instead
|
||||||
ProxyProtocol uint8 `json:"proxy_protocol,omitempty"`
|
OverridePort uint16 `json:"override_port,omitempty"`
|
||||||
|
// Deprecated: removed
|
||||||
|
ProxyProtocol uint8 `json:"proxy_protocol,omitempty"`
|
||||||
|
}
|
||||||
|
|
||||||
|
type DirectOutboundOptions _DirectOutboundOptions
|
||||||
|
|
||||||
|
func (d *DirectOutboundOptions) UnmarshalJSONContext(ctx context.Context, content []byte) error {
|
||||||
|
err := json.UnmarshalDisallowUnknownFields(content, (*_DirectOutboundOptions)(d))
|
||||||
|
if err != nil {
|
||||||
|
return err
|
||||||
|
}
|
||||||
|
if d.OverrideAddress != "" || d.OverridePort != 0 {
|
||||||
|
deprecated.Report(ctx, deprecated.OptionDestinationOverrideFields)
|
||||||
|
}
|
||||||
|
return nil
|
||||||
}
|
}
|
||||||
|
|
|
@ -137,24 +137,25 @@ func (r *DNSRuleAction) UnmarshalJSONContext(ctx context.Context, data []byte) e
|
||||||
}
|
}
|
||||||
|
|
||||||
type RouteActionOptions struct {
|
type RouteActionOptions struct {
|
||||||
Outbound string `json:"outbound,omitempty"`
|
Outbound string `json:"outbound,omitempty"`
|
||||||
NetworkStrategy NetworkStrategy `json:"network_strategy,omitempty"`
|
RawRouteOptionsActionOptions
|
||||||
FallbackDelay uint32 `json:"fallback_delay,omitempty"`
|
|
||||||
UDPDisableDomainUnmapping bool `json:"udp_disable_domain_unmapping,omitempty"`
|
|
||||||
UDPConnect bool `json:"udp_connect,omitempty"`
|
|
||||||
}
|
}
|
||||||
|
|
||||||
type _RouteOptionsActionOptions struct {
|
type RawRouteOptionsActionOptions struct {
|
||||||
NetworkStrategy NetworkStrategy `json:"network_strategy,omitempty"`
|
OverrideAddress string `json:"override_address,omitempty"`
|
||||||
FallbackDelay uint32 `json:"fallback_delay,omitempty"`
|
OverridePort uint16 `json:"override_port,omitempty"`
|
||||||
UDPDisableDomainUnmapping bool `json:"udp_disable_domain_unmapping,omitempty"`
|
|
||||||
UDPConnect bool `json:"udp_connect,omitempty"`
|
NetworkStrategy NetworkStrategy `json:"network_strategy,omitempty"`
|
||||||
|
FallbackDelay uint32 `json:"fallback_delay,omitempty"`
|
||||||
|
|
||||||
|
UDPDisableDomainUnmapping bool `json:"udp_disable_domain_unmapping,omitempty"`
|
||||||
|
UDPConnect bool `json:"udp_connect,omitempty"`
|
||||||
}
|
}
|
||||||
|
|
||||||
type RouteOptionsActionOptions _RouteOptionsActionOptions
|
type RouteOptionsActionOptions RawRouteOptionsActionOptions
|
||||||
|
|
||||||
func (r *RouteOptionsActionOptions) UnmarshalJSON(data []byte) error {
|
func (r *RouteOptionsActionOptions) UnmarshalJSON(data []byte) error {
|
||||||
err := json.Unmarshal(data, (*_RouteOptionsActionOptions)(r))
|
err := json.Unmarshal(data, (*RawRouteOptionsActionOptions)(r))
|
||||||
if err != nil {
|
if err != nil {
|
||||||
return err
|
return err
|
||||||
}
|
}
|
||||||
|
|
|
@ -422,17 +422,38 @@ match:
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
var routeOptions *rule.RuleActionRouteOptions
|
||||||
switch action := currentRule.Action().(type) {
|
switch action := currentRule.Action().(type) {
|
||||||
case *rule.RuleActionRoute:
|
case *rule.RuleActionRoute:
|
||||||
metadata.NetworkStrategy = action.NetworkStrategy
|
routeOptions = &action.RuleActionRouteOptions
|
||||||
metadata.FallbackDelay = action.FallbackDelay
|
|
||||||
metadata.UDPDisableDomainUnmapping = action.UDPDisableDomainUnmapping
|
|
||||||
metadata.UDPConnect = action.UDPConnect
|
|
||||||
case *rule.RuleActionRouteOptions:
|
case *rule.RuleActionRouteOptions:
|
||||||
metadata.NetworkStrategy = action.NetworkStrategy
|
routeOptions = action
|
||||||
metadata.FallbackDelay = action.FallbackDelay
|
}
|
||||||
metadata.UDPDisableDomainUnmapping = action.UDPDisableDomainUnmapping
|
if routeOptions != nil {
|
||||||
metadata.UDPConnect = action.UDPConnect
|
// TODO: add nat
|
||||||
|
if (routeOptions.OverrideAddress.IsValid() || routeOptions.OverridePort > 0) && !metadata.RouteOriginalDestination.IsValid() {
|
||||||
|
metadata.RouteOriginalDestination = metadata.Destination
|
||||||
|
}
|
||||||
|
if routeOptions.OverrideAddress.IsValid() {
|
||||||
|
metadata.Destination = M.Socksaddr{
|
||||||
|
Addr: routeOptions.OverrideAddress.Addr,
|
||||||
|
Port: metadata.Destination.Port,
|
||||||
|
Fqdn: routeOptions.OverrideAddress.Fqdn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if routeOptions.OverridePort > 0 {
|
||||||
|
metadata.Destination = M.Socksaddr{
|
||||||
|
Addr: metadata.Destination.Addr,
|
||||||
|
Port: routeOptions.OverridePort,
|
||||||
|
Fqdn: metadata.Destination.Fqdn,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
metadata.NetworkStrategy = routeOptions.NetworkStrategy
|
||||||
|
metadata.FallbackDelay = routeOptions.FallbackDelay
|
||||||
|
metadata.UDPDisableDomainUnmapping = routeOptions.UDPDisableDomainUnmapping
|
||||||
|
metadata.UDPConnect = routeOptions.UDPConnect
|
||||||
|
}
|
||||||
|
switch action := currentRule.Action().(type) {
|
||||||
case *rule.RuleActionSniff:
|
case *rule.RuleActionSniff:
|
||||||
if !preMatch {
|
if !preMatch {
|
||||||
newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, action, inputConn, inputPacketConn)
|
newBuffer, newPacketBuffers, newErr := r.actionSniff(ctx, metadata, action, inputConn, inputPacketConn)
|
||||||
|
|
|
@ -19,6 +19,7 @@ import (
|
||||||
E "github.com/sagernet/sing/common/exceptions"
|
E "github.com/sagernet/sing/common/exceptions"
|
||||||
F "github.com/sagernet/sing/common/format"
|
F "github.com/sagernet/sing/common/format"
|
||||||
"github.com/sagernet/sing/common/logger"
|
"github.com/sagernet/sing/common/logger"
|
||||||
|
M "github.com/sagernet/sing/common/metadata"
|
||||||
N "github.com/sagernet/sing/common/network"
|
N "github.com/sagernet/sing/common/network"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -30,6 +31,8 @@ func NewRuleAction(ctx context.Context, logger logger.ContextLogger, action opti
|
||||||
return &RuleActionRoute{
|
return &RuleActionRoute{
|
||||||
Outbound: action.RouteOptions.Outbound,
|
Outbound: action.RouteOptions.Outbound,
|
||||||
RuleActionRouteOptions: RuleActionRouteOptions{
|
RuleActionRouteOptions: RuleActionRouteOptions{
|
||||||
|
OverrideAddress: M.ParseSocksaddrHostPort(action.RouteOptions.OverrideAddress, 0),
|
||||||
|
OverridePort: action.RouteOptions.OverridePort,
|
||||||
NetworkStrategy: C.NetworkStrategy(action.RouteOptions.NetworkStrategy),
|
NetworkStrategy: C.NetworkStrategy(action.RouteOptions.NetworkStrategy),
|
||||||
FallbackDelay: time.Duration(action.RouteOptions.FallbackDelay),
|
FallbackDelay: time.Duration(action.RouteOptions.FallbackDelay),
|
||||||
UDPDisableDomainUnmapping: action.RouteOptions.UDPDisableDomainUnmapping,
|
UDPDisableDomainUnmapping: action.RouteOptions.UDPDisableDomainUnmapping,
|
||||||
|
@ -38,6 +41,8 @@ func NewRuleAction(ctx context.Context, logger logger.ContextLogger, action opti
|
||||||
}, nil
|
}, nil
|
||||||
case C.RuleActionTypeRouteOptions:
|
case C.RuleActionTypeRouteOptions:
|
||||||
return &RuleActionRouteOptions{
|
return &RuleActionRouteOptions{
|
||||||
|
OverrideAddress: M.ParseSocksaddrHostPort(action.RouteOptionsOptions.OverrideAddress, 0),
|
||||||
|
OverridePort: action.RouteOptionsOptions.OverridePort,
|
||||||
NetworkStrategy: C.NetworkStrategy(action.RouteOptionsOptions.NetworkStrategy),
|
NetworkStrategy: C.NetworkStrategy(action.RouteOptionsOptions.NetworkStrategy),
|
||||||
FallbackDelay: time.Duration(action.RouteOptionsOptions.FallbackDelay),
|
FallbackDelay: time.Duration(action.RouteOptionsOptions.FallbackDelay),
|
||||||
UDPDisableDomainUnmapping: action.RouteOptionsOptions.UDPDisableDomainUnmapping,
|
UDPDisableDomainUnmapping: action.RouteOptionsOptions.UDPDisableDomainUnmapping,
|
||||||
|
@ -139,6 +144,8 @@ func (r *RuleActionRoute) String() string {
|
||||||
}
|
}
|
||||||
|
|
||||||
type RuleActionRouteOptions struct {
|
type RuleActionRouteOptions struct {
|
||||||
|
OverrideAddress M.Socksaddr
|
||||||
|
OverridePort uint16
|
||||||
NetworkStrategy C.NetworkStrategy
|
NetworkStrategy C.NetworkStrategy
|
||||||
NetworkType []C.InterfaceType
|
NetworkType []C.InterfaceType
|
||||||
FallbackNetworkType []C.InterfaceType
|
FallbackNetworkType []C.InterfaceType
|
||||||
|
|
Loading…
Reference in New Issue
Block a user