Merge remote-tracking branch 'upstream/dev' into dev-next

# Conflicts:
#	adapter/router.go
#	dns/transport/udp.go
#	docs/configuration/dns/server/index.md
#	docs/configuration/dns/server/index.zh.md
#	docs/installation/tools/install.sh
#	docs/migration.md
#	docs/migration.zh.md
#	option/dns.go
#	option/rule_dns.go
#	route/rule_conds.go
This commit is contained in:
mingtianquan 2025-04-21 15:41:55 +08:00
commit d512411b96
9 changed files with 159 additions and 146 deletions

View File

@ -117,7 +117,7 @@ func (t *UDPTransport) exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M
conn.access.Unlock() conn.access.Unlock()
defer func() { defer func() {
conn.access.Lock() conn.access.Lock()
delete(conn.callbacks, messageId) delete(conn.callbacks, exMessage.Id)
conn.access.Unlock() conn.access.Unlock()
}() }()
rawMessage, err := exMessage.PackBuffer(buffer.FreeBytes()) rawMessage, err := exMessage.PackBuffer(buffer.FreeBytes())

View File

@ -27,19 +27,20 @@ icon: material/alert-decagram
The type of the DNS server. The type of the DNS server.
| Type | Format | | Type | Format |
|-----------------|-----------------------------| |-----------------|---------------------------|
| empty (default) | [Legacy](./legacy/) | | empty (default) | [Legacy](./legacy/) |
| `tcp` | [TCP](./tcp/) | | `local` | [Local](./local/) |
| `udp` | [UDP](./udp/) | | `hosts` | [Hosts](./hosts/) |
| `tls` | [TLS](./tls/) | | `tcp` | [TCP](./tcp/) |
| `https` | [HTTPS](./https/) | | `udp` | [UDP](./udp/) |
| `quic` | [QUIC](./quic/) | | `tls` | [TLS](./tls/) |
| `h3` | [HTTP/3](./http3/) | | `quic` | [QUIC](./quic/) |
| `predefined` | [Predefined](./predefined/) | | `https` | [HTTPS](./https/) |
| `dhcp` | [DHCP](./dhcp/) | | `h3` | [HTTP/3](./http3/) |
| `fakeip` | [Fake IP](./fakeip/) | | `dhcp` | [DHCP](./dhcp/) |
| `tailscale` | [Tailscale](./tailscale/) | | `fakeip` | [Fake IP](./fakeip/) |
| `tailscale` | [Tailscale](./tailscale/) |
#### tag #### tag

View File

@ -27,19 +27,20 @@ icon: material/alert-decagram
DNS 服务器的类型。 DNS 服务器的类型。
| 类型 | 格式 | | 类型 | 格式 |
|-----------------|-----------------------------| |-----------------|---------------------------|
| empty (default) | [Legacy](./legacy/) | | empty (default) | [Legacy](./legacy/) |
| `tcp` | [TCP](./tcp/) | | `local` | [Local](./local/) |
| `udp` | [UDP](./udp/) | | `hosts` | [Hosts](./hosts/) |
| `tls` | [TLS](./tls/) | | `tcp` | [TCP](./tcp/) |
| `https` | [HTTPS](./https/) | | `udp` | [UDP](./udp/) |
| `quic` | [QUIC](./quic/) | | `tls` | [TLS](./tls/) |
| `h3` | [HTTP/3](./http3/) | | `quic` | [QUIC](./quic/) |
| `predefined` | [Predefined](./predefined/) | | `https` | [HTTPS](./https/) |
| `dhcp` | [DHCP](./dhcp/) | | `h3` | [HTTP/3](./http3/) |
| `fakeip` | [Fake IP](./fakeip/) | | `dhcp` | [DHCP](./dhcp/) |
| `tailscale` | [Tailscale](./tailscale/) | | `fakeip` | [Fake IP](./fakeip/) |
| `tailscale` | [Tailscale](./tailscale/) |
#### tag #### tag

View File

@ -26,7 +26,7 @@
| QUIC 客户端 | 类型 | | QUIC 客户端 | 类型 |
|:------------------------:|:----------:| |:------------------------:|:----------:|
| Chromium/Cronet | `chrimium` | | Chromium/Cronet | `chromium` |
| Safari/Apple Network API | `safari` | | Safari/Apple Network API | `safari` |
| Firefox / uquic firefox | `firefox` | | Firefox / uquic firefox | `firefox` |
| quic-go / uquic chrome | `quic-go` | | quic-go / uquic chrome | `quic-go` |

View File

@ -1,87 +1,97 @@
#!/bin/bash #!/bin/sh
set -xeuo pipefail
download_beta=false download_beta=false
download_version="" download_version=""
for arg in "$@"; do for arg in "$@"; do
if [[ "$arg" == "--beta" ]]; then if [[ "$arg" == "--beta" ]]; then
download_beta=true download_beta=true
elif [[ "$arg" == "--version" ]]; then elif [[ "$arg" == "--version" ]]; then
download_version=true download_version=true
elif [[ "$download_version" == 'true' ]]; then elif [[ "$download_version" == 'true' ]]; then
download_version="$arg" download_version="$arg"
else else
echo "Unknown argument: $arg" echo "Unknown argument: $arg"
echo "Usage: $0 [--beta] [--version <version>]" echo "Usage: $0 [--beta] [--version <version>]"
exit 1 exit 1
fi fi
done done
if [[ $(command -v dpkg) ]]; then if [[ $(command -v dpkg) ]]; then
os="linux" os="linux"
arch=$(dpkg --print-architecture) arch=$(dpkg --print-architecture)
package_suffix=".deb" package_suffix=".deb"
package_install="dpkg -i" package_install="dpkg -i"
elif [[ $(command -v dnf) ]]; then elif [[ $(command -v dnf) ]]; then
os="linux" os="linux"
arch=$(uname -m) arch=$(uname -m)
package_suffix=".rpm" package_suffix=".rpm"
package_install="dnf install -y" package_install="dnf install -y"
elif [[ $(command -v rpm) ]]; then elif [[ $(command -v rpm) ]]; then
os="linux" os="linux"
arch=$(uname -m) arch=$(uname -m)
package_suffix=".rpm" package_suffix=".rpm"
package_install="rpm -i" package_install="rpm -i"
elif [[ $(command -v pacman) ]]; then elif [[ $(command -v pacman) ]]; then
os="linux" os="linux"
arch=$(uname -m) arch=$(uname -m)
package_suffix=".pkg.tar.zst" package_suffix=".pkg.tar.zst"
package_install="pacman -U --noconfirm" package_install="pacman -U --noconfirm"
elif [[ $(command -v opkg) ]]; then elif [[ $(command -v opkg) ]]; then
os="openwrt" os="openwrt"
source /etc/os-release source /etc/os-release
arch="$OPENWRT_ARCH" arch="$OPENWRT_ARCH"
package_suffix=".ipk" package_suffix=".ipk"
package_install="opkg update && opkg install -y" package_install="opkg update && opkg install -y"
else else
echo "Missing supported package manager." echo "Missing supported package manager."
exit 1 exit 1
fi fi
if [[ -z "$download_version" ]]; then if [[ -z "$download_version" ]]; then
if [[ "$download_beta" != 'true' ]]; then
header="" if [[ -n "$GITHUB_TOKEN" ]]; then
if [ -n "$GITHUB_TOKEN" ]; then latest_release=$(curl -s --fail-with-body -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/SagerNet/sing-box/releases/latest)
header="-H \"Authorization: token $GITHUB_TOKEN\"" else
fi latest_release=$(curl -s --fail-with-body https://api.github.com/repos/SagerNet/sing-box/releases/latest)
fi
if [[ "$download_beta" != 'true' ]]; then curl_exit_status=$?
download_version=$(curl -s --fail-with-body "$header" https://api.github.com/repos/SagerNet/sing-box/releases/latest | if [[ $curl_exit_status -ne 0 ]]; then
grep tag_name | echo "$latest_release"
cut -d ":" -f2 | exit $?
sed 's/\"//g;s/\,//g;s/\ //g;s/v//') fi
else download_version=$(echo "$latest_release" | grep tag_name | cut -d ":" -f2 | sed 's/\"//g;s/\,//g;s/\ //g;s/v//')
download_version=$(curl -s --fail-with-body "$header" https://api.github.com/repos/SagerNet/sing-box/releases | else
grep tag_name | if [[ -n "$GITHUB_TOKEN" ]]; then
head -n 1 | latest_release=$(curl -s --fail-with-body -H "Authorization: token ${GITHUB_TOKEN}" https://api.github.com/repos/SagerNet/sing-box/releases)
cut -d ":" -f2 | else
sed 's/\"//g;s/\,//g;s/\ //g;s/v//') latest_release=$(curl -s --fail-with-body https://api.github.com/repos/SagerNet/sing-box/releases)
fi fi
curl_exit_status=$?
if [[ $? -ne 0 ]]; then
echo "$latest_release"
exit $?
fi
download_version=$(echo "$latest_release" | grep tag_name | head -n 1 | cut -d ":" -f2 | sed 's/\"//g;s/\,//g;s/\ //g;s/v//')
fi
fi fi
package_name="sing-box_${download_version}_${os}_${arch}${package_suffix}" package_name="sing-box_${download_version}_${os}_${arch}${package_suffix}"
package_url="https://github.com/SagerNet/sing-box/releases/download/v${download_version}/${package_name}" package_url="https://github.com/SagerNet/sing-box/releases/download/v${download_version}/${package_name}"
echo "Downloading $package_url" echo "Downloading $package_url"
curl --fail-with-body -Lo "$package_name" "$package_url" if [[ -n "$GITHUB_TOKEN" ]]; then
curl --fail-with-body -Lo "$package_name" -H "Authorization: token ${GITHUB_TOKEN}" "$package_url"
if [[ $(command -v sudo) ]]; then else
package_install="sudo $package_install" curl --fail-with-body -Lo "$package_name" "$package_url"
fi fi
echo "$package_install $package_name" if [[ $? -ne 0 ]]; then
$package_install "$package_name" exit $?
rm "$package_name" fi
if [[ $(command -v sudo) ]]; then
package_install="sudo $package_install"
fi
echo "$package_install $package_name" && $package_install "$package_name" && rm "$package_name"

View File

@ -292,7 +292,7 @@ DNS servers are refactored for better performance and scalability.
} }
], ],
"fakeip": { "fakeip": {
"enable": true, "enabled": true,
"inet4_range": "198.18.0.0/15", "inet4_range": "198.18.0.0/15",
"inet6_range": "fc00::/18" "inet6_range": "fc00::/18"
} }
@ -556,7 +556,8 @@ The legacy outbound DNS rules are deprecated and can be replaced by new domain r
"dns": { "dns": {
"servers": [ "servers": [
{ {
"type": "local" "type": "local",
"tag": "local"
} }
] ]
}, },
@ -619,7 +620,8 @@ some people mistakenly believe that `domain_strategy` is the same feature as in
"dns": { "dns": {
"servers": [ "servers": [
{ {
"type": "local" "type": "local",
"tag": "local"
} }
] ]
}, },

View File

@ -292,7 +292,7 @@ DNS 服务器已经重构。
} }
], ],
"fakeip": { "fakeip": {
"enable": true, "enabled": true,
"inet4_range": "198.18.0.0/15", "inet4_range": "198.18.0.0/15",
"inet6_range": "fc00::/18" "inet6_range": "fc00::/18"
} }
@ -556,7 +556,8 @@ DNS 服务器已经重构。
"dns": { "dns": {
"servers": [ "servers": [
{ {
"type": "local" "type": "local",
"tag": "local"
} }
] ]
}, },
@ -618,7 +619,8 @@ DNS 服务器已经重构。
"dns": { "dns": {
"servers": [ "servers": [
{ {
"type": "local" "type": "local",
"tag": "local"
} }
] ]
}, },

View File

@ -387,50 +387,3 @@ type DHCPDNSServerOptions struct {
LocalDNSServerOptions LocalDNSServerOptions
Interface string `json:"interface,omitempty"` Interface string `json:"interface,omitempty"`
} }
type RawDefaultDNSRule struct {
Inbound badoption.Listable[string] `json:"inbound,omitempty"`
IPVersion int `json:"ip_version,omitempty"`
QueryType badoption.Listable[DNSQueryType] `json:"query_type,omitempty"`
Network badoption.Listable[string] `json:"network,omitempty"`
AuthUser badoption.Listable[string] `json:"auth_user,omitempty"`
Protocol badoption.Listable[string] `json:"protocol,omitempty"`
Client badoption.Listable[string] `json:"client,omitempty"`
Domain badoption.Listable[string] `json:"domain,omitempty"`
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
Geosite badoption.Listable[string] `json:"geosite,omitempty"`
SourceGeoIP badoption.Listable[string] `json:"source_geoip,omitempty"`
GeoIP badoption.Listable[string] `json:"geoip,omitempty"`
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
IPIsPrivate bool `json:"ip_is_private,omitempty"`
IPAcceptAny bool `json:"ip_accept_any,omitempty"`
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
Port badoption.Listable[uint16] `json:"port,omitempty"`
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
ProcessPID badoption.Listable[uint32] `json:"process_pid,omitempty"`
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
User badoption.Listable[string] `json:"user,omitempty"`
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
Outbound badoption.Listable[string] `json:"outbound,omitempty"`
ClashMode string `json:"clash_mode,omitempty"`
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
RuleSet badoption.Listable[string] `json:"rule_set,omitempty"`
RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"`
RuleSetIPCIDRAcceptEmpty bool `json:"rule_set_ip_cidr_accept_empty,omitempty"`
Invert bool `json:"invert,omitempty"`
// Deprecated: renamed to rule_set_ip_cidr_match_source
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
}

View File

@ -9,6 +9,7 @@ import (
E "github.com/sagernet/sing/common/exceptions" E "github.com/sagernet/sing/common/exceptions"
"github.com/sagernet/sing/common/json" "github.com/sagernet/sing/common/json"
"github.com/sagernet/sing/common/json/badjson" "github.com/sagernet/sing/common/json/badjson"
"github.com/sagernet/sing/common/json/badoption"
) )
type _DNSRule struct { type _DNSRule struct {
@ -66,7 +67,50 @@ func (r DNSRule) IsValid() bool {
} }
} }
// RawDefaultDNSRule已在dns.go中定义 type RawDefaultDNSRule struct {
Inbound badoption.Listable[string] `json:"inbound,omitempty"`
IPVersion int `json:"ip_version,omitempty"`
QueryType badoption.Listable[DNSQueryType] `json:"query_type,omitempty"`
Network badoption.Listable[string] `json:"network,omitempty"`
AuthUser badoption.Listable[string] `json:"auth_user,omitempty"`
Protocol badoption.Listable[string] `json:"protocol,omitempty"`
Domain badoption.Listable[string] `json:"domain,omitempty"`
DomainSuffix badoption.Listable[string] `json:"domain_suffix,omitempty"`
DomainKeyword badoption.Listable[string] `json:"domain_keyword,omitempty"`
DomainRegex badoption.Listable[string] `json:"domain_regex,omitempty"`
Geosite badoption.Listable[string] `json:"geosite,omitempty"`
SourceGeoIP badoption.Listable[string] `json:"source_geoip,omitempty"`
GeoIP badoption.Listable[string] `json:"geoip,omitempty"`
IPCIDR badoption.Listable[string] `json:"ip_cidr,omitempty"`
IPIsPrivate bool `json:"ip_is_private,omitempty"`
IPAcceptAny bool `json:"ip_accept_any,omitempty"`
SourceIPCIDR badoption.Listable[string] `json:"source_ip_cidr,omitempty"`
SourceIPIsPrivate bool `json:"source_ip_is_private,omitempty"`
SourcePort badoption.Listable[uint16] `json:"source_port,omitempty"`
SourcePortRange badoption.Listable[string] `json:"source_port_range,omitempty"`
Port badoption.Listable[uint16] `json:"port,omitempty"`
PortRange badoption.Listable[string] `json:"port_range,omitempty"`
ProcessName badoption.Listable[string] `json:"process_name,omitempty"`
ProcessPath badoption.Listable[string] `json:"process_path,omitempty"`
ProcessPathRegex badoption.Listable[string] `json:"process_path_regex,omitempty"`
PackageName badoption.Listable[string] `json:"package_name,omitempty"`
User badoption.Listable[string] `json:"user,omitempty"`
UserID badoption.Listable[int32] `json:"user_id,omitempty"`
Outbound badoption.Listable[string] `json:"outbound,omitempty"`
ClashMode string `json:"clash_mode,omitempty"`
NetworkType badoption.Listable[InterfaceType] `json:"network_type,omitempty"`
NetworkIsExpensive bool `json:"network_is_expensive,omitempty"`
NetworkIsConstrained bool `json:"network_is_constrained,omitempty"`
WIFISSID badoption.Listable[string] `json:"wifi_ssid,omitempty"`
WIFIBSSID badoption.Listable[string] `json:"wifi_bssid,omitempty"`
RuleSet badoption.Listable[string] `json:"rule_set,omitempty"`
RuleSetIPCIDRMatchSource bool `json:"rule_set_ip_cidr_match_source,omitempty"`
RuleSetIPCIDRAcceptEmpty bool `json:"rule_set_ip_cidr_accept_empty,omitempty"`
Invert bool `json:"invert,omitempty"`
// Deprecated: renamed to rule_set_ip_cidr_match_source
Deprecated_RulesetIPCIDRMatchSource bool `json:"rule_set_ipcidr_match_source,omitempty"`
}
type DefaultDNSRule struct { type DefaultDNSRule struct {
RawDefaultDNSRule RawDefaultDNSRule