diff --git a/dns/transport/udp.go b/dns/transport/udp.go index ec17c71b..e2ad9db7 100644 --- a/dns/transport/udp.go +++ b/dns/transport/udp.go @@ -117,7 +117,7 @@ func (t *UDPTransport) exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.M conn.access.Unlock() defer func() { conn.access.Lock() - delete(conn.callbacks, messageId) + delete(conn.callbacks, exMessage.Id) conn.access.Unlock() }() rawMessage, err := exMessage.PackBuffer(buffer.FreeBytes()) diff --git a/docs/configuration/dns/server/index.md b/docs/configuration/dns/server/index.md index 0dae05c3..706eb54f 100644 --- a/docs/configuration/dns/server/index.md +++ b/docs/configuration/dns/server/index.md @@ -27,19 +27,20 @@ icon: material/alert-decagram The type of the DNS server. -| Type | Format | -|-----------------|-----------------------------| -| empty (default) | [Legacy](./legacy/) | -| `tcp` | [TCP](./tcp/) | -| `udp` | [UDP](./udp/) | -| `tls` | [TLS](./tls/) | -| `https` | [HTTPS](./https/) | -| `quic` | [QUIC](./quic/) | -| `h3` | [HTTP/3](./http3/) | -| `predefined` | [Predefined](./predefined/) | -| `dhcp` | [DHCP](./dhcp/) | -| `fakeip` | [Fake IP](./fakeip/) | -| `tailscale` | [Tailscale](./tailscale/) | +| Type | Format | +|-----------------|---------------------------| +| empty (default) | [Legacy](./legacy/) | +| `local` | [Local](./local/) | +| `hosts` | [Hosts](./hosts/) | +| `tcp` | [TCP](./tcp/) | +| `udp` | [UDP](./udp/) | +| `tls` | [TLS](./tls/) | +| `quic` | [QUIC](./quic/) | +| `https` | [HTTPS](./https/) | +| `h3` | [HTTP/3](./http3/) | +| `dhcp` | [DHCP](./dhcp/) | +| `fakeip` | [Fake IP](./fakeip/) | +| `tailscale` | [Tailscale](./tailscale/) | #### tag diff --git a/docs/configuration/dns/server/index.zh.md b/docs/configuration/dns/server/index.zh.md index 2ad99502..61977c67 100644 --- a/docs/configuration/dns/server/index.zh.md +++ b/docs/configuration/dns/server/index.zh.md @@ -27,19 +27,20 @@ icon: material/alert-decagram DNS 服务器的类型。 -| 类型 | 格式 | -|-----------------|-----------------------------| -| empty (default) | [Legacy](./legacy/) | -| `tcp` | [TCP](./tcp/) | -| `udp` | [UDP](./udp/) | -| `tls` | [TLS](./tls/) | -| `https` | [HTTPS](./https/) | -| `quic` | [QUIC](./quic/) | -| `h3` | [HTTP/3](./http3/) | -| `predefined` | [Predefined](./predefined/) | -| `dhcp` | [DHCP](./dhcp/) | -| `fakeip` | [Fake IP](./fakeip/) | -| `tailscale` | [Tailscale](./tailscale/) | +| 类型 | 格式 | +|-----------------|---------------------------| +| empty (default) | [Legacy](./legacy/) | +| `local` | [Local](./local/) | +| `hosts` | [Hosts](./hosts/) | +| `tcp` | [TCP](./tcp/) | +| `udp` | [UDP](./udp/) | +| `tls` | [TLS](./tls/) | +| `quic` | [QUIC](./quic/) | +| `https` | [HTTPS](./https/) | +| `h3` | [HTTP/3](./http3/) | +| `dhcp` | [DHCP](./dhcp/) | +| `fakeip` | [Fake IP](./fakeip/) | +| `tailscale` | [Tailscale](./tailscale/) | #### tag diff --git a/docs/configuration/route/sniff.zh.md b/docs/configuration/route/sniff.zh.md index 546210c8..8cb9488f 100644 --- a/docs/configuration/route/sniff.zh.md +++ b/docs/configuration/route/sniff.zh.md @@ -26,7 +26,7 @@ | QUIC 客户端 | 类型 | |:------------------------:|:----------:| -| Chromium/Cronet | `chrimium` | +| Chromium/Cronet | `chromium` | | Safari/Apple Network API | `safari` | | Firefox / uquic firefox | `firefox` | -| quic-go / uquic chrome | `quic-go` | \ No newline at end of file +| quic-go / uquic chrome | `quic-go` | diff --git a/docs/installation/tools/install.sh b/docs/installation/tools/install.sh index 4b6ef00d..e042dde8 100755 --- a/docs/installation/tools/install.sh +++ b/docs/installation/tools/install.sh @@ -1,87 +1,97 @@ -#!/bin/bash - -set -xeuo pipefail +#!/bin/sh download_beta=false download_version="" for arg in "$@"; do - if [[ "$arg" == "--beta" ]]; then - download_beta=true - elif [[ "$arg" == "--version" ]]; then - download_version=true - elif [[ "$download_version" == 'true' ]]; then - download_version="$arg" - else - echo "Unknown argument: $arg" - echo "Usage: $0 [--beta] [--version ]" - exit 1 - fi + if [[ "$arg" == "--beta" ]]; then + download_beta=true + elif [[ "$arg" == "--version" ]]; then + download_version=true + elif [[ "$download_version" == 'true' ]]; then + download_version="$arg" + else + echo "Unknown argument: $arg" + echo "Usage: $0 [--beta] [--version ]" + exit 1 + fi done if [[ $(command -v dpkg) ]]; then - os="linux" - arch=$(dpkg --print-architecture) - package_suffix=".deb" - package_install="dpkg -i" + os="linux" + arch=$(dpkg --print-architecture) + package_suffix=".deb" + package_install="dpkg -i" elif [[ $(command -v dnf) ]]; then - os="linux" - arch=$(uname -m) - package_suffix=".rpm" - package_install="dnf install -y" + os="linux" + arch=$(uname -m) + package_suffix=".rpm" + package_install="dnf install -y" elif [[ $(command -v rpm) ]]; then - os="linux" - arch=$(uname -m) - package_suffix=".rpm" - package_install="rpm -i" + os="linux" + arch=$(uname -m) + package_suffix=".rpm" + package_install="rpm -i" elif [[ $(command -v pacman) ]]; then - os="linux" - arch=$(uname -m) - package_suffix=".pkg.tar.zst" - package_install="pacman -U --noconfirm" + os="linux" + arch=$(uname -m) + package_suffix=".pkg.tar.zst" + package_install="pacman -U --noconfirm" elif [[ $(command -v opkg) ]]; then - os="openwrt" - source /etc/os-release - arch="$OPENWRT_ARCH" - package_suffix=".ipk" - package_install="opkg update && opkg install -y" + os="openwrt" + source /etc/os-release + arch="$OPENWRT_ARCH" + package_suffix=".ipk" + package_install="opkg update && opkg install -y" else - echo "Missing supported package manager." - exit 1 + echo "Missing supported package manager." + exit 1 fi if [[ -z "$download_version" ]]; then - - header="" - if [ -n "$GITHUB_TOKEN" ]; then - header="-H \"Authorization: token $GITHUB_TOKEN\"" - fi - - if [[ "$download_beta" != 'true' ]]; then - download_version=$(curl -s --fail-with-body "$header" https://api.github.com/repos/SagerNet/sing-box/releases/latest | - grep tag_name | - cut -d ":" -f2 | - sed 's/\"//g;s/\,//g;s/\ //g;s/v//') - else - download_version=$(curl -s --fail-with-body "$header" https://api.github.com/repos/SagerNet/sing-box/releases | - grep tag_name | - head -n 1 | - cut -d ":" -f2 | - sed 's/\"//g;s/\,//g;s/\ //g;s/v//') - fi - + if [[ "$download_beta" != 'true' ]]; 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) + else + latest_release=$(curl -s --fail-with-body https://api.github.com/repos/SagerNet/sing-box/releases/latest) + fi + curl_exit_status=$? + if [[ $curl_exit_status -ne 0 ]]; then + echo "$latest_release" + exit $? + fi + download_version=$(echo "$latest_release" | grep tag_name | cut -d ":" -f2 | sed 's/\"//g;s/\,//g;s/\ //g;s/v//') + else + 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) + else + latest_release=$(curl -s --fail-with-body https://api.github.com/repos/SagerNet/sing-box/releases) + 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 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}" echo "Downloading $package_url" -curl --fail-with-body -Lo "$package_name" "$package_url" - -if [[ $(command -v sudo) ]]; then - package_install="sudo $package_install" +if [[ -n "$GITHUB_TOKEN" ]]; then + curl --fail-with-body -Lo "$package_name" -H "Authorization: token ${GITHUB_TOKEN}" "$package_url" +else + curl --fail-with-body -Lo "$package_name" "$package_url" fi -echo "$package_install $package_name" -$package_install "$package_name" -rm "$package_name" +if [[ $? -ne 0 ]]; then + exit $? +fi + +if [[ $(command -v sudo) ]]; then + package_install="sudo $package_install" +fi + +echo "$package_install $package_name" && $package_install "$package_name" && rm "$package_name" diff --git a/docs/migration.md b/docs/migration.md index ca50a70a..50a0655f 100644 --- a/docs/migration.md +++ b/docs/migration.md @@ -292,7 +292,7 @@ DNS servers are refactored for better performance and scalability. } ], "fakeip": { - "enable": true, + "enabled": true, "inet4_range": "198.18.0.0/15", "inet6_range": "fc00::/18" } @@ -556,7 +556,8 @@ The legacy outbound DNS rules are deprecated and can be replaced by new domain r "dns": { "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": { "servers": [ { - "type": "local" + "type": "local", + "tag": "local" } ] }, diff --git a/docs/migration.zh.md b/docs/migration.zh.md index a2779e23..255b7069 100644 --- a/docs/migration.zh.md +++ b/docs/migration.zh.md @@ -292,7 +292,7 @@ DNS 服务器已经重构。 } ], "fakeip": { - "enable": true, + "enabled": true, "inet4_range": "198.18.0.0/15", "inet6_range": "fc00::/18" } @@ -556,7 +556,8 @@ DNS 服务器已经重构。 "dns": { "servers": [ { - "type": "local" + "type": "local", + "tag": "local" } ] }, @@ -618,7 +619,8 @@ DNS 服务器已经重构。 "dns": { "servers": [ { - "type": "local" + "type": "local", + "tag": "local" } ] }, diff --git a/option/dns.go b/option/dns.go index 9ff1e9a5..f303b894 100644 --- a/option/dns.go +++ b/option/dns.go @@ -387,50 +387,3 @@ type DHCPDNSServerOptions struct { LocalDNSServerOptions 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"` -} diff --git a/option/rule_dns.go b/option/rule_dns.go index 2ad08b4f..87b15017 100644 --- a/option/rule_dns.go +++ b/option/rule_dns.go @@ -9,6 +9,7 @@ import ( E "github.com/sagernet/sing/common/exceptions" "github.com/sagernet/sing/common/json" "github.com/sagernet/sing/common/json/badjson" + "github.com/sagernet/sing/common/json/badoption" ) 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 { RawDefaultDNSRule