Compare commits

..

24 Commits

Author SHA1 Message Date
wwqgtxx
b585bfdf1b Update cast using in sing-vmess 2025-08-19 23:55:11 +08:00
wwqgtxx
194aad8d40 Make utlsConnWrapper replaceable 2025-08-19 23:26:00 +08:00
wwqgtxx
4e52c357fe Make realityConnWrapper replaceable 2025-08-19 23:26:00 +08:00
世界
3d8a72b9ba
documentation: Bump version 2025-08-19 23:13:53 +08:00
世界
31fca03ef5
Fix wireguard crash 2025-08-19 23:13:53 +08:00
世界
eb09af768c
documentation: Update behavior of local DNS server on darwin 2025-08-19 23:04:22 +08:00
世界
023fcf6572
Stop using DHCP on iOS and tvOS
We do not have the `com.apple.developer.networking.multicast` entitlement and are unable to obtain it for non-technical reasons.
2025-08-19 23:04:22 +08:00
世界
1596e072ab
Remove use of ldflags -checklinkname=0 on darwin 2025-08-19 21:56:56 +08:00
世界
31d88ac7d3
Fix local DNS server on darwin
We mistakenly believed that `libresolv`'s `search` function worked correctly in NetworkExtension, but it seems only `getaddrinfo` does.

This commit changes the behavior of the `local` DNS server in NetworkExtension to prefer DHCP, falling back to `getaddrinfo` if DHCP servers are unavailable.

It's worth noting that `prefer_go` does not disable DHCP since it respects Dial Fields, but `getaddrinfo` does the opposite. The new behavior only applies to NetworkExtension, not to all scenarios (primarily command-line binaries) as it did previously.

In addition, this commit also improves the DHCP DNS server to use the same robust query logic as `local`.
2025-08-19 21:56:56 +08:00
世界
ea9f344763
Fix legacy DNS config 2025-08-19 21:56:56 +08:00
世界
6adc6a5a1d
Fix rule-set format 2025-08-19 21:56:56 +08:00
世界
ec2695aff6
documentation: Remove outdated icons 2025-08-19 21:56:56 +08:00
世界
5f2ec82448
documentation: Improve local DNS server 2025-08-19 21:56:56 +08:00
世界
c84e5d7784
Use libresolv in local DNS server on darwin 2025-08-19 21:56:55 +08:00
世界
169d496b37
Use resolved in local DNS server if available 2025-08-19 21:56:55 +08:00
xchacha20-poly1305
6c468eee6d
Fix rule set version 2025-08-19 21:56:55 +08:00
世界
a031cf2160
documentation: Add preferred_by route rule item 2025-08-19 21:56:54 +08:00
世界
1c39344e00
Add preferred_by route rule item 2025-08-19 21:56:54 +08:00
世界
8e86ada5eb
documentation: Add interface address rule items 2025-08-19 21:56:54 +08:00
世界
fa8141f0d0
Add interface address rule items 2025-08-19 21:56:54 +08:00
neletor
6054fd8ab4
Add support for ech retry configs 2025-08-19 21:56:54 +08:00
Zephyruso
da3cabb548
Add /dns/flush-clash meta api 2025-08-19 21:56:54 +08:00
世界
57e945300c
Bump version 2025-08-19 21:56:05 +08:00
世界
f462ce5615
Update tfo-go 2025-08-19 21:56:05 +08:00
11 changed files with 86 additions and 57 deletions

View File

@ -149,7 +149,7 @@ jobs:
TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale' TAGS='with_gvisor,with_quic,with_dhcp,with_wireguard,with_utls,with_acme,with_clash_api,with_tailscale'
echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}" echo "BUILD_TAGS=${TAGS}" >> "${GITHUB_ENV}"
- name: Build - name: Build
if: matrix.os != 'darwin' && matrix.os != 'android' if: matrix.os != 'android'
run: | run: |
set -xeuo pipefail set -xeuo pipefail
mkdir -p dist mkdir -p dist
@ -165,23 +165,6 @@ jobs:
GOMIPS: ${{ matrix.gomips }} GOMIPS: ${{ matrix.gomips }}
GOMIPS64: ${{ matrix.gomips }} GOMIPS64: ${{ matrix.gomips }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }} GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build darwin
if: matrix.os == 'darwin'
run: |
set -xeuo pipefail
mkdir -p dist
go build -v -trimpath -o dist/sing-box -tags "${BUILD_TAGS}" \
-ldflags '-s -buildid= -X github.com/sagernet/sing-box/constant.Version=${{ needs.calculate_version.outputs.version }} -checklinkname=0' \
./cmd/sing-box
env:
CGO_ENABLED: "0"
GOOS: ${{ matrix.os }}
GOARCH: ${{ matrix.arch }}
GO386: ${{ matrix.go386 }}
GOARM: ${{ matrix.goarm }}
GOMIPS: ${{ matrix.gomips }}
GOMIPS64: ${{ matrix.gomips }}
GITHUB_TOKEN: ${{ secrets.GITHUB_TOKEN }}
- name: Build Android - name: Build Android
if: matrix.os == 'android' if: matrix.os == 'android'
run: | run: |

View File

@ -46,7 +46,7 @@ var (
sharedFlags []string sharedFlags []string
debugFlags []string debugFlags []string
sharedTags []string sharedTags []string
darwinTags []string macOSTags []string
memcTags []string memcTags []string
notMemcTags []string notMemcTags []string
debugTags []string debugTags []string
@ -59,11 +59,11 @@ func init() {
if err != nil { if err != nil {
currentTag = "unknown" currentTag = "unknown"
} }
sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid= -checklinkname=0") sharedFlags = append(sharedFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+" -s -w -buildid=")
debugFlags = append(debugFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag+"-s -w -buildid= -checklinkname=0") debugFlags = append(debugFlags, "-ldflags", "-X github.com/sagernet/sing-box/constant.Version="+currentTag)
sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_clash_api", "with_conntrack") sharedTags = append(sharedTags, "with_gvisor", "with_quic", "with_wireguard", "with_utls", "with_clash_api", "with_conntrack")
darwinTags = append(darwinTags, "with_dhcp") macOSTags = append(macOSTags, "with_dhcp")
memcTags = append(memcTags, "with_tailscale") memcTags = append(memcTags, "with_tailscale")
notMemcTags = append(notMemcTags, "with_low_memory") notMemcTags = append(notMemcTags, "with_low_memory")
debugTags = append(debugTags, "debug") debugTags = append(debugTags, "debug")
@ -106,17 +106,19 @@ func buildAndroid() {
"-libname=box", "-libname=box",
} }
if !debugEnabled {
sharedFlags[3] = sharedFlags[3] + " -checklinkname=0"
args = append(args, sharedFlags...)
} else {
debugFlags[1] = debugFlags[1] + " -checklinkname=0"
args = append(args, debugFlags...)
}
tags := append(sharedTags, memcTags...) tags := append(sharedTags, memcTags...)
if debugEnabled { if debugEnabled {
tags = append(tags, debugTags...) tags = append(tags, debugTags...)
} }
if !debugEnabled {
args = append(args, sharedFlags...)
} else {
args = append(args, debugFlags...)
}
args = append(args, "-tags", strings.Join(tags, ",")) args = append(args, "-tags", strings.Join(tags, ","))
args = append(args, "./experimental/libbox") args = append(args, "./experimental/libbox")
@ -158,7 +160,9 @@ func buildApple() {
"-tags-not-macos=with_low_memory", "-tags-not-macos=with_low_memory",
} }
if !withTailscale { if !withTailscale {
args = append(args, "-tags-macos="+strings.Join(memcTags, ",")) args = append(args, "-tags-macos="+strings.Join(append(macOSTags, memcTags...), ","))
} else {
args = append(args, "-tags-macos="+strings.Join(macOSTags, ","))
} }
if !debugEnabled { if !debugEnabled {
@ -167,7 +171,7 @@ func buildApple() {
args = append(args, debugFlags...) args = append(args, debugFlags...)
} }
tags := append(sharedTags, darwinTags...) tags := sharedTags
if withTailscale { if withTailscale {
tags = append(tags, memcTags...) tags = append(tags, memcTags...)
} }

View File

@ -206,3 +206,11 @@ func (c *realityConnWrapper) Upstream() any {
func (c *realityConnWrapper) CloseWrite() error { func (c *realityConnWrapper) CloseWrite() error {
return c.Close() return c.Close()
} }
func (c *realityConnWrapper) ReaderReplaceable() bool {
return true
}
func (c *realityConnWrapper) WriterReplaceable() bool {
return true
}

View File

@ -106,6 +106,14 @@ func (c *utlsConnWrapper) Upstream() any {
return c.UConn return c.UConn
} }
func (c *utlsConnWrapper) ReaderReplaceable() bool {
return true
}
func (c *utlsConnWrapper) WriterReplaceable() bool {
return true
}
type utlsALPNWrapper struct { type utlsALPNWrapper struct {
utlsConnWrapper utlsConnWrapper
nextProtocols []string nextProtocols []string

View File

@ -197,7 +197,11 @@ func (t *Transport) fetchServers0(ctx context.Context, iface *control.Interface)
} }
defer packetConn.Close() defer packetConn.Close()
discovery, err := dhcpv4.NewDiscovery(iface.HardwareAddr, dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(dhcpv4.OptionDomainNameServer, dhcpv4.OptionDNSDomainSearchList)) discovery, err := dhcpv4.NewDiscovery(iface.HardwareAddr, dhcpv4.WithBroadcast(true), dhcpv4.WithRequestedOptions(
dhcpv4.OptionDomainName,
dhcpv4.OptionDomainNameServer,
dhcpv4.OptionDNSDomainSearchList,
))
if err != nil { if err != nil {
return err return err
} }
@ -249,8 +253,10 @@ func (t *Transport) fetchServersResponse(iface *control.Interface, packetConn ne
func (t *Transport) recreateServers(iface *control.Interface, dhcpPacket *dhcpv4.DHCPv4) error { func (t *Transport) recreateServers(iface *control.Interface, dhcpPacket *dhcpv4.DHCPv4) error {
searchList := dhcpPacket.DomainSearch() searchList := dhcpPacket.DomainSearch()
if searchList != nil { if searchList != nil && len(searchList.Labels) > 0 {
t.search = searchList.Labels t.search = searchList.Labels
} else if dhcpPacket.DomainName() != "" {
t.search = []string{dhcpPacket.DomainName()}
} }
serverAddrs := common.Map(dhcpPacket.DNS(), func(it net.IP) M.Socksaddr { serverAddrs := common.Map(dhcpPacket.DNS(), func(it net.IP) M.Socksaddr {
return M.SocksaddrFrom(M.AddrFromIP(it), 53) return M.SocksaddrFrom(M.AddrFromIP(it), 53)

View File

@ -7,6 +7,7 @@ import (
"errors" "errors"
"net" "net"
mDNS "github.com/miekg/dns"
"github.com/sagernet/sing-box/adapter" "github.com/sagernet/sing-box/adapter"
C "github.com/sagernet/sing-box/constant" C "github.com/sagernet/sing-box/constant"
"github.com/sagernet/sing-box/dns" "github.com/sagernet/sing-box/dns"
@ -19,8 +20,6 @@ import (
M "github.com/sagernet/sing/common/metadata" M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network" N "github.com/sagernet/sing/common/network"
"github.com/sagernet/sing/service" "github.com/sagernet/sing/service"
mDNS "github.com/miekg/dns"
) )
func RegisterTransport(registry *dns.TransportRegistry) { func RegisterTransport(registry *dns.TransportRegistry) {
@ -74,12 +73,14 @@ func (t *Transport) Start(stage adapter.StartStage) error {
break break
} }
} }
if t.fallback { if !C.IsIos {
t.dhcpTransport = newDHCPTransport(t.TransportAdapter, log.ContextWithOverrideLevel(t.ctx, log.LevelDebug), t.dialer, t.logger) if t.fallback {
if t.dhcpTransport != nil { t.dhcpTransport = newDHCPTransport(t.TransportAdapter, log.ContextWithOverrideLevel(t.ctx, log.LevelDebug), t.dialer, t.logger)
err := t.dhcpTransport.Start(stage) if t.dhcpTransport != nil {
if err != nil { err := t.dhcpTransport.Start(stage)
return err if err != nil {
return err
}
} }
} }
} }
@ -104,10 +105,12 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
if !t.fallback { if !t.fallback {
return t.exchange(ctx, message, domain) return t.exchange(ctx, message, domain)
} }
if t.dhcpTransport != nil { if !C.IsIos {
dhcpTransports, _ := t.dhcpTransport.Fetch() if t.dhcpTransport != nil {
if len(dhcpTransports) > 0 { dhcpTransports, _ := t.dhcpTransport.Fetch()
return t.dhcpTransport.Exchange0(ctx, message, dhcpTransports) if len(dhcpTransports) > 0 {
return t.dhcpTransport.Exchange0(ctx, message, dhcpTransports)
}
} }
} }
if t.preferGo { if t.preferGo {
@ -131,5 +134,9 @@ func (t *Transport) Exchange(ctx context.Context, message *mDNS.Msg) (*mDNS.Msg,
} }
return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil return dns.FixedResponse(message.Id, question, addresses, C.DefaultDNSTTL), nil
} }
return nil, E.New("only A and AAAA queries are supported on Apple platforms when using TUN and DHCP unavailable.") if C.IsIos {
return nil, E.New("only A and AAAA queries are supported on iOS and tvOS when using NetworkExtension.")
} else {
return nil, E.New("only A and AAAA queries are supported on macOS when using NetworkExtension and DHCP unavailable.")
}
} }

View File

@ -2,6 +2,14 @@
icon: material/alert-decagram icon: material/alert-decagram
--- ---
#### 1.13.0-alpha.4
* Fixes and improvements
#### 1.12.2
* Fixes and improvements
#### 1.13.0-alpha.3 #### 1.13.0-alpha.3
* Improve `local` DNS server **1** * Improve `local` DNS server **1**

View File

@ -43,16 +43,18 @@ When enabled, `local` DNS server will resolve DNS by dialing itself whenever pos
Specifically, it disables following behaviors which was added as features in sing-box 1.13.0: Specifically, it disables following behaviors which was added as features in sing-box 1.13.0:
* On Apple platforms: Use `libresolv` for resolution, as it is the only one that works properly with NetworkExtension 1. On Apple platforms: Attempt to resolve A/AAAA requests using `getaddrinfo` in NetworkExtension.
that overrides DNS servers (DHCP is also possible but is not considered). 2. On Linux: Resolve through `systemd-resolvd`'s DBus interface when available.
* On Linux: Resolve through `systemd-resolvd`'s DBus interface when available.
As a sole exception, it cannot disable the following behavior: As a sole exception, it cannot disable the following behavior:
In the Android graphical client, the `local` DNS server will always resolve DNS through the platform interface, 1. In the Android graphical client,
as there is no other way to obtain upstream DNS servers. `local` will always resolve DNS through the platform interface,
as there is no other way to obtain upstream DNS servers;
On devices running Android versions lower than 10, this interface can only resolve A/AAAA requests.
On devices running Android versions lower than 10, this interface can only resolve IP queries. 2. On macOS, `local` will try DHCP first in Network Extension, since DHCP respects DIal Fields,
it will not be disabled by `prefer_go`.
### Dial Fields ### Dial Fields

4
go.mod
View File

@ -15,7 +15,7 @@ require (
github.com/libdns/alidns v1.0.5-libdns.v1.beta1 github.com/libdns/alidns v1.0.5-libdns.v1.beta1
github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6 github.com/libdns/cloudflare v0.2.2-0.20250708034226-c574dccb31a6
github.com/logrusorgru/aurora v2.0.3+incompatible github.com/logrusorgru/aurora v2.0.3+incompatible
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4
github.com/metacubex/utls v1.8.0 github.com/metacubex/utls v1.8.0
github.com/mholt/acmez/v3 v3.1.2 github.com/mholt/acmez/v3 v3.1.2
github.com/miekg/dns v1.1.67 github.com/miekg/dns v1.1.67
@ -34,7 +34,7 @@ require (
github.com/sagernet/sing-shadowsocks2 v0.2.1 github.com/sagernet/sing-shadowsocks2 v0.2.1
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11
github.com/sagernet/sing-tun v0.7.0-beta.1 github.com/sagernet/sing-tun v0.7.0-beta.1
github.com/sagernet/sing-vmess v0.2.6 github.com/sagernet/sing-vmess v0.2.7
github.com/sagernet/smux v1.5.34-mod.2 github.com/sagernet/smux v1.5.34-mod.2
github.com/sagernet/tailscale v1.80.3-mod.5 github.com/sagernet/tailscale v1.80.3-mod.5
github.com/sagernet/wireguard-go v0.0.1-beta.7 github.com/sagernet/wireguard-go v0.0.1-beta.7

8
go.sum
View File

@ -122,8 +122,8 @@ github.com/mdlayher/sdnotify v1.0.0 h1:Ma9XeLVN/l0qpyx1tNeMSeTjCPH6NtuD6/N9XdTlQ
github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE= github.com/mdlayher/sdnotify v1.0.0/go.mod h1:HQUmpM4XgYkhDLtd+Uad8ZFK1T9D5+pNxnXQjCeJlGE=
github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos= github.com/mdlayher/socket v0.5.1 h1:VZaqt6RkGkt2OE9l3GcC6nZkqD3xKeQLyfleW/uBcos=
github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ= github.com/mdlayher/socket v0.5.1/go.mod h1:TjPLHI1UgwEv5J1B5q0zTZq12A/6H7nKmtTanQE37IQ=
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422 h1:zGeQt3UyNydIVrMRB97AA5WsYEau/TyCnRtTf1yUmJY= github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4 h1:j1VRTiC9JLR4nUbSikx9OGdu/3AgFDqgcLj4GoqyQkc=
github.com/metacubex/tfo-go v0.0.0-20241231083714-66613d49c422/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw= github.com/metacubex/tfo-go v0.0.0-20250516165257-e29c16ae41d4/go.mod h1:l9oLnLoEXyGZ5RVLsh7QCC5XsouTUyKk4F2nLm2DHLw=
github.com/metacubex/utls v1.8.0 h1:mSYi6FMnmc5riARl5UZDmWVy710z+P5b7xuGW0lV9ac= github.com/metacubex/utls v1.8.0 h1:mSYi6FMnmc5riARl5UZDmWVy710z+P5b7xuGW0lV9ac=
github.com/metacubex/utls v1.8.0/go.mod h1:FdjYzVfCtgtna19hX0ER1Xsa5uJInwdQ4IcaaI98lEQ= github.com/metacubex/utls v1.8.0/go.mod h1:FdjYzVfCtgtna19hX0ER1Xsa5uJInwdQ4IcaaI98lEQ=
github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc= github.com/mholt/acmez/v3 v3.1.2 h1:auob8J/0FhmdClQicvJvuDavgd5ezwLBfKuYmynhYzc=
@ -181,8 +181,8 @@ github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11 h1:tK+75
github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA= github.com/sagernet/sing-shadowtls v0.2.1-0.20250503051639-fcd445d33c11/go.mod h1:sWqKnGlMipCHaGsw1sTTlimyUpgzP4WP3pjhCsYt9oA=
github.com/sagernet/sing-tun v0.7.0-beta.1 h1:mBIFXYAnGO5ey/HcCYanqnBx61E7yF8zTFGRZonGYmY= github.com/sagernet/sing-tun v0.7.0-beta.1 h1:mBIFXYAnGO5ey/HcCYanqnBx61E7yF8zTFGRZonGYmY=
github.com/sagernet/sing-tun v0.7.0-beta.1/go.mod h1:AHJuRrLbNRJuivuFZ2VhXwDj4ViYp14szG5EkkKAqRQ= github.com/sagernet/sing-tun v0.7.0-beta.1/go.mod h1:AHJuRrLbNRJuivuFZ2VhXwDj4ViYp14szG5EkkKAqRQ=
github.com/sagernet/sing-vmess v0.2.6 h1:1c4dGzeGy0kpBXXrT1sgiMZtHhdJylIT8eWrGhJYZec= github.com/sagernet/sing-vmess v0.2.7 h1:2ee+9kO0xW5P4mfe6TYVWf9VtY8k1JhNysBqsiYj0sk=
github.com/sagernet/sing-vmess v0.2.6/go.mod h1:5aYoOtYksAyS0NXDm0qKeTYW1yoE1bJVcv+XLcVoyJs= github.com/sagernet/sing-vmess v0.2.7/go.mod h1:5aYoOtYksAyS0NXDm0qKeTYW1yoE1bJVcv+XLcVoyJs=
github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4= github.com/sagernet/smux v1.5.34-mod.2 h1:gkmBjIjlJ2zQKpLigOkFur5kBKdV6bNRoFu2WkltRQ4=
github.com/sagernet/smux v1.5.34-mod.2/go.mod h1:0KW0+R+ycvA2INW4gbsd7BNyg+HEfLIAxa5N02/28Zc= github.com/sagernet/smux v1.5.34-mod.2/go.mod h1:0KW0+R+ycvA2INW4gbsd7BNyg+HEfLIAxa5N02/28Zc=
github.com/sagernet/tailscale v1.80.3-mod.5 h1:7V7z+p2C//TGtff20pPnDCt3qP6uFyY62peJoKF9z/A= github.com/sagernet/tailscale v1.80.3-mod.5 h1:7V7z+p2C//TGtff20pPnDCt3qP6uFyY62peJoKF9z/A=

View File

@ -223,6 +223,9 @@ func (e *Endpoint) Close() error {
} }
func (e *Endpoint) Lookup(address netip.Addr) *device.Peer { func (e *Endpoint) Lookup(address netip.Addr) *device.Peer {
if e.allowedIPs == nil {
return nil
}
return e.allowedIPs.Lookup(address.AsSlice()) return e.allowedIPs.Lookup(address.AsSlice())
} }