mirror of
https://github.com/shtorm-7/sing-box-extended.git
synced 2026-10-20 16:24:25 +00:00
Compare commits
39
Commits
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
100d971218 | ||
|
|
a8067f6eb8 | ||
|
|
b48db4778d | ||
|
|
a925fff9d0 | ||
|
|
d21bd8f37b | ||
|
|
5bff64ab72 | ||
|
|
f5ccff0dc8 | ||
|
|
3428f6dc07 | ||
|
|
42643c6489 | ||
|
|
cd2edabba7 | ||
|
|
5fe026b170 | ||
|
|
f026b661bf | ||
|
|
9219211d4b | ||
|
|
e6f2d37e93 | ||
|
|
06e8ee885d | ||
|
|
9dcb96e919 | ||
|
|
ed3f5c3c41 | ||
|
|
3986d2aa51 | ||
|
|
6821954630 | ||
|
|
aecfff29cb | ||
|
|
969f7e02cd | ||
|
|
31f98525be | ||
|
|
f523029953 | ||
|
|
791b840919 | ||
|
|
fd30f5c6c2 | ||
|
|
c6aedd125b | ||
|
|
02bc3e0a0a | ||
|
|
87be6dc235 | ||
|
|
c1c30976dc | ||
|
|
9bac18bcd1 | ||
|
|
ceda5cc95d | ||
|
|
27d6b63e71 | ||
|
|
b57abcc73c | ||
|
|
f1147965dd | ||
|
|
45f3234c73 | ||
|
|
aae3fded32 | ||
|
|
090494faf5 | ||
|
|
db5719e22f | ||
|
|
064fb9b873 |
@@ -28,8 +28,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.22
|
||||
continue-on-error: true
|
||||
go-version: ^1.23
|
||||
- name: Run Test
|
||||
run: |
|
||||
go test -v ./...
|
||||
@@ -73,6 +72,26 @@ jobs:
|
||||
key: go121-${{ hashFiles('**/go.sum') }}
|
||||
- name: Run Test
|
||||
run: make ci_build
|
||||
build_go122:
|
||||
name: Debug build (Go 1.22)
|
||||
runs-on: ubuntu-latest
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
with:
|
||||
fetch-depth: 0
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ~1.22
|
||||
- name: Cache go module
|
||||
uses: actions/cache@v4
|
||||
with:
|
||||
path: |
|
||||
~/go/pkg/mod
|
||||
key: go122-${{ hashFiles('**/go.sum') }}
|
||||
- name: Run Test
|
||||
run: make ci_build
|
||||
cross:
|
||||
strategy:
|
||||
matrix:
|
||||
|
||||
@@ -1,16 +1,82 @@
|
||||
name: Build Docker Images
|
||||
name: Publish Docker Images
|
||||
|
||||
on:
|
||||
release:
|
||||
types:
|
||||
- released
|
||||
- published
|
||||
workflow_dispatch:
|
||||
inputs:
|
||||
tag:
|
||||
description: "The tag version you want to build"
|
||||
|
||||
env:
|
||||
REGISTRY_IMAGE: ghcr.io/sagernet/sing-box
|
||||
|
||||
jobs:
|
||||
build:
|
||||
runs-on: ubuntu-latest
|
||||
strategy:
|
||||
fail-fast: true
|
||||
matrix:
|
||||
platform:
|
||||
- linux/amd64
|
||||
- linux/arm/v6
|
||||
- linux/arm/v7
|
||||
- linux/arm64
|
||||
- linux/386
|
||||
- linux/ppc64le
|
||||
- linux/riscv64
|
||||
- linux/s390x
|
||||
steps:
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
with:
|
||||
ref: ${{ steps.ref.outputs.ref }}
|
||||
- name: Prepare
|
||||
run: |
|
||||
platform=${{ matrix.platform }}
|
||||
echo "PLATFORM_PAIR=${platform//\//-}" >> $GITHUB_ENV
|
||||
- name: Setup QEMU
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Setup Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Docker meta
|
||||
id: meta
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ${{ env.REGISTRY_IMAGE }}
|
||||
- name: Build and push by digest
|
||||
id: build
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: ${{ matrix.platform }}
|
||||
context: .
|
||||
build-args: |
|
||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
|
||||
labels: ${{ steps.meta.outputs.labels }}
|
||||
outputs: type=image,name=${{ env.REGISTRY_IMAGE }},push-by-digest=true,name-canonical=true,push=true
|
||||
- name: Export digest
|
||||
run: |
|
||||
mkdir -p /tmp/digests
|
||||
digest="${{ steps.build.outputs.digest }}"
|
||||
touch "/tmp/digests/${digest#sha256:}"
|
||||
- name: Upload digest
|
||||
uses: actions/upload-artifact@v4
|
||||
with:
|
||||
name: digests-${{ env.PLATFORM_PAIR }}
|
||||
path: /tmp/digests/*
|
||||
if-no-files-found: error
|
||||
retention-days: 1
|
||||
merge:
|
||||
runs-on: ubuntu-latest
|
||||
needs:
|
||||
- build
|
||||
steps:
|
||||
- name: Get commit to build
|
||||
id: ref
|
||||
@@ -29,34 +95,28 @@ jobs:
|
||||
fi
|
||||
echo "latest=$latest"
|
||||
echo "latest=$latest" >> $GITHUB_OUTPUT
|
||||
- name: Checkout
|
||||
uses: actions/checkout@692973e3d937129bcbf40652eb9f2f61becf3332 # v4
|
||||
- name: Download digests
|
||||
uses: actions/download-artifact@v4
|
||||
with:
|
||||
ref: ${{ steps.ref.outputs.ref }}
|
||||
- name: Setup Docker Buildx
|
||||
path: /tmp/digests
|
||||
pattern: digests-*
|
||||
merge-multiple: true
|
||||
- name: Set up Docker Buildx
|
||||
uses: docker/setup-buildx-action@v3
|
||||
- name: Setup QEMU for Docker Buildx
|
||||
uses: docker/setup-qemu-action@v3
|
||||
- name: Login to GitHub Container Registry
|
||||
uses: docker/login-action@v3
|
||||
with:
|
||||
registry: ghcr.io
|
||||
username: ${{ github.repository_owner }}
|
||||
password: ${{ secrets.GITHUB_TOKEN }}
|
||||
- name: Docker metadata
|
||||
id: metadata
|
||||
uses: docker/metadata-action@v5
|
||||
with:
|
||||
images: ghcr.io/sagernet/sing-box
|
||||
- name: Build and release Docker images
|
||||
uses: docker/build-push-action@v6
|
||||
with:
|
||||
platforms: linux/386,linux/amd64,linux/arm64,linux/s390x
|
||||
context: .
|
||||
target: dist
|
||||
build-args: |
|
||||
BUILDKIT_CONTEXT_KEEP_GIT_DIR=1
|
||||
tags: |
|
||||
ghcr.io/sagernet/sing-box:${{ steps.ref.outputs.latest }}
|
||||
ghcr.io/sagernet/sing-box:${{ steps.ref.outputs.ref }}
|
||||
push: true
|
||||
- name: Create manifest list and push
|
||||
working-directory: /tmp/digests
|
||||
run: |
|
||||
docker buildx imagetools create \
|
||||
-t "${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.latest }}" \
|
||||
-t "${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.ref }}" \
|
||||
$(printf '${{ env.REGISTRY_IMAGE }}@sha256:%s ' *)
|
||||
- name: Inspect image
|
||||
run: |
|
||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.latest }}
|
||||
docker buildx imagetools inspect ${{ env.REGISTRY_IMAGE }}:${{ steps.ref.outputs.ref }}
|
||||
|
||||
@@ -28,7 +28,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.22
|
||||
go-version: ^1.23
|
||||
- name: golangci-lint
|
||||
uses: golangci/golangci-lint-action@v6
|
||||
with:
|
||||
|
||||
@@ -16,7 +16,7 @@ jobs:
|
||||
- name: Setup Go
|
||||
uses: actions/setup-go@v5
|
||||
with:
|
||||
go-version: ^1.22
|
||||
go-version: ^1.23
|
||||
- name: Extract signing key
|
||||
run: |-
|
||||
mkdir -p $HOME/.gnupg
|
||||
|
||||
@@ -12,4 +12,5 @@ jobs:
|
||||
with:
|
||||
stale-issue-message: 'This issue is stale because it has been open 60 days with no activity. Remove stale label or comment or this will be closed in 5 days'
|
||||
days-before-stale: 60
|
||||
days-before-close: 5
|
||||
days-before-close: 5
|
||||
exempt-issue-labels: 'bug,enhancement'
|
||||
|
||||
@@ -10,7 +10,6 @@ builds:
|
||||
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }}
|
||||
- -s
|
||||
- -buildid=
|
||||
- -checklinkname=0
|
||||
tags:
|
||||
- with_gvisor
|
||||
- with_quic
|
||||
@@ -49,10 +48,6 @@ builds:
|
||||
- with_reality_server
|
||||
- with_acme
|
||||
- with_clash_api
|
||||
ldflags:
|
||||
- -X github.com/sagernet/sing-box/constant.Version={{ .Version }}
|
||||
- -s
|
||||
- -buildid=
|
||||
env:
|
||||
- CGO_ENABLED=0
|
||||
- GOROOT={{ .Env.GOPATH }}/go1.20.14
|
||||
|
||||
+2
-2
@@ -1,4 +1,4 @@
|
||||
FROM --platform=$BUILDPLATFORM golang:1.22-alpine AS builder
|
||||
FROM --platform=$BUILDPLATFORM golang:1.23-alpine AS builder
|
||||
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
|
||||
COPY . /go/src/github.com/sagernet/sing-box
|
||||
WORKDIR /go/src/github.com/sagernet/sing-box
|
||||
@@ -21,7 +21,7 @@ FROM --platform=$TARGETPLATFORM alpine AS dist
|
||||
LABEL maintainer="nekohasekai <contact-git@sekai.icu>"
|
||||
RUN set -ex \
|
||||
&& apk upgrade \
|
||||
&& apk add bash tzdata ca-certificates \
|
||||
&& apk add bash tzdata ca-certificates nftables \
|
||||
&& rm -rf /var/cache/apk/*
|
||||
COPY --from=builder /go/bin/sing-box /usr/local/bin/sing-box
|
||||
ENTRYPOINT ["sing-box"]
|
||||
|
||||
@@ -4,9 +4,9 @@ The universal proxy platform.
|
||||
|
||||
[](https://repology.org/project/sing-box/versions)
|
||||
|
||||
## Support
|
||||
## Documentation
|
||||
|
||||
https://community.sagernet.org/c/sing-box/
|
||||
https://sing-box.sagernet.org
|
||||
|
||||
## License
|
||||
|
||||
|
||||
@@ -5,7 +5,7 @@ package dialer
|
||||
import (
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/tfo-go"
|
||||
"github.com/metacubex/tfo-go"
|
||||
)
|
||||
|
||||
type tcpDialer = tfo.Dialer
|
||||
|
||||
@@ -28,13 +28,12 @@ func New(router adapter.Router, options option.DialerOptions) (N.Dialer, error)
|
||||
} else {
|
||||
dialer = NewDetour(router, options.Detour)
|
||||
}
|
||||
domainStrategy := dns.DomainStrategy(options.DomainStrategy)
|
||||
if domainStrategy != dns.DomainStrategyAsIS || options.Detour == "" {
|
||||
if options.Detour == "" {
|
||||
dialer = NewResolveDialer(
|
||||
router,
|
||||
dialer,
|
||||
options.Detour == "" && !options.TCPFastOpen,
|
||||
domainStrategy,
|
||||
dns.DomainStrategy(options.DomainStrategy),
|
||||
time.Duration(options.FallbackDelay))
|
||||
}
|
||||
return dialer, nil
|
||||
|
||||
@@ -15,7 +15,8 @@ import (
|
||||
E "github.com/sagernet/sing/common/exceptions"
|
||||
M "github.com/sagernet/sing/common/metadata"
|
||||
N "github.com/sagernet/sing/common/network"
|
||||
"github.com/sagernet/tfo-go"
|
||||
|
||||
"github.com/metacubex/tfo-go"
|
||||
)
|
||||
|
||||
type slowOpenConn struct {
|
||||
|
||||
@@ -0,0 +1,90 @@
|
||||
package sniff
|
||||
|
||||
import (
|
||||
"context"
|
||||
"encoding/binary"
|
||||
"io"
|
||||
"os"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
"github.com/sagernet/sing/common/rw"
|
||||
)
|
||||
|
||||
func RDP(_ context.Context, metadata *adapter.InboundContext, reader io.Reader) error {
|
||||
var tpktVersion uint8
|
||||
err := binary.Read(reader, binary.BigEndian, &tpktVersion)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tpktVersion != 0x03 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
var tpktReserved uint8
|
||||
err = binary.Read(reader, binary.BigEndian, &tpktReserved)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if tpktReserved != 0x00 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
var tpktLength uint16
|
||||
err = binary.Read(reader, binary.BigEndian, &tpktLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if tpktLength != 19 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
var cotpLength uint8
|
||||
err = binary.Read(reader, binary.BigEndian, &cotpLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
if cotpLength != 14 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
var cotpTpduType uint8
|
||||
err = binary.Read(reader, binary.BigEndian, &cotpTpduType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if cotpTpduType != 0xE0 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
|
||||
err = rw.SkipN(reader, 5)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
|
||||
var rdpType uint8
|
||||
err = binary.Read(reader, binary.BigEndian, &rdpType)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rdpType != 0x01 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
var rdpFlags uint8
|
||||
err = binary.Read(reader, binary.BigEndian, &rdpFlags)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
var rdpLength uint8
|
||||
err = binary.Read(reader, binary.BigEndian, &rdpLength)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if rdpLength != 8 {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
metadata.Protocol = C.ProtocolRDP
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,25 @@
|
||||
package sniff_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/sniff"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSniffRDP(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
pkt, err := hex.DecodeString("030000130ee00000000000010008000b000000010008000b000000")
|
||||
require.NoError(t, err)
|
||||
var metadata adapter.InboundContext
|
||||
err = sniff.RDP(context.TODO(), &metadata, bytes.NewReader(pkt))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, C.ProtocolRDP, metadata.Protocol)
|
||||
}
|
||||
+29
-19
@@ -18,33 +18,43 @@ type (
|
||||
PacketSniffer = func(ctx context.Context, metadata *adapter.InboundContext, packet []byte) error
|
||||
)
|
||||
|
||||
func Skip(metadata adapter.InboundContext) bool {
|
||||
// skip server first protocols
|
||||
switch metadata.Destination.Port {
|
||||
case 25, 465, 587:
|
||||
// SMTP
|
||||
return true
|
||||
case 143, 993:
|
||||
// IMAP
|
||||
return true
|
||||
case 110, 995:
|
||||
// POP3
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func PeekStream(ctx context.Context, metadata *adapter.InboundContext, conn net.Conn, buffer *buf.Buffer, timeout time.Duration, sniffers ...StreamSniffer) error {
|
||||
if timeout == 0 {
|
||||
timeout = C.ReadPayloadTimeout
|
||||
}
|
||||
deadline := time.Now().Add(timeout)
|
||||
var errors []error
|
||||
|
||||
for i := 0; i < 3; i++ {
|
||||
err := conn.SetReadDeadline(deadline)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set read deadline")
|
||||
err := conn.SetReadDeadline(deadline)
|
||||
if err != nil {
|
||||
return E.Cause(err, "set read deadline")
|
||||
}
|
||||
defer conn.SetReadDeadline(time.Time{})
|
||||
for _, sniffer := range sniffers {
|
||||
if buffer.IsEmpty() {
|
||||
err = sniffer(ctx, metadata, io.TeeReader(conn, buffer))
|
||||
} else {
|
||||
err = sniffer(ctx, metadata, io.MultiReader(bytes.NewReader(buffer.Bytes()), io.TeeReader(conn, buffer)))
|
||||
}
|
||||
_, err = buffer.ReadOnceFrom(conn)
|
||||
err = E.Errors(err, conn.SetReadDeadline(time.Time{}))
|
||||
if err != nil {
|
||||
if i > 0 {
|
||||
break
|
||||
}
|
||||
return E.Cause(err, "read payload")
|
||||
}
|
||||
for _, sniffer := range sniffers {
|
||||
err = sniffer(ctx, metadata, bytes.NewReader(buffer.Bytes()))
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
errors = append(errors, err)
|
||||
if err == nil {
|
||||
return nil
|
||||
}
|
||||
errors = append(errors, err)
|
||||
}
|
||||
return E.Errors(errors...)
|
||||
}
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
package sniff
|
||||
|
||||
import (
|
||||
"bufio"
|
||||
"context"
|
||||
"io"
|
||||
"os"
|
||||
"strings"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
)
|
||||
|
||||
func SSH(_ context.Context, metadata *adapter.InboundContext, reader io.Reader) error {
|
||||
scanner := bufio.NewScanner(reader)
|
||||
if !scanner.Scan() {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
fistLine := scanner.Text()
|
||||
if !strings.HasPrefix(fistLine, "SSH-2.0-") {
|
||||
return os.ErrInvalid
|
||||
}
|
||||
metadata.Protocol = C.ProtocolSSH
|
||||
metadata.Client = fistLine[8:]
|
||||
return nil
|
||||
}
|
||||
@@ -0,0 +1,26 @@
|
||||
package sniff_test
|
||||
|
||||
import (
|
||||
"bytes"
|
||||
"context"
|
||||
"encoding/hex"
|
||||
"testing"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/sniff"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
|
||||
"github.com/stretchr/testify/require"
|
||||
)
|
||||
|
||||
func TestSniffSSH(t *testing.T) {
|
||||
t.Parallel()
|
||||
|
||||
pkt, err := hex.DecodeString("5353482d322e302d64726f70626561720d0a000001a40a1492892570d1223aef61b0d647972c8bd30000009f637572766532353531392d7368613235362c637572766532353531392d736861323536406c69627373682e6f72672c6469666669652d68656c6c6d616e2d67726f757031342d7368613235362c6469666669652d68656c6c6d616e2d67726f757031342d736861312c6b6578677565737332406d6174742e7563632e61736e2e61752c6b65782d7374726963742d732d763030406f70656e7373682e636f6d000000207373682d656432353531392c7273612d736861322d3235362c7373682d7273610000003363686163686132302d706f6c7931333035406f70656e7373682e636f6d2c6165733132382d6374722c6165733235362d6374720000003363686163686132302d706f6c7931333035406f70656e7373682e636f6d2c6165733132382d6374722c6165733235362d63747200000017686d61632d736861312c686d61632d736861322d32353600000017686d61632d736861312c686d61632d736861322d323536000000046e6f6e65000000046e6f6e65000000000000000000000000002aa6ed090585b7d635b6")
|
||||
require.NoError(t, err)
|
||||
var metadata adapter.InboundContext
|
||||
err = sniff.SSH(context.TODO(), &metadata, bytes.NewReader(pkt))
|
||||
require.NoError(t, err)
|
||||
require.Equal(t, C.ProtocolSSH, metadata.Protocol)
|
||||
require.Equal(t, "dropbear", metadata.Client)
|
||||
}
|
||||
@@ -8,6 +8,8 @@ const (
|
||||
ProtocolSTUN = "stun"
|
||||
ProtocolBitTorrent = "bittorrent"
|
||||
ProtocolDTLS = "dtls"
|
||||
ProtocolSSH = "ssh"
|
||||
ProtocolRDP = "rdp"
|
||||
)
|
||||
|
||||
const (
|
||||
|
||||
@@ -8,6 +8,26 @@ icon: material/alert-decagram
|
||||
|
||||
If your company or organization is willing to help us return to the App Store, please [contact us](mailto:contact@sagernet.org).
|
||||
|
||||
#### 1.10.0-beta.7
|
||||
|
||||
* Update quic-go to v0.47.0
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.10.0-beta.6
|
||||
|
||||
* Add RDP sniffer
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.10.0-beta.5
|
||||
|
||||
* Add PNA support for [Clash API](/configuration/experimental/clash-api/)
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.10.0-beta.3
|
||||
|
||||
* Add SSH sniffer
|
||||
* Fixes and improvements
|
||||
|
||||
#### 1.10.0-beta.2
|
||||
|
||||
* Build with go1.23
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
---
|
||||
icon: material/new-box
|
||||
---
|
||||
|
||||
!!! quote "Changes in sing-box 1.10.0"
|
||||
|
||||
:material-plus: [access_control_allow_origin](#access_control_allow_origin)
|
||||
:material-plus: [access_control_allow_private_network](#access_control_allow_private_network)
|
||||
|
||||
!!! quote "Changes in sing-box 1.8.0"
|
||||
|
||||
:material-delete-alert: [store_mode](#store_mode)
|
||||
@@ -8,24 +17,59 @@
|
||||
|
||||
### Structure
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"external_ui": "",
|
||||
"external_ui_download_url": "",
|
||||
"external_ui_download_detour": "",
|
||||
"secret": "",
|
||||
"default_mode": "",
|
||||
|
||||
// Deprecated
|
||||
|
||||
"store_mode": false,
|
||||
"store_selected": false,
|
||||
"store_fakeip": false,
|
||||
"cache_file": "",
|
||||
"cache_id": ""
|
||||
}
|
||||
```
|
||||
=== "Structure"
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"external_ui": "",
|
||||
"external_ui_download_url": "",
|
||||
"external_ui_download_detour": "",
|
||||
"secret": "",
|
||||
"default_mode": "",
|
||||
"access_control_allow_origin": [],
|
||||
"access_control_allow_private_network": false,
|
||||
|
||||
// Deprecated
|
||||
|
||||
"store_mode": false,
|
||||
"store_selected": false,
|
||||
"store_fakeip": false,
|
||||
"cache_file": "",
|
||||
"cache_id": ""
|
||||
}
|
||||
```
|
||||
|
||||
=== "Example (online)"
|
||||
|
||||
!!! question "Since sing-box 1.10.0"
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"access_control_allow_origin": [
|
||||
"http://127.0.0.1",
|
||||
"http://yacd.haishan.me"
|
||||
],
|
||||
"access_control_allow_private_network": true
|
||||
}
|
||||
```
|
||||
|
||||
=== "Example (download)"
|
||||
|
||||
!!! question "Since sing-box 1.10.0"
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "0.0.0.0:9090",
|
||||
"external_ui": "dashboard"
|
||||
// external_ui_download_detour: "direct"
|
||||
}
|
||||
```
|
||||
|
||||
!!! note ""
|
||||
|
||||
You can ignore the JSON Array [] tag when the content is only one item
|
||||
|
||||
### Fields
|
||||
|
||||
@@ -63,6 +107,22 @@ Default mode in clash, `Rule` will be used if empty.
|
||||
|
||||
This setting has no direct effect, but can be used in routing and DNS rules via the `clash_mode` rule item.
|
||||
|
||||
#### access_control_allow_origin
|
||||
|
||||
!!! question "Since sing-box 1.10.0"
|
||||
|
||||
CORS allowed origins, `*` will be used if empty.
|
||||
|
||||
To access the Clash API on a private network from a public website, you must explicitly specify it in `access_control_allow_origin` instead of using `*`.
|
||||
|
||||
#### access_control_allow_private_network
|
||||
|
||||
!!! question "Since sing-box 1.10.0"
|
||||
|
||||
Allow access from private network.
|
||||
|
||||
To access the Clash API on a private network from a public website, `access_control_allow_private_network` must be enabled.
|
||||
|
||||
#### store_mode
|
||||
|
||||
!!! failure "Deprecated in sing-box 1.8.0"
|
||||
|
||||
@@ -1,3 +1,12 @@
|
||||
---
|
||||
icon: material/new-box
|
||||
---
|
||||
|
||||
!!! quote "sing-box 1.10.0 中的更改"
|
||||
|
||||
:material-plus: [access_control_allow_origin](#access_control_allow_origin)
|
||||
:material-plus: [access_control_allow_private_network](#access_control_allow_private_network)
|
||||
|
||||
!!! quote "sing-box 1.8.0 中的更改"
|
||||
|
||||
:material-delete-alert: [store_mode](#store_mode)
|
||||
@@ -8,24 +17,59 @@
|
||||
|
||||
### 结构
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"external_ui": "",
|
||||
"external_ui_download_url": "",
|
||||
"external_ui_download_detour": "",
|
||||
"secret": "",
|
||||
"default_mode": "",
|
||||
|
||||
// Deprecated
|
||||
|
||||
"store_mode": false,
|
||||
"store_selected": false,
|
||||
"store_fakeip": false,
|
||||
"cache_file": "",
|
||||
"cache_id": ""
|
||||
}
|
||||
```
|
||||
=== "结构"
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"external_ui": "",
|
||||
"external_ui_download_url": "",
|
||||
"external_ui_download_detour": "",
|
||||
"secret": "",
|
||||
"default_mode": "",
|
||||
"access_control_allow_origin": [],
|
||||
"access_control_allow_private_network": false,
|
||||
|
||||
// Deprecated
|
||||
|
||||
"store_mode": false,
|
||||
"store_selected": false,
|
||||
"store_fakeip": false,
|
||||
"cache_file": "",
|
||||
"cache_id": ""
|
||||
}
|
||||
```
|
||||
|
||||
=== "示例 (在线)"
|
||||
|
||||
!!! question "自 sing-box 1.10.0 起"
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "127.0.0.1:9090",
|
||||
"access_control_allow_origin": [
|
||||
"http://127.0.0.1",
|
||||
"http://yacd.haishan.me"
|
||||
],
|
||||
"access_control_allow_private_network": true
|
||||
}
|
||||
```
|
||||
|
||||
=== "示例 (下载)"
|
||||
|
||||
!!! question "自 sing-box 1.10.0 起"
|
||||
|
||||
```json
|
||||
{
|
||||
"external_controller": "0.0.0.0:9090",
|
||||
"external_ui": "dashboard"
|
||||
// external_ui_download_detour: "direct"
|
||||
}
|
||||
```
|
||||
|
||||
!!! note ""
|
||||
|
||||
当内容只有一项时,可以忽略 JSON 数组 [] 标签
|
||||
|
||||
### Fields
|
||||
|
||||
@@ -61,6 +105,22 @@ Clash 中的默认模式,默认使用 `Rule`。
|
||||
|
||||
此设置没有直接影响,但可以通过 `clash_mode` 规则项在路由和 DNS 规则中使用。
|
||||
|
||||
#### access_control_allow_origin
|
||||
|
||||
!!! question "自 sing-box 1.10.0 起"
|
||||
|
||||
允许的 CORS 来源,默认使用 `*`。
|
||||
|
||||
要从公共网站访问私有网络上的 Clash API,必须在 `access_control_allow_origin` 中明确指定它而不是使用 `*`。
|
||||
|
||||
#### access_control_allow_private_network
|
||||
|
||||
!!! question "自 sing-box 1.10.0 起"
|
||||
|
||||
允许从私有网络访问。
|
||||
|
||||
要从公共网站访问私有网络上的 Clash API,必须启用 `access_control_allow_private_network`。
|
||||
|
||||
#### store_mode
|
||||
|
||||
!!! failure "已在 sing-box 1.8.0 废弃"
|
||||
|
||||
@@ -7,7 +7,9 @@ icon: material/new-box
|
||||
:material-plus: QUIC client type detect support for QUIC
|
||||
:material-plus: Chromium support for QUIC
|
||||
:material-plus: BitTorrent support
|
||||
:material-plus: DTLS support
|
||||
:material-plus: DTLS support
|
||||
:material-plus: SSH support
|
||||
:material-plus: RDP support
|
||||
|
||||
If enabled in the inbound, the protocol and domain name (if present) of by the connection can be sniffed.
|
||||
|
||||
@@ -22,6 +24,8 @@ If enabled in the inbound, the protocol and domain name (if present) of by the c
|
||||
| TCP/UDP | `dns` | / | / |
|
||||
| TCP/UDP | `bittorrent` | / | / |
|
||||
| UDP | `dtls` | / | / |
|
||||
| TCP | `ssh` | / | SSH Client Name |
|
||||
| TCP | `rdp` | / | / |
|
||||
|
||||
| QUIC Client | Type |
|
||||
|:------------------------:|:----------:|
|
||||
|
||||
@@ -7,7 +7,9 @@ icon: material/new-box
|
||||
:material-plus: QUIC 的 客户端类型探测支持
|
||||
:material-plus: QUIC 的 Chromium 支持
|
||||
:material-plus: BitTorrent 支持
|
||||
:material-plus: DTLS 支持
|
||||
:material-plus: DTLS 支持
|
||||
:material-plus: SSH 支持
|
||||
:material-plus: RDP 支持
|
||||
|
||||
如果在入站中启用,则可以嗅探连接的协议和域名(如果存在)。
|
||||
|
||||
@@ -22,6 +24,8 @@ icon: material/new-box
|
||||
| TCP/UDP | `dns` | / | / |
|
||||
| TCP/UDP | `bittorrent` | / | / |
|
||||
| UDP | `dtls` | / | / |
|
||||
| TCP | `ssh` | / | SSH 客户端名称 |
|
||||
| TCP | `rdp` | / | / |
|
||||
|
||||
| QUIC 客户端 | 类型 |
|
||||
|:------------------------:|:----------:|
|
||||
|
||||
@@ -4,6 +4,13 @@ description: 欢迎来到该 sing-box 项目的文档页。
|
||||
|
||||
# :material-home: 开始
|
||||
|
||||
!!! failure "需要帮助"
|
||||
|
||||
由于我们的 Apple 开发者账户出现问题,Apple 平台上的 sing-box 应用暂时无法下载或更新。
|
||||
|
||||
如果您的公司或组织愿意帮助我们重返 App Store,请[联系我们](mailto:contact@sagernet.org)。
|
||||
|
||||
|
||||
欢迎来到该 sing-box 项目的文档页。
|
||||
|
||||
通用代理平台。
|
||||
|
||||
@@ -24,14 +24,7 @@ icon: material/package
|
||||
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo dnf install sing-box # or sing-box-beta
|
||||
```
|
||||
|
||||
=== ":material-redhat: CentOS / YUM"
|
||||
|
||||
```bash
|
||||
sudo yum install -y yum-utils
|
||||
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo yum install sing-box # or sing-box-beta
|
||||
```
|
||||
(This applies to any distribution that uses `dnf` as the package manager: Fedora, CentOS, even OpenSUSE with DNF installed.)
|
||||
|
||||
## :material-download-box: Manual Installation
|
||||
|
||||
@@ -46,6 +39,7 @@ icon: material/package
|
||||
```bash
|
||||
bash <(curl -fsSL https://sing-box.app/rpm-install.sh)
|
||||
```
|
||||
(This applies to any distribution that uses `rpm` and `systemd`. Because of how `rpm` defines dependencies, if it installs, it probably works.)
|
||||
|
||||
=== ":simple-archlinux: Archlinux / PKG"
|
||||
|
||||
@@ -63,6 +57,7 @@ icon: material/package
|
||||
| nixpkgs | NixOS | `nix-env -iA nixos.sing-box` | [][nixpkgs] |
|
||||
| Homebrew | macOS / Linux | `brew install sing-box` | [][brew] |
|
||||
| APK | Alpine | `apk add sing-box` | [][alpine] |
|
||||
| DEB | AOSC | `apt install sing-box` | [][aosc] |
|
||||
|
||||
=== ":material-apple: macOS"
|
||||
|
||||
@@ -90,6 +85,22 @@ icon: material/package
|
||||
|------------|----------|------------------------|--------------------------------------------------------------------------------------------|
|
||||
| FreshPorts | FreeBSD | `pkg install sing-box` | [][ports] |
|
||||
|
||||
## :material-alert: Problematic Sources
|
||||
|
||||
| Type | Platform | Link | Promblem(s) |
|
||||
|------------|----------|-------------------------------------------------------------------------------------------|------------------------------------------------------------------|
|
||||
| DEB | AOSC | [aosc-os-abbs](https://github.com/AOSC-Dev/aosc-os-abbs/tree/stable/app-network/sing-box) | Problematic build tag list modification; Not actively maintained |
|
||||
| Homebrew | / | [homebrew-core][brew] | Problematic build tag list modification |
|
||||
| Termux | Android | [termux-packages][termux] | Problematic build tag list modification |
|
||||
| FreshPorts | FreeBSD | [FreeBSD ports][ports] | Old Go (go1.20) |
|
||||
|
||||
If you are a user of them, please report issues to them:
|
||||
|
||||
1. Please do not modify release build tags without full understanding of the related functionality: enabling non-default
|
||||
labels may result in decreased performance; the lack of default labels may cause user confusion.
|
||||
2. sing-box supports compiling with some older Go versions, but it is not recommended (especially versions that are no
|
||||
longer supported by Go).
|
||||
|
||||
## :material-book-multiple: Service Management
|
||||
|
||||
For Linux systems with [systemd][systemd], usually the installation already includes a sing-box service,
|
||||
@@ -128,4 +139,6 @@ you can manage the service using the following command:
|
||||
|
||||
[ports]: https://www.freshports.org/net/sing-box
|
||||
|
||||
[aosc]: https://packages.aosc.io/packages/sing-box
|
||||
|
||||
[systemd]: https://systemd.io/
|
||||
|
||||
@@ -24,14 +24,7 @@ icon: material/package
|
||||
sudo dnf config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo dnf install sing-box # or sing-box-beta
|
||||
```
|
||||
|
||||
=== ":material-redhat: CentOS / YUM"
|
||||
|
||||
```bash
|
||||
sudo yum install -y yum-utils
|
||||
sudo yum-config-manager --add-repo https://sing-box.app/sing-box.repo
|
||||
sudo yum install sing-box # or sing-box-beta
|
||||
```
|
||||
(这适用于任何使用 `dnf` 作为包管理器的发行版:Fedora、CentOS,甚至安装了 DNF 的 OpenSUSE。)
|
||||
|
||||
## :material-download-box: 手动安装
|
||||
|
||||
@@ -46,6 +39,7 @@ icon: material/package
|
||||
```bash
|
||||
bash <(curl -fsSL https://sing-box.app/rpm-install.sh)
|
||||
```
|
||||
(这适用于任何使用 `rpm` 和 `systemd` 的发行版。由于 `rpm` 定义依赖关系的方式,如果安装成功,就多半能用。)
|
||||
|
||||
=== ":simple-archlinux: Archlinux / PKG"
|
||||
|
||||
@@ -63,6 +57,7 @@ icon: material/package
|
||||
| nixpkgs | NixOS | `nix-env -iA nixos.sing-box` | [][nixpkgs] |
|
||||
| Homebrew | macOS / Linux | `brew install sing-box` | [][brew] |
|
||||
| APK | Alpine | `apk add sing-box` | [][alpine] |
|
||||
| DEB | AOSC | `apt install sing-box` | [][aosc] |
|
||||
|
||||
=== ":material-apple: macOS"
|
||||
|
||||
@@ -90,6 +85,21 @@ icon: material/package
|
||||
|------------|---------|------------------------|--------------------------------------------------------------------------------------------|
|
||||
| FreshPorts | FreeBSD | `pkg install sing-box` | [][ports] |
|
||||
|
||||
|
||||
## :material-alert: 存在问题的源
|
||||
|
||||
| 类型 | 平台 | 链接 | 原因 |
|
||||
|------------|---------|-------------------------------------------------------------------------------------------|-----------------------|
|
||||
| DEB | AOSC | [aosc-os-abbs](https://github.com/AOSC-Dev/aosc-os-abbs/tree/stable/app-network/sing-box) | 存在问题的构建标志列表修改; 没有活跃维护 |
|
||||
| Homebrew | / | [homebrew-core][brew] | 存在问题的构建标志列表修改 |
|
||||
| Termux | Android | [termux-packages][termux] | 存在问题的构建标志列表修改 |
|
||||
| FreshPorts | FreeBSD | [FreeBSD ports][ports] | 太旧的 Go (go1.20) |
|
||||
|
||||
如果您是其用户,请向他们报告问题:
|
||||
|
||||
1. 在未完全了解相关功能的情况下,请勿修改发布版本标签:启用非默认标签可能会导致性能下降;缺少默认标签可能会引起用户混淆。
|
||||
2. sing-box 支持使用一些较旧的 Go 版本进行编译,但不推荐使用(特别是已不再受 Go 支持的版本)。
|
||||
|
||||
## :material-book-multiple: 服务管理
|
||||
|
||||
对于带有 [systemd][systemd] 的 Linux 系统,通常安装已经包含 sing-box 服务,
|
||||
@@ -124,4 +134,6 @@ icon: material/package
|
||||
|
||||
[ports]: https://www.freshports.org/net/sing-box
|
||||
|
||||
[aosc]: https://packages.aosc.io/packages/sing-box
|
||||
|
||||
[systemd]: https://systemd.io/
|
||||
|
||||
@@ -4,16 +4,17 @@ icon: material/lightning-bolt
|
||||
|
||||
# Hysteria 2
|
||||
|
||||
The most popular Chinese-made simple protocol based on QUIC, the selling point is Brutal,
|
||||
a congestion control algorithm that can resist packet loss by manually specifying the required rate by the user.
|
||||
Hysteria 2 is a simple, Chinese-made protocol based on QUIC.
|
||||
The selling point is Brutal, a congestion control algorithm that
|
||||
tries to achieve a user-defined bandwidth despite packet loss.
|
||||
|
||||
!!! warning
|
||||
|
||||
Even though GFW rarely blocks UDP-based proxies, such protocols actually have far more characteristics than TCP based proxies.
|
||||
Even though GFW rarely blocks UDP-based proxies, such protocols actually have far more obvious characteristics than TCP based proxies.
|
||||
|
||||
| Specification | Binary Characteristics | Active Detect Hiddenness |
|
||||
|---------------------------------------------------------------------------|------------------------|--------------------------|
|
||||
| [hysteria.network](https://v2.hysteria.network/docs/developers/Protocol/) | :material-alert: | :material-check: |
|
||||
| Specification | Resists passive detection | Resists active probes |
|
||||
|---------------------------------------------------------------------------|---------------------------|-----------------------|
|
||||
| [hysteria.network](https://v2.hysteria.network/docs/developers/Protocol/) | :material-alert: | :material-check: |
|
||||
|
||||
## :material-text-box-check: Password Generator
|
||||
|
||||
@@ -44,7 +45,7 @@ To use sing-box with the official program, you need to fill in that combination
|
||||
Replace `up_mbps` and `down_mbps` values with the actual bandwidth of your server.
|
||||
|
||||
=== ":material-harddisk: With local certificate"
|
||||
|
||||
|
||||
```json
|
||||
{
|
||||
"inbounds": [
|
||||
|
||||
@@ -4,15 +4,18 @@ icon: material/send
|
||||
|
||||
# Shadowsocks
|
||||
|
||||
As the most well-known Chinese-made proxy protocol,
|
||||
Shadowsocks exists in multiple versions,
|
||||
but only AEAD 2022 ciphers TCP with multiplexing is recommended.
|
||||
Shadowsocks is the most well-known Chinese-made proxy protocol.
|
||||
It exists in multiple versions, but only AEAD 2022 ciphers
|
||||
over TCP with multiplexing is recommended.
|
||||
|
||||
| Ciphers | Specification | Cryptographic Security | Binary Characteristics | Active Detect Hiddenness |
|
||||
|----------------|------------------------------------------------------------|------------------------|------------------------|--------------------------|
|
||||
| Stream Ciphers | [shadowsocks.org](https://shadowsocks.org/doc/stream.html) | :material-alert: | :material-alert: | :material-alert: |
|
||||
| AEAD | [shadowsocks.org](https://shadowsocks.org/doc/aead.html) | :material-check: | :material-alert: | :material-alert: |
|
||||
| AEAD 2022 | [shadowsocks.org](https://shadowsocks.org/doc/sip022.html) | :material-check: | :material-check: | :material-help: |
|
||||
| Ciphers | Specification | Cryptographically sound | Resists passive detection | Resists active probes |
|
||||
|----------------|------------------------------------------------------------|-------------------------|---------------------------|-----------------------|
|
||||
| Stream Ciphers | [shadowsocks.org](https://shadowsocks.org/doc/stream.html) | :material-alert: | :material-alert: | :material-alert: |
|
||||
| AEAD | [shadowsocks.org](https://shadowsocks.org/doc/aead.html) | :material-check: | :material-alert: | :material-alert: |
|
||||
| AEAD 2022 | [shadowsocks.org](https://shadowsocks.org/doc/sip022.html) | :material-check: | :material-check: | :material-help: |
|
||||
|
||||
(We strongly recommend using multiplexing to send UDP traffic over TCP, because
|
||||
doing otherwise is vulnerable to passive detection.)
|
||||
|
||||
## :material-text-box-check: Password Generator
|
||||
|
||||
|
||||
@@ -4,15 +4,15 @@ icon: material/horse
|
||||
|
||||
# Trojan
|
||||
|
||||
As the most commonly used TLS proxy made in China, Trojan can be used in various combinations,
|
||||
Torjan is the most commonly used TLS proxy made in China. It can be used in various combinations,
|
||||
but only the combination of uTLS and multiplexing is recommended.
|
||||
|
||||
| Protocol and implementation combination | Specification | Binary Characteristics | Active Detect Hiddenness |
|
||||
|-----------------------------------------|----------------------------------------------------------------------|------------------------|--------------------------|
|
||||
| Origin / trojan-gfw | [trojan-gfw.github.io](https://trojan-gfw.github.io/trojan/protocol) | :material-check: | :material-check: |
|
||||
| Basic Go implementation | / | :material-alert: | :material-check: |
|
||||
| with privates transport by V2Ray | No formal definition | :material-alert: | :material-alert: |
|
||||
| with uTLS enabled | No formal definition | :material-help: | :material-check: |
|
||||
| Protocol and implementation combination | Specification | Resists passive detection | Resists active probes |
|
||||
|-----------------------------------------|----------------------------------------------------------------------|---------------------------|-----------------------|
|
||||
| Origin / trojan-gfw | [trojan-gfw.github.io](https://trojan-gfw.github.io/trojan/protocol) | :material-check: | :material-check: |
|
||||
| Basic Go implementation | / | :material-alert: | :material-check: |
|
||||
| with privates transport by V2Ray | No formal definition | :material-alert: | :material-alert: |
|
||||
| with uTLS enabled | No formal definition | :material-help: | :material-check: |
|
||||
|
||||
## :material-text-box-check: Password Generator
|
||||
|
||||
@@ -211,4 +211,3 @@ but only the combination of uTLS and multiplexing is recommended.
|
||||
]
|
||||
}
|
||||
```
|
||||
|
||||
|
||||
@@ -12,6 +12,7 @@ import (
|
||||
"syscall"
|
||||
"time"
|
||||
|
||||
"github.com/sagernet/cors"
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/urltest"
|
||||
C "github.com/sagernet/sing-box/constant"
|
||||
@@ -29,7 +30,6 @@ import (
|
||||
"github.com/sagernet/ws/wsutil"
|
||||
|
||||
"github.com/go-chi/chi/v5"
|
||||
"github.com/go-chi/cors"
|
||||
"github.com/go-chi/render"
|
||||
)
|
||||
|
||||
@@ -90,11 +90,16 @@ func NewServer(ctx context.Context, router adapter.Router, logFactory log.Observ
|
||||
if options.StoreMode || options.StoreSelected || options.StoreFakeIP || options.CacheFile != "" || options.CacheID != "" {
|
||||
return nil, E.New("cache_file and related fields in Clash API is deprecated in sing-box 1.8.0, use experimental.cache_file instead.")
|
||||
}
|
||||
allowedOrigins := options.AccessControlAllowOrigin
|
||||
if len(allowedOrigins) == 0 {
|
||||
allowedOrigins = []string{"*"}
|
||||
}
|
||||
cors := cors.New(cors.Options{
|
||||
AllowedOrigins: []string{"*"},
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE"},
|
||||
AllowedHeaders: []string{"Content-Type", "Authorization"},
|
||||
MaxAge: 300,
|
||||
AllowedOrigins: allowedOrigins,
|
||||
AllowedMethods: []string{"GET", "POST", "PUT", "PATCH", "DELETE"},
|
||||
AllowedHeaders: []string{"Content-Type", "Authorization"},
|
||||
AllowPrivateNetwork: options.AccessControlAllowPrivateNetwork,
|
||||
MaxAge: 300,
|
||||
})
|
||||
chiRouter.Use(cors.Handler)
|
||||
chiRouter.Group(func(r chi.Router) {
|
||||
@@ -277,10 +282,11 @@ func authentication(serverSecret string) func(next http.Handler) http.Handler {
|
||||
|
||||
func hello(redirect bool) func(w http.ResponseWriter, r *http.Request) {
|
||||
return func(w http.ResponseWriter, r *http.Request) {
|
||||
if redirect {
|
||||
http.Redirect(w, r, "/ui/", http.StatusTemporaryRedirect)
|
||||
} else {
|
||||
contentType := r.Header.Get("Content-Type")
|
||||
if !redirect || contentType == "application/json" {
|
||||
render.JSON(w, r, render.M{"hello": "clash"})
|
||||
} else {
|
||||
http.Redirect(w, r, "/ui/", http.StatusTemporaryRedirect)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -8,35 +8,35 @@ require (
|
||||
github.com/cloudflare/circl v1.3.7
|
||||
github.com/cretz/bine v0.2.0
|
||||
github.com/go-chi/chi/v5 v5.0.12
|
||||
github.com/go-chi/cors v1.2.1
|
||||
github.com/go-chi/render v1.0.3
|
||||
github.com/gofrs/uuid/v5 v5.2.0
|
||||
github.com/insomniacslk/dhcp v0.0.0-20231206064809-8c70d406f6d2
|
||||
github.com/libdns/alidns v1.0.3
|
||||
github.com/libdns/cloudflare v0.1.1
|
||||
github.com/logrusorgru/aurora v2.0.3+incompatible
|
||||
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d
|
||||
github.com/mholt/acmez v1.2.0
|
||||
github.com/miekg/dns v1.1.61
|
||||
github.com/ooni/go-libtor v1.1.8
|
||||
github.com/oschwald/maxminddb-golang v1.12.0
|
||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1
|
||||
github.com/sagernet/cors v1.2.1
|
||||
github.com/sagernet/fswatch v0.1.1
|
||||
github.com/sagernet/gomobile v0.1.3
|
||||
github.com/sagernet/gvisor v0.0.0-20240428053021-e691de28565f
|
||||
github.com/sagernet/quic-go v0.46.0-beta.4
|
||||
github.com/sagernet/quic-go v0.47.0-beta.2
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691
|
||||
github.com/sagernet/sing v0.5.0-beta.1
|
||||
github.com/sagernet/sing-dns v0.3.0-beta.14
|
||||
github.com/sagernet/sing-mux v0.2.0
|
||||
github.com/sagernet/sing-quic v0.3.0-beta.2
|
||||
github.com/sagernet/sing-quic v0.3.0-beta.3
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0
|
||||
github.com/sagernet/sing-shadowtls v0.1.4
|
||||
github.com/sagernet/sing-tun v0.4.0-beta.13.0.20240703164908-1f043289199d
|
||||
github.com/sagernet/sing-vmess v0.1.12
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7
|
||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6
|
||||
github.com/sagernet/utls v1.5.4
|
||||
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8
|
||||
github.com/sagernet/ws v0.0.0-20231204124109-acfe8907c854
|
||||
@@ -47,7 +47,7 @@ require (
|
||||
golang.org/x/crypto v0.25.0
|
||||
golang.org/x/exp v0.0.0-20240719175910-8a7402abbf56
|
||||
golang.org/x/net v0.27.0
|
||||
golang.org/x/sys v0.22.0
|
||||
golang.org/x/sys v0.25.0
|
||||
golang.zx2c4.com/wireguard/wgctrl v0.0.0-20230429144221-925a1e7659e6
|
||||
google.golang.org/grpc v1.63.2
|
||||
google.golang.org/protobuf v1.33.0
|
||||
@@ -91,8 +91,8 @@ require (
|
||||
github.com/zeebo/blake3 v0.2.3 // indirect
|
||||
go.uber.org/multierr v1.11.0 // indirect
|
||||
golang.org/x/mod v0.19.0 // indirect
|
||||
golang.org/x/sync v0.7.0 // indirect
|
||||
golang.org/x/text v0.16.0 // indirect
|
||||
golang.org/x/sync v0.8.0 // indirect
|
||||
golang.org/x/text v0.18.0 // indirect
|
||||
golang.org/x/time v0.5.0 // indirect
|
||||
golang.org/x/tools v0.23.0 // indirect
|
||||
google.golang.org/genproto/googleapis/rpc v0.0.0-20240227224415-6ceb2ff114de // indirect
|
||||
|
||||
@@ -21,8 +21,6 @@ github.com/gaukas/godicttls v0.0.4 h1:NlRaXb3J6hAnTmWdsEKb9bcSBD6BvcIjdGdeb0zfXb
|
||||
github.com/gaukas/godicttls v0.0.4/go.mod h1:l6EenT4TLWgTdwslVb4sEMOCf7Bv0JAK67deKr9/NCI=
|
||||
github.com/go-chi/chi/v5 v5.0.12 h1:9euLV5sTrTNTRUU9POmDUvfxyj6LAABLUcEWO+JJb4s=
|
||||
github.com/go-chi/chi/v5 v5.0.12/go.mod h1:DslCQbL2OYiznFReuXYUmQ2hGd1aDpCnlMNITLSKoi8=
|
||||
github.com/go-chi/cors v1.2.1 h1:xEC8UT3Rlp2QuWNEr4Fs/c2EAGVKBwy/1vHx3bppil4=
|
||||
github.com/go-chi/cors v1.2.1/go.mod h1:sSbTewc+6wYHBBCW7ytsFSn836hqM7JxpglAy2Vzc58=
|
||||
github.com/go-chi/render v1.0.3 h1:AsXqd2a1/INaIfUSKq3G5uA8weYx20FOsM7uSoCyyt4=
|
||||
github.com/go-chi/render v1.0.3/go.mod h1:/gr3hVkmYR0YlEy3LxCuVRFzEu9Ruok+gFqbIofjao0=
|
||||
github.com/go-logr/logr v1.2.4 h1:g01GSCwiDw2xSZfjJ2/T9M+S6pFdcNtFYsp+Y43HYDQ=
|
||||
@@ -74,6 +72,8 @@ github.com/mdlayher/netlink v1.7.2 h1:/UtM3ofJap7Vl4QWCPDGXY8d3GIY2UGSDbK+QWmY8/
|
||||
github.com/mdlayher/netlink v1.7.2/go.mod h1:xraEF7uJbxLhc5fpHL4cPe221LI2bdttWlU+ZGLfQSw=
|
||||
github.com/mdlayher/socket v0.4.1 h1:eM9y2/jlbs1M615oshPQOHZzj6R6wMT7bX5NPiQvn2U=
|
||||
github.com/mdlayher/socket v0.4.1/go.mod h1:cAqeGjoufqdxWkD7DkpyS+wcefOtmu5OQ8KuoJGIReA=
|
||||
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d h1:j9LtzkYstLFoNvXW824QQeN7Y26uPL5249kzWKbzO9U=
|
||||
github.com/metacubex/tfo-go v0.0.0-20240821025650-e9be0afd5e7d/go.mod h1:c7bVFM9f5+VzeZ/6Kg77T/jrg1Xp8QpqlSHvG/aXVts=
|
||||
github.com/mholt/acmez v1.2.0 h1:1hhLxSgY5FvH5HCnGUuwbKY2VQVo8IU7rxXKSnZ7F30=
|
||||
github.com/mholt/acmez v1.2.0/go.mod h1:VT9YwH1xgNX1kmYY89gY8xPJC84BFAisjo8Egigt4kE=
|
||||
github.com/miekg/dns v1.1.61 h1:nLxbwF3XxhwVSm8g9Dghm9MHPaUZuqhPiGL+675ZmEs=
|
||||
@@ -100,6 +100,8 @@ github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a h1:+NkI2670SQpQWvkk
|
||||
github.com/sagernet/bbolt v0.0.0-20231014093535-ea5cb2fe9f0a/go.mod h1:63s7jpZqcDAIpj8oI/1v4Izok+npJOHACFCU6+huCkM=
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1 h1:YbmpqPQEMdlk9oFSKYWRqVuu9qzNiOayIonKmv1gCXY=
|
||||
github.com/sagernet/cloudflare-tls v0.0.0-20231208171750-a4483c1b7cd1/go.mod h1:J2yAxTFPDjrDPhuAi9aWFz2L3ox9it4qAluBBbN0H5k=
|
||||
github.com/sagernet/cors v1.2.1 h1:Cv5Z8y9YSD6Gm+qSpNrL3LO4lD3eQVvbFYJSG7JCMHQ=
|
||||
github.com/sagernet/cors v1.2.1/go.mod h1:O64VyOjjhrkLmQIjF4KGRrJO/5dVXFdpEmCW/eISRAI=
|
||||
github.com/sagernet/fswatch v0.1.1 h1:YqID+93B7VRfqIH3PArW/XpJv5H4OLEVWDfProGoRQs=
|
||||
github.com/sagernet/fswatch v0.1.1/go.mod h1:nz85laH0mkQqJfaOrqPpkwtU1znMFNVTpT/5oRsVz/o=
|
||||
github.com/sagernet/gomobile v0.1.3 h1:ohjIb1Ou2+1558PnZour3od69suSuvkdSVOlO1tC4B8=
|
||||
@@ -110,8 +112,8 @@ github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a h1:ObwtHN2VpqE0ZN
|
||||
github.com/sagernet/netlink v0.0.0-20240612041022-b9a21c07ac6a/go.mod h1:xLnfdiJbSp8rNqYEdIW/6eDO4mVoogml14Bh2hSiFpM=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4 h1:kbULlAwAC3jvdGAC1P5Fa3GSxVwQJibNenDW2zaXr8I=
|
||||
github.com/sagernet/nftables v0.3.0-beta.4/go.mod h1:OQXAjvjNGGFxaTgVCSTRIhYB5/llyVDeapVoENYBDS8=
|
||||
github.com/sagernet/quic-go v0.46.0-beta.4 h1:k9f7VSKaM47AY6MPND0Qf1KRN7HwimPg9zdOFTXTiCk=
|
||||
github.com/sagernet/quic-go v0.46.0-beta.4/go.mod h1:zJmVdJUNqEDXfubf4KtIOUHHerggjBduiGRLNzJspcM=
|
||||
github.com/sagernet/quic-go v0.47.0-beta.2 h1:1tCGWFOSaXIeuQaHrwOMJIYvlupjTcaVInGQw5ArULU=
|
||||
github.com/sagernet/quic-go v0.47.0-beta.2/go.mod h1:bLVKvElSEMNv7pu7SZHscW02TYigzQ5lQu3Nh4wNh8Q=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691 h1:5Th31OC6yj8byLGkEnIYp6grlXfo1QYUfiYFGjewIdc=
|
||||
github.com/sagernet/reality v0.0.0-20230406110435-ee17307e7691/go.mod h1:B8lp4WkQ1PwNnrVMM6KyuFR20pU8jYBD+A4EhJovEXU=
|
||||
github.com/sagernet/sing v0.2.18/go.mod h1:OL6k2F0vHmEzXz2KW19qQzu172FDgSbUSODylighuVo=
|
||||
@@ -121,8 +123,8 @@ github.com/sagernet/sing-dns v0.3.0-beta.14 h1:/s+fJzYKsvLaNDt/2rjpsrDcN8wmCO2Jb
|
||||
github.com/sagernet/sing-dns v0.3.0-beta.14/go.mod h1:rscgSr5ixOPk8XM9ZMLuMXCyldEQ1nLvdl0nfv+lp00=
|
||||
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.3.0-beta.2 h1:9TiaW4js4fXD6GPCGMbwb3/bIRKpXm7skJBdV1OdvMs=
|
||||
github.com/sagernet/sing-quic v0.3.0-beta.2/go.mod h1:YLV1dUDv8Eyp/8e55O/EvfsrwxOgEDVgDCIoPqmDREE=
|
||||
github.com/sagernet/sing-quic v0.3.0-beta.3 h1:8S98VXZxtSiOqVCFbCNbMEvKDPhOF/VNBYMjVC3xMhw=
|
||||
github.com/sagernet/sing-quic v0.3.0-beta.3/go.mod h1:rFPUlYnSj1Bx9gFSghjCqrCzfGvpjhkisOiTKpjq5vQ=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7 h1:zaopR1tbHEw5Nk6FAkM05wCslV6ahVegEZaKMv9ipx8=
|
||||
github.com/sagernet/sing-shadowsocks v0.2.7/go.mod h1:0rIKJZBR65Qi0zwdKezt4s57y/Tl1ofkaq6NlkzVuyE=
|
||||
github.com/sagernet/sing-shadowsocks2 v0.2.0 h1:wpZNs6wKnR7mh1wV9OHwOyUr21VkS3wKFHi+8XwgADg=
|
||||
@@ -135,8 +137,6 @@ github.com/sagernet/sing-vmess v0.1.12 h1:2gFD8JJb+eTFMoa8FIVMnknEi+vCSfaiTXTfEY
|
||||
github.com/sagernet/sing-vmess v0.1.12/go.mod h1:luTSsfyBGAc9VhtCqwjR+dt1QgqBhuYBCONB/POhF8I=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7 h1:DImB4lELfQhplLTxeq2z31Fpv8CQqqrUwTbrIRumZqQ=
|
||||
github.com/sagernet/smux v0.0.0-20231208180855-7041f6ea79e7/go.mod h1:FP9X2xjT/Az1EsG/orYYoC+5MojWnuI7hrffz8fGwwo=
|
||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6 h1:z3SJQhVyU63FT26Wn/UByW6b7q8QKB0ZkPqsyqcz2PI=
|
||||
github.com/sagernet/tfo-go v0.0.0-20231209031829-7b5343ac1dc6/go.mod h1:73xRZuxwkFk4aiLw28hG8W6o9cr2UPrGL9pdY2UTbvY=
|
||||
github.com/sagernet/utls v1.5.4 h1:KmsEGbB2dKUtCNC+44NwAdNAqnqQ6GA4pTO0Yik56co=
|
||||
github.com/sagernet/utls v1.5.4/go.mod h1:CTGxPWExIloRipK3XFpYv0OVyhO8kk3XCGW/ieyTh1s=
|
||||
github.com/sagernet/wireguard-go v0.0.0-20231215174105-89dec3b2f3e8 h1:R0OMYAScomNAVpTfbHFpxqJpvwuhxSRi+g6z7gZhABs=
|
||||
@@ -182,8 +182,8 @@ golang.org/x/net v0.0.0-20210226172049-e18ecbb05110/go.mod h1:m0MpNAwzfU5UDzcl9v
|
||||
golang.org/x/net v0.0.0-20210525063256-abc453219eb5/go.mod h1:9nx3DQGgdP8bBQD5qxJ1jj9UTztislL4KSBs9R2vV5Y=
|
||||
golang.org/x/net v0.27.0 h1:5K3Njcw06/l2y9vpGCSdcxWOYHOUk3dVNGDXN+FvAys=
|
||||
golang.org/x/net v0.27.0/go.mod h1:dDi0PyhWNoiUOrAS8uXv/vnScO4wnHQO4mj9fn/RytE=
|
||||
golang.org/x/sync v0.7.0 h1:YsImfSBoP9QPYL0xyKJPq0gcaJdG3rInoqxTWbfQu9M=
|
||||
golang.org/x/sync v0.7.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sync v0.8.0 h1:3NFvSEYkUoMifnESzZl15y791HH1qU2xm6eCJU5ZPXQ=
|
||||
golang.org/x/sync v0.8.0/go.mod h1:Czt+wKu1gCyEFDUtn0jG5QVvpJ6rzVqr5aXyt9drQfk=
|
||||
golang.org/x/sys v0.0.0-20190403152447-81d4e9dc473e/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20201119102817-f84b799fce68/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
golang.org/x/sys v0.0.0-20210423082822-04245dca01da/go.mod h1:h1NjWce9XRLGQEsW7wpKNCjG9DtNlClVuFLEZdDNbEs=
|
||||
@@ -192,14 +192,14 @@ golang.org/x/sys v0.1.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.6.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg=
|
||||
golang.org/x/sys v0.14.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.22.0 h1:RI27ohtqKCnwULzJLqkv897zojh5/DwS/ENaMzUOaWI=
|
||||
golang.org/x/sys v0.22.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/sys v0.25.0 h1:r+8e+loiHxRqhXVl6ML1nO3l1+oFoWbnlu2Ehimmi34=
|
||||
golang.org/x/sys v0.25.0/go.mod h1:/VUhepiaJMQUp4+oa/7Zr1D23ma6VTLIYjOOTFZPUcA=
|
||||
golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo=
|
||||
golang.org/x/term v0.22.0 h1:BbsgPEJULsl2fV/AT3v15Mjva5yXKQDyKf+TbDz7QJk=
|
||||
golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.3.6/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ=
|
||||
golang.org/x/text v0.16.0 h1:a94ExnEXNtEwYLGJSIUxnWoxoRz/ZcCsV63ROupILh4=
|
||||
golang.org/x/text v0.16.0/go.mod h1:GhwF1Be+LQoKShO3cGOHzqOgRrGaYc9AvblQOmPVHnI=
|
||||
golang.org/x/text v0.18.0 h1:XvMDiNzPAl0jr17s6W9lcaIhGUfUORdGCNsuLmPG224=
|
||||
golang.org/x/text v0.18.0/go.mod h1:BuEKDfySbSR4drPmRPG/7iBdf8hvFMuRexcpahXilzY=
|
||||
golang.org/x/time v0.5.0 h1:o7cqy6amK/52YcAKIPlM3a+Fpj35zvRj2TP+e1xFSfk=
|
||||
golang.org/x/time v0.5.0/go.mod h1:3BpzKBy/shNhVucY/MWOyx10tF3SFh9QdLuxbVysPQM=
|
||||
golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ=
|
||||
|
||||
@@ -6,7 +6,7 @@ import (
|
||||
"context"
|
||||
"net"
|
||||
|
||||
"github.com/sagernet/tfo-go"
|
||||
"github.com/metacubex/tfo-go"
|
||||
)
|
||||
|
||||
const go120Available = true
|
||||
|
||||
@@ -17,13 +17,15 @@ type CacheFileOptions struct {
|
||||
}
|
||||
|
||||
type ClashAPIOptions struct {
|
||||
ExternalController string `json:"external_controller,omitempty"`
|
||||
ExternalUI string `json:"external_ui,omitempty"`
|
||||
ExternalUIDownloadURL string `json:"external_ui_download_url,omitempty"`
|
||||
ExternalUIDownloadDetour string `json:"external_ui_download_detour,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
DefaultMode string `json:"default_mode,omitempty"`
|
||||
ModeList []string `json:"-"`
|
||||
ExternalController string `json:"external_controller,omitempty"`
|
||||
ExternalUI string `json:"external_ui,omitempty"`
|
||||
ExternalUIDownloadURL string `json:"external_ui_download_url,omitempty"`
|
||||
ExternalUIDownloadDetour string `json:"external_ui_download_detour,omitempty"`
|
||||
Secret string `json:"secret,omitempty"`
|
||||
DefaultMode string `json:"default_mode,omitempty"`
|
||||
ModeList []string `json:"-"`
|
||||
AccessControlAllowOrigin Listable[string] `json:"access_control_allow_origin,omitempty"`
|
||||
AccessControlAllowPrivateNetwork bool `json:"access_control_allow_private_network,omitempty"`
|
||||
|
||||
// Deprecated: migrated to global cache file
|
||||
CacheFile string `json:"cache_file,omitempty"`
|
||||
|
||||
+2
-2
@@ -14,9 +14,9 @@ import (
|
||||
)
|
||||
|
||||
type _RuleSet struct {
|
||||
Type string `json:"type"`
|
||||
Type string `json:"type,omitempty"`
|
||||
Tag string `json:"tag"`
|
||||
Format string `json:"format"`
|
||||
Format string `json:"format,omitempty"`
|
||||
InlineOptions PlainRuleSet `json:"-"`
|
||||
LocalOptions LocalRuleSet `json:"-"`
|
||||
RemoteOptions RemoteRuleSet `json:"-"`
|
||||
|
||||
@@ -152,6 +152,10 @@ func (w *WireGuard) start() error {
|
||||
}
|
||||
bind = wireguard.NewClientBind(w.ctx, w, w.listener, isConnect, connectAddr, reserved)
|
||||
}
|
||||
err = w.tunDevice.Start()
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
wgDevice := device.NewDevice(w.tunDevice, bind, &device.Logger{
|
||||
Verbosef: func(format string, args ...interface{}) {
|
||||
w.logger.Debug(fmt.Sprintf(strings.ToLower(format), args...))
|
||||
@@ -170,7 +174,7 @@ func (w *WireGuard) start() error {
|
||||
}
|
||||
w.device = wgDevice
|
||||
w.pauseCallback = w.pauseManager.RegisterCallback(w.onPauseUpdated)
|
||||
return w.tunDevice.Start()
|
||||
return nil
|
||||
}
|
||||
|
||||
func (w *WireGuard) Close() error {
|
||||
@@ -180,7 +184,6 @@ func (w *WireGuard) Close() error {
|
||||
if w.pauseCallback != nil {
|
||||
w.pauseManager.UnregisterCallback(w.pauseCallback)
|
||||
}
|
||||
w.tunDevice.Close()
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
+6
-3
@@ -852,7 +852,7 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
conn = deadline.NewConn(conn)
|
||||
}
|
||||
|
||||
if metadata.InboundOptions.SniffEnabled {
|
||||
if metadata.InboundOptions.SniffEnabled && !sniff.Skip(metadata) {
|
||||
buffer := buf.NewPacket()
|
||||
err := sniff.PeekStream(
|
||||
ctx,
|
||||
@@ -860,9 +860,10 @@ func (r *Router) RouteConnection(ctx context.Context, conn net.Conn, metadata ad
|
||||
conn,
|
||||
buffer,
|
||||
time.Duration(metadata.InboundOptions.SniffTimeout),
|
||||
sniff.StreamDomainNameQuery,
|
||||
sniff.TLSClientHello,
|
||||
sniff.HTTPHost,
|
||||
sniff.StreamDomainNameQuery,
|
||||
sniff.SSH,
|
||||
sniff.BitTorrent,
|
||||
)
|
||||
if err == nil {
|
||||
@@ -1055,7 +1056,9 @@ func (r *Router) RoutePacketConnection(ctx context.Context, conn N.PacketConn, m
|
||||
}
|
||||
}
|
||||
}
|
||||
conn = bufio.NewCachedPacketConn(conn, buffer, destination)
|
||||
if err == nil {
|
||||
conn = bufio.NewCachedPacketConn(conn, buffer, destination)
|
||||
}
|
||||
for _, cachedBuffer := range common.Reverse(bufferList) {
|
||||
conn = bufio.NewCachedPacketConn(conn, cachedBuffer, destination)
|
||||
}
|
||||
|
||||
@@ -189,6 +189,9 @@ func (r *Router) Lookup(ctx context.Context, domain string, strategy dns.DomainS
|
||||
)
|
||||
responseAddrs, cached = r.dnsClient.LookupCache(ctx, domain, strategy)
|
||||
if cached {
|
||||
if len(responseAddrs) == 0 {
|
||||
return nil, dns.RCodeNameError
|
||||
}
|
||||
return responseAddrs, nil
|
||||
}
|
||||
r.dnsLogger.DebugContext(ctx, "lookup domain ", domain)
|
||||
|
||||
@@ -230,17 +230,13 @@ func (w *StackDevice) Events() <-chan wgTun.Event {
|
||||
}
|
||||
|
||||
func (w *StackDevice) Close() error {
|
||||
select {
|
||||
case <-w.done:
|
||||
return os.ErrClosed
|
||||
default:
|
||||
}
|
||||
close(w.done)
|
||||
close(w.events)
|
||||
w.stack.Close()
|
||||
for _, endpoint := range w.stack.CleanupEndpoints() {
|
||||
endpoint.Abort()
|
||||
}
|
||||
w.stack.Wait()
|
||||
close(w.done)
|
||||
return nil
|
||||
}
|
||||
|
||||
|
||||
@@ -6,6 +6,7 @@ import (
|
||||
"net"
|
||||
"net/netip"
|
||||
"os"
|
||||
"sync"
|
||||
|
||||
"github.com/sagernet/sing-box/adapter"
|
||||
"github.com/sagernet/sing-box/common/dialer"
|
||||
@@ -21,14 +22,16 @@ import (
|
||||
var _ Device = (*SystemDevice)(nil)
|
||||
|
||||
type SystemDevice struct {
|
||||
dialer N.Dialer
|
||||
device tun.Tun
|
||||
batchDevice tun.LinuxTUN
|
||||
name string
|
||||
mtu int
|
||||
events chan wgTun.Event
|
||||
addr4 netip.Addr
|
||||
addr6 netip.Addr
|
||||
dialer N.Dialer
|
||||
device tun.Tun
|
||||
batchDevice tun.LinuxTUN
|
||||
name string
|
||||
mtu uint32
|
||||
inet4Addresses []netip.Prefix
|
||||
inet6Addresses []netip.Prefix
|
||||
gso bool
|
||||
events chan wgTun.Event
|
||||
closeOnce sync.Once
|
||||
}
|
||||
|
||||
func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes []netip.Prefix, mtu uint32, gso bool) (*SystemDevice, error) {
|
||||
@@ -44,43 +47,17 @@ func NewSystemDevice(router adapter.Router, interfaceName string, localPrefixes
|
||||
if interfaceName == "" {
|
||||
interfaceName = tun.CalculateInterfaceName("wg")
|
||||
}
|
||||
tunInterface, err := tun.New(tun.Options{
|
||||
Name: interfaceName,
|
||||
Inet4Address: inet4Addresses,
|
||||
Inet6Address: inet6Addresses,
|
||||
MTU: mtu,
|
||||
GSO: gso,
|
||||
})
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
var inet4Address netip.Addr
|
||||
var inet6Address netip.Addr
|
||||
if len(inet4Addresses) > 0 {
|
||||
inet4Address = inet4Addresses[0].Addr()
|
||||
}
|
||||
if len(inet6Addresses) > 0 {
|
||||
inet6Address = inet6Addresses[0].Addr()
|
||||
}
|
||||
var batchDevice tun.LinuxTUN
|
||||
if gso {
|
||||
batchTUN, isBatchTUN := tunInterface.(tun.LinuxTUN)
|
||||
if !isBatchTUN {
|
||||
return nil, E.New("GSO is not supported on current platform")
|
||||
}
|
||||
batchDevice = batchTUN
|
||||
}
|
||||
|
||||
return &SystemDevice{
|
||||
dialer: common.Must1(dialer.NewDefault(router, option.DialerOptions{
|
||||
BindInterface: interfaceName,
|
||||
})),
|
||||
device: tunInterface,
|
||||
batchDevice: batchDevice,
|
||||
name: interfaceName,
|
||||
mtu: int(mtu),
|
||||
events: make(chan wgTun.Event),
|
||||
addr4: inet4Address,
|
||||
addr6: inet6Address,
|
||||
name: interfaceName,
|
||||
mtu: mtu,
|
||||
inet4Addresses: inet4Addresses,
|
||||
inet6Addresses: inet6Addresses,
|
||||
gso: gso,
|
||||
events: make(chan wgTun.Event),
|
||||
}, nil
|
||||
}
|
||||
|
||||
@@ -93,14 +70,39 @@ func (w *SystemDevice) ListenPacket(ctx context.Context, destination M.Socksaddr
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Inet4Address() netip.Addr {
|
||||
return w.addr4
|
||||
if len(w.inet4Addresses) == 0 {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return w.inet4Addresses[0].Addr()
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Inet6Address() netip.Addr {
|
||||
return w.addr6
|
||||
if len(w.inet6Addresses) == 0 {
|
||||
return netip.Addr{}
|
||||
}
|
||||
return w.inet6Addresses[0].Addr()
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Start() error {
|
||||
tunInterface, err := tun.New(tun.Options{
|
||||
Name: w.name,
|
||||
Inet4Address: w.inet4Addresses,
|
||||
Inet6Address: w.inet6Addresses,
|
||||
MTU: w.mtu,
|
||||
GSO: w.gso,
|
||||
})
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
w.device = tunInterface
|
||||
if w.gso {
|
||||
batchTUN, isBatchTUN := tunInterface.(tun.LinuxTUN)
|
||||
if !isBatchTUN {
|
||||
tunInterface.Close()
|
||||
return E.New("GSO is not supported on current platform")
|
||||
}
|
||||
w.batchDevice = batchTUN
|
||||
}
|
||||
w.events <- wgTun.EventUp
|
||||
return nil
|
||||
}
|
||||
@@ -143,7 +145,7 @@ func (w *SystemDevice) Flush() error {
|
||||
}
|
||||
|
||||
func (w *SystemDevice) MTU() (int, error) {
|
||||
return w.mtu, nil
|
||||
return int(w.mtu), nil
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Name() (string, error) {
|
||||
@@ -155,6 +157,7 @@ func (w *SystemDevice) Events() <-chan wgTun.Event {
|
||||
}
|
||||
|
||||
func (w *SystemDevice) Close() error {
|
||||
close(w.events)
|
||||
return w.device.Close()
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user