Compare commits

...

9 Commits

Author SHA1 Message Date
世界
996c1730c6
documentation: Bump version 2024-05-21 15:16:37 +08:00
世界
a70144f758
documentation: Bump version 2024-05-21 15:16:27 +08:00
世界
18975a0d22
documentation: Add manuel for mitigating tunnelvision attacks 2024-05-21 15:12:08 +08:00
世界
5726e024eb
documentation: Update DNS manual 2024-05-21 15:12:07 +08:00
世界
1284e1fbd1
dialer: Allow nil router 2024-05-21 15:12:07 +08:00
世界
842cb5c747
Add rule-set match command 2024-05-21 15:12:07 +08:00
世界
2be5139f1d
Add bypass_domain and search_domain platform HTTP proxy options 2024-05-21 15:12:07 +08:00
世界
0cc77fd725
Handle includeAllNetworks 2024-05-21 15:12:06 +08:00
世界
bc0964ee1d
Update gVisor to 20240422.0 2024-05-21 15:12:06 +08:00
29 changed files with 520 additions and 254 deletions

View File

@ -71,6 +71,7 @@ func RouterFromContext(ctx context.Context) Router {
type HeadlessRule interface { type HeadlessRule interface {
Match(metadata *InboundContext) bool Match(metadata *InboundContext) bool
String() string
} }
type Rule interface { type Rule interface {
@ -79,7 +80,6 @@ type Rule interface {
Type() string Type() string
UpdateGeosite() error UpdateGeosite() error
Outbound() string Outbound() string
String() string
} }
type DNSRule interface { type DNSRule interface {

View File

@ -0,0 +1,86 @@
package main
import (
"bytes"
"io"
"os"
"github.com/sagernet/sing-box/adapter"
"github.com/sagernet/sing-box/common/srs"
C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/log"
"github.com/sagernet/sing-box/option"
"github.com/sagernet/sing-box/route"
E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json"
"github.com/spf13/cobra"
)
var flagRuleSetMatchFormat string
var commandRuleSetMatch = &cobra.Command{
Use: "match <rule-set path> <domain>",
Short: "Check if a domain matches the rule set",
Args: cobra.ExactArgs(2),
Run: func(cmd *cobra.Command, args []string) {
err := ruleSetMatch(args[0], args[1])
if err != nil {
log.Fatal(err)
}
},
}
func init() {
commandRuleSetMatch.Flags().StringVarP(&flagRuleSetMatchFormat, "format", "f", "source", "rule-set format")
commandRuleSet.AddCommand(commandRuleSetMatch)
}
func ruleSetMatch(sourcePath string, domain string) error {
var (
reader io.Reader
err error
)
if sourcePath == "stdin" {
reader = os.Stdin
} else {
reader, err = os.Open(sourcePath)
if err != nil {
return E.Cause(err, "read rule-set")
}
}
content, err := io.ReadAll(reader)
if err != nil {
return E.Cause(err, "read rule-set")
}
var plainRuleSet option.PlainRuleSet
switch flagRuleSetMatchFormat {
case C.RuleSetFormatSource:
var compat option.PlainRuleSetCompat
compat, err = json.UnmarshalExtended[option.PlainRuleSetCompat](content)
if err != nil {
return err
}
plainRuleSet = compat.Upgrade()
case C.RuleSetFormatBinary:
plainRuleSet, err = srs.Read(bytes.NewReader(content), false)
if err != nil {
return err
}
default:
return E.New("unknown rule set format: ", flagRuleSetMatchFormat)
}
for i, ruleOptions := range plainRuleSet.Rules {
var currentRule adapter.HeadlessRule
currentRule, err = route.NewHeadlessRule(nil, ruleOptions)
if err != nil {
return E.Cause(err, "parse rule_set.rules.[", i, "]")
}
if currentRule.Match(&adapter.InboundContext{
Domain: domain,
}) {
println("match rules.[", i, "]: "+currentRule.String())
}
}
return nil
}

View File

@ -32,14 +32,20 @@ func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDi
var dialer net.Dialer var dialer net.Dialer
var listener net.ListenConfig var listener net.ListenConfig
if options.BindInterface != "" { if options.BindInterface != "" {
bindFunc := control.BindToInterface(router.InterfaceFinder(), options.BindInterface, -1) var interfaceFinder control.InterfaceFinder
if router != nil {
interfaceFinder = router.InterfaceFinder()
} else {
interfaceFinder = control.NewDefaultInterfaceFinder()
}
bindFunc := control.BindToInterface(interfaceFinder, options.BindInterface, -1)
dialer.Control = control.Append(dialer.Control, bindFunc) dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc) listener.Control = control.Append(listener.Control, bindFunc)
} else if router.AutoDetectInterface() { } else if router != nil && router.AutoDetectInterface() {
bindFunc := router.AutoDetectInterfaceFunc() bindFunc := router.AutoDetectInterfaceFunc()
dialer.Control = control.Append(dialer.Control, bindFunc) dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc) listener.Control = control.Append(listener.Control, bindFunc)
} else if router.DefaultInterface() != "" { } else if router != nil && router.DefaultInterface() != "" {
bindFunc := control.BindToInterface(router.InterfaceFinder(), router.DefaultInterface(), -1) bindFunc := control.BindToInterface(router.InterfaceFinder(), router.DefaultInterface(), -1)
dialer.Control = control.Append(dialer.Control, bindFunc) dialer.Control = control.Append(dialer.Control, bindFunc)
listener.Control = control.Append(listener.Control, bindFunc) listener.Control = control.Append(listener.Control, bindFunc)
@ -47,7 +53,7 @@ func NewDefault(router adapter.Router, options option.DialerOptions) (*DefaultDi
if options.RoutingMark != 0 { if options.RoutingMark != 0 {
dialer.Control = control.Append(dialer.Control, control.RoutingMark(options.RoutingMark)) dialer.Control = control.Append(dialer.Control, control.RoutingMark(options.RoutingMark))
listener.Control = control.Append(listener.Control, control.RoutingMark(options.RoutingMark)) listener.Control = control.Append(listener.Control, control.RoutingMark(options.RoutingMark))
} else if router.DefaultMark() != 0 { } else if router != nil && router.DefaultMark() != 0 {
dialer.Control = control.Append(dialer.Control, control.RoutingMark(router.DefaultMark())) dialer.Control = control.Append(dialer.Control, control.RoutingMark(router.DefaultMark()))
listener.Control = control.Append(listener.Control, control.RoutingMark(router.DefaultMark())) listener.Control = control.Append(listener.Control, control.RoutingMark(router.DefaultMark()))
} }

View File

@ -13,6 +13,9 @@ func New(router adapter.Router, options option.DialerOptions) (N.Dialer, error)
if options.IsWireGuardListener { if options.IsWireGuardListener {
return NewDefault(router, options) return NewDefault(router, options)
} }
if router == nil {
return NewDefault(nil, options)
}
var ( var (
dialer N.Dialer dialer N.Dialer
err error err error

View File

@ -2,16 +2,57 @@
icon: material/alert-decagram icon: material/alert-decagram
--- ---
#### 1.9.0-rc.21
* Fixes and improvements
#### 1.9.0-rc.20
* Prioritize `*_route_address` in linux auto-route
* Fix `*_route_address` in darwin auto-route
#### 1.8.14 #### 1.8.14
* Fix hysteria2 panic * Fix hysteria2 panic
* Fixes and improvements * Fixes and improvements
#### 1.9.0-rc.18
* Add custom prefix support in EDNS0 client subnet options
* Fix hysteria2 crash
* Fix `store_rdrc` corrupted
* Update quic-go to v0.43.1
* Fixes and improvements
#### 1.9.0-rc.16
* Mitigating TunnelVision attacks **1**
* Fixes and improvements
**1**:
See [TunnelVision](/manual/misc/tunnelvision).
#### 1.9.0-rc.15
* Fixes and improvements
#### 1.8.13 #### 1.8.13
* Fix fake-ip mapping * Fix fake-ip mapping
* Fixes and improvements * Fixes and improvements
#### 1.9.0-rc.14
* Fixes and improvements
#### 1.9.0-rc.13
* Update Hysteria protocol
* Update quic-go to v0.43.0
* Update gVisor to 20240422.0
* Fixes and improvements
#### 1.8.12 #### 1.8.12
* Now we have official APT and DNF repositories **1** * Now we have official APT and DNF repositories **1**
@ -22,6 +63,10 @@ icon: material/alert-decagram
Including stable and beta versions, see https://sing-box.sagernet.org/installation/package-manager/ Including stable and beta versions, see https://sing-box.sagernet.org/installation/package-manager/
#### 1.9.0-rc.11
* Fixes and improvements
#### 1.8.11 #### 1.8.11
* Fixes and improvements * Fixes and improvements
@ -30,6 +75,24 @@ Including stable and beta versions, see https://sing-box.sagernet.org/installati
* Fixes and improvements * Fixes and improvements
#### 1.9.0-beta.17
* Update `quic-go` to v0.42.0
* Fixes and improvements
#### 1.9.0-beta.16
* Fixes and improvements
_Our Testflight distribution has been temporarily blocked by Apple (possibly due to too many beta versions)
and you cannot join the test, install or update the sing-box beta app right now.
Please wait patiently for processing._
#### 1.9.0-beta.14
* Update gVisor to 20240212.0-65-g71212d503
* Fixes and improvements
#### 1.8.9 #### 1.8.9
* Fixes and improvements * Fixes and improvements
@ -38,14 +101,125 @@ Including stable and beta versions, see https://sing-box.sagernet.org/installati
* Fixes and improvements * Fixes and improvements
#### 1.9.0-beta.7
* Fixes and improvements
#### 1.9.0-beta.6
* Fix address filter DNS rule items **1**
* Fix DNS outbound responding with wrong data
* Fixes and improvements
**1**:
Fixed an issue where address filter DNS rule was incorrectly rejected under certain circumstances.
If you have enabled `store_rdrc` to save results, consider clearing the cache file.
#### 1.8.7 #### 1.8.7
* Fixes and improvements * Fixes and improvements
#### 1.9.0-alpha.15
* Fixes and improvements
#### 1.9.0-alpha.14
* Improve DNS truncate behavior
* Fixes and improvements
#### 1.9.0-alpha.13
* Fixes and improvements
#### 1.8.6 #### 1.8.6
* Fixes and improvements * Fixes and improvements
#### 1.9.0-alpha.12
* Handle Windows power events
* Always disable cache for fake-ip DNS transport if `dns.independent_cache` disabled
* Fixes and improvements
#### 1.9.0-alpha.11
* Fix missing `rule_set_ipcidr_match_source` item in DNS rules **1**
* Fixes and improvements
**1**:
See [DNS Rule](/configuration/dns/rule/).
#### 1.9.0-alpha.10
* Add `bypass_domain` and `search_domain` platform HTTP proxy options **1**
* Fixes and improvements
**1**:
See [TUN](/configuration/inbound/tun) inbound.
#### 1.9.0-alpha.8
* Add rejected DNS response cache support **1**
* Fixes and improvements
**1**:
The new feature allows you to cache the check results of
[Address filter DNS rule items](/configuration/dns/rule/#address-filter-fields) until expiration.
#### 1.9.0-alpha.7
* Update gVisor to 20240206.0
* Fixes and improvements
#### 1.9.0-alpha.6
* Fixes and improvements
#### 1.9.0-alpha.3
* Update `quic-go` to v0.41.0
* Fixes and improvements
#### 1.9.0-alpha.2
* Add support for `client-subnet` DNS options **1**
* Fixes and improvements
**1**:
See [DNS](/configuration/dns), [DNS Server](/configuration/dns/server) and [DNS Rules](/configuration/dns/rule).
Since this feature makes the scenario mentioned in `alpha.1` no longer leak DNS requests,
the [Client example](/manual/proxy/client#traffic-bypass-usage-for-chinese-users) has been updated.
#### 1.9.0-alpha.1
* `domain_suffix` behavior update **1**
* `process_path` format update on Windows **2**
* Add address filter DNS rule items **3**
**1**:
See [Migration](/migration/#domain_suffix-behavior-update).
**2**:
See [Migration](/migration/#process_path-format-update-on-windows).
**3**:
The new DNS feature allows you to more precisely bypass Chinese websites via **DNS leaks**. Do not use plain local DNS
if using this method.
See [Address Filter Fields](/configuration/dns/rule#address-filter-fields).
[Client example](/manual/proxy/client#traffic-bypass-usage-for-chinese-users) updated.
#### 1.8.5 #### 1.8.5
* Fixes and improvements * Fixes and improvements
@ -395,7 +569,7 @@ see [TCP Brutal](/configuration/shared/tcp-brutal/) for details.
**5**: **5**:
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
#### 1.7.0-rc.3 #### 1.7.0-rc.3
@ -432,7 +606,7 @@ Only supported in graphical clients on Android and iOS.
**1**: **1**:
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
#### 1.7.0-beta.3 #### 1.7.0-beta.3

View File

@ -287,7 +287,7 @@ Match Clash mode.
!!! quote "" !!! quote ""
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
Match WiFi SSID. Match WiFi SSID.
@ -295,7 +295,7 @@ Match WiFi SSID.
!!! quote "" !!! quote ""
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
Match WiFi BSSID. Match WiFi BSSID.

View File

@ -285,7 +285,7 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
!!! quote "" !!! quote ""
仅在 Android 与 iOS 的图形客户端中支持。 仅在 Android 与 Apple 平台图形客户端中支持。
匹配 WiFi SSID。 匹配 WiFi SSID。
@ -293,7 +293,7 @@ DNS 查询类型。值可以为整数或者类型名称字符串。
!!! quote "" !!! quote ""
仅在 Android 与 iOS 的图形客户端中支持。 仅在 Android 与 Apple 平台图形客户端中支持。
匹配 WiFi BSSID。 匹配 WiFi BSSID。

View File

@ -42,6 +42,6 @@ No authentication required if empty.
!!! warning "" !!! warning ""
To work on Android and iOS without privileges, use tun.platform.http_proxy instead. To work on Android and Apple platforms without privileges, use tun.platform.http_proxy instead.
Automatically set system proxy configuration when start and clean up when stop. Automatically set system proxy configuration when start and clean up when stop.

View File

@ -39,6 +39,6 @@ No authentication required if empty.
!!! warning "" !!! warning ""
To work on Android and iOS without privileges, use tun.platform.http_proxy instead. To work on Android and Apple platforms without privileges, use tun.platform.http_proxy instead.
Automatically set system proxy configuration when start and clean up when stop. Automatically set system proxy configuration when start and clean up when stop.

View File

@ -1,3 +1,12 @@
---
icon: material/new-box
---
!!! quote "Changes in sing-box 1.9.0"
:material-plus: [platform.http_proxy.bypass_domain](#platformhttp_proxybypass_domain)
:material-plus: [platform.http_proxy.match_domain](#platformhttp_proxymatch_domain)
!!! quote "Changes in sing-box 1.8.0" !!! quote "Changes in sing-box 1.8.0"
:material-plus: [gso](#gso) :material-plus: [gso](#gso)
@ -69,7 +78,9 @@
"http_proxy": { "http_proxy": {
"enabled": false, "enabled": false,
"server": "127.0.0.1", "server": "127.0.0.1",
"server_port": 8080 "server_port": 8080,
"bypass_domain": [],
"match_domain": []
} }
}, },
@ -256,6 +267,38 @@ Platform-specific settings, provided by client applications.
System HTTP proxy settings. System HTTP proxy settings.
#### platform.http_proxy.enabled
Enable system HTTP proxy.
#### platform.http_proxy.server
==Required==
HTTP proxy server address.
#### platform.http_proxy.server_port
==Required==
HTTP proxy server port.
#### platform.http_proxy.bypass_domain
!!! note ""
On Apple platforms, `bypass_domain` items matches hostname **suffixes**.
Hostnames that bypass the HTTP proxy.
#### platform.http_proxy.match_domain
!!! quote ""
Only supported in graphical clients on Apple platforms.
Hostnames that use the HTTP proxy.
### Listen Fields ### Listen Fields
See [Listen Fields](/configuration/shared/listen/) for details. See [Listen Fields](/configuration/shared/listen/) for details.

View File

@ -1,3 +1,12 @@
---
icon: material/new-box
---
!!! quote "sing-box 1.9.0 中的更改"
:material-plus: [platform.http_proxy.bypass_domain](#platformhttp_proxybypass_domain)
:material-plus: [platform.http_proxy.match_domain](#platformhttp_proxymatch_domain)
!!! quote "sing-box 1.8.0 中的更改" !!! quote "sing-box 1.8.0 中的更改"
:material-plus: [gso](#gso) :material-plus: [gso](#gso)
@ -69,7 +78,9 @@
"http_proxy": { "http_proxy": {
"enabled": false, "enabled": false,
"server": "127.0.0.1", "server": "127.0.0.1",
"server_port": 8080 "server_port": 8080,
"bypass_domain": [],
"match_domain": []
} }
}, },
@ -253,6 +264,38 @@ TCP/IP 栈。
系统 HTTP 代理设置。 系统 HTTP 代理设置。
##### platform.http_proxy.enabled
启用系统 HTTP 代理。
##### platform.http_proxy.server
==必填==
系统 HTTP 代理服务器地址。
##### platform.http_proxy.server_port
==必填==
系统 HTTP 代理服务器端口。
##### platform.http_proxy.bypass_domain
!!! note ""
在 Apple 平台,`bypass_domain` 项匹配主机名 **后缀**.
绕过代理的主机名列表。
##### platform.http_proxy.match_domain
!!! quote ""
仅在 Apple 平台图形客户端中支持。
代理的主机名列表。
### 监听字段 ### 监听字段
参阅 [监听字段](/zh/configuration/shared/listen/)。 参阅 [监听字段](/zh/configuration/shared/listen/)。

View File

@ -281,7 +281,7 @@ Match Clash mode.
!!! quote "" !!! quote ""
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
Match WiFi SSID. Match WiFi SSID.
@ -289,7 +289,7 @@ Match WiFi SSID.
!!! quote "" !!! quote ""
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
Match WiFi BSSID. Match WiFi BSSID.

View File

@ -279,7 +279,7 @@
!!! quote "" !!! quote ""
仅在 Android 与 iOS 的图形客户端中支持。 仅在 Android 与 Apple 平台图形客户端中支持。
匹配 WiFi SSID。 匹配 WiFi SSID。
@ -287,7 +287,7 @@
!!! quote "" !!! quote ""
仅在 Android 与 iOS 的图形客户端中支持。 仅在 Android 与 Apple 平台图形客户端中支持。
匹配 WiFi BSSID。 匹配 WiFi BSSID。

View File

@ -168,7 +168,7 @@ Match android package name.
!!! quote "" !!! quote ""
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
Match WiFi SSID. Match WiFi SSID.
@ -176,7 +176,7 @@ Match WiFi SSID.
!!! quote "" !!! quote ""
Only supported in graphical clients on Android and iOS. Only supported in graphical clients on Android and Apple platforms.
Match WiFi BSSID. Match WiFi BSSID.

View File

@ -0,0 +1,38 @@
---
icon: material/book-lock-open
---
# TunnelVision
TunnelVision is an attack that uses DHCP option 121 to set higher priority routes
so that traffic does not go through the VPN.
Reference: https://cve.mitre.org/cgi-bin/cvename.cgi?name=CVE-2024-3661
## Status
### Android
Android does not handle DHCP option 121 and is not affected.
### Apple platforms
Update [sing-box graphical client](/clients/apple/#download) to `1.9.0-rc.16` or newer,
then enable `includeAllNetworks` in `Settings``Packet Tunnel` and you will be unaffected.
Note: when `includeAllNetworks` is enabled, the default TUN stack is changed to `gvisor`,
and the `system` and `mixed` stacks are not available.
### Linux
Update sing-box to `1.9.0-rc.16` or newer, rules generated by `auto-route` are unaffected.
### Windows
No solution yet.
## Workarounds
* Don't connect to untrusted networks
* Relay untrusted network through another device
* Just ignore it

View File

@ -1,208 +0,0 @@
---
icon: material/alpha-t-box
---
# TUIC
A recently popular Chinese-made simple protocol based on QUIC, the selling point is the BBR congestion control algorithm.
!!! warning
Even though GFW rarely blocks UDP-based proxies, such protocols actually have far more characteristics than TCP based proxies.
| Specification | Binary Characteristics | Active Detect Hiddenness |
|-----------------------------------------------------------|------------------------|--------------------------|
| [GitHub](https://github.com/EAimTY/tuic/blob/dev/SPEC.md) | :material-alert: | :material-check: |
## Password Generator
| Generated UUID | Generated Password | Action |
|------------------------|----------------------------|-----------------------------------------------------------------|
| <code id="uuid"><code> | <code id="password"><code> | <button class="md-button" onclick="generate()">Refresh</button> |
<script>
function generateUUID() {
const uuid = 'xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx'.replace(/[xy]/g, function(c) {
let r = Math.random() * 16 | 0,
v = c === 'x' ? r : (r & 0x3 | 0x8);
return v.toString(16);
});
document.getElementById("uuid").textContent = uuid;
}
function generatePassword() {
const array = new Uint8Array(16);
window.crypto.getRandomValues(array);
document.getElementById("password").textContent = btoa(String.fromCharCode.apply(null, array));
}
function generate() {
generateUUID();
generatePassword();
}
generate();
</script>
## :material-server: Server Example
=== ":material-harddisk: With local certificate"
```json
{
"inbounds": [
{
"type": "tuic",
"listen": "::",
"listen_port": 8080,
"users": [
{
"name": "sekai",
"uuid": "<uuid>",
"password": "<password>"
}
],
"congestion_control": "bbr",
"tls": {
"enabled": true,
"server_name": "example.org",
"key_path": "/path/to/key.pem",
"certificate_path": "/path/to/certificate.pem"
}
}
]
}
```
=== ":material-auto-fix: With ACME"
```json
{
"inbounds": [
{
"type": "tuic",
"listen": "::",
"listen_port": 8080,
"users": [
{
"name": "sekai",
"uuid": "<uuid>",
"password": "<password>"
}
],
"congestion_control": "bbr",
"tls": {
"enabled": true,
"server_name": "example.org",
"acme": {
"domain": "example.org",
"email": "admin@example.org"
}
}
}
]
}
```
=== ":material-cloud: With ACME and Cloudflare API"
```json
{
"inbounds": [
{
"type": "tuic",
"listen": "::",
"listen_port": 8080,
"users": [
{
"name": "sekai",
"uuid": "<uuid>",
"password": "<password>"
}
],
"congestion_control": "bbr",
"tls": {
"enabled": true,
"server_name": "example.org",
"acme": {
"domain": "example.org",
"email": "admin@example.org",
"dns01_challenge": {
"provider": "cloudflare",
"api_token": "my_token"
}
}
}
}
]
}
```
## :material-cellphone-link: Client Example
=== ":material-web-check: With valid certificate"
```json
{
"outbounds": [
{
"type": "tuic",
"server": "127.0.0.1",
"server_port": 8080,
"uuid": "<uuid>",
"password": "<password>",
"congestion_control": "bbr",
"tls": {
"enabled": true,
"server_name": "example.org"
}
}
]
}
```
=== ":material-check: With self-sign certificate"
!!! info "Tip"
Use `sing-box merge` command to merge configuration and certificate into one file.
```json
{
"outbounds": [
{
"type": "tuic",
"server": "127.0.0.1",
"server_port": 8080,
"uuid": "<uuid>",
"password": "<password>",
"congestion_control": "bbr",
"tls": {
"enabled": true,
"server_name": "example.org",
"certificate_path": "/path/to/certificate.pem"
}
}
]
}
```
=== ":material-alert: Ignore certificate verification"
```json
{
"outbounds": [
{
"type": "tuic",
"server": "127.0.0.1",
"server_port": 8080,
"uuid": "<uuid>",
"password": "<password>",
"congestion_control": "bbr",
"tls": {
"enabled": true,
"server_name": "example.org",
"insecure": true
}
}
]
}
```

View File

@ -336,9 +336,9 @@ flowchart TB
} }
``` ```
=== ":material-dns: DNS rules (1.9.0+)" === ":material-dns: DNS rules (Enhanced, but slower) (1.9.0+)"
=== ":material-shield-off: With DNS Leaks" === ":material-shield-off: With DNS leaks"
```json ```json
{ {
@ -376,7 +376,17 @@ flowchart TB
"server": "google" "server": "google"
}, },
{ {
"rule_set": "geoip-cn", "type": "logical",
"mode": "and",
"rules": [
{
"rule_set": "geosite-geolocation-!cn",
"invert": true
},
{
"rule_set": "geoip-cn"
}
],
"server": "local" "server": "local"
} }
] ]
@ -389,6 +399,12 @@ flowchart TB
"format": "binary", "format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs" "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
}, },
{
"type": "remote",
"tag": "geosite-geolocation-!cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-!cn.srs"
},
{ {
"type": "remote", "type": "remote",
"tag": "geoip-cn", "tag": "geoip-cn",
@ -398,14 +414,18 @@ flowchart TB
] ]
}, },
"experimental": { "experimental": {
"cache_file": {
"enabled": true,
"store_rdrc": true
},
"clash_api": { "clash_api": {
"default_mode": "Leak" "default_mode": "Enhanced"
} }
} }
} }
``` ```
=== ":material-security: Without DNS Leaks (1.9.0-alpha.2+)" === ":material-security: Without DNS leaks, but slower (1.9.0-alpha.2+)"
```json ```json
{ {
@ -439,7 +459,17 @@ flowchart TB
"server": "local" "server": "local"
}, },
{ {
"rule_set": "geoip-cn", "type": "logical",
"mode": "and",
"rules": [
{
"rule_set": "geosite-geolocation-!cn",
"invert": true
},
{
"rule_set": "geoip-cn"
}
],
"server": "google", "server": "google",
"client_subnet": "114.114.114.114/24" // Any China client IP address "client_subnet": "114.114.114.114/24" // Any China client IP address
} }
@ -453,6 +483,12 @@ flowchart TB
"format": "binary", "format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs" "url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-cn.srs"
}, },
{
"type": "remote",
"tag": "geosite-geolocation-!cn",
"format": "binary",
"url": "https://raw.githubusercontent.com/SagerNet/sing-geosite/rule-set/geosite-geolocation-!cn.srs"
},
{ {
"type": "remote", "type": "remote",
"tag": "geoip-cn", "tag": "geoip-cn",
@ -460,6 +496,15 @@ flowchart TB
"url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs" "url": "https://raw.githubusercontent.com/SagerNet/sing-geoip/rule-set/geoip-cn.srs"
} }
] ]
},
"experimental": {
"cache_file": {
"enabled": true,
"store_rdrc": true
},
"clash_api": {
"default_mode": "Enhanced"
}
} }
} }
``` ```

View File

@ -82,6 +82,10 @@ func (s *platformInterfaceStub) UnderNetworkExtension() bool {
return false return false
} }
func (s *platformInterfaceStub) IncludeAllNetworks() bool {
return false
}
func (s *platformInterfaceStub) ClearDNSCache() { func (s *platformInterfaceStub) ClearDNSCache() {
} }

View File

@ -19,6 +19,7 @@ type PlatformInterface interface {
UsePlatformInterfaceGetter() bool UsePlatformInterfaceGetter() bool
GetInterfaces() (NetworkInterfaceIterator, error) GetInterfaces() (NetworkInterfaceIterator, error)
UnderNetworkExtension() bool UnderNetworkExtension() bool
IncludeAllNetworks() bool
ReadWIFIState() *WIFIState ReadWIFIState() *WIFIState
ClearDNSCache() ClearDNSCache()
} }

View File

@ -21,6 +21,7 @@ type Interface interface {
UsePlatformInterfaceGetter() bool UsePlatformInterfaceGetter() bool
Interfaces() ([]control.Interface, error) Interfaces() ([]control.Interface, error)
UnderNetworkExtension() bool UnderNetworkExtension() bool
IncludeAllNetworks() bool
ClearDNSCache() ClearDNSCache()
ReadWIFIState() adapter.WIFIState ReadWIFIState() adapter.WIFIState
process.Searcher process.Searcher

View File

@ -213,6 +213,10 @@ func (w *platformInterfaceWrapper) UnderNetworkExtension() bool {
return w.iif.UnderNetworkExtension() return w.iif.UnderNetworkExtension()
} }
func (w *platformInterfaceWrapper) IncludeAllNetworks() bool {
return w.iif.IncludeAllNetworks()
}
func (w *platformInterfaceWrapper) ClearDNSCache() { func (w *platformInterfaceWrapper) ClearDNSCache() {
w.iif.ClearDNSCache() w.iif.ClearDNSCache()
} }

View File

@ -28,6 +28,8 @@ type TunOptions interface {
IsHTTPProxyEnabled() bool IsHTTPProxyEnabled() bool
GetHTTPProxyServer() string GetHTTPProxyServer() string
GetHTTPProxyServerPort() int32 GetHTTPProxyServerPort() int32
GetHTTPProxyBypassDomain() StringIterator
GetHTTPProxyMatchDomain() StringIterator
} }
type RoutePrefix struct { type RoutePrefix struct {
@ -156,3 +158,11 @@ func (o *tunOptions) GetHTTPProxyServer() string {
func (o *tunOptions) GetHTTPProxyServerPort() int32 { func (o *tunOptions) GetHTTPProxyServerPort() int32 {
return int32(o.TunPlatformOptions.HTTPProxy.ServerPort) return int32(o.TunPlatformOptions.HTTPProxy.ServerPort)
} }
func (o *tunOptions) GetHTTPProxyBypassDomain() StringIterator {
return newIterator(o.TunPlatformOptions.HTTPProxy.BypassDomain)
}
func (o *tunOptions) GetHTTPProxyMatchDomain() StringIterator {
return newIterator(o.TunPlatformOptions.HTTPProxy.MatchDomain)
}

4
go.mod
View File

@ -23,7 +23,7 @@ require (
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
github.com/sagernet/gomobile v0.1.3 github.com/sagernet/gomobile v0.1.3
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f
github.com/sagernet/quic-go v0.43.1-beta.1 github.com/sagernet/quic-go v0.43.1-beta.1
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
github.com/sagernet/sing v0.4.0-beta.20 github.com/sagernet/sing v0.4.0-beta.20
@ -33,7 +33,7 @@ require (
github.com/sagernet/sing-shadowsocks v0.2.6 github.com/sagernet/sing-shadowsocks v0.2.6
github.com/sagernet/sing-shadowsocks2 v0.2.0 github.com/sagernet/sing-shadowsocks2 v0.2.0
github.com/sagernet/sing-shadowtls v0.1.4 github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/sing-tun v0.2.7 github.com/sagernet/sing-tun v0.3.0-beta.5
github.com/sagernet/sing-vmess v0.1.8 github.com/sagernet/sing-vmess v0.1.8
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6

8
go.sum
View File

@ -97,8 +97,8 @@ github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQ
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k= github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
github.com/sagernet/gomobile v0.1.3 h1:ohjIb1Ou2+1558PnZour3od69suSuvkdSVOlO1tC4B8= github.com/sagernet/gomobile v0.1.3 h1:ohjIb1Ou2+1558PnZour3od69suSuvkdSVOlO1tC4B8=
github.com/sagernet/gomobile v0.1.3/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E= github.com/sagernet/gomobile v0.1.3/go.mod h1:Pqq2+ZVvs10U7xK+UwJgwYWUykewi8H6vlslAO73n9E=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e h1:DOkjByVeAR56dkszjnMZke4wr7yM/1xHaJF3G9olkEE= github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f h1:NkhuupzH5ch7b/Y/6ZHJWrnNLoiNnSJaow6DPb8VW2I=
github.com/sagernet/gvisor v0.0.0-20231209105102-8d27a30e436e/go.mod h1:fLxq/gtp0qzkaEwywlRRiGmjOK5ES/xUzyIKIFP2Asw= github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f/go.mod h1:KXmw+ouSJNOsuRpg4wgwwCQuunrGz4yoAqQjsLjc6N0=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97 h1:iL5gZI3uFp0X6EslacyapiRz7LLSJyr4RajF/BhMVyE=
github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM= github.com/sagernet/netlink v0.0.0-20220905062125-8043b4a9aa97/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
github.com/sagernet/quic-go v0.43.1-beta.1 h1:alizUjpvWYcz08dBCQsULOd+1xu0o7UtlyYf6SLbRNg= github.com/sagernet/quic-go v0.43.1-beta.1 h1:alizUjpvWYcz08dBCQsULOd+1xu0o7UtlyYf6SLbRNg=
@ -120,8 +120,8 @@ github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wK
github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ= github.com/sagernet/sing-shadowsocks2 v0.2.0/go.mod h1:RnXS0lExcDAovvDeniJ4IKa2IuChrdipolPYWBv9hWQ=
github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k= github.com/sagernet/sing-shadowtls v0.1.4 h1:aTgBSJEgnumzFenPvc+kbD9/W0PywzWevnVpEx6Tw3k=
github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4= github.com/sagernet/sing-shadowtls v0.1.4/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
github.com/sagernet/sing-tun v0.2.7 h1:6QtJkeSj6BTTQPGxbbiuV8eh7GdV46w2G0N8CmISwdc= github.com/sagernet/sing-tun v0.3.0-beta.5 h1:z+4l1mGjPeepxT3mzHzE2pms995iUac/AyKQvRnWbWA=
github.com/sagernet/sing-tun v0.2.7/go.mod h1:MKAAHUzVfj7d9zos4lsz6wjXu86/mJyd/gejiAnWj/w= github.com/sagernet/sing-tun v0.3.0-beta.5/go.mod h1:xPaOkQhngPMILx+/9DMLCFl4vSxUU2tMnCPSlf05HLo=
github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc= github.com/sagernet/sing-vmess v0.1.8 h1:XVWad1RpTy9b5tPxdm5MCU8cGfrTGdR8qCq6HV2aCNc=
github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA= github.com/sagernet/sing-vmess v0.1.8/go.mod h1:vhx32UNzTDUkNwOyIjcZQohre1CaytquC5mPplId8uA=
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ= github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=

View File

@ -166,6 +166,14 @@ func (t *Tun) Start() error {
} }
t.logger.Trace("creating stack") t.logger.Trace("creating stack")
t.tunIf = tunInterface t.tunIf = tunInterface
var (
forwarderBindInterface bool
includeAllNetworks bool
)
if t.platformInterface != nil {
forwarderBindInterface = true
includeAllNetworks = t.platformInterface.IncludeAllNetworks()
}
t.tunStack, err = tun.NewStack(t.stack, tun.StackOptions{ t.tunStack, err = tun.NewStack(t.stack, tun.StackOptions{
Context: t.ctx, Context: t.ctx,
Tun: tunInterface, Tun: tunInterface,
@ -174,8 +182,9 @@ func (t *Tun) Start() error {
UDPTimeout: t.udpTimeout, UDPTimeout: t.udpTimeout,
Handler: t, Handler: t,
Logger: t.logger, Logger: t.logger,
ForwarderBindInterface: t.platformInterface != nil, ForwarderBindInterface: forwarderBindInterface,
InterfaceFinder: t.router.InterfaceFinder(), InterfaceFinder: t.router.InterfaceFinder(),
IncludeAllNetworks: includeAllNetworks,
}) })
if err != nil { if err != nil {
return err return err

View File

@ -66,8 +66,9 @@ nav:
- Proxy Protocol: - Proxy Protocol:
- Shadowsocks: manual/proxy-protocol/shadowsocks.md - Shadowsocks: manual/proxy-protocol/shadowsocks.md
- Trojan: manual/proxy-protocol/trojan.md - Trojan: manual/proxy-protocol/trojan.md
- TUIC: manual/proxy-protocol/tuic.md
- Hysteria 2: manual/proxy-protocol/hysteria2.md - Hysteria 2: manual/proxy-protocol/hysteria2.md
- Misc:
- TunnelVision: manual/misc/tunnelvision.md
- Configuration: - Configuration:
- configuration/index.md - configuration/index.md
- Log: - Log:

View File

@ -7,4 +7,6 @@ type TunPlatformOptions struct {
type HTTPProxyOptions struct { type HTTPProxyOptions struct {
Enabled bool `json:"enabled,omitempty"` Enabled bool `json:"enabled,omitempty"`
ServerOptions ServerOptions
BypassDomain Listable[string] `json:"bypass_domain,omitempty"`
MatchDomain Listable[string] `json:"match_domain,omitempty"`
} }

View File

@ -129,15 +129,19 @@ func NewDefaultHeadlessRule(router adapter.Router, options option.DefaultHeadles
rule.allItems = append(rule.allItems, item) rule.allItems = append(rule.allItems, item)
} }
if len(options.WIFISSID) > 0 { if len(options.WIFISSID) > 0 {
if router != nil {
item := NewWIFISSIDItem(router, options.WIFISSID) item := NewWIFISSIDItem(router, options.WIFISSID)
rule.items = append(rule.items, item) rule.items = append(rule.items, item)
rule.allItems = append(rule.allItems, item) rule.allItems = append(rule.allItems, item)
} }
}
if len(options.WIFIBSSID) > 0 { if len(options.WIFIBSSID) > 0 {
if router != nil {
item := NewWIFIBSSIDItem(router, options.WIFIBSSID) item := NewWIFIBSSIDItem(router, options.WIFIBSSID)
rule.items = append(rule.items, item) rule.items = append(rule.items, item)
rule.allItems = append(rule.allItems, item) rule.allItems = append(rule.allItems, item)
} }
}
return rule, nil return rule, nil
} }

View File

@ -34,7 +34,7 @@ type StackDevice struct {
stack *stack.Stack stack *stack.Stack
mtu uint32 mtu uint32
events chan wgTun.Event events chan wgTun.Event
outbound chan stack.PacketBufferPtr outbound chan *stack.PacketBuffer
packetOutbound chan *buf.Buffer packetOutbound chan *buf.Buffer
done chan struct{} done chan struct{}
dispatcher stack.NetworkDispatcher dispatcher stack.NetworkDispatcher
@ -52,7 +52,7 @@ func NewStackDevice(localAddresses []netip.Prefix, mtu uint32) (*StackDevice, er
stack: ipStack, stack: ipStack,
mtu: mtu, mtu: mtu,
events: make(chan wgTun.Event, 1), events: make(chan wgTun.Event, 1),
outbound: make(chan stack.PacketBufferPtr, 256), outbound: make(chan *stack.PacketBuffer, 256),
packetOutbound: make(chan *buf.Buffer, 256), packetOutbound: make(chan *buf.Buffer, 256),
done: make(chan struct{}), done: make(chan struct{}),
} }
@ -283,10 +283,10 @@ func (ep *wireEndpoint) ARPHardwareType() header.ARPHardwareType {
return header.ARPHardwareNone return header.ARPHardwareNone
} }
func (ep *wireEndpoint) AddHeader(buffer stack.PacketBufferPtr) { func (ep *wireEndpoint) AddHeader(buffer *stack.PacketBuffer) {
} }
func (ep *wireEndpoint) ParseHeader(ptr stack.PacketBufferPtr) bool { func (ep *wireEndpoint) ParseHeader(ptr *stack.PacketBuffer) bool {
return true return true
} }