Compare commits

...

10 Commits

Author SHA1 Message Date
世界
3d735281f4 documentation: Bump version 2024-02-02 17:51:40 +08:00
世界
8760a0d94d Fix android interface monitor 2024-02-02 17:51:40 +08:00
世界
2239b59933 Remove duplicated rules 2024-02-02 14:30:27 +08:00
世界
425a63f59d Fix rawConn not closed for hy/hy2 2024-02-02 14:30:27 +08:00
世界
b85725c009 urltest: Remember the last choice when there is no valid result 2024-02-02 11:27:36 +08:00
世界
17aebc56c1 Fix UDP DNS response not truncated 2024-02-01 14:43:59 +08:00
Devman
f76b21b02c Fix mobile build on windows
gobind executable name is not exactly `gobind` on windows it's `gobind.exe`

Signed-off-by: Devman <85770917+amir-devman@users.noreply.github.com>
2024-02-01 12:07:39 +08:00
kkocdko
704545a2ec Fix rule description header of domain_suffix
I read other rule_item_xxx.go files, they are all snake case. This description is showed on dashboard like yacd.

Signed-off-by: kkocdko <31189892+kkocdko@users.noreply.github.com>
2024-02-01 10:42:12 +08:00
dyhkwong
dc7b7afc06 Fix loop back detector 2024-02-01 10:41:38 +08:00
世界
e478d3c2dc Update workflow 2024-01-24 12:21:18 +08:00
13 changed files with 103 additions and 101 deletions

View File

@@ -25,22 +25,10 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
fetch-depth: 0
- name: Get latest go version
id: version
run: |
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ steps.version.outputs.go_version }}
- name: Add cache to Go proxy
run: |
version=`git rev-parse HEAD`
mkdir build
pushd build
go mod init build
go get -v github.com/sagernet/sing-box@$version
popd
go-version: ^1.21
continue-on-error: true
- name: Run Test
run: |
@@ -56,7 +44,7 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.18.10
go-version: ~1.18
- name: Cache go module
uses: actions/cache@v3
with:
@@ -76,13 +64,13 @@ jobs:
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: 1.20.7
go-version: ^1.20
- name: Cache go module
uses: actions/cache@v3
with:
path: |
~/go/pkg/mod
key: go118-${{ hashFiles('**/go.sum') }}
key: go120-${{ hashFiles('**/go.sum') }}
- name: Run Test
run: make ci_build
cross:
@@ -188,8 +176,7 @@ jobs:
- name: freebsd-arm64
goos: freebsd
goarch: arm64
fail-fast: false
fail-fast: true
runs-on: ubuntu-latest
env:
GOOS: ${{ matrix.goos }}
@@ -204,19 +191,10 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
fetch-depth: 0
- name: Get latest go version
id: version
run: |
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
- name: Setup Go
uses: actions/setup-go@v5
with:
go-version: ${{ steps.version.outputs.go_version }}
go-version: ^1.21
- name: Build
id: build
run: make
- name: Upload artifact
uses: actions/upload-artifact@v4
with:
name: sing-box-${{ matrix.name }}
path: sing-box*
run: make

View File

@@ -1,9 +1,10 @@
name: Build Docker Images
on:
workflow_dispatch:
inputs:
tag:
description: "The tag version you want to build"
release:
types:
- published
jobs:
build:
runs-on: ubuntu-latest
@@ -25,15 +26,6 @@ jobs:
uses: docker/metadata-action@v5
with:
images: ghcr.io/sagernet/sing-box
- name: Get tag to build
id: tag
run: |
echo "latest=ghcr.io/sagernet/sing-box:latest" >> $GITHUB_OUTPUT
if [[ -z "${{ github.event.inputs.tag }}" ]]; then
echo "versioned=ghcr.io/sagernet/sing-box:${{ github.ref_name }}" >> $GITHUB_OUTPUT
else
echo "versioned=ghcr.io/sagernet/sing-box:${{ github.event.inputs.tag }}" >> $GITHUB_OUTPUT
fi
- name: Build and release Docker images
uses: docker/build-push-action@v5
with:
@@ -42,6 +34,6 @@ jobs:
build-args: |
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
tags: |
${{ steps.tag.outputs.latest }}
${{ steps.tag.outputs.versioned }}
ghcr.io/sagernet/sing-box:latest
ghcr.io/sagernet/sing-box:${{ github.ref_name }}
push: true

View File

@@ -25,10 +25,10 @@ jobs:
uses: actions/checkout@b4ffde65f46336ab88eb53be808477a3936bae11 # v4
with:
fetch-depth: 0
- name: Get latest go version
id: version
run: |
echo go_version=$(curl -s https://raw.githubusercontent.com/actions/go-versions/main/versions-manifest.json | grep -oE '"version": "[0-9]{1}.[0-9]{1,}(.[0-9]{1,})?"' | head -1 | cut -d':' -f2 | sed 's/ //g; s/"//g') >> $GITHUB_OUTPUT
- name: Setup Go
uses: actions/setup-go@v4
with:
go-version: ^1.21
- name: Setup Go
uses: actions/setup-go@v5
with:

View File

@@ -85,8 +85,15 @@ var GoBinPath string
func FindMobile() {
goBin := filepath.Join(build.Default.GOPATH, "bin")
if !rw.FileExists(goBin + "/" + "gobind") {
log.Fatal("missing gomobile installation")
if runtime.GOOS == "windows" {
if !rw.FileExists(goBin + "/" + "gobind.exe") {
log.Fatal("missing gomobile.exe installation")
}
} else {
if !rw.FileExists(goBin + "/" + "gobind") {
log.Fatal("missing gomobile installation")
}
}
GoBinPath = goBin
}

View File

@@ -2,6 +2,10 @@
icon: material/alert-decagram
---
#### 1.8.5
* Fixes and improvements
#### 1.8.4
* Fixes and improvements

View File

@@ -97,6 +97,17 @@ func (m *platformDefaultInterfaceMonitor) UnregisterCallback(element *list.Eleme
}
func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName string, interfaceIndex32 int32) {
if interfaceName == "" || interfaceIndex32 == -1 {
m.defaultInterfaceName = ""
m.defaultInterfaceIndex = -1
m.access.Lock()
callbacks := m.callbacks.Array()
m.access.Unlock()
for _, callback := range callbacks {
callback(tun.EventNoRoute)
}
return
}
var err error
if m.iif.UsePlatformInterfaceGetter() {
err = m.updateInterfacesPlatform()
@@ -110,28 +121,6 @@ func (m *platformDefaultInterfaceMonitor) UpdateDefaultInterface(interfaceName s
m.logger.Error(E.Cause(err, "update interfaces"))
}
interfaceIndex := int(interfaceIndex32)
if interfaceName == "" {
for _, netIf := range m.networkAddresses {
if netIf.interfaceIndex == interfaceIndex {
interfaceName = netIf.interfaceName
break
}
}
} else if interfaceIndex == -1 {
for _, netIf := range m.networkAddresses {
if netIf.interfaceName == interfaceName {
interfaceIndex = netIf.interfaceIndex
break
}
}
}
if interfaceName == "" {
m.logger.Error(E.New("invalid interface name for ", interfaceIndex))
return
} else if interfaceIndex == -1 {
m.logger.Error(E.New("invalid interface index for ", interfaceName))
return
}
if m.defaultInterfaceName == interfaceName && m.defaultInterfaceIndex == interfaceIndex {
return
}

6
go.mod
View File

@@ -29,11 +29,11 @@ require (
github.com/sagernet/sing v0.3.0
github.com/sagernet/sing-dns v0.1.12
github.com/sagernet/sing-mux v0.2.0
github.com/sagernet/sing-quic v0.1.7
github.com/sagernet/sing-quic v0.1.8
github.com/sagernet/sing-shadowsocks v0.2.6
github.com/sagernet/sing-shadowsocks2 v0.2.0
github.com/sagernet/sing-shadowtls v0.1.4
github.com/sagernet/sing-tun v0.2.0
github.com/sagernet/sing-tun v0.2.1
github.com/sagernet/sing-vmess v0.1.8
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
@@ -86,7 +86,7 @@ require (
github.com/vishvananda/netns v0.0.0-20211101163701-50045581ed74 // indirect
github.com/zeebo/blake3 v0.2.3 // indirect
go.uber.org/multierr v1.11.0 // indirect
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc // indirect
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a // indirect
golang.org/x/mod v0.14.0 // indirect
golang.org/x/text v0.14.0 // indirect
golang.org/x/time v0.5.0 // indirect

12
go.sum
View File

@@ -115,16 +115,16 @@ github.com/sagernet/sing-dns v0.1.12 h1:1HqZ+ln+Rezx/aJMStaS0d7oPeX2EobSV1NT537k
github.com/sagernet/sing-dns v0.1.12/go.mod h1:rx/DTOisneQpCgNQ4jbFU/JNEtnz0lYcHXenlVzpjEU=
github.com/sagernet/sing-mux v0.2.0 h1:4C+vd8HztJCWNYfufvgL49xaOoOHXty2+EAjnzN3IYo=
github.com/sagernet/sing-mux v0.2.0/go.mod h1:khzr9AOPocLa+g53dBplwNDz4gdsyx/YM3swtAhlkHQ=
github.com/sagernet/sing-quic v0.1.7 h1:SC45rAnvQ9BuyO0V186OdDScMBitmZo0XcM9LBYRUW8=
github.com/sagernet/sing-quic v0.1.7/go.mod h1:wUg1Z6AGKeJguruZo0lhrie3dqPiRCKaidLAbK2ttEs=
github.com/sagernet/sing-quic v0.1.8 h1:G4iBXAKIII+uTzd55oZ/9cAQswGjlvHh/0yKMQioDS0=
github.com/sagernet/sing-quic v0.1.8/go.mod h1:2w7DZXtf4MPjIGpovA3+vpI6bvOf1n1f9cQ1E2qQJSg=
github.com/sagernet/sing-shadowsocks v0.2.6 h1:xr7ylAS/q1cQYS8oxKKajhuQcchd5VJJ4K4UZrrpp0s=
github.com/sagernet/sing-shadowsocks v0.2.6/go.mod h1:j2YZBIpWIuElPFL/5sJAj470bcn/3QQ5lxZUNKLDNAM=
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
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/go.mod h1:F8NBgsY5YN2beQavdgdm1DPlhaKQlaL6lpDdcBglGK4=
github.com/sagernet/sing-tun v0.2.0 h1:/WloeRTWvwKIuiIvY+HVJaaZsTGb3XqJXZUbn6wVhz4=
github.com/sagernet/sing-tun v0.2.0/go.mod h1:vJHzPAbwFUHxdFHUFQlH+Fb4rT3K4/SHODdMLU1rrQI=
github.com/sagernet/sing-tun v0.2.1 h1:xZ/MkQbAX4yuOXq/s1pfhWa0lK1Ld7t4gOpSUbRl1Rs=
github.com/sagernet/sing-tun v0.2.1/go.mod h1:w1HTPPEL575m+Ob3GOIWaTs3ZrTdgLIwoldce/p3WPU=
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/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
@@ -170,8 +170,8 @@ golang.org/x/crypto v0.0.0-20190404164418-38d8ce5564a5/go.mod h1:WFFai1msRO1wXaE
golang.org/x/crypto v0.0.0-20210513164829-c07d793c2f9a/go.mod h1:P+XmwS30IXTQdn5tA2iutPOUgjI07+tq3H3K9MVA1s8=
golang.org/x/crypto v0.18.0 h1:PGVlW0xEltQnzFZ55hkuX5+KLyrMYhHld1YHO4AKcdc=
golang.org/x/crypto v0.18.0/go.mod h1:R0j02AL6hcrfOiy9T4ZYp/rcWeMxM3L6QYxlOuEG1mg=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc h1:ao2WRsKSzW6KuUY9IWPwWahcHCgR0s52IfwutMfEbdM=
golang.org/x/exp v0.0.0-20240103183307-be819d1f06fc/go.mod h1:iRJReGqOEeBhDZGkGbynYwcHlctCvnjTYIamk7uXpHI=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a h1:Q8/wZp0KX97QFTc2ywcOE0YRjZPVIx+MXInMzdvQqcA=
golang.org/x/exp v0.0.0-20240119083558-1b970713d09a/go.mod h1:idGWGoKP1toJGkd5/ig9ZLuPcZBC3ewk7SzmH0uou08=
golang.org/x/mod v0.14.0 h1:dGoOF9QVLYng8IHTm7BAyWqCqSheQ5pYWGhzW00YJr0=
golang.org/x/mod v0.14.0/go.mod h1:hTbmBsO62+eylJbnUtE2MGJUyE7QWk4xUqPFrRgJ+7c=
golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v0D8zg8gWTRqZa9RBIspLL5mdg=

View File

@@ -148,7 +148,7 @@ func (h *Direct) ListenPacket(ctx context.Context, destination M.Socksaddr) (net
if err != nil {
return nil, err
}
conn = h.loopBack.NewPacketConn(conn)
conn = h.loopBack.NewPacketConn(bufio.NewPacketConn(conn))
if originDestination != destination {
conn = bufio.NewNATPacketConn(bufio.NewPacketConn(conn), destination, originDestination)
}

View File

@@ -6,6 +6,7 @@ import (
"sync"
M "github.com/sagernet/sing/common/metadata"
N "github.com/sagernet/sing/common/network"
)
type loopBackDetector struct {
@@ -40,7 +41,7 @@ func (l *loopBackDetector) NewConn(conn net.Conn) net.Conn {
}
}
func (l *loopBackDetector) NewPacketConn(conn net.PacketConn) net.PacketConn {
func (l *loopBackDetector) NewPacketConn(conn N.NetPacketConn) N.NetPacketConn {
connAddr := M.AddrPortFromNet(conn.LocalAddr())
if !connAddr.IsValid() {
return conn
@@ -48,7 +49,7 @@ func (l *loopBackDetector) NewPacketConn(conn net.PacketConn) net.PacketConn {
l.packetConnAccess.Lock()
l.packetConnMap[connAddr] = true
l.packetConnAccess.Unlock()
return &loopBackDetectPacketWrapper{PacketConn: conn, detector: l, connAddr: connAddr}
return &loopBackDetectPacketWrapper{NetPacketConn: conn, detector: l, connAddr: connAddr}
}
func (l *loopBackDetector) CheckConn(connAddr netip.AddrPort) bool {
@@ -92,7 +93,7 @@ func (w *loopBackDetectWrapper) Upstream() any {
}
type loopBackDetectPacketWrapper struct {
net.PacketConn
N.NetPacketConn
detector *loopBackDetector
connAddr netip.AddrPort
closeOnce sync.Once
@@ -104,7 +105,7 @@ func (w *loopBackDetectPacketWrapper) Close() error {
delete(w.detector.packetConnMap, w.connAddr)
w.detector.packetConnAccess.Unlock()
})
return w.PacketConn.Close()
return w.NetPacketConn.Close()
}
func (w *loopBackDetectPacketWrapper) ReaderReplaceable() bool {
@@ -116,7 +117,7 @@ func (w *loopBackDetectPacketWrapper) WriterReplaceable() bool {
}
func (w *loopBackDetectPacketWrapper) Upstream() any {
return w.PacketConn
return w.NetPacketConn
}
type abstractUDPConn interface {

View File

@@ -241,7 +241,8 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
return err
}
timeout.Update()
responseBuffer := buf.NewPacket()
response = truncateDNSMessage(response, 512) // TODO: add an option to custom UDP buffer size
responseBuffer := buf.NewSize(dns.FixedPacketSize)
responseBuffer.Resize(1024, 0)
n, err := response.PackBuffer(responseBuffer.FreeBytes())
if err != nil {
@@ -263,3 +264,21 @@ func (d *DNS) newPacketConnection(ctx context.Context, conn N.PacketConn, readWa
})
return group.Run(fastClose)
}
func truncateDNSMessage(response *mDNS.Msg, maxLen int) *mDNS.Msg {
responseLen := response.Len()
if responseLen <= maxLen {
return response
}
response = response.Copy()
for len(response.Answer) > 0 && responseLen > maxLen {
response.Answer = response.Answer[:len(response.Answer)-1]
response.Truncated = true
responseLen = response.Len()
}
if responseLen > maxLen {
response.Ns = nil
response.Extra = nil
}
return response
}

View File

@@ -125,7 +125,18 @@ func (s *URLTest) CheckOutbounds() {
func (s *URLTest) DialContext(ctx context.Context, network string, destination M.Socksaddr) (net.Conn, error) {
s.group.Touch()
outbound := s.group.Select(network)
var outbound adapter.Outbound
switch N.NetworkName(network) {
case N.NetworkTCP:
outbound = s.group.selectedOutboundTCP
case N.NetworkUDP:
outbound = s.group.selectedOutboundUDP
default:
return nil, E.Extend(N.ErrUnknownNetwork, network)
}
if outbound == nil {
outbound, _ = s.group.Select(network)
}
if outbound == nil {
return nil, E.New("missing supported outbound")
}
@@ -140,7 +151,10 @@ func (s *URLTest) DialContext(ctx context.Context, network string, destination M
func (s *URLTest) ListenPacket(ctx context.Context, destination M.Socksaddr) (net.PacketConn, error) {
s.group.Touch()
outbound := s.group.Select(N.NetworkUDP)
outbound := s.group.selectedOutboundUDP
if outbound == nil {
outbound, _ = s.group.Select(N.NetworkUDP)
}
if outbound == nil {
return nil, E.New("missing supported outbound")
}
@@ -271,7 +285,7 @@ func (g *URLTestGroup) Close() error {
return nil
}
func (g *URLTestGroup) Select(network string) adapter.Outbound {
func (g *URLTestGroup) Select(network string) (adapter.Outbound, bool) {
var minDelay uint16
var minTime time.Time
var minOutbound adapter.Outbound
@@ -294,11 +308,11 @@ func (g *URLTestGroup) Select(network string) adapter.Outbound {
if !common.Contains(detour.Network(), network) {
continue
}
minOutbound = detour
break
return detour, false
}
return nil, false
}
return minOutbound
return minOutbound, true
}
func (g *URLTestGroup) loopCheck() {
@@ -382,14 +396,12 @@ func (g *URLTestGroup) urlTest(ctx context.Context, force bool) (map[string]uint
}
func (g *URLTestGroup) performUpdateCheck() {
outbound := g.Select(N.NetworkTCP)
var updated bool
if outbound != nil && outbound != g.selectedOutboundTCP {
if outbound, exists := g.Select(N.NetworkTCP); outbound != nil && (g.selectedOutboundTCP == nil || (exists && outbound != g.selectedOutboundTCP)) {
g.selectedOutboundTCP = outbound
updated = true
}
outbound = g.Select(N.NetworkUDP)
if outbound != nil && outbound != g.selectedOutboundUDP {
if outbound, exists := g.Select(N.NetworkUDP); outbound != nil && (g.selectedOutboundUDP == nil || (exists && outbound != g.selectedOutboundUDP)) {
g.selectedOutboundUDP = outbound
updated = true
}

View File

@@ -30,11 +30,11 @@ func NewDomainItem(domains []string, domainSuffixes []string) *DomainItem {
description += " "
}
if dsLen == 1 {
description += "domainSuffix=" + domainSuffixes[0]
description += "domain_suffix=" + domainSuffixes[0]
} else if dsLen > 3 {
description += "domainSuffix=[" + strings.Join(domainSuffixes[:3], " ") + "...]"
description += "domain_suffix=[" + strings.Join(domainSuffixes[:3], " ") + "...]"
} else {
description += "domainSuffix=[" + strings.Join(domainSuffixes, " ") + "]"
description += "domain_suffix=[" + strings.Join(domainSuffixes, " ") + "]"
}
}
return &DomainItem{